diff options
Diffstat (limited to 'sys/i386')
242 files changed, 24842 insertions, 13228 deletions
diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index 42515c8d5cf30..c871151c7ae04 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -15,7 +15,7 @@ * * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm.c,v 1.76 1998/12/04 21:28:39 archie Exp $ + * $Id: apm.c,v 1.73 1998/07/06 06:29:03 imp Exp $ */ #include "opt_devfs.h" @@ -29,7 +29,6 @@ #endif /*DEVFS*/ #include <sys/systm.h> #include <sys/time.h> -#include <sys/reboot.h> #include <i386/isa/isa_device.h> #include <machine/apm_bios.h> #include <machine/segments.h> @@ -246,13 +245,12 @@ apm_display(int newstate) /* * Turn off the entire system. */ -static void -apm_power_off(int howto, void *junk) +void +apm_power_off(void) { u_long eax, ebx, ecx, edx; - /* Not halting powering off, or not active */ - if (!(howto & RB_POWEROFF) || !apm_softc.active) + if (!apm_softc.active) return; eax = (APM_BIOS << 8) | APM_SETPWSTATE; ebx = PMDV_ALLDEV; @@ -795,7 +793,7 @@ apmattach(struct isa_device *dvp) sc->ds_base = (apm_ds_base << 4) + APM_KERNBASE; sc->cs32_limit = apm_cs32_limit - 1; if (apm_cs16_limit == 0) - apm_cs16_limit = apm_cs32_limit; + apm_cs16_limit == apm_cs32_limit; sc->cs16_limit = apm_cs16_limit - 1; sc->ds_limit = apm_ds_limit - 1; sc->cs_entry = apm_cs_entry; @@ -905,9 +903,6 @@ apmattach(struct isa_device *dvp) apm_event_enable(); - /* Power the system off using APM */ - at_shutdown_pri(apm_power_off, NULL, SHUTDOWN_FINAL, SHUTDOWN_PRI_LAST); - sc->initialized = 1; #ifdef DEVFS diff --git a/sys/i386/boot/Makefile b/sys/i386/boot/Makefile index dc8ad32a5f6a3..a075627ba2496 100644 --- a/sys/i386/boot/Makefile +++ b/sys/i386/boot/Makefile @@ -1,5 +1,5 @@ -# $Id: Makefile,v 1.29 1997/07/10 21:58:43 joerg Exp $ +# $Id: Makefile,v 1.28 1997/02/22 09:29:58 peter Exp $ -SUBDIR= cdboot dosboot kzipboot netboot rawboot +SUBDIR= biosboot cdboot dosboot kzipboot netboot rawboot .include <bsd.subdir.mk> diff --git a/sys/i386/boot/Makefile.inc b/sys/i386/boot/Makefile.inc index 520458a2126b6..2b92805e79772 100644 --- a/sys/i386/boot/Makefile.inc +++ b/sys/i386/boot/Makefile.inc @@ -1,7 +1,5 @@ -# $Id: Makefile.inc,v 1.3 1998/12/30 10:05:56 bde Exp $ +# $Id$ -BINDIR?= /usr/mdec -CFLAGS+= -aout .if exists(${.CURDIR}/../../../../include) CFLAGS+= -nostdinc -I${.CURDIR}/../../../../include .endif diff --git a/sys/i386/boot/biosboot/Makefile b/sys/i386/boot/biosboot/Makefile index e4feaf98de984..cf517706cdb92 100644 --- a/sys/i386/boot/biosboot/Makefile +++ b/sys/i386/boot/biosboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.67 1998/11/21 21:07:17 ache Exp $ +# $Id: Makefile,v 1.65 1998/09/15 09:59:57 gibbs 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 \ @@ -59,8 +60,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 @@ -81,11 +82,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/i386/boot/biosboot/README.serial b/sys/i386/boot/biosboot/README.serial index 732e4787e35ce..f00d7d0f2d111 100644 --- a/sys/i386/boot/biosboot/README.serial +++ b/sys/i386/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.9 1997/06/16 06:32:51 charnier Exp $ +$Id: README.serial,v 1.8 1997/06/09 05:10:54 bde Exp $ diff --git a/sys/i386/boot/biosboot/probe_keyboard.c b/sys/i386/boot/biosboot/probe_keyboard.c index 7856d586a58ff..951d92bcc57fb 100644 --- a/sys/i386/boot/biosboot/probe_keyboard.c +++ b/sys/i386/boot/biosboot/probe_keyboard.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp $ + * $Id:$ */ #include <sys/types.h> @@ -31,8 +31,7 @@ #include <machine/cpufunc.h> #include <i386/isa/isa.h> - -#include <dev/kbd/atkbdcreg.h> +#include <i386/isa/kbdio.h> #include "boot.h" diff --git a/sys/i386/boot/cdboot/Makefile b/sys/i386/boot/cdboot/Makefile index b59e851fd870a..4c01c44b33730 100644 --- a/sys/i386/boot/cdboot/Makefile +++ b/sys/i386/boot/cdboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 1998/03/12 12:26:47 bde Exp $ +# $Id: Makefile,v 1.3 1997/07/21 16:12:52 bde Exp $ # PROG= boot @@ -8,6 +8,7 @@ SRCS+= probe_keyboard.c io.c cdrom.c malloc.c .PATH: ${.CURDIR}/../biosboot +BINDIR= /usr/mdec BINMODE= 444 CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \ -mno-486 \ @@ -46,6 +47,10 @@ CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED} CLEANFILES+= boot.img boot.nohdr boot.strip LDFLAGS+= -N -T 0 -nostdlib +#LINKS= ${BINDIR}/sdboot ${BINDIR}/wdboot\ +# ${BINDIR}/sdboot ${BINDIR}/fdboot\ +# ${BINDIR}/bootsd ${BINDIR}/bootwd\ +# ${BINDIR}/bootsd ${BINDIR}/bootfd NOSHARED= YES NOMAN= STRIP= @@ -63,8 +68,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/i386/boot/dosboot/Makefile b/sys/i386/boot/dosboot/Makefile index 26c0d0bf04aac..d73363f3eb52a 100644 --- a/sys/i386/boot/dosboot/Makefile +++ b/sys/i386/boot/dosboot/Makefile @@ -1,8 +1,9 @@ -# $Id: Makefile,v 1.4 1997/02/22 09:30:28 peter Exp $ +# $Id$ # MPROG= fbsdboot.exe CLEANFILES+= ${MPROG} +BINDIR= /usr/mdec BINMODE= 444 NOMAN= STRIP= diff --git a/sys/i386/boot/dosboot/disklabe.h b/sys/i386/boot/dosboot/disklabe.h index 81a7c06af6d69..d550d47bcc1f2 100644 --- a/sys/i386/boot/dosboot/disklabe.h +++ b/sys/i386/boot/dosboot/disklabe.h @@ -31,7 +31,7 @@ * SUCH DAMAGE.
*
* @(#)disklabel.h 8.1 (Berkeley) 6/2/93
- * $Id: disklabe.h,v 1.4 1997/02/22 09:30:46 peter Exp $
+ * $Id$
*/
#ifndef _SYS_DISKLABEL_H_
@@ -100,7 +100,7 @@ struct disklabel { * the disklabel is read off the disk or in-core copy.
* d_boot0 and d_boot1 are the (optional) names of the
* primary (block 0) and secondary (block 1-15) bootstraps
- * as found in /boot. These are returned when using
+ * as found in /usr/mdec. These are returned when using
* getdiskbyname(3) to retrieve the values from /etc/disktab.
*/
#if defined(KERNEL) || defined(STANDALONE)
diff --git a/sys/i386/boot/kzipboot/Makefile b/sys/i386/boot/kzipboot/Makefile index c1dc06009dad9..74eb39347480a 100644 --- a/sys/i386/boot/kzipboot/Makefile +++ b/sys/i386/boot/kzipboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.9 1998/05/27 08:06:33 sos Exp $ +# $Id: Makefile,v 1.8 1998/03/07 10:48:10 eivind Exp $ PROG= kztail.o kzhead.o BINMODE = 444 # target is a relocatable object @@ -21,9 +21,9 @@ CFLAGS+= -DKADDR=$(KADDR) -DCSEG=$(CSEG) CFLAGS+= -DKZIP -DCOMCONSOLE=0x3F8 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/i386/boot/kzipboot/malloc.c b/sys/i386/boot/kzipboot/malloc.c index 052e5e357dbbd..cf51be721a517 100644 --- a/sys/i386/boot/kzipboot/malloc.c +++ b/sys/i386/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/i386/boot/netboot/Makefile b/sys/i386/boot/netboot/Makefile index 2d50c65a58e76..ec81713c1d049 100644 --- a/sys/i386/boot/netboot/Makefile +++ b/sys/i386/boot/netboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.21 1998/11/28 08:03:24 joerg Exp $ +# $Id: Makefile,v 1.18 1998/06/30 11:10:24 phk Exp $ # # Makefile for NETBOOT # @@ -30,6 +30,7 @@ PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.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= -O2 -DNFS -DROMSIZE=${ROMSIZE} -DRELOC=${RELOCADDR} # -DASK_BOOT @@ -40,12 +41,10 @@ NS8390= -DINCLUDE_NE #NS8390+= -DINCLUDE_3COM -D_3COM_BASE=0x300 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 MAN8= netboot.8 -SIZE= size -aout STRIP= -STRIPCMD= strip -aout ROMSIZE=16384 RELOCADDR=0x90000 @@ -66,27 +65,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/i386/boot/rawboot/Makefile b/sys/i386/boot/rawboot/Makefile index 061b6959ecf76..5b2729f0a61a8 100644 --- a/sys/i386/boot/rawboot/Makefile +++ b/sys/i386/boot/rawboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.11 1998/03/12 12:26:49 bde Exp $ +# $Id: Makefile,v 1.10 1998/03/07 10:48:15 eivind 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 \ -DRAWBOOT \ @@ -62,8 +63,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/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 76781f47b02a7..1b64ab682db20 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -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: GENERIC,v 1.142 1999/01/09 18:12:07 wpaul Exp $ +# $Id: GENERIC,v 1.124 1998/10/10 08:13:58 jkh Exp $ machine "i386" cpu "I386_CPU" @@ -42,40 +42,36 @@ options VISUAL_USERCONFIG #visual boot -c editor 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 eisa0 controller pci0 -controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 +controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 +# 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 2 options "CMD640" # work around CMD640 chip deficiency -controller wdc0 at isa? port "IO_WD1" bio irq 14 +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 -controller wdc1 at isa? port "IO_WD2" bio irq 15 +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 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 device wfd0 #IDE Floppy (e.g. LS-120) -# A single entry for any of these controllers (ncr, ahb, ahc) is +# A single entry for any of these controllers (ncr, ahb, ahc, amd) is # sufficient for any number of installed devices. controller ncr0 +#controller amd0 controller ahb0 controller ahc0 controller isp0 @@ -89,7 +85,11 @@ controller adv0 at isa? port ? cam irq ? controller adw0 controller bt0 at isa? port ? cam irq ? controller aha0 at isa? port ? cam irq ? -#controller aic0 at isa? port 0x340 bio irq 11 +#controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr +#controller aic0 at isa? port 0x340 bio irq 11 vector aicintr +#controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr +#controller nca1 at isa? port 0x350 bio irq 5 vector ncaintr +#controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr controller scbus0 @@ -101,33 +101,23 @@ device pass0 device cd0 #Only need one of these, the code dynamically grows -device wt0 at isa? port 0x300 bio irq 5 drq 1 -device mcd0 at isa? port 0x300 bio irq 10 +device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr +device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr controller matcd0 at isa? port 0x230 bio device scd0 at isa? port 0x230 bio -# atkbdc0 controlls both the keyboard and the PS/2 mouse -controller atkbdc0 at isa? port IO_KBD tty -device atkbd0 at isa? tty irq 1 -device psm0 at isa? tty irq 12 - -device vga0 at isa? port ? conflicts - -# splash screen/screen saver -pseudo-device splash - # syscons is the default console driver, resembling an SCO console -device sc0 at isa? tty +device sc0 at isa? port "IO_KBD" conflicts tty irq 1 vector scintr # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver -#device vt0 at isa? tty +#device vt0 at isa? port "IO_KBD" conflicts tty irq 1 vector pcrint #options XSERVER # support for X server #options FAT_CURSOR # start with block cursor # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines #options PCVT_SCANSET=2 # IBM keyboards are non-std -device npx0 at isa? port IO_NPX irq 13 +device npx0 at isa? port "IO_NPX" irq 13 vector npxintr # # Laptop support (see LINT for more options) @@ -139,40 +129,36 @@ device apm0 at isa? disable flags 0x31 # Advanced Power Management #device pcic0 at card? #device pcic1 at card? -device sio0 at isa? port "IO_COM1" flags 0x10 tty irq 4 -device sio1 at isa? port "IO_COM2" tty irq 3 -device sio2 at isa? disable port "IO_COM3" tty irq 5 -device sio3 at isa? disable port "IO_COM4" tty irq 9 +device sio0 at isa? port "IO_COM1" flags 0x10 tty irq 4 vector siointr +device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr +device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr +device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + +device lpt0 at isa? port? tty irq 7 vector lptintr -device lpt0 at isa? port? tty irq 7 +device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # 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 ax0 device de0 device fxp0 -device mx0 -device pn0 -device rl0 device tl0 device tx0 -device vr0 device vx0 -device wb0 device xl0 -device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 -device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 -device ep0 at isa? port 0x300 net irq 10 -device ex0 at isa? port? net irq? -device fe0 at isa? port 0x300 net irq ? -device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 -device lnc0 at isa? port 0x280 net irq 10 drq 0 -device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 -device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 -device cs0 at isa? port 0x300 net irq ? +device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr +device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr +device ep0 at isa? port 0x300 net irq 10 vector epintr +device ex0 at isa? port? net irq? vector exintr +device fe0 at isa? port 0x300 net irq ? vector feintr +device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr +device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr +device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zeintr +device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr +device cs0 at isa? port 0x300 net irq ? vector csintr pseudo-device loop pseudo-device ether @@ -195,27 +181,4 @@ options SYSVSHM # 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 - - -# USB support -#controller uhci0 -#controller ohci0 -#controller usb0 -# -# for the moment we have to specify the priorities of the device -# drivers explicitly by the ordering in the list below. This will -# be changed in the future. -# -#device ums0 -#device ukbd0 -#device ulpt0 -#device uhub0 -#device ucom0 -#device umodem0 -#device hid0 -#device ugen0 - -# -#options USB_DEBUG -#options USBVERBOSE +#pseudo-device bpfilter 4 #Berkeley packet filter diff --git a/sys/i386/conf/GENERICupgrade b/sys/i386/conf/GENERICupgrade new file mode 100644 index 0000000000000..83e9619456c82 --- /dev/null +++ b/sys/i386/conf/GENERICupgrade @@ -0,0 +1,176 @@ +# +# GENERICupgrade (a copy of GENERIC) +# +# 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.2 1998/09/16 17:44:37 phk Exp $ + +machine "i386" +cpu "I386_CPU" +cpu "I486_CPU" +cpu "I586_CPU" +cpu "I686_CPU" +ident GENERIC +maxusers 32 + +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 FAILSAFE #Be conservative +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor + +config kernel root on wd0 + +controller isa0 +controller eisa0 +controller pci0 + +controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr +disk fd0 at fdc0 drive 0 +disk fd1 at fdc0 drive 1 +# 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 2 + +options "CMD640" # work around CMD640 chip deficiency +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr +disk wd0 at wdc0 drive 0 +disk wd1 at wdc0 drive 1 + +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr +disk wd2 at wdc1 drive 0 +disk wd3 at wdc1 drive 1 + +options ATAPI #Enable ATAPI support for IDE bus +options ATAPI_STATIC #Don't do it as an LKM +device wcd0 #IDE CD-ROM +device wfd0 #IDE Floppy (e.g. LS-120) + +# A single entry for any of these controllers (ncr, ahb, ahc, amd) is +# sufficient for any number of installed devices. +controller ncr0 +#controller amd0 +controller ahb0 +controller ahc0 +controller isp0 + +# This controller offers a number of configuration options, too many to +# document here - see the LINT file in this directory and look up the +# dpt0 entry there for much fuller documentation on this. The options +# line following dpt0 here is also currently a *required* option for it. +# controller dpt0 +# options DPT_MEASURE_PERFORMANCE + +controller adv0 at isa? port ? cam irq ? +controller bt0 at isa? port ? cam irq ? +controller aha0 at isa? port ? cam irq ? +#controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr +#controller aic0 at isa? port 0x340 bio irq 11 vector aicintr +#controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr +#controller nca1 at isa? port 0x350 bio irq 5 vector ncaintr +#controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr + +controller scbus0 + +device da0 + +device sa0 + +device pass0 + +device cd0 #Only need one of these, the code dynamically grows + +device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr +device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr + +controller matcd0 at isa? port 0x230 bio + +device scd0 at isa? port 0x230 bio + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" conflicts tty irq 1 vector scintr +# Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver +#device vt0 at isa? port "IO_KBD" conflicts tty irq 1 vector pcrint +#options XSERVER # support for X server +#options FAT_CURSOR # start with block cursor +# If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines +#options PCVT_SCANSET=2 # IBM keyboards are non-std + +device npx0 at isa? port "IO_NPX" irq 13 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" flags 0x10 tty irq 4 vector siointr +device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr +device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr +device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + +device lpt0 at isa? port? tty irq 7 vector lptintr +device lpt1 at isa? port? tty +device mse0 at isa? port 0x23c tty irq 5 vector mseintr + +device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr + +# 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 + +device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr +device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr +device ep0 at isa? port 0x300 net irq 10 vector epintr +device ex0 at isa? port? net irq? vector exintr +device fe0 at isa? port 0x300 net irq ? vector feintr +device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr +device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr +device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zeintr +device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr +device cs0 at isa? port 0x300 net irq ? vector csintr + +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/i386/conf/LINT b/sys/i386/conf/LINT index 762e124d525a5..db48f5f82bdd3 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.538 1999/01/20 03:29:51 msmith Exp $ +# $Id: LINT,v 1.486 1998/10/10 09:25:12 obrien Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -178,10 +178,6 @@ cpu "I686_CPU" # aka Pentium Pro(tm) # executed. This should be included for ALL kernels that won't run # on a Pentium. # -# NO_MEMORY_HOLE is an optimisation for systems with AMD K6 processors -# which indicates that the 15-16MB range is *definitely* not being -# occupied by an ISA memory hole. -# # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should not be used becasue of CPU bugs. # These options may crash your system. @@ -232,12 +228,6 @@ options GPL_MATH_EMULATE #Support for x87 emulation via options "COMPAT_43" # -# Statically compile in the i386 a.out LKM compatability support. -# Also available as an KLD module. -# -options LKM - -# # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). @@ -297,29 +287,12 @@ options GDB_REMOTE_CHAT options KTRACE #kernel tracing # -# The INVARIANTS option is used in a number of source files to enable +# The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # -options INVARIANTS - -# -# The INVARIANT_SUPPORT option makes us compile in support for -# verifying some of the internal structures. It is a prerequisite for -# 'INVARIANTS', as enabling 'INVARIANTS' will make these functions be -# called. The intent is that you can set 'INVARIANTS' for single -# source files (by changing the source file or specifying it on the -# command line) if you have 'INVARIANT_SUPPORT' enabled. -# -options INVARIANT_SUPPORT - -# -# The DIAGNOSTIC option is used to enable extra debugging information -# from some parts of the kernel. As this makes everything more noisy, -# it is disabled by default. -# options DIAGNOSTIC # @@ -344,7 +317,7 @@ options UCONSOLE # XXX - this doesn't belong here either options USERCONFIG #boot -c editor -options INTRO_USERCONFIG #imply -c and show intro screen +options USERCONFIG_BOOT #imply -c and parse info area options VISUAL_USERCONFIG #visual boot -c editor ##################################################################### @@ -408,7 +381,7 @@ pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device -pseudo-device bpfilter 4 #Berkeley packet filter +pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver (user process ppp(8)) pseudo-device sl 2 #Serial Line IP @@ -460,7 +433,7 @@ options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets -options IPFIREWALL_FORWARD #enable transparent proxy support +options IPFIREWALL_FORWARD #enable xparent proxy support options "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default options IPDIVERT #divert sockets @@ -469,19 +442,6 @@ options IPFILTER_LOG #ipfilter logging #options IPFILTER_LKM #kernel support for ip_fil.o LKM options TCPDEBUG -# ICMP_BANDLIM enables icmp error response bandwidth limiting. You -# typically want this option as it will help protect the machine from -# D.O.S. packet attacks. -# -options "ICMP_BANDLIM" - -# DUMMYNET enables the "dummynet" bandwidth limiter. You need -# IPFIREWALL as well. See the dummynet(4) manpage for more info. -# BRIDGE enables bridging between ethernet cards -- see bridge(4). -# You can use IPFIREWALL and dummynet together with bridging. -options DUMMYNET -options BRIDGE - # # ATM (HARP version) options # @@ -554,15 +514,14 @@ options NFS_ROOT #NFS usable as root device # Also, 'options MFS' is currently incompatible with DEVFS. options DEVFS #devices filesystem -# Soft updates is technique for improving file system speed and -# making abrupt shutdown less risky. It is not enabled by default due -# to copyright restraints on the code that implement it. -# -# Read .../../ufs/ffs/README.softupdates to learn what you need to -# do to enable this. ../../../contrib/sys/softupdates/README gives -# more details on how they actually work. -# +# Allow the FFS to use Softupdates technology. +# To do this you need to copy the two files +# /sys/ufs/ffs/softdep.h and /sys/ufs/ffs/ffs_softdep.c +# from /usr/src/contrib/sys/softupdates +# and understand the licensing restrictions. +# You should also check on the FreeBSD website for newer versions. #options SOFTUPDATES +# (we can't actually enable it because the files may not be present) # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. @@ -768,8 +727,6 @@ pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 #Concatenated disk driver -pseudo-device vinum #Vinum concat/mirror/raid driver -options VINUMDEBUG #enable Vinum debugging hooks # These are only for watching for bitrot in old tty code. # broken @@ -835,55 +792,22 @@ options "TUNE_1542" options PPS_SYNC -# If you see the "calcru: negative time of %ld usec for pid %d (%s)\n" -# message you probably have some broken sw/hw which disables interrupts -# for too long. You can make the system more resistant to this by -# choosing a high value for NTIMECOUNTER. The default is 5, there -# is no upper limit but more than a couple of hundred are not productive. - -options "NTIMECOUNTER=20" - # Enable PnP support in the kernel. This allows you to automaticly # attach to PnP cards for drivers that support it and allows you to # configure cards from USERCONFIG. See pnp(4) for more info. controller pnp0 -# The keyboard controller; it controlls the keyboard and the PS/2 mouse. -controller atkbdc0 at isa? port IO_KBD tty - -# The AT keyboard -device atkbd0 at isa? tty irq 1 - -# `flags' for atkbd: -# 0x01 Force detection of keyboard, else we always assume a keyboard -# 0x02 Don't reset keyboard, useful for some newer ThinkPads -# 0x04 Old-style (XT) keyboard support, useful for older ThinkPads - -# PS/2 mouse -device psm0 at isa? tty irq 12 - -# Options for psm: -options PSM_HOOKAPM #hook the APM resume event, useful - #for some laptops -options PSM_RESETAFTERSUSPEND #reset the device at the resume event - -# The video card driver. -device vga0 at isa? port ? conflicts - -# Splash screen at start up! Screen savers require this too. -pseudo-device splash - # The pcvt console driver (vt220 compatible). -device vt0 at isa? tty +device vt0 at isa? port "IO_KBD" conflicts tty irq 1 vector pcrint options XSERVER # support for running an X server. options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible). -device sc0 at isa? tty +device sc0 at isa? port "IO_KBD" conflicts tty irq 1 vector scintr options MAXCONS=16 # number of virtual consoles -options VGA_SLOW_IOACCESS # do byte-wide i/o's to TS and GDC regs +options SLOW_VGA # do byte-wide i/o's to TS and GDC regs options "STD8X16FONT" # Compile font in makeoptions "STD8X16FONT"="cp850" options SC_HISTORY_SIZE=200 # number of history buffer lines @@ -903,6 +827,9 @@ options VESA # needs VM86 defined too!! # 0x02 Use a 'blink' cursor # 0x04 Use a 'underline' cursor # 0x06 Use a 'blinking underline' (destructive) cursor +# 0x08 Force detection of keyboard, else we always assume a keyboard +# 0x10 Old-style (XT) keyboard support, useful for older ThinkPads +# 0x20 Don't reset keyboard, useful for some newer ThinkPads # 0x40 Make the bell quiet if it is rung in the backgroud vty. # @@ -911,7 +838,7 @@ options VESA # needs VM86 defined too!! # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). -device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 +device npx0 at isa? port "IO_NPX" iosiz 0x0 flags 0x0 irq 13 vector npxintr # # `flags' for npx0: @@ -945,7 +872,7 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 # # -# SCSI host adapters: `aha', `aic', `bt' +# SCSI host adapters: `aha', `aic', `bt', `nca' # # adv: All Narrow SCSI bus AdvanSys controllers. # adw: Second Generation AdvanSys controllers including the ADV940UW. @@ -953,6 +880,10 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers +# nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 +# uha: UltraStor ULTRA 14F/24F/34F +# sea: Seagate ST01/02 8 bit controller (slow!) +# wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. @@ -962,9 +893,17 @@ controller bt0 at isa? port "IO_BT0" cam irq ? controller adv0 at isa? port ? cam irq ? controller adw0 controller aha0 at isa? port ? cam irq ? +#!CAM# controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr -#!CAM# controller aic0 at isa? port 0x340 bio irq 11 +#!CAM# controller aic0 at isa? port 0x340 bio irq 11 vector aicintr +#!CAM# controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr +#!CAM# controller nca1 at isa? port 0x1f84 +#!CAM# controller nca2 at isa? port 0x1f8c +#!CAM# controller nca3 at isa? port 0x1e88 +#!CAM# controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr +#!CAM# controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr +#!CAM# controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' @@ -988,7 +927,7 @@ controller aha0 at isa? port ? cam irq ? # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: -#controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 +#controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be @@ -999,11 +938,11 @@ controller aha0 at isa? port ? cam irq ? # mode (for example, it is a 2nd IDE PCI interface), then use config line(s) # such as: # -#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff +#controller wdc2 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr #disk wd4 at wdc2 drive 0 #disk wd5 at wdc2 drive 1 # -#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff +#controller wdc3 at isa? port "0" bio irq ? flags 0xa0ffa0ff vector wdintr #disk wd6 at wdc3 drive 0 #disk wd7 at wdc3 drive 1 # @@ -1012,10 +951,10 @@ controller aha0 at isa? port ? cam irq ? # entries. These are automatically filled in by the IDE/PCI support. # -controller wdc0 at isa? port "IO_WD1" bio irq 14 +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 -controller wdc1 at isa? port "IO_WD2" bio irq 15 +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 @@ -1033,17 +972,13 @@ options "CMD640" #Enable work around for CMD640 h/w bug options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM -# -# This option allow you to override the default probe time for IDE -# devices, to get a faster probe. Setting this below 10000 violate -# the IDE specs, but may still work for you (it will work for most -# people). -# -options IDE_DELAY=8000 # Be optimistic about Joe IDE device - +# Use either the acd or the wcd device, not both! # IDE CD-ROM & CD-R/RW driver - requires wdc controller and ATAPI option device acd0 +# IDE CD-ROM driver - requires wdc controller and ATAPI option +device wcd0 + # IDE floppy driver - requires wdc controller and ATAPI option device wfd0 @@ -1054,46 +989,49 @@ device wst0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # -controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 +controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # FDC_DEBUG enables floppy debugging. Since the debug output is huge, you # gotta turn it actually on by setting the variable fd_debug with DDB, # however. options FDC_DEBUG -# FDC_YE enables support for the floppies used on the Libretto. This is a -# pcmcia floppy. You will also need to add -#card "Y-E DATA" "External FDD" -# config 0x4 "fdc0" 10 -# to your pccard.conf file. -options FDC_YE # This option is undocumented on purpose. options FDC_PRINT_BOGUS_CHIPTYPE # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: -#controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 +#controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 +tape ft0 at fdc0 drive 2 + # -# Other standard PC hardware: `lpt', `mse', `sio', etc. +# Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: -# The port may be specified as ?. This will cause the -# driver to scan the BIOS port list. -# The irq clause may be omitted. This will force the port -# into polling mode. +# port can be specified as ?, this will cause the driver to scan +# the BIOS port list; +# the irq and vector clauses may be omitted, this +# will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports +# psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) -device lpt0 at isa? port? tty irq 7 -device lpt1 at isa? port "IO_LPT3" tty irq 5 -device mse0 at isa? port 0x23c tty irq 5 +device lpt0 at isa? port? tty irq 7 vector lptintr +device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr +device mse0 at isa? port 0x23c tty irq 5 vector mseintr +device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr -device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 +# Options for psm: +options PSM_HOOKAPM #hook the APM resume event, useful + #for some laptops +options PSM_RESETAFTERSUSPEND #reset the device at the resume event + +device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr # # `flags' for serial drivers that support consoles (only for sio now): @@ -1107,7 +1045,6 @@ device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 # 0x20 force this unit to be the console (unless there is another # higher priority console). This replaces the COMCONSOLE option. # 0x40 reserve this unit for low level console operations. Do not -# access the device in any normal way. # # PnP `flags' (set via userconfig using pnp x flags y) # 0x1 disable probing of this device. Used to prevent your modem @@ -1122,6 +1059,7 @@ options CONSPEED=9600 #default speed for serial console (default 9600) # Options for sio: options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs +options DSI_SOFT_MODEM #code for DSI Softmodems options "EXTRA_SIO=2" #number of extra sio ports to allocate # Other flags for sio that aren't documented in the man page. @@ -1137,13 +1075,11 @@ options "EXTRA_SIO=2" #number of extra sio ports to allocate # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) -# ex: Intel EtherExpress Pro/10 and other i82595-based adapters # fe: Fujitsu MB86960A/MB86965A Ethernet # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210; Intel EtherExpress # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) -# lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL, AMD Am7990 & Am79C960) -# rdp: RealTek RTL 8002-based pocket ethernet adapters +# lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp) # wl: Lucent Wavelan (ISA card only). # ze: IBM/National Semiconductor PCMCIA ethernet controller. @@ -1152,27 +1088,27 @@ options "EXTRA_SIO=2" #number of extra sio ports to allocate # attribute memory) # -device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 -device cs0 at isa? port 0x300 net irq ? -device cx0 at isa? port 0x240 net irq 15 drq 7 -device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 -device el0 at isa? port 0x300 net irq 9 -device ep0 at isa? port 0x300 net irq 10 -device ex0 at isa? port? net irq? -device fe0 at isa? port 0x300 net irq ? -device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 -device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 -device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 -device lnc0 at isa? port 0x280 net irq 10 drq 0 -device rdp0 at isa? port 0x378 net irq 7 flags 2 -device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 +device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr +device cs0 at isa? port 0x300 net irq ? vector csintr +device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr +device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr +device eg0 at isa? port 0x310 net irq 5 vector egintr +device el0 at isa? port 0x300 net irq 9 vector elintr +device ep0 at isa? port 0x300 net irq 10 vector epintr +device ex0 at isa? port? net irq? vector exintr +device fe0 at isa? port 0x300 net irq ? vector feintr +device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector ieintr +device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr +device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr +device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr +device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector srintr options WLCACHE # enables the signal-strength cache options WLDEBUG # enables verbose debugging output -device wl0 at isa? port 0x300 net irq ? +device wl0 at isa? port 0x300 net irq ? vector wlintr # We can (bogusly) include both the dedicated PCCARD drivers and the generic # support when COMPILING_LINT. -device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 -device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 +device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr +device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ATM related options @@ -1218,10 +1154,9 @@ options NATM #native ATM # # pcm: PCM audio through various sound cards. # -# This has support for a large number of new audio cards, based on -# CS423x, OPTi931, Yamaha OPL-SAx, and also for SB16, GusPnP. -# For more information about this driver and supported cards, -# see the pcm.4 man page and /sys/i386/isa/snd/CARDS. +# This is the work in progress from Luigi Rizzo. This has support for +# CS423x based cards, OPTi931, SB16 PnP, GusPnP. For more information +# about this driver, take a look at sys/i386/isa/snd/README. # # The flags of the device tells the device a bit more info about the # device that normally is obtained through the PnP interface. @@ -1259,30 +1194,30 @@ options NATM #native ATM # below for an alternate which may work better for some cards. # controller snd0 -device pas0 at isa? port 0x388 irq 10 drq 6 -device sb0 at isa? port 0x220 irq 5 drq 1 +device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr +device sb0 at isa? port 0x220 irq 5 drq 1 vector sbintr device sbxvi0 at isa? drq 5 device sbmidi0 at isa? port 0x330 device awe0 at isa? port 0x620 -device gus0 at isa? port 0x220 irq 12 drq 1 -#device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 -device mss0 at isa? port 0x530 irq 10 drq 1 -device css0 at isa? port 0x534 irq 5 drq 1 flags 0x08 -device sscape0 at isa? port 0x330 irq 9 drq 0 -device trix0 at isa? port 0x330 irq 6 drq 0 -device sscape_mss0 at isa? port 0x534 irq 5 drq 1 +device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr +#device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr +device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr +device css0 at isa? port 0x534 irq 5 drq 1 flags 0x08 vector adintr +device sscape0 at isa? port 0x330 irq 9 drq 0 vector sscapeintr +device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr +device sscape_mss0 at isa? port 0x534 irq 5 drq 1 vector sndintr device opl0 at isa? port 0x388 device mpu0 at isa? port 0x330 irq 6 drq 0 -device uart0 at isa? port 0x330 irq 5 +device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # Luigi's snd code (use INSTEAD of snd0 and all VOXWARE drivers!). # You may also wish to enable the pnp controller with this, for pnp # sound cards. # -#device pcm0 at isa? port ? tty irq 10 drq 1 flags 0x0 +#device pcm0 at isa? port ? tty irq 10 drq 1 flags 0x0 vector pcmintr # Not controlled by `snd' -device pca0 at isa? port "IO_TIMER1" tty +device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: @@ -1296,6 +1231,7 @@ device pca0 at isa? port "IO_TIMER1" tty # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # bktr: Brooktree bt848/848a/849/878/879 family video capture and TV Tuner board +# alog: Industrial Computer Source AIO8-P driver # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # dgm: Digiboard PC/Xem driver @@ -1389,33 +1325,34 @@ device pca0 at isa? port "IO_TIMER1" tty # Brumby: flags 2 iosiz 0x4000 # Stallion: flags 1 iosiz 0x10000 -device mcd0 at isa? port 0x300 bio irq 10 +device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio -device wt0 at isa? port 0x300 bio irq 5 drq 1 +device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 -device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 +device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 -device joy0 at isa? port IO_GAME -device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 -options CY_PCI_FASTINTR # Use with cy_pci unless irq is shared +device joy0 at isa? port "IO_GAME" +device alog0 at isa? port 0x260 tty irq 5 vector alogintr +device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device dgm0 at isa? port 0x104 iomem 0xd00000 iosiz ? tty -device labpc0 at isa? port 0x260 tty irq 5 -device rc0 at isa? port 0x220 tty irq 12 +device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr +device rc0 at isa? port 0x220 tty irq 12 vector rcintr device rp0 at isa? port 0x280 tty # the port and irq for tw0 are fictitious -device tw0 at isa? port 0x380 tty irq 11 +device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 -device asc0 at isa? port "IO_ASC1" tty drq 3 irq 10 -device stl0 at isa? port 0x2a0 tty irq 10 +device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr +device bqu0 at isa? port 0x150 +device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr device stli0 at isa? port 0x2a0 tty iomem 0xcc000 flags 23 iosiz 0x1000 # You are unlikely to have the hardware for loran0 <phk@FreeBSD.org> -device loran0 at isa? port ? tty irq 5 +device loran0 at isa? port ? tty irq 5 vector loranintr # HOT1 Xilinx 6200 card (www.vcc.com) device xrpu0 @@ -1468,9 +1405,11 @@ options "EISA_SLOTS=12" # nd 1040B PCI SCSI host adapters, as well as the Qlogic ISP 2100 # FC/AL Host Adapter. # -# The `ax' device provides support for PCI fast ethernet adapters -# based on the ASIX Electronics AX88140A chip, including the Alfa -# Inc. GFC2204. +# The `amd' device provides support for the Tekram DC-390 and 390T +# SCSI host adapters, but is expected to work with any AMD 53c974 +# PCI SCSI chip and the AMD Ethernet+SCSI Combo chip, after some +# local patches were applied to the sources (that had originally +# been written by Tekram and limited to work with their SCSI cards). # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. @@ -1478,22 +1417,6 @@ options "EISA_SLOTS=12" # The `fxp' device provides support for the Intel EtherExpress Pro/100B # PCI Fast Ethernet adapters. # -# The `mx' device provides support for various fast ethernet adapters -# based on the Macronix 98713, 987615 ans 98725 series chips. -# -# The `pn' device provides support for various fast ethernet adapters -# based on the Lite-On 82c168 and 82c169 PNIC chips, including the -# LinkSys LNE100TX, the NetGear FA310TX rev. D1 and the Matrox -# FastNIC 10/100. -# -# The 'rl' device provides support for PCI fast ethernet adapters based -# on the RealTek 8129/8139 chipset. Note that the RealTek driver defaults -# to useing programmed I/O to do register accesses because memory mapped -# mode seems to cause severe lockups on SMP hardware. This driver also -# supports the Accton EN1207D `Cheetah' adapter, which uses a chip called -# the MPX 5030/5038, which is either a RealTek in disguise or a RealTek -# workalike. -# # The 'tl' device provides support for the Texas Instruments TNETE100 # series 'ThunderLAN' cards and integrated ethernet controllers. This # includes several Compaq Netelligent 10/100 cards and the built-in @@ -1503,18 +1426,10 @@ options "EISA_SLOTS=12" # # The `tx' device provides support for the SMC 9432TX cards. # -# The `vr' device provides support for various fast ethernet adapters -# based on the VIA Technologies VT3043 `Rhine I' and VT86C100A `Rhine II' -# chips, including the D-Link DFE530TX. -# # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # -# The `wb' device provides support for various fast ethernet adapters -# based on the Winbond W89C840F chip. Note: this is not the same as -# the Winbond W89C940F, which is an NE2000 clone. -# -# The `xl' device provides support for the 3Com 3c900, 3c905 and +# The `xl' driver provides support for the 3Com 3c900, 3c905 and # 3c905B (Fast) Etherlink XL cards and integrated controllers. This # includes the integrated 3c905B-TX chips in certain Dell Optiplex and # Dell Precision desktop machines and the integrated 3c905-TX chips @@ -1559,26 +1474,15 @@ controller pci0 controller ahc1 controller ncr0 controller isp0 -device ax0 +#!CAM# controller amd0 device de0 device fxp0 -device mx0 -device pn0 -device rl0 device tl0 device tx0 -device vr0 device vx0 -device wb0 device xl0 device fpa0 device meteor0 - -# Brooktree driver has been ported to the new I2C framework. Thus, -# you'll need at least iicbus, iicbb and smbus. iic/smb are only needed if you -# want to control other I2C slaves connected to the external connector of -# some cards. -# device bktr0 # @@ -1619,8 +1523,7 @@ options POWERFAIL_NMI # make it beep instead of panicing # smb standard io # # Supported interfaces: -# iicsmb I2C to SMB bridge with any iicbus interface -# bktr brooktree848 I2C hardware interface +# iicsmb I2C to SMB bridge # controller smbus0 @@ -1638,135 +1541,16 @@ device smb0 at smbus? # # Supported interfaces: # pcf Philips PCF8584 ISA-bus controller -# bktr brooktree848 I2C software interface -# -# Other: -# iicbb generic I2C bit-banging code (needed by lpbb, bktr) # controller iicbus0 -controller iicbb0 device ic0 at iicbus? device iic0 at iicbus? device iicsmb0 at iicbus? -controller pcf0 at isa? port 0x320 net irq 5 +controller pcf0 at isa? port 0x320 net irq 5 vector pcfintr -# ISDN4BSD section - -# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver) -# note that the ``options'' and ``device'' lines must BOTH be defined ! -# -# Non-PnP Cards: -# -------------- -# -# Teles S0/8 or Niccy 1008 -options "TEL_S0_8" -#device isic0 at isa? iomem 0xd0000 net irq 5 flags 1 -# -# Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 -options "TEL_S0_16" -#device isic0 at isa? port 0xd80 iomem 0xd0000 net irq 5 flags 2 -# -# Teles S0/16.3 -options "TEL_S0_16_3" -#device isic0 at isa? port 0xd80 net irq 5 flags 3 -# -# AVM A1 or AVM Fritz!Card -options "AVM_A1" -#device isic0 at isa? port 0x340 net irq 5 flags 4 -# -# USRobotics Sportster ISDN TA intern -options "USR_STI" -#device isic0 at isa? port 0x268 net irq 5 flags 7 -# -# ITK ix1 Micro -options "ITKIX1" -#device isic0 at isa? port 0x398 net irq 10 flags 18 -# -# PnP-Cards: -# ---------- -# -# Teles S0/16.3 PnP -options "TEL_S0_16_3_P" -#device isic0 at isa? port ? net irq ? -# -# Creatix ISDN-S0 P&P -options "CRTX_S0_P" -#device isic0 at isa? port ? net irq ? -# -# Dr. Neuhaus Niccy Go@ -options "DRN_NGO" -#device isic0 at isa? port ? net irq ? -# -# Sedlbauer Win Speed -options "SEDLBAUER" -#device isic0 at isa? port ? net irq ? -# -# Dynalink IS64PH -options "DYNALINK" -#device isic0 at isa? port ? net irq ? -# -# ELSA QuickStep 1000pro ISA -options "ELSA_QS1ISA" -#device isic0 at isa? port ? net irq ? -# -# PCI-Cards: -# ---------- -# -# ELSA QuickStep 1000pro PCI -options "ELSA_QS1PCI" -#device isic0 -# -# PCMCIA-Cards: -# ------------- # -# AVM PCMCIA Fritz!Card -options "AVM_A1_PCMCIA" -device isic0 at isa? port 0x340 net irq 5 flags 10 -# -# Active Cards: -# ------------- -# -# Stollmann Tina-dd control device -device tina0 at isa? port 0x260 net irq 10 -# -# ISDN Protocol Stack -# ------------------- -# -# Q.921 / layer 2 - i4b passive cards D channel handling -pseudo-device "i4bq921" -# -# Q.931 / layer 3 - i4b passive cards D channel handling -pseudo-device "i4bq931" -# -# layer 4 - i4b common passive and active card handling -pseudo-device "i4b" -# -# ISDN devices -# ------------ -# -# userland driver to do ISDN tracing (for passive cards only) -pseudo-device "i4btrc" 4 -# -# userland driver to control the whole thing -pseudo-device "i4bctl" -# -# userland driver for access to raw B channel -pseudo-device "i4brbch" 4 -# -# userland driver for telephony -pseudo-device "i4btel" 2 -# -# network driver for IP over raw HDLC ISDN -pseudo-device "i4bipr" 4 -# enable VJ header compression detection for ipr i/f -options IPR_VJ -# -# network driver for sync PPP over ISDN -pseudo-device "i4bisppp" 4 - - # Parallel-Port Bus # # Parallel port bus support is provided by the `ppbus' device. @@ -1781,7 +1565,6 @@ pseudo-device "i4bisppp" 4 # plip Parallel network interface # ppi General-purpose I/O ("Geek Port") # pps Pulse per second Timing Interface -# lpbb Philips official parallel port I2C bit-banging interface # # Supported interfaces: # ppc ISA-bus parallel port interfaces. @@ -1792,9 +1575,8 @@ device nlpt0 at ppbus? device plip0 at ppbus? device ppi0 at ppbus? device pps0 at ppbus? -device lpbb0 at ppbus? -controller ppc0 at isa? disable port ? tty irq 7 +controller ppc0 at isa? disable port ? tty irq 7 vector ppcintr # Kernel BOOTP support @@ -1837,21 +1619,6 @@ options "PMAP_SHPGPERPROC=201" # #options NO_SWAPPING -# Set the number of sf_bufs to allocate. sf_bufs are virtual buffers -# for sendfile(2) that are used to map file VM pages, and normally -# default to a quantity that is roughly 16*MAXUSERS+512. You would -# typically want about 4 of these for each simultaneous file send. -# -options "NSFBUFS=1024" - -# -# Enable extra debugging code for locks. This include storing the -# filename and line of whatever aquired the lock in the lock itself, -# and changing a number of function calls to pass around the relevant -# data. This is not at all useful unless you are debugging lock code. -# -options DEBUG_LOCKS - # More undocumented options for linting. options CLK_CALIBRATION_LOOP @@ -1861,7 +1628,6 @@ options CLUSTERDEBUG options COMPAT_LINUX options CPU_UPGRADE_HW_CACHE options DEBUG -options DEBUG_VFS_LOCKS options "DEBUG_1284" #options DISABLE_PSE options "EXT2FS" @@ -1918,7 +1684,6 @@ options SHMSEG=9 options SI_DEBUG options SIMPLELOCK_DEBUG options SPX_HACK -options VFS_BIO_DEBUG # The 'dpt' driver provides support for DPT controllers (http://www.dpt.com/). # These have hardware RAID-{0,1,5} support, and do multi-initiator I/O. @@ -1977,35 +1742,3 @@ options DPT_RESET_HBA # Don't EVER set this without having talked to Simon Shapiro on the phone # first. options DPT_SHUTDOWN_SLEEP=500 - -# USB support -# UHCI controller -controller uhci0 -# OHCI controller -controller ohci0 -# General USB code (mandatory for USB) -controller usb0 -# -# for the moment we have to specify the priorities of the device -# drivers explicitly by the ordering in the list below. This will -# be changed in the future. -# -# USB mouse -device ums0 -# USB keyboard -device ukbd0 -# USB printer -device ulpt0 -# USB hub (kind of mandatory, no other driver is available for the root hub) -device uhub0 -# USB communications driver -device ucom0 -# USB modem driver -device umodem0 -# Human Interface Device (anything with buttons and dials) -device hid0 -# Generic USB device driver -device ugen0 -# -options USB_DEBUG -options USBVERBOSE diff --git a/sys/i386/conf/LKM b/sys/i386/conf/LKM index d29ac86e78843..4e123a617455b 100644 --- a/sys/i386/conf/LKM +++ b/sys/i386/conf/LKM @@ -2,7 +2,7 @@ # LKM - verification kernel for LKMs. This is not intended to be run # on any real hardware, only to make it possible to test-link LKMs. # -# $Id: LKM,v 1.2 1998/10/22 12:23:04 bde Exp $ +# $Id$ # ## @@ -23,7 +23,7 @@ options FFS # missing NPX... controller isa0 # npx is mandated by config(8) -device npx0 at isa? port IO_NPX irq 13 +device npx0 at isa? port "IO_NPX" irq 13 vector npxintr ## # Requirements for various LKMs @@ -32,7 +32,7 @@ device npx0 at isa? port IO_NPX irq 13 # # Options required for the ATAPI LKM # -controller wdc0 at isa? port "IO_WD1" bio irq 14 +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr options ATAPI @@ -59,13 +59,13 @@ controller card0 # Cascading requirement from card0 - any device that have a DATA_SET of # pccarddrv_set -device sio0 at isa? port "IO_COM1" tty irq 4 +device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr # # For the screensavers # -device sc0 at isa? port IO_KBD tty irq 1 +device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr # diff --git a/sys/i386/conf/Makefile.i386 b/sys/i386/conf/Makefile.i386 index 226f7475e625a..449064d45cf21 100644 --- a/sys/i386/conf/Makefile.i386 +++ b/sys/i386/conf/Makefile.i386 @@ -1,7 +1,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.135 1999/01/17 21:17:27 peter Exp $ +# $Id: Makefile.i386,v 1.125 1998/09/30 12:14:39 peter Exp $ # # Makefile for FreeBSD # @@ -17,9 +17,9 @@ # # Which version of config(8) is required. -%VERSREQ= 300009 +%VERSREQ= 300007 -KERNFORMAT?= elf +KERNFORMAT?= aout STD8X16FONT?= iso @@ -74,8 +74,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. @@ -86,7 +86,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; \ @@ -94,8 +101,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 @@ -117,14 +125,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 @@ -148,21 +151,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 @@ -176,7 +184,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} @@ -207,16 +215,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/i386/conf/PCCARD b/sys/i386/conf/PCCARD new file mode 100644 index 0000000000000..ef0b6e7ae7fe8 --- /dev/null +++ b/sys/i386/conf/PCCARD @@ -0,0 +1,114 @@ +# +# PCCARD -- GENERIC laptop support +# +# 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: PCCARD,v 1.6 1998/09/25 17:34:48 peter Exp $ + +machine "i386" +cpu "I386_CPU" +cpu "I486_CPU" +cpu "I586_CPU" +cpu "I686_CPU" +ident PCCARD +maxusers 10 + +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 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 FAILSAFE #Be conservative +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor + +config kernel root on wd0 + +controller isa0 +controller pci0 + +controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr +disk fd0 at fdc0 drive 0 + +options "CMD640" # work around CMD640 chip deficiency +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr +disk wd0 at wdc0 drive 0 + +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr + +options ATAPI #Enable ATAPI support for IDE bus +options ATAPI_STATIC #Don't do it as an LKM +device wcd0 #IDE CD-ROM + +#controller aic0 at isa? port 0x340 cam irq 11 vector aicintr + +#controller scbus0 + +#device da0 + +#device sa0 + +#device cd0 #Only need one of these, the code dynamically grows + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr + +device npx0 at isa? port "IO_NPX" irq 13 vector npxintr + +# +# Laptop support (see LINT for more options) +# +device apm0 at isa? flags 0x31 # Advanced Power Management + +# PCCARD (PCMCIA) support +controller card0 +device pcic0 at card? +device pcic1 at card? + +options PCIC_RESUME_RESET # reset after resume + +device sio0 at isa? port "IO_COM1" flags 0x10 tty irq 4 vector siointr +device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr +device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr +device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + +device lpt0 at isa? port? tty irq 7 vector lptintr + +device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr +options PSM_HOOKAPM #hook the APM resume event +options PSM_RESETAFTERSUSPEND #reset the device at the resume event + +device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr +device ep0 at isa? port 0x300 net irq 10 vector epintr +device fe0 at isa? port 0x300 net irq ? vector feintr + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +# iijppp uses tun instead of ppp device +#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/i386/conf/SMP-GENERIC b/sys/i386/conf/SMP-GENERIC new file mode 100644 index 0000000000000..c31ed1cccb392 --- /dev/null +++ b/sys/i386/conf/SMP-GENERIC @@ -0,0 +1,201 @@ +# +# SMP-GENERIC -- Smp 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-GENERIC,v 1.16 1998/09/25 17:34:48 peter Exp $ + +machine "i386" +# SMP does NOT support 386/486 CPUs. +#cpu "I386_CPU" +#cpu "I486_CPU" + +cpu "I586_CPU" +cpu "I686_CPU" +ident SMP-GENERIC +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 + +# Lets always enable the kernel debugger for SMP. +options DDB + +# 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 FFS_ROOT #FFS usable as root device [keep this!] +options MFS #Memory Filesystem +options MFS_ROOT #MFS usable as root device, "MFS" req'ed +options NFS #Network Filesystem +options NFS_ROOT #NFS usable as root device, "NFS" req'ed +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root. "CD9660" req'ed +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 FAILSAFE #Be conservative +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor + +config kernel root on wd0 + +controller isa0 +controller eisa0 +controller pci0 + +controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr +disk fd0 at fdc0 drive 0 +disk fd1 at fdc0 drive 1 +# 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 2 + +options "CMD640" # work around CMD640 chip deficiency +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr +disk wd0 at wdc0 drive 0 +disk wd1 at wdc0 drive 1 + +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr +disk wd2 at wdc1 drive 0 +disk wd3 at wdc1 drive 1 + +options ATAPI #Enable ATAPI support for IDE bus +options ATAPI_STATIC #Don't do it as an LKM +device wcd0 #IDE CD-ROM +device wfd0 #IDE Floppy (e.g. LS-120) + +# A single entry for any of these controllers (ncr, ahb, ahc, amd) is +# sufficient for any number of installed devices. +controller ncr0 +#controller amd0 +controller ahb0 +controller ahc0 +controller isp0 + +# This controller offers a number of configuration options, too many to +# document here - see the LINT file in this directory and look up the +# dpt0 entry there for much fuller documentation on this. +controller dpt0 + +controller adv0 at isa? port ? cam irq ? +controller adw0 +controller bt0 at isa? port ? cam irq ? +controller aha0 at isa? port ? cam irq ? +#controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr +#controller aic0 at isa? port 0x340 bio irq 11 vector aicintr +#controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr +#controller nca1 at isa? port 0x350 bio irq 5 vector ncaintr +#controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr + +controller scbus0 + +device da0 + +device sa0 + +device pass0 + +device cd0 #Only need one of these, the code dynamically grows + +device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr +device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr + +controller matcd0 at isa? port 0x230 bio + +device scd0 at isa? port 0x230 bio + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" conflicts tty irq 1 vector scintr +# Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver +#device vt0 at isa? port "IO_KBD" conflicts tty irq 1 vector pcrint +#options XSERVER # support for X server +#options FAT_CURSOR # start with block cursor +# If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines +#options PCVT_SCANSET=2 # IBM keyboards are non-std + +device npx0 at isa? port "IO_NPX" irq 13 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" flags 0x10 tty irq 4 vector siointr +device sio1 at isa? port "IO_COM2" tty irq 3 vector siointr +device sio2 at isa? disable port "IO_COM3" tty irq 5 vector siointr +device sio3 at isa? disable port "IO_COM4" tty irq 9 vector siointr + +device lpt0 at isa? port? tty irq 7 vector lptintr + +device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr + +# 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 + +device ed0 at isa? port 0x280 net irq 10 iomem 0xd8000 vector edintr +device ie0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector ieintr +device ep0 at isa? port 0x300 net irq 10 vector epintr +device ex0 at isa? port? net irq? vector exintr +device fe0 at isa? port 0x300 net irq ? vector feintr +device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr +device lnc0 at isa? port 0x280 net irq 10 drq 0 vector lncintr +device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zeintr +device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr +device cs0 at isa? port 0x300 net irq ? vector csintr + +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 + +# 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/i386/conf/devices.i386 b/sys/i386/conf/devices.i386 index b8d866441c5f2..ccba4ecc30b16 100644 --- a/sys/i386/conf/devices.i386 +++ b/sys/i386/conf/devices.i386 @@ -1,6 +1,6 @@ # This file tells what major numbers the various possible swap devices have. # -# $Id: devices.i386,v 1.14 1998/09/15 10:01:13 gibbs Exp $ +# $Id: devices.i386,v 1.13 1998/02/17 11:33:31 sos 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/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 6993be0c5023f..a343f19635fbf 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.219 1999/01/19 11:31:22 yokota Exp $ +# $Id: files.i386,v 1.205 1998/09/20 06:04:55 bde Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -24,17 +24,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 vga device-driver -dev/fb/splash.c optional splash -dev/kbd/atkbd.c optional atkbd device-driver -dev/kbd/atkbdc.c optional atkbdc device-driver -dev/kbd/kbd.c optional atkbd device-driver -dev/kbd/kbd.c optional kbd device-driver -#dev/kbd/kbd.c optional ukbd device-driver -dev/syscons/syscons.c optional sc device-driver -dev/syscons/scvidctl.c optional sc device-driver -dev/syscons/scvesactl.c optional sc 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 @@ -108,8 +97,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/atkbd_isa.c optional atkbd device-driver -i386/isa/atkbdc_isa.c optional atkbdc 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 i386/isa/clock.c standard i386/isa/cronyx.c optional cx device-driver @@ -120,6 +109,7 @@ i386/isa/diskslice_machdep.c standard i386/isa/elink.c optional ep device-driver i386/isa/elink.c optional ie device-driver i386/isa/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,6 +117,7 @@ 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 i386/isa/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 @@ -134,7 +125,6 @@ i386/isa/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,11 +135,15 @@ i386/isa/intr_machdep.c standard i386/isa/isa.c optional isa device-driver i386/isa/istallion.c optional stli device-driver i386/isa/joy.c optional joy 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 i386/isa/lpt.c optional lpt device-driver i386/isa/labpc.c optional labpc device-driver i386/isa/mcd.c optional mcd device-driver i386/isa/mse.c optional mse device-driver +#i386/isa/ncr5380.c optional nca device-driver i386/isa/npx.c mandatory npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver @@ -171,6 +165,7 @@ 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 @@ -244,16 +239,21 @@ i386/isa/sound/cs4232.c optional css device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/stallion.c optional stl device-driver -i386/isa/syscons_isa.c optional sc device-driver -i386/isa/vesa.c optional vga device-driver -i386/isa/vga_isa.c optional vga device-driver +i386/isa/syscons.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 i386/isa/wd.c optional wdc device-driver i386/isa/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 @@ -269,30 +269,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 @@ -347,5 +323,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/i386/conf/majors.i386 b/sys/i386/conf/majors.i386 index 822d908cf0b5d..7b56d1d9cdc4e 100644 --- a/sys/i386/conf/majors.i386 +++ b/sys/i386/conf/majors.i386 @@ -1,4 +1,4 @@ -$Id: majors.i386,v 1.64 1999/01/14 03:47:55 msmith Exp $ +$Id: majors.i386,v 1.49 1998/09/15 10:01:14 gibbs 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/i386/conf/options.i386 b/sys/i386/conf/options.i386 index 2704d563788d0..9cb9eb8c9e021 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,7 +1,6 @@ -# $Id: options.i386,v 1.102 1999/01/10 17:41:33 nsouch Exp $ +# $Id: options.i386,v 1.89 1998/09/25 17:34:48 peter Exp $ DISABLE_PSE -IDE_DELAY USER_LDT MATH_EMULATE opt_math_emulate.h GPL_MATH_EMULATE opt_math_emulate.h @@ -14,8 +13,6 @@ LINUX opt_dontuse.h DEBUG_LINUX opt_linux.h -PPC_DEBUG opt_ppc.h - SHOW_BUSYBUFS TUNE_1542 PANIC_REBOOT_WAIT_TIME opt_panic.h @@ -28,13 +25,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 @@ -58,7 +61,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 @@ -66,26 +68,16 @@ 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 -# obsolete, use VGA_SLOW_IOACCESS -#SLOW_VGA 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 -# obsolete, use VGA_ALT_SEQACCESS -#SC_ALT_SEQACCESS opt_syscons.h - -FB_INSTALL_CDEV opt_fb.h - -VGA_ALT_SEQACCESS opt_vga.h -VGA_DEBUG opt_vga.h -VGA_NO_FONT_LOADING opt_vga.h -VGA_NO_MODE_CHANGE opt_vga.h -VGA_SLOW_IOACCESS opt_vga.h +SC_ALT_SEQACCESS opt_syscons.h VESA opt_vesa.h -VESA_DEBUG opt_vesa.h PSM_HOOKAPM opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h @@ -93,11 +85,10 @@ 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 @@ -106,13 +97,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 @@ -136,39 +126,3 @@ 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 -# ------------------------------- diff --git a/sys/i386/eisa/adv_eisa.c b/sys/i386/eisa/adv_eisa.c index 87ff8dd276fd4..77b2a92684323 100644 --- a/sys/i386/eisa/adv_eisa.c +++ b/sys/i386/eisa/adv_eisa.c @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: adv_eisa.c,v 1.1 1998/09/15 07:05:39 gibbs Exp $ + * $Id$ */ #include "eisa.h" @@ -76,9 +76,9 @@ static int adveisaattach(struct eisa_device *e_dev); * The overrun buffer shared amongst all EISA adapters. */ static u_int8_t* overrun_buf; -static bus_dma_tag_t overrun_dmat; -static bus_dmamap_t overrun_dmamap; -static bus_addr_t overrun_physbase; +bus_dma_tag_t overrun_dmat; +bus_dmamap_t overrun_dmamap; +bus_addr_t overrun_physbase; static struct eisa_driver adv_eisa_driver = { diff --git a/sys/i386/eisa/ahc_eisa.c b/sys/i386/eisa/ahc_eisa.c index 039878da4bf08..d69159ecaca0e 100644 --- a/sys/i386/eisa/ahc_eisa.c +++ b/sys/i386/eisa/ahc_eisa.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahc_eisa.c,v 1.3 1998/10/15 18:21:50 gibbs Exp $ + * $Id: ahc_eisa.c,v 1.2 1998/10/09 17:42:28 gibbs Exp $ */ #include "eisa.h" @@ -44,7 +44,6 @@ #include <cam/cam.h> #include <cam/cam_ccb.h> #include <cam/cam_sim.h> -#include <cam/cam_xpt_sim.h> #include <cam/scsi/scsi_all.h> #include <dev/aic7xxx/aic7xxx.h> diff --git a/sys/i386/eisa/eisaconf.c b/sys/i386/eisa/eisaconf.c index e1eee615d1412..11418e70bf671 100644 --- a/sys/i386/eisa/eisaconf.c +++ b/sys/i386/eisa/eisaconf.c @@ -28,14 +28,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: eisaconf.c,v 1.36 1998/12/04 22:54:46 archie Exp $ + * $Id: eisaconf.c,v 1.34 1998/02/09 06:08:09 eivind Exp $ */ #include "opt_eisa.h" #include <sys/param.h> #include <sys/systm.h> -#include <sys/linker_set.h> +#include <sys/kernel.h> #include <sys/malloc.h> #include <machine/limits.h> @@ -350,7 +350,7 @@ eisa_reg_end(e_dev) { char string[25]; - snprintf(string, sizeof(string), " on %s0 slot %d", + sprintf(string, " on %s0 slot %d", mainboard_drv.name, e_dev->ioconf.slot); eisa_reg_print(e_dev, string, NULL); @@ -432,7 +432,7 @@ eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared) return EPERM; } - snprintf(string, sizeof(string), " irq %d", irq); + sprintf(string, " irq %d", irq); eisa_reg_print(e_dev, string, reg_state.num_interrupts ? &separator : NULL); reg_state.num_interrupts++; diff --git a/sys/i386/eisa/if_fea.c b/sys/i386/eisa/if_fea.c index fd9447e2c009c..4113b1ac7ca0e 100644 --- a/sys/i386/eisa/if_fea.c +++ b/sys/i386/eisa/if_fea.c @@ -21,7 +21,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: if_fea.c,v 1.12 1999/01/01 12:35:47 bde Exp $ + * $Id: if_fea.c,v 1.9 1998/02/20 13:11:46 bde Exp $ */ /* @@ -205,9 +205,9 @@ pdq_eisa_attach( irq = TAILQ_FIRST(&ed->ioconf.irqs)->irq_no; - sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); + sc = (pdq_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_WAITOK); if (sc == NULL) { - printf("fea%ld: malloc failed!\n", ed->unit); + printf("fea%d: malloc failed!\n", sc->sc_if.if_unit); return -1; } pdqs_eisa[ed->unit] = sc; diff --git a/sys/i386/eisa/if_vx_eisa.c b/sys/i386/eisa/if_vx_eisa.c index b46fc752b95ef..fcee846452a20 100644 --- a/sys/i386/eisa/if_vx_eisa.c +++ b/sys/i386/eisa/if_vx_eisa.c @@ -159,7 +159,7 @@ vx_eisa_attach(e_dev) level_intr = FALSE; - if (eisa_reg_intr(e_dev, irq, vxintr, (void *) sc, &net_imask, + if (eisa_reg_intr(e_dev, irq, (void (*)(void *)) vxintr, (void *) sc, &net_imask, /* shared == */ level_intr)) { vxfree(sc); return -1; @@ -172,7 +172,7 @@ vx_eisa_attach(e_dev) if (eisa_enable_intr(e_dev, irq)) { vxfree(sc); - eisa_release_intr(e_dev, irq, vxintr); + eisa_release_intr(e_dev, irq, (void (*)(void *)) vxintr); return -1; } return 0; diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c index 528e27061277f..dd97021f36673 100644 --- a/sys/i386/i386/autoconf.c +++ b/sys/i386/i386/autoconf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.110 1998/10/26 07:05:34 bde Exp $ + * $Id: autoconf.c,v 1.108 1998/10/05 21:09:21 obrien Exp $ */ /* @@ -92,24 +92,23 @@ #include <pci/pcivar.h> #endif +#include "card.h" +#if NCARD > 0 +#include <pccard/driver.h> +#endif + +#include "scbus.h" + #include <sys/bus.h> -static void configure_first __P((void *)); static void configure __P((void *)); -static void configure_final __P((void *)); +SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) static void configure_finish __P((void)); static void configure_start __P((void)); static int setdumpdev __P((dev_t dev)); static void setroot __P((void)); -SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); -/* SI_ORDER_SECOND is hookable */ -SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); -/* SI_ORDER_MIDDLE is hookable */ -SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); - - #if defined(CD9660) || defined(CD9660_ROOT) #include <sys/fcntl.h> @@ -172,6 +171,8 @@ find_cdrom_root() } #endif /* CD9660 || CD9660_ROOT */ +extern void xpt_init __P((void)); + #ifdef MFS_ROOT extern u_char *mfs_getimage __P((void)); #endif @@ -179,6 +180,9 @@ extern u_char *mfs_getimage __P((void)); static void configure_start() { +#if NSCBUS > 0 + xpt_init(); +#endif } static void @@ -190,17 +194,12 @@ configure_finish() * Determine i/o configuration for a machine. */ static void -configure_first(dummy) - void *dummy; -{ - - configure_start(); /* DDB hook? */ -} - -static void configure(dummy) void *dummy; { + int i; + + configure_start(); /* Allow all routines to decide for themselves if they want intrs */ /* @@ -256,15 +255,13 @@ configure(dummy) * at splhigh()), but we want at least bio interrupts to work. */ safepri = cpl; -} -static void -configure_final(dummy) - void *dummy; -{ - int i; +#if NCARD > 0 + /* After everyone else has a chance at grabbing resources */ + pccard_configure(); +#endif - configure_finish(); /* DDB hook? */ + configure_finish(); cninit_finish(); @@ -410,7 +407,9 @@ setdumpdev(dev) return (0); } maj = major(dev); - if (maj >= nblkdev || bdevsw[maj] == NULL) + if (maj >= nblkdev) + return (ENXIO); + if (bdevsw[maj] == NULL) return (ENXIO); /* XXX is this right? */ if (bdevsw[maj]->d_psize == NULL) return (ENXIO); /* XXX should be ENODEV ? */ @@ -453,7 +452,7 @@ setroot() if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != B_DEVMAGIC) return; majdev = B_TYPE(bootdev); - if (majdev >= nblkdev || bdevsw[majdev] == NULL) + if (bdevsw[majdev] == NULL) return; unit = B_UNIT(bootdev); slice = B_SLICE(bootdev); diff --git a/sys/i386/i386/busdma_machdep.c b/sys/i386/i386/busdma_machdep.c index 30571e558e159..d35967e18f44f 100644 --- a/sys/i386/i386/busdma_machdep.c +++ b/sys/i386/i386/busdma_machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: busdma_machdep.c,v 1.11 1998/10/13 08:24:33 dg Exp $ + * $Id: busdma_machdep.c,v 1.10 1998/10/07 03:38:14 gibbs Exp $ */ #include <sys/param.h> @@ -435,45 +435,38 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, seg = 1; sg->ds_len = 0; - { - /* - * note: nextpaddr not used on first loop - */ - vm_offset_t nextpaddr = 0; + do { + bus_size_t size; + vm_offset_t nextpaddr; /* GCC warning expected */ - do { - bus_size_t size; + paddr = pmap_kextract(vaddr); + size = PAGE_SIZE - (paddr & PAGE_MASK); + if (size > buflen) + size = buflen; - paddr = pmap_kextract(vaddr); - size = PAGE_SIZE - (paddr & PAGE_MASK); - if (size > buflen) - size = buflen; - - if (map->pagesneeded != 0 - && run_filter(dmat, paddr)) { - paddr = add_bounce_page(dmat, map, - vaddr, size); - } + if (map->pagesneeded != 0 + && run_filter(dmat, paddr)) { + paddr = add_bounce_page(dmat, map, vaddr, size); + } - if (sg->ds_len == 0) { - sg->ds_addr = paddr; - sg->ds_len = size; - } else if (paddr == nextpaddr) { - sg->ds_len += size; - } else { - /* Go to the next segment */ - sg++; - seg++; - if (seg > dmat->nsegments) - break; - sg->ds_addr = paddr; - sg->ds_len = size; - } - vaddr += size; - nextpaddr = paddr + size; - buflen -= size; - } while (buflen > 0); - } + if (sg->ds_len == 0) { + sg->ds_addr = paddr; + sg->ds_len = size; + } else if (paddr == nextpaddr) { + sg->ds_len += size; + } else { + /* Go to the next segment */ + sg++; + seg++; + if (seg > dmat->nsegments) + break; + sg->ds_addr = paddr; + sg->ds_len = size; + } + vaddr += size; + nextpaddr = paddr + size; + buflen -= size; + } while (buflen > 0); if (buflen != 0) { printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n", diff --git a/sys/i386/i386/cons.c b/sys/i386/i386/cons.c index 581ff3f9c1dda..1482c61855571 100644 --- a/sys/i386/i386/cons.c +++ b/sys/i386/i386/cons.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: @(#)cons.c 7.2 (Berkeley) 5/9/91 - * $Id: cons.c,v 1.59 1998/08/23 08:26:40 bde Exp $ + * $Id: cons.c,v 1.58 1998/06/07 17:09:58 dfr Exp $ */ #include "opt_devfs.h" @@ -57,6 +57,23 @@ #include <machine/cpu.h> #include <machine/cons.h> +/* XXX this should be config(8)ed. */ +#include "sc.h" +#include "vt.h" +#include "sio.h" +static struct consdev constab[] = { +#if NSC > 0 + { sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc }, +#endif +#if NVT > 0 + { pccnprobe, pccninit, pccngetc, pccncheckc, pccnputc }, +#endif +#if NSIO > 0 + { siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc }, +#endif + { 0 }, +}; + static d_open_t cnopen; static d_close_t cnclose; static d_read_t cnread; @@ -74,7 +91,7 @@ static struct cdevsw cn_cdevsw = { }; static dev_t cn_dev_t; /* seems to be never really used */ -SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD, +SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLTYPE_OPAQUE|CTLFLAG_RD, &cn_dev_t, sizeof cn_dev_t, "T,dev_t", ""); static int cn_mute; @@ -95,22 +112,16 @@ static struct tty *cn_tp; /* physical console tty struct */ static void *cn_devfs_token; /* represents the devfs entry */ #endif /* DEVFS */ -CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL); - void cninit() { struct consdev *best_cp, *cp; - struct consdev **list; /* * Find the first console with the highest priority. */ best_cp = NULL; - list = (struct consdev **)cons_set.ls_items; - while ((cp = *list++) != NULL) { - if (cp->cn_probe == NULL) - continue; + for (cp = constab; cp->cn_probe; cp++) { (*cp->cn_probe)(cp); if (cp->cn_pri > CN_DEAD && (best_cp == NULL || cp->cn_pri > best_cp->cn_pri)) diff --git a/sys/i386/i386/cons.h b/sys/i386/i386/cons.h index 1656b1261d47a..76bc0739facae 100644 --- a/sys/i386/i386/cons.h +++ b/sys/i386/i386/cons.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: @(#)cons.h 7.2 (Berkeley) 5/9/91 - * $Id: cons.h,v 1.18 1999/01/07 14:14:11 yokota Exp $ + * $Id: cons.h,v 1.16 1997/04/01 16:13:31 bde Exp $ */ #ifndef _MACHINE_CONS_H_ @@ -49,6 +49,30 @@ typedef int cn_getc_t __P((dev_t)); typedef int cn_checkc_t __P((dev_t)); typedef void cn_putc_t __P((dev_t, int)); +#ifdef KERNEL +/* + * XXX public functions in drivers should be declared in headers produced + * by `config', not here. + */ +cn_probe_t pccnprobe; +cn_init_t pccninit; +cn_getc_t pccngetc; +cn_checkc_t pccncheckc; +cn_putc_t pccnputc; + +cn_probe_t sccnprobe; +cn_init_t sccninit; +cn_getc_t sccngetc; +cn_checkc_t sccncheckc; +cn_putc_t sccnputc; + +cn_probe_t siocnprobe; +cn_init_t siocninit; +cn_getc_t siocngetc; +cn_checkc_t siocncheckc; +cn_putc_t siocnputc; +#endif /* KERNEL */ + struct consdev { cn_probe_t *cn_probe; /* probe hardware and fill in consdev info */ @@ -72,15 +96,8 @@ struct consdev { #define CN_REMOTE 3 /* serial interface with remote bit set */ #ifdef KERNEL -extern struct linker_set cons_set; extern int cons_unavail; -#define CONS_DRIVER(name, probe, init, getc, checkc, putc) \ - static struct consdev name##_consdev = { \ - probe, init, getc, checkc, putc \ - }; \ - DATA_SET(cons_set, name##_consdev) - /* Other kernel entry points. */ int cncheckc __P((void)); int cngetc __P((void)); diff --git a/sys/i386/i386/db_interface.c b/sys/i386/i386/db_interface.c index 7f01f1d735e69..3f5f893a677c1 100644 --- a/sys/i386/i386/db_interface.c +++ b/sys/i386/i386/db_interface.c @@ -23,7 +23,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: db_interface.c,v 1.42 1998/12/14 05:34:33 dillon Exp $ + * $Id: db_interface.c,v 1.40 1998/06/08 08:43:20 dfr Exp $ */ /* @@ -69,7 +69,7 @@ kdb_trap(type, code, regs) int type, code; register struct i386_saved_state *regs; { - volatile int ddb_mode = !(boothowto & RB_GDB); + int ddb_mode = !(boothowto & RB_GDB); /* * XXX try to do nothing if the console is in graphics mode. @@ -295,12 +295,11 @@ db_write_bytes(addr, size, data) * Move this to machdep.c and allow it to be called if any debugger is * installed. */ -volatile int in_Debugger = 0; - void Debugger(msg) const char *msg; { + static volatile u_char in_Debugger; /* * XXX diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c index aad9d89fa2b88..eae2f4fcbbb11 100644 --- a/sys/i386/i386/elf_machdep.c +++ b/sys/i386/i386/elf_machdep.c @@ -22,7 +22,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: elf_machdep.c,v 1.3 1998/10/16 03:54:59 peter Exp $ + * $Id: elf_machdep.c,v 1.2 1998/10/09 20:38:03 peter Exp $ */ #include <sys/param.h> @@ -42,7 +42,7 @@ elf_reloc(linker_file_t lf, const void *data, int type, const char *sym) { Elf_Addr relocbase = (Elf_Addr) lf->address; Elf_Addr *where; - Elf_Addr addr; + Elf_Addr addr, tmp_value; Elf_Addr addend; Elf_Word rtype; const Elf_Rel *rel; diff --git a/sys/i386/i386/gensetdefs.c b/sys/i386/i386/gensetdefs.c new file mode 100644 index 0000000000000..21029168d5aae --- /dev/null +++ b/sys/i386/i386/gensetdefs.c @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/types.h> +#include <machine/elf.h> + +#include <err.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define HASHSIZE 1009u /* Number of hash chains. */ +#define PREFIX ".set." /* Section name prefix for linker sets. */ + +/* One entry in the hash table. */ +typedef struct hashent { + struct hashent *next; /* Next entry with the same hash. */ + char *name; /* Name of the linker set. */ + size_t size; /* Size in bytes. */ +} hashent; + +/* Allocate storage for "count" objects of type "type". */ +#define NEW(type, count) ((type *) xmalloc((count) * sizeof(type))) + +static hashent *hashtab[HASHSIZE]; /* Hash chain heads. */ + +static void enter(const char *, size_t); +static int enter_sets(const char *); +static unsigned int hash(const char *); +static hashent *merge(void); +static int my_byte_order(void); +static void *xmalloc(size_t); +static char *xstrdup(const char *); + +/* + * This is a special-purpose program to generate the linker set definitions + * needed when building an ELF kernel. Its arguments are the names of + * ELF object files. It scans the section names of the object files, + * building a table of those that begin with ".set.", which represent + * linker sets. Finally, for each set "foo" with "count" elements, it + * writes a line "DEFINE_SET(foo, count);" to the standard output. + */ +int +main(int argc, char **argv) +{ + int i; + int status = EXIT_SUCCESS; + hashent *list; + + for (i = 1; i < argc; i++) + if (enter_sets(argv[i]) == -1) + status = EXIT_FAILURE; + + list = merge(); + while (list != NULL) { + hashent *next; + + printf("DEFINE_SET(%s, %lu);\n", list->name, + (unsigned long) (list->size / sizeof (void *))); + next = list->next; + free(list->name); + free(list); + list = next; + } + + return (status); +} + +/* + * Enter the given string into the hash table, if it is not already there. + * Each hash chain is kept sorted, so that it will be easy to merge the + * chains to get a single sorted list. + */ +static void +enter(const char *name, size_t size) +{ + int c; + hashent *entp; + hashent **linkp; + hashent *newp; + + linkp = &hashtab[hash(name) % HASHSIZE]; + while ((entp = *linkp) != NULL && (c = strcmp(name, entp->name)) > 0) + linkp = &entp->next; + + if (entp == NULL || c != 0) { /* Not found; create a new entry. */ + newp = NEW(hashent, 1); + newp->name = xstrdup(name); + newp->size = 0; + newp->next = entp; + *linkp = newp; + entp = newp; + } + + entp->size += size; +} + +/* + * Return a hash value for the given string. + */ +static unsigned int +hash(const char *s) +{ + unsigned char ch; + unsigned int h = 0; + + while((ch = *s) != '\0') { + h = 9*h + ch; + s++; + } + return (h); +} + +/* + * Enter the linker sets from the given ELF object file. Returns 0 on + * success, or -1 if an error occurred. + */ +static int +enter_sets(const char *filename) +{ + int i; + FILE *iop; + Elf32_Shdr *shdr; + char *shstr; + Elf32_Ehdr ehdr; + + if ((iop = fopen(filename, "rb")) == NULL) { + warn("%s", filename); + return (-1); + } + if (fread(&ehdr, sizeof ehdr, 1, iop) != 1 || + ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) { + warnx("%s: not an ELF file", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { + warnx("%s: unsupported ELF version", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_DATA] != my_byte_order()) { + warnx("%s: unsupported byte order", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shoff == 0) { + warnx("%s: no section table", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shstrndx == SHN_UNDEF) { + warnx("%s: no section name string table", filename); + fclose(iop); + return (-1); + } + + shdr = NEW(Elf32_Shdr, ehdr.e_shnum); + if (fseek(iop, ehdr.e_shoff, SEEK_SET) == -1) { + warn("%s", filename); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shdr, sizeof *shdr, ehdr.e_shnum, iop) != ehdr.e_shnum) { + warnx("%s: truncated section table", filename); + free(shdr); + fclose(iop); + return (-1); + } + + shstr = NEW(char, shdr[ehdr.e_shstrndx].sh_size); + if (fseek(iop, shdr[ehdr.e_shstrndx].sh_offset, SEEK_SET) == -1) { + warn("%s", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shstr, sizeof *shstr, shdr[ehdr.e_shstrndx].sh_size, iop) != + shdr[ehdr.e_shstrndx].sh_size) { + warnx("%s: truncated section name string table", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + + for (i = 1; i < ehdr.e_shnum; i++) { + const char *name = shstr + shdr[i].sh_name; + + if (strncmp(name, PREFIX, sizeof (PREFIX) - 1) == 0) + enter(name + sizeof (PREFIX) - 1, shdr[i].sh_size); + } + + free(shstr); + free(shdr); + fclose(iop); + return (0); +} + +/* + * Destructively merge all the sorted hash chains into a single sorted + * list, and return a pointer to its first element. + */ +static hashent * +merge(void) +{ + unsigned int numchains = HASHSIZE; + + while (numchains > 1) { /* More merging to do. */ + unsigned int lo = 0; + /* + * Merge chains pairwise from the outside in, halving the + * number of chains. + */ + while (numchains - lo >= 2) { + hashent **linkp = &hashtab[lo]; + hashent *l1 = hashtab[lo++]; + hashent *l2 = hashtab[--numchains]; + + while (l1 != NULL && l2 != NULL) { + if (strcmp(l1->name, l2->name) < 0) { + *linkp = l1; + linkp = &l1->next; + l1 = l1->next; + } else { + *linkp = l2; + linkp = &l2->next; + l2 = l2->next; + } + } + *linkp = l1==NULL ? l2 : l1; + } + } + + return (hashtab[0]); +} + +/* + * Determine the host byte order. + */ +static int +my_byte_order(void) +{ + static unsigned short s = 0xbbaa; + int byte0; + + byte0 = *(unsigned char *)&s; + if (byte0 == 0xaa) + return (ELFDATA2LSB); + else if (byte0 == 0xbb) + return (ELFDATA2MSB); + else + return (ELFDATANONE); +} + +/* + * Allocate a chunk of memory and return a pointer to it. Die if the + * malloc fails. + */ +static void * +xmalloc(size_t size) +{ + void *p; + + p = malloc(size); + if (p == NULL) + err(EXIT_FAILURE, "malloc"); + return (p); +} + +/* + * Duplicate a string and return a pointer to the copy. Die if there is + * not enough memory. + */ +static char * +xstrdup(const char *s) +{ + int size; + + size = strlen(s) + 1; + return (memcpy(xmalloc(size), s, size)); +} diff --git a/sys/i386/i386/i386-gdbstub.c b/sys/i386/i386/i386-gdbstub.c index 25e283897da55..0c5f82bb4f61a 100644 --- a/sys/i386/i386/i386-gdbstub.c +++ b/sys/i386/i386/i386-gdbstub.c @@ -153,9 +153,6 @@ strcpy (char *dst, const char *src) /* XXX sio always uses its major with minor 0 no matter what we specify. */ #define REMOTE_DEV 0 -cn_getc_t siocngetc; -cn_putc_t siocnputc; - static int putDebugChar (int c) /* write a single character */ { diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index 146db244a836c..98b9edf708d02 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id: identcpu.c,v 1.56 1999/01/09 13:07:18 bde Exp $ + * $Id: identcpu.c,v 1.51 1998/07/11 07:45:28 bde Exp $ */ #include "opt_cpu.h" @@ -59,17 +59,17 @@ #define IDENTBLUE_IBMCPU 1 #define IDENTBLUE_CYRIXM2 2 -/* XXX - should be in header file: */ -void printcpuinfo(void); +/* XXX - should be in header file */ +void i486_bzero __P((void *buf, size_t len)); + +void printcpuinfo(void); /* XXX should be in different header file */ void finishidentcpu(void); void earlysetcpuclass(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); -void enable_K6_2_wt_alloc(void); #endif void panicifcpuunsupported(void); - static void identifycyrix(void); static void print_AMD_info(void); static void print_AMD_assoc(int i); @@ -106,13 +106,13 @@ do_cpuid(u_int ax, u_int *p) { __asm __volatile( ".byte 0x0f, 0xa2;" - "movl %%eax, (%2);" - "movl %%ebx, 4(%2);" - "movl %%ecx, 8(%2);" - "movl %%edx, 12(%2);" - : "=a" (ax) - : "0" (ax), "S" (p) - : "bx", "cx", "dx" + "movl %%eax, (%%esi);" + "movl %%ebx, (4)(%%esi);" + "movl %%ecx, (8)(%%esi);" + "movl %%edx, (12)(%%esi);" + : + : "a" (ax), "S" (p) + : "ax", "bx", "cx", "dx" ); } @@ -291,13 +291,9 @@ printcpuinfo(void) if ((cpu_id & 0xf00) == 0x500) { if (((cpu_id & 0x0f0) > 0) && ((cpu_id & 0x0f0) < 0x60) - && ((cpu_id & 0x00f) > 3)) + && ((cpu_id & 0x00f) > 3)) { enable_K5_wt_alloc(); - else if (((cpu_id & 0x0f0) > 0x80) - || (((cpu_id & 0x0f0) == 0x80) - && (cpu_id & 0x00f) > 0x07)) - enable_K6_2_wt_alloc(); - else if ((cpu_id & 0x0f0) > 0x50) + } else if ((cpu_id & 0x0f0) > 0x50) enable_K6_wt_alloc(); } #endif @@ -843,7 +839,6 @@ static void print_AMD_info(void) { u_int regs[4]; - quad_t amd_whcr; do_cpuid(0x80000000, regs); if (regs[0] >= 0x80000005) { @@ -861,33 +856,4 @@ print_AMD_info(void) printf(", %d lines/tag", (regs[3] >> 8) & 0xff); print_AMD_assoc((regs[3] >> 16) & 0xff); } - if (((cpu_id & 0xf00) == 0x500) - && (((cpu_id & 0x0f0) > 0x80) - || (((cpu_id & 0x0f0) == 0x80) - && (cpu_id & 0x00f) > 0x07))) { - /* K6-2(new core [Stepping 8-F]), K6-3 or later */ - amd_whcr = rdmsr(0xc0000082); - if (!(amd_whcr & (0x3ff << 22))) { - printf("Write Allocate Disable\n"); - } else { - printf("Write Allocate Enable Limit: %dM bytes\n", - (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); - printf("Write Allocate 15-16M bytes: %s\n", - (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); - } - } else if (((cpu_id & 0xf00) == 0x500) - && ((cpu_id & 0x0f0) > 0x50)) { - /* K6, K6-2(old core) */ - amd_whcr = rdmsr(0xc0000082); - if (!(amd_whcr & (0x7f << 1))) { - printf("Write Allocate Disable\n"); - } else { - printf("Write Allocate Enable Limit: %dM bytes\n", - (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4); - printf("Write Allocate 15-16M bytes: %s\n", - (amd_whcr & 0x0001) ? "Enable" : "Disable"); - printf("Hardware Write Allocate Control: %s\n", - (amd_whcr & 0x0100) ? "Enable" : "Disable"); - } - } } diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c index d64f4eefedd1a..9f1f2a9b7190e 100644 --- a/sys/i386/i386/initcpu.c +++ b/sys/i386/i386/initcpu.c @@ -26,7 +26,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: initcpu.c,v 1.16 1998/12/27 23:23:26 msmith Exp $ + * $Id: initcpu.c,v 1.13 1998/05/16 14:38:10 kato Exp $ */ #include "opt_cpu.h" @@ -44,7 +44,6 @@ void initializecpu(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); -void enable_K6_2_wt_alloc(void); #endif #ifdef I486_CPU @@ -617,18 +616,20 @@ enable_K6_wt_alloc(void) #endif /* Don't assume that memory size is aligned with 4M. */ if (Maxmem > 0) - size = ((Maxmem >> 8) + 3) >> 2; + size = Maxmem / 256; else size = 0; + size = (size + 3) / 4; /* Limit is 508M bytes. */ - if (size > 0x7f) - size = 0x7f; - whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1); + if (size > 127) + size = 127; + whcr = rdmsr(0xc0000082); + whcr &= ~0x00feLL; + whcr |= (size << 1); -#if defined(PC98) || defined(NO_MEMORY_HOLE) - if (whcr & (0x7fLL << 1)) { #ifdef PC98 + if (whcr & 0x00feLL) { /* * If bit 2 of port 0x43b is 0, disable wrte allocate for the * 15-16M range. @@ -636,7 +637,6 @@ enable_K6_wt_alloc(void) if (!(inb(0x43b) & 4)) whcr &= ~0x0001LL; else -#endif whcr |= 0x0001LL; } #else @@ -644,69 +644,7 @@ enable_K6_wt_alloc(void) * There is no way to know wheter 15-16M hole exists or not. * Therefore, we disable write allocate for this range. */ - whcr &= ~0x0001LL; -#endif - wrmsr(0x0c0000082, whcr); - - write_eflags(eflags); - enable_intr(); -} - -void -enable_K6_2_wt_alloc(void) -{ - quad_t size; - u_int64_t whcr; - u_long eflags; - - eflags = read_eflags(); - disable_intr(); - wbinvd(); - -#ifdef CPU_DISABLE_CACHE - /* - * Certain K6-2 box becomes unstable when write allocation is - * enabled. - */ - /* - * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), - * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. - * All other bits in TR12 have no effect on the processer's operation. - * The I/O Trap Restart function (bit 9 of TR12) is always enabled - * on the AMD-K6. - */ - wrmsr(0x0000000e, (u_int64_t)0x0008); -#endif - /* Don't assume that memory size is aligned with 4M. */ - if (Maxmem > 0) - size = ((Maxmem >> 8) + 3) >> 2; - else - size = 0; - - /* Limit is 4092M bytes. */ - if (size > 0x3fff) - size = 0x3ff; - whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22); - -#if defined(PC98) || defined(NO_MEMORY_HOLE) - if (whcr & (0x3ffLL << 22)) { -#ifdef PC98 - /* - * If bit 2 of port 0x43b is 0, disable wrte allocate for the - * 15-16M range. - */ - if (!(inb(0x43b) & 4)) - whcr &= ~(1LL << 16); - else -#endif - whcr |= 1LL << 16; - } -#else - /* - * There is no way to know wheter 15-16M hole exists or not. - * Therefore, we disable write allocate for this range. - */ - whcr &= ~(1LL << 16); + whcr &= 0x00feLL; #endif wrmsr(0x0c0000082, whcr); @@ -723,8 +661,7 @@ DB_SHOW_COMMAND(cyrixreg, cyrixreg) { u_long eflags; u_int cr0; - u_char ccr1, ccr2, ccr3; - u_char ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0; + u_char ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, pcr0; cr0 = rcr0(); if (strcmp(cpu_vendor,"CyrixInstead") == 0) { diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index 42955056d4239..f6f735d9f2ed9 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.117 1998/11/03 21:07:50 msmith Exp $ + * $Id: locore.s,v 1.115 1998/10/09 23:36:25 peter Exp $ * * originally from: locore.s, by William F. Jolitz * @@ -206,9 +206,9 @@ NON_GPROF_ENTRY(btext) #ifdef PC98 jmp 1f - .globl CNAME(pc98_system_parameter) + .globl _pc98_system_parameter .org 0x400 -CNAME(pc98_system_parameter): +_pc98_system_parameter: .space 0x240 /* BIOS parameter block */ 1: /* save SYSTEM PARAMETER for resume (NS/T or other) */ @@ -599,6 +599,15 @@ olddiskboot: movl 12(%ebp),%eax movl %eax,R(_bootdev) +#if defined(USERCONFIG_BOOT) && defined(USERCONFIG) + movl $0x10200, %esi + movl $R(_userconfig_from_boot),%edi + movl $512,%ecx + cld + rep + movsb +#endif /* USERCONFIG_BOOT */ + ret diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 1bd6f6c5f04ae..06db0703bc201 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.321 1999/01/09 15:41:49 bde Exp $ + * $Id: machdep.c,v 1.312 1998/10/09 00:31:06 msmith 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> @@ -159,9 +162,9 @@ SYSCTL_INT(_debug, OID_AUTO, tlb_flush_count, #endif #ifdef PC98 -static int ispc98 = 1; +int ispc98 = 1; #else -static int ispc98 = 0; +int ispc98 = 0; #endif SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, ""); @@ -410,12 +413,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)); @@ -439,8 +436,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), @@ -532,11 +535,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 @@ -631,7 +630,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; @@ -795,6 +794,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 @@ -1235,7 +1245,7 @@ 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)); - setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 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)); @@ -1626,7 +1636,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/i386/i386/math_emulate.c b/sys/i386/i386/math_emulate.c index a7077bd0df5dc..df44b5f75182c 100644 --- a/sys/i386/i386/math_emulate.c +++ b/sys/i386/i386/math_emulate.c @@ -6,7 +6,7 @@ * [expediant "port" of linux 8087 emulator to 386BSD, with apologies -wfj] * * from: 386BSD 0.1 - * $Id: math_emulate.c,v 1.31 1998/11/15 15:33:50 bde Exp $ + * $Id: math_emulate.c,v 1.27 1998/07/15 09:01:18 bde Exp $ */ /* @@ -117,10 +117,7 @@ math_emulate(struct trapframe * info) (u_long)oldeip); panic("?Math emulation needed in kernel?"); } - /* completely ignore an operand-size prefix */ - if (get_fs_byte((char *) info->tf_eip) == 0x66) - info->tf_eip++; - code = get_fs_word((unsigned short *) info->tf_eip); + code = get_fs_word((unsigned short *) oldeip); bswapw(code); code &= 0x7ff; I387.fip = oldeip; @@ -1543,18 +1540,46 @@ int_to_real(const temp_int * a, temp_real * b) } } +#ifdef LKM +MOD_MISC(fpu); +static int +fpu_load(struct lkm_table *lkmtp, int cmd) +{ + if (pmath_emulate) { + printf("Math emulator already present\n"); + return EBUSY; + } + pmath_emulate = math_emulate; + return 0; +} + +static int +fpu_unload(struct lkm_table *lkmtp, int cmd) +{ + if (pmath_emulate != math_emulate) { + printf("Cannot unload another math emulator\n"); + return EACCES; + } + pmath_emulate = 0; + return 0; +} + +int +fpu_mod(struct lkm_table *lkmtp, int cmd, int ver) +{ + MOD_DISPATCH(fpu, lkmtp, cmd, ver, fpu_load, fpu_unload, lkm_nullcmd); +} +#else /* !LKM */ + static int -fpu_modevent(module_t mod, int type, void *unused) +fpu_modevent(module_t mod, modeventtype_t type, void *unused) { switch (type) { case MOD_LOAD: - if (pmath_emulate) { + if (pmath_emulate) printf("Another Math emulator already present\n"); - return EBUSY; - } - pmath_emulate = math_emulate; - if (bootverbose) - printf("Math emulator present\n"); + else + pmath_emulate = math_emulate; break; case MOD_UNLOAD: if (pmath_emulate != math_emulate) { @@ -1562,9 +1587,6 @@ fpu_modevent(module_t mod, int type, void *unused) return EACCES; } pmath_emulate = 0; - if (bootverbose) - printf("Math emulator unloaded\n"); - break; default: break; } @@ -1575,4 +1597,6 @@ moduledata_t fpumod = { fpu_modevent, 0 }; -DECLARE_MODULE(fpu, fpumod, SI_SUB_DRIVERS, SI_ORDER_ANY); +DECLARE_MODULE(fpu, fpumod, SI_SUB_PSEUDO, SI_ORDER_ANY); + +#endif /* LKM */ diff --git a/sys/i386/i386/mem.c b/sys/i386/i386/mem.c index 1994f12ce5382..d26b9ee5ebf5c 100644 --- a/sys/i386/i386/mem.c +++ b/sys/i386/i386/mem.c @@ -38,7 +38,7 @@ * * from: Utah $Hdr: mem.c 1.13 89/10/08$ * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 - * $Id: mem.c,v 1.52 1998/06/21 11:33:29 bde Exp $ + * $Id: mem.c,v 1.51 1998/06/07 17:10:02 dfr Exp $ */ /* @@ -381,7 +381,7 @@ mmrw(dev, uio, flags) * instead of going through read/write * \*******************************************************/ static int -memmmap(dev_t dev, vm_offset_t offset, int nprot) +memmmap(dev_t dev, int offset, int nprot) { switch (minor(dev)) { diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 569f04baf6597..adf5131b1d84c 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp_machdep.c,v 1.87 1999/01/12 00:19:31 eivind Exp $ + * $Id: mp_machdep.c,v 1.82 1998/10/10 09:38:02 kato Exp $ */ #include "opt_smp.h" @@ -1009,8 +1009,8 @@ fix_mp_table(void) { int x; int id; - int bus_0 = 0; /* Stop GCC warning */ - int bus_pci = 0; /* Stop GCC warning */ + int bus_0; + int bus_pci; int num_pci_bus; /* @@ -1197,26 +1197,11 @@ lookup_bus_type(char *name) static int int_entry(int_entry_ptr entry, int intr) { - int apic; - io_apic_ints[intr].int_type = entry->int_type; io_apic_ints[intr].int_flags = entry->int_flags; io_apic_ints[intr].src_bus_id = entry->src_bus_id; io_apic_ints[intr].src_bus_irq = entry->src_bus_irq; - if (entry->dst_apic_id == 255) { - /* This signal goes to all IO APICS. Select an IO APIC - with sufficient number of interrupt pins */ - for (apic = 0; apic < mp_napics; apic++) - if (((io_apic_read(apic, IOAPIC_VER) & - IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) >= - entry->dst_apic_int) - break; - if (apic < mp_napics) - io_apic_ints[intr].dst_apic_id = IO_TO_ID(apic); - else - io_apic_ints[intr].dst_apic_id = entry->dst_apic_id; - } else - io_apic_ints[intr].dst_apic_id = entry->dst_apic_id; + io_apic_ints[intr].dst_apic_id = entry->dst_apic_id; io_apic_ints[intr].dst_apic_int = entry->dst_apic_int; return 1; @@ -1388,13 +1373,11 @@ int undirect_isa_irq(int rirq) { #if defined(READY) - if (bootverbose) - printf("Freeing redirected ISA irq %d.\n", rirq); + printf("Freeing redirected ISA irq %d.\n", rirq); /** FIXME: tickle the MB redirector chip */ return ???; #else - if (bootverbose) - printf("Freeing (NOT implemented) redirected ISA irq %d.\n", rirq); + printf("Freeing (NOT implemented) redirected ISA irq %d.\n", rirq); return 0; #endif /* READY */ } @@ -2200,12 +2183,12 @@ SYSCTL_INT(_machdep, OID_AUTO, forward_irq_enabled, CTLFLAG_RW, &forward_irq_enabled, 0, ""); /* Enable forwarding of a signal to a process running on a different CPU */ -static int forward_signal_enabled = 1; +int forward_signal_enabled = 1; SYSCTL_INT(_machdep, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, &forward_signal_enabled, 0, ""); /* Enable forwarding of roundrobin to all other cpus */ -static int forward_roundrobin_enabled = 1; +int forward_roundrobin_enabled = 1; SYSCTL_INT(_machdep, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW, &forward_roundrobin_enabled, 0, ""); @@ -2218,6 +2201,7 @@ void ap_init(void); void ap_init() { + u_int temp; u_int apic_id; smp_cpus++; diff --git a/sys/i386/i386/perfmon.c b/sys/i386/i386/perfmon.c index 0720c62ea0f20..d79527e3d37c5 100644 --- a/sys/i386/i386/perfmon.c +++ b/sys/i386/i386/perfmon.c @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: perfmon.c,v 1.16 1998/12/07 21:58:18 archie Exp $ + * $Id: perfmon.c,v 1.14 1997/12/28 17:33:01 phk Exp $ */ #include <sys/param.h> @@ -41,17 +41,13 @@ static int perfmon_inuse; static int perfmon_cpuok; -#ifndef SMP static int msr_ctl[NPMC]; -#endif static int msr_pmc[NPMC]; static unsigned int ctl_shadow[NPMC]; static quad_t pmc_shadow[NPMC]; /* used when ctr is stopped on P5 */ static int (*writectl)(int); -#ifndef SMP static int writectl5(int); static int writectl6(int); -#endif /* * Must be called after cpu_class is set up. @@ -199,7 +195,6 @@ perfmon_reset(int pmc) return EBUSY; } -#ifndef SMP /* * Unfortunately, the performance-monitoring registers are laid out * differently in the P5 and P6. We keep everything in P6 format @@ -250,7 +245,6 @@ writectl5(int pmc) wrmsr(msr_ctl[0], newval); return 0; /* XXX should check for unimplemented bits */ } -#endif /* !SMP */ /* * Now the user-mode interface, called from a subdevice of mem.c. diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 66c9b632f1c0b..2be04c8eeabfb 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 - * $Id: pmap.c,v 1.218 1999/01/09 21:41:22 dt Exp $ + * $Id: pmap.c,v 1.208 1998/09/04 13:10:34 ache Exp $ */ /* @@ -184,14 +184,6 @@ static caddr_t CADDR2; static pt_entry_t *msgbufmap; struct msgbuf *msgbufp=0; -/* - * PPro_vmtrr - */ -struct ppro_vmtrr PPro_vmtrr[NPPROVMTRR]; - -/* AIO support */ -extern struct vmspace *aiovmspace; - #ifdef SMP extern char prv_CPAGE1[], prv_CPAGE2[], prv_CPAGE3[]; extern pt_entry_t *prv_CMAP1, *prv_CMAP2, *prv_CMAP3; @@ -297,9 +289,7 @@ pmap_bootstrap(firstaddr, loadaddr) { vm_offset_t va; pt_entry_t *pte; -#ifdef SMP int i, j; -#endif avail_start = firstaddr; @@ -469,7 +459,7 @@ getmtrr() { int i; - if (cpu_class == CPUCLASS_686) { + if (cpu == CPU_686) { for(i = 0; i < NPPROVMTRR; i++) { PPro_vmtrr[i].base = rdmsr(PPRO_VMTRRphysBase0 + i * 2); PPro_vmtrr[i].mask = rdmsr(PPRO_VMTRRphysMask0 + i * 2); @@ -482,7 +472,7 @@ putmtrr() { int i; - if (cpu_class == CPUCLASS_686) { + if (cpu == CPU_686) { wbinvd(); for(i = 0; i < NPPROVMTRR; i++) { wrmsr(PPRO_VMTRRphysBase0 + i * 2, PPro_vmtrr[i].base); @@ -495,7 +485,7 @@ void pmap_setvidram(void) { #if 0 - if (cpu_class == CPUCLASS_686) { + if (cpu == CPU_686) { wbinvd(); /* * Set memory between 0-640K to be WB @@ -518,7 +508,7 @@ pmap_setdevram(unsigned long long basea, vm_offset_t sizea) unsigned long long base; unsigned long long mask; - if (cpu_class != CPUCLASS_686) + if (cpu != CPU_686) return; free = -1; @@ -606,11 +596,6 @@ pmap_init(phys_start, phys_end) int initial_pvs; /* - * object for kernel page table pages - */ - kptobj = vm_object_allocate(OBJT_DEFAULT, NKPDE); - - /* * calculate the number of pv_entries needed */ vm_first_phys = phys_avail[0]; @@ -644,6 +629,10 @@ pmap_init(phys_start, phys_end) pvinit = (struct pv_entry *) kmem_alloc(kernel_map, initial_pvs * sizeof (struct pv_entry)); zbootinit(pvzone, "PV ENTRY", sizeof (struct pv_entry), pvinit, pv_npg); + /* + * object for kernel page table pages + */ + kptobj = vm_object_allocate(OBJT_DEFAULT, NKPDE); /* * Now it is safe to enable pv_table recording. @@ -734,6 +723,19 @@ invltlb_1pg( vm_offset_t va) { } } +static PMAP_INLINE void +invltlb_2pg( vm_offset_t va1, vm_offset_t va2) { +#if defined(I386_CPU) + if (cpu_class == CPUCLASS_386) { + invltlb(); + } else +#endif + { + invlpg(va1); + invlpg(va2); + } +} + static unsigned * get_ptbase(pmap) pmap_t pmap; @@ -1044,7 +1046,7 @@ pmap_dispose_proc(p) *(ptek + i) = 0; if ((oldpte & PG_G) || (cpu_class > CPUCLASS_386)) invlpg((vm_offset_t) p->p_addr + i * PAGE_SIZE); - vm_page_unwire(m, 0); + vm_page_unwire(m); vm_page_free(m); } @@ -1071,7 +1073,8 @@ pmap_swapout_proc(p) if ((m = vm_page_lookup(upobj, i)) == NULL) panic("pmap_swapout_proc: upage already missing???"); m->dirty = VM_PAGE_BITS_ALL; - vm_page_unwire(m, 0); + vm_page_unwire(m); + vm_page_deactivate(m); pmap_kremove( (vm_offset_t) p->p_addr + PAGE_SIZE * i); } } @@ -1121,6 +1124,7 @@ pmap_swapin_proc(p) */ static int _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m) { + int s; while (vm_page_sleep(m, "pmuwpt", NULL)); @@ -1251,6 +1255,7 @@ pmap_pinit(pmap) /* * allocate the page directory page */ +retry: ptdpg = vm_page_grab( pmap->pm_pteobj, PTDPTDI, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); @@ -1284,6 +1289,7 @@ pmap_release_free_page(pmap, p) struct pmap *pmap; vm_page_t p; { + int s; unsigned *pde = (unsigned *) pmap->pm_pdir; /* * This code optimizes the case of freeing non-busy @@ -1322,8 +1328,6 @@ pmap_release_free_page(pmap, p) if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) pmap->pm_ptphint = NULL; - p->wire_count--; - cnt.v_wire_count--; vm_page_free_zero(p); return 1; } @@ -1558,10 +1562,6 @@ pmap_growkernel(vm_offset_t addr) *pmap_pde(pmap, kernel_vm_end) = newpdir; } } - if (aiovmspace != NULL) { - pmap = &aiovmspace->vm_pmap; - *pmap_pde(pmap, kernel_vm_end) = newpdir; - } *pmap_pde(kernel_pmap, kernel_vm_end) = newpdir; kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); } @@ -2426,6 +2426,7 @@ pmap_object_init_pt(pmap, addr, object, pindex, size, limit) ((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0) ) { int i; + int s; vm_page_t m[1]; unsigned int ptepindex; int npdes; @@ -2818,7 +2819,7 @@ pmap_zero_page(phys) cpu_invlpg(&prv_CPAGE3); #if defined(I686_CPU) - if (cpu_class == CPUCLASS_686) + if (cpu == CPU_686) i686_pagezero(&prv_CPAGE3); else #endif @@ -2839,7 +2840,7 @@ pmap_zero_page(phys) } #if defined(I686_CPU) - if (cpu_class == CPUCLASS_686) + if (cpu == CPU_686) i686_pagezero(CADDR2); else #endif @@ -3193,7 +3194,7 @@ pmap_phys_address(ppn) int pmap_ts_referenced(vm_offset_t pa) { - register pv_entry_t pv, pvf, pvn; + register pv_entry_t pv; pv_table_t *ppv; unsigned *pte; int s; @@ -3214,11 +3215,9 @@ pmap_ts_referenced(vm_offset_t pa) /* * Not found, check current mappings returning immediately if found. */ - pvf = 0; - for (pv = TAILQ_FIRST(&ppv->pv_list); pv && pv != pvf; pv = pvn) { - if (!pvf) - pvf = pv; - pvn = TAILQ_NEXT(pv, pv_list); + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); /* @@ -3493,7 +3492,7 @@ pmap_pid_dump(int pid) { #if defined(DEBUG) static void pads __P((pmap_t pm)); -void pmap_pvdump __P((vm_offset_t pa)); +static void pmap_pvdump __P((vm_offset_t pa)); /* print address space of pmap*/ static void @@ -3520,7 +3519,7 @@ pads(pm) } -void +static void pmap_pvdump(pa) vm_offset_t pa; { diff --git a/sys/i386/include/i4b_tel_ioctl.h b/sys/i386/i386/setdef0.c index b7f0f73cd92a5..e57ce17f05156 100644 --- a/sys/i386/include/i4b_tel_ioctl.h +++ b/sys/i386/i386/setdef0.c @@ -1,5 +1,6 @@ -/* - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +/*- + * Copyright (c) 1997 John D. Polstra + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,31 +23,27 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - *--------------------------------------------------------------------------- - * - * i4b_tel_ioctl.h telephony interface ioctls - * ------------------------------------------ - * - * $Id: i4b_tel_ioctl.h,v 1.5 1998/12/14 10:31:58 hm Exp $ - * - * last edit-date: [Sat Dec 5 18:37:36 1998] - * - *---------------------------------------------------------------------------*/ + * $Id: setdef0.c,v 1.1 1997/04/22 06:55:28 jdp Exp $ + */ -#ifndef _I4B_TEL_IOCTL_H_ -#define _I4B_TEL_IOCTL_H_ +#ifdef __ELF__ -/* supported audio format conversions for /dev/i4btelXX devices */ +#include <sys/param.h> +#include <sys/kernel.h> -#define CVT_NONE 0 /* no format conversion */ -#define CVT_ALAW2ULAW 1 /* kernel A-law, userland mu-law */ - -/*---------------------------------------------------------------------------* - * get / set audio format - *---------------------------------------------------------------------------*/ +/* + * DEFINE_SET creates the section and label for a set, and emits the + * count word at the front of it. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".globl " #set); \ + __asm__(".type " #set ",@object"); \ + __asm__(".p2align 2"); \ + __asm__(#set ":"); \ + __asm__(".long " #count); \ + __asm__(".previous") -#define I4B_TEL_GETAUDIOFMT _IOR('A', 0, int) -#define I4B_TEL_SETAUDIOFMT _IOW('A', 1, int) -#define I4B_TEL_EMPTYINPUTQUEUE _IOW('A', 2, int) +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ -#endif /* _I4B_TEL_IOCTL_H_ */ +#endif /* __ELF__ */ diff --git a/sys/i386/isa/atkbdc_isa.c b/sys/i386/i386/setdef1.c index c547a405600b6..c9dd23458cdc0 100644 --- a/sys/i386/isa/atkbdc_isa.c +++ b/sys/i386/i386/setdef1.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp) + * Copyright (c) 1997 John D. Polstra * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,9 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,58 +23,19 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: $ + * $Id: setdef1.c,v 1.1 1997/04/22 06:55:28 jdp Exp $ */ -#include "atkbdc.h" -#include "opt_kbd.h" +#ifdef __ELF__ -#if NATKBDC > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> - -#include <dev/kbd/atkbdcreg.h> - -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> - -static int atkbdc_probe(struct isa_device *dev); -static int atkbdc_attach(struct isa_device *dev); - -struct isa_driver atkbdcdriver = { - atkbdc_probe, - atkbdc_attach, - ATKBDC_DRIVER_NAME, - 0, -}; - -static int -atkbdc_probe(struct isa_device *dev) -{ - atkbdc_softc_t *sc; - int error; - - sc = atkbdc_get_softc(dev->id_unit); - if (sc == NULL) - return 0; - - error = atkbdc_probe_unit(sc, dev->id_unit, dev->id_iobase); - if (error) - return 0; - if (dev->id_iobase <= 0) - dev->id_iobase = sc->port; - return IO_KBDSIZE; -} +/* + * DEFINE_SET emits the NULL terminator for a set. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".long 0"); \ + __asm__(".previous") -static int -atkbdc_attach(struct isa_device *dev) -{ - atkbdc_softc_t *sc; - - sc = atkbdc_get_softc(dev->id_unit); - return ((sc == NULL) ? 0 : 1); -} +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ -#endif /* NATKBDC > 0 */ +#endif /* __ELF__ */ diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 5ed5780c6a835..d1e77c8a4413b 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: support.s,v 1.59 1998/05/11 02:13:43 dyson Exp $ + * $Id: support.s,v 1.58 1997/12/14 02:11:09 dyson Exp $ */ #include "npx.h" @@ -398,6 +398,7 @@ ENTRY(fillw) ret ENTRY(bcopyb) +bcopyb: pushl %esi pushl %edi movl 12(%esp),%esi diff --git a/sys/i386/i386/swapgeneric.c b/sys/i386/i386/swapgeneric.c index 7cc6e4b029cf4..5575e6223f87d 100644 --- a/sys/i386/i386/swapgeneric.c +++ b/sys/i386/i386/swapgeneric.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)swapgeneric.c 5.5 (Berkeley) 5/9/91 - * $Id: swapgeneric.c,v 1.24 1998/09/15 10:03:43 gibbs Exp $ + * $Id: swapgeneric.c,v 1.23 1998/02/20 13:37:37 bde Exp $ */ #include <sys/param.h> @@ -138,8 +138,7 @@ bad: unit = 0; for (gc = genericconf; gc->gc_name; gc++) { for (bd = 0; bd < nblkdev; bd++) { - if (bdevsw[bd] != NULL && - strcmp(bdevsw[bd]->d_name, gc->gc_name) == 0) { + if (!strcmp(bdevsw[bd]->d_name, gc->gc_name)) { printf("root on %s0\n", bdevsw[bd]->d_name); goto found; } diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c index 63804abe0d469..0f569f25f1a42 100644 --- a/sys/i386/i386/sys_machdep.c +++ b/sys/i386/i386/sys_machdep.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 - * $Id: sys_machdep.c,v 1.37 1998/08/24 02:28:15 bde Exp $ + * $Id: sys_machdep.c,v 1.36 1998/08/18 07:46:58 msmith Exp $ * */ @@ -124,6 +124,7 @@ i386_extend_pcb(struct proc *p) int i, offset; u_long *addr; struct pcb_ext *ext; + struct segment_descriptor sd; struct soft_segment_descriptor ssd = { 0, /* segment base address (overwritten) */ ctob(IOPAGES + 1) - 1, /* length */ diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 42b0c85c23295..c4935d0160a76 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.132 1998/12/28 23:02:56 msmith Exp $ + * $Id: trap.c,v 1.127 1998/04/28 18:15:04 eivind Exp $ */ /* @@ -93,10 +93,6 @@ #include <machine/vm86.h> #endif -#ifdef DDB - extern int in_Debugger, debugger_on_panic; -#endif - #include "isa.h" #include "npx.h" @@ -108,8 +104,8 @@ extern void trap __P((struct trapframe frame)); extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); -static int trap_pfault __P((struct trapframe *, int, vm_offset_t)); -static void trap_fatal __P((struct trapframe *, vm_offset_t)); +static int trap_pfault __P((struct trapframe *, int)); +static void trap_fatal __P((struct trapframe *)); void dblfault_handler __P((void)); extern inthand_t IDTVEC(syscall); @@ -220,46 +216,9 @@ trap(frame) struct proc *p = curproc; u_quad_t sticks = 0; int i = 0, ucode = 0, type, code; - vm_offset_t eva; - - if (!(frame.tf_eflags & PSL_I)) { - /* - * Buggy application or kernel code has disabled interrupts - * and then trapped. Enabling interrupts now is wrong, but - * it is better than running with interrupts disabled until - * they are accidentally enabled later. - */ - type = frame.tf_trapno; - if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM)) - printf( - "pid %ld (%s): trap %d with interrupts disabled\n", - (long)curproc->p_pid, curproc->p_comm, type); - else if (type != T_BPTFLT && type != T_TRCTRAP) - /* - * XXX not quite right, since this may be for a - * multiple fault in user mode. - */ - printf("kernel trap %d with interrupts disabled\n", - type); - enable_intr(); - } - - eva = 0; - if (frame.tf_trapno == T_PAGEFLT) { - /* - * For some Cyrix CPUs, %cr2 is clobbered by interrupts. - * This problem is worked around by using an interrupt - * gate for the pagefault handler. We are finally ready - * to read %cr2 and then must reenable interrupts. - * - * XXX this should be in the switch statement, but the - * NO_FOOF_HACK and VM86 goto and ifdefs obfuscate the - * flow of control too much for this to be obviously - * correct. - */ - eva = rcr2(); - enable_intr(); - } +#ifdef DEBUG + u_long eva; +#endif #if defined(I586_CPU) && !defined(NO_F00F_HACK) restart: @@ -286,7 +245,7 @@ restart: */ case T_PROTFLT: case T_SEGNPFLT: - trap_fatal(&frame, eva); + trap_fatal(&frame); return; case T_TRCTRAP: type = T_BPTFLT; /* kernel breakpoint */ @@ -355,7 +314,7 @@ restart: break; case T_PAGEFLT: /* page fault */ - i = trap_pfault(&frame, TRUE, eva); + i = trap_pfault(&frame, TRUE); if (i == -1) return; #if defined(I586_CPU) && !defined(NO_F00F_HACK) @@ -434,7 +393,7 @@ kernel_trap: switch (type) { case T_PAGEFLT: /* page fault */ - (void) trap_pfault(&frame, FALSE, eva); + (void) trap_pfault(&frame, FALSE); return; case T_DNA: @@ -582,7 +541,7 @@ kernel_trap: #endif /* NISA > 0 */ } - trap_fatal(&frame, eva); + trap_fatal(&frame); return; } @@ -593,11 +552,12 @@ kernel_trap: 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", (u_long)eva); + uprintf(", fault VA = 0x%lx", eva); uprintf("\n"); } #endif @@ -615,16 +575,16 @@ out: * debugging code. */ static int -trap_pfault(frame, usermode, eva) +trap_pfault(frame, usermode) struct trapframe *frame; int usermode; - vm_offset_t eva; { 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) @@ -632,7 +592,9 @@ trap_pfault(frame, usermode, eva) else ftype = VM_PROT_READ; - va = trunc_page(eva); + eva = rcr2(); + va = trunc_page((vm_offset_t)eva); + if (va < VM_MIN_KERNEL_ADDRESS) { vm_offset_t v; vm_page_t mpte; @@ -641,7 +603,7 @@ trap_pfault(frame, usermode, eva) (!usermode && va < VM_MAXUSER_ADDRESS && (intr_nesting_level != 0 || curpcb == NULL || curpcb->pcb_onfault == NULL))) { - trap_fatal(frame, eva); + trap_fatal(frame); return (-1); } @@ -665,8 +627,8 @@ trap_pfault(frame, usermode, eva) /* * Grow the stack if necessary */ -#ifndef VM_STACK - if ((caddr_t)va > vm->vm_maxsaddr && va < USRSTACK) { + if ((caddr_t)va > vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; @@ -674,20 +636,6 @@ trap_pfault(frame, usermode, eva) } } -#else - /* grow_stack returns false only if va falls into - * a growable stack region and the stack growth - * fails. It returns true if va was not within - * a growable stack region, or if the stack - * growth succeeded. - */ - if (!grow_stack (p, va)) { - rv = KERN_FAILURE; - --p->p_lock; - goto nogo; - } -#endif - /* Fault in the user page: */ rv = vm_fault(map, va, ftype, (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY : 0); @@ -716,7 +664,7 @@ nogo: frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } - trap_fatal(frame, eva); + trap_fatal(frame); return (-1); } @@ -728,19 +676,21 @@ nogo: #endif int -trap_pfault(frame, usermode, eva) +trap_pfault(frame, usermode) struct trapframe *frame; int usermode; - vm_offset_t eva; { 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; - va = trunc_page(eva); + eva = rcr2(); + va = trunc_page((vm_offset_t)eva); + if (va >= KERNBASE) { /* * Don't allow user-mode faults in kernel address space. @@ -790,27 +740,14 @@ trap_pfault(frame, usermode, eva) /* * Grow the stack if necessary */ -#ifndef VM_STACK - if ((caddr_t)va > vm->vm_maxsaddr && va < USRSTACK) { + 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; } } -#else - /* grow_stack returns false only if va falls into - * a growable stack region and the stack growth - * fails. It returns true if va was not within - * a growable stack region, or if the stack - * growth succeeded. - */ - if (!grow_stack (p, va)) { - rv = KERN_FAILURE; - --p->p_lock; - goto nogo; - } -#endif /* Fault in the user page: */ rv = vm_fault(map, va, ftype, @@ -832,7 +769,7 @@ nogo: frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } - trap_fatal(frame, eva); + trap_fatal(frame); return (-1); } @@ -843,15 +780,15 @@ nogo: } static void -trap_fatal(frame, eva) +trap_fatal(frame) struct trapframe *frame; - vm_offset_t eva; { - int code, type, ss, esp; + 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) @@ -934,7 +871,7 @@ trap_fatal(frame, eva) return; #endif #ifdef DDB - if ((debugger_on_panic || in_Debugger) && kdb_trap(type, 0, frame)) + if (kdb_trap (type, 0, frame)) return; #endif printf("trap number = %d\n", type); @@ -998,19 +935,13 @@ int trapwrite(addr) ++p->p_lock; -#ifndef VM_STACK - if ((caddr_t)va >= vm->vm_maxsaddr && va < USRSTACK) { + if ((caddr_t)va >= vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { --p->p_lock; return (1); } } -#else - if (!grow_stack (p, va)) { - --p->p_lock; - return (1); - } -#endif /* * fault the data page diff --git a/sys/i386/i386/userconfig.c b/sys/i386/i386/userconfig.c index c505d71e0e79e..a6361ebaf7b18 100644 --- a/sys/i386/i386/userconfig.c +++ b/sys/i386/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.125 1999/01/14 23:43:22 bde Exp $ + ** $Id: userconfig.c,v 1.111 1998/10/06 07:34:26 msmith Exp $ **/ /** @@ -113,8 +113,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> @@ -133,156 +131,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 -{ - struct isa_device *id; - int error=0; - char name[8]; - - 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)); - } 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; - } - } - } + static char *next = userconfig_from_boot; - if (assize > 0) - { - /* Consume character from loaded userconfig script, display */ - 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 - 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; + if (next == userconfig_from_boot) { + if (strncmp(next, "USERCONFIG\n", 11)) { + next++; + strcpy(next, "intro\n"); } 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; + next += 11; } + } + if (*next) { + userconfig_boot_parsing = 1; + return (*next++); + } else { + userconfig_boot_parsing = 0; + 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) @@ -392,16 +270,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}, @@ -2066,17 +1938,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++) @@ -2516,7 +2386,7 @@ visuserconfig(void) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: userconfig.c,v 1.125 1999/01/14 23:43:22 bde Exp $ + * $Id: userconfig.c,v 1.111 1998/10/06 07:34:26 msmith Exp $ */ #include "scbus.h" @@ -2569,7 +2439,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 @@ -2607,12 +2477,10 @@ static CmdParm dev_parms[] = { { -1, {} }, }; -#if NPNP > 0 static CmdParm string_arg[] = { { PARM_STRING, {} }, { -1, {} }, }; -#endif #if NEISA > 0 static CmdParm int_arg[] = { @@ -2632,7 +2500,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 */ @@ -2661,6 +2529,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); @@ -2970,6 +2848,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 @@ -2977,6 +2856,7 @@ quitfunc(CmdParm *parms) */ if ((boothowto & RB_CONFIG) && userconfig_boot_parsing) return 0; +#endif return 1; } @@ -3019,7 +2899,7 @@ helpfunc(CmdParm *parms) return 0; } -#if defined(INTRO_USERCONFIG) +#if defined(USERCONFIG_BOOT) #if defined (VISUAL_USERCONFIG) static void @@ -3153,10 +3033,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; @@ -3185,14 +3062,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) @@ -3238,13 +3113,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/i386/i386/vm86.c b/sys/i386/i386/vm86.c index 3a536e2d9a6a7..eef835b188668 100644 --- a/sys/i386/i386/vm86.c +++ b/sys/i386/i386/vm86.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: vm86.c,v 1.18 1998/09/29 22:06:33 ache Exp $ + * $Id: vm86.c,v 1.17 1998/09/29 20:36:31 ache Exp $ */ #include "opt_vm86.h" @@ -359,6 +359,7 @@ vm86_initialize(void) struct vm86_layout *vml = (struct vm86_layout *)vm86paddr; struct pcb *pcb; struct pcb_ext *ext; + struct segment_descriptor sd; struct soft_segment_descriptor ssd = { 0, /* segment base address (overwritten) */ 0, /* length (overwritten) */ diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index d0bdc9393b55e..de8b52cc466b7 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -38,7 +38,7 @@ * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.114 1998/12/16 15:21:51 bde Exp $ + * $Id: vm_machdep.c,v 1.111 1998/09/28 03:34:39 tegge Exp $ */ #include "npx.h" @@ -507,7 +507,6 @@ cpu_reset_real() while(1); } -#ifndef VM_STACK /* * Grow the user stack to allow for 'sp'. This version grows the stack in * chunks of SGROWSIZ. @@ -521,10 +520,10 @@ grow(p, sp) caddr_t v; struct vmspace *vm = p->p_vmspace; - if ((caddr_t)sp <= vm->vm_maxsaddr || sp >= USRSTACK) - return (1); + if ((caddr_t)sp <= vm->vm_maxsaddr || (unsigned)sp >= (unsigned)USRSTACK) + return (1); - nss = roundup(USRSTACK - sp, PAGE_SIZE); + nss = roundup(USRSTACK - (unsigned)sp, PAGE_SIZE); if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur) return (0); @@ -560,27 +559,10 @@ grow(p, sp) return (1); } -#else -int -grow_stack(p, sp) - struct proc *p; - u_int sp; -{ - int rv; - - rv = vm_map_growstack (p, sp); - if (rv != KERN_SUCCESS) - return (0); - - return (1); -} -#endif - static int cnt_prezero; -SYSCTL_INT(_vm_stats_misc, OID_AUTO, - cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, ""); /* * Implement the pre-zeroed page mechanism. diff --git a/sys/i386/ibcs2/ibcs2_errno.c b/sys/i386/ibcs2/ibcs2_errno.c index b2e78c9053b55..657985926eadc 100644 --- a/sys/i386/ibcs2/ibcs2_errno.c +++ b/sys/i386/ibcs2/ibcs2_errno.c @@ -29,10 +29,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/errno.h> #include <i386/ibcs2/ibcs2_errno.h> -int bsd_to_ibcs2_errno[ELAST + 1] = { +int bsd_to_ibcs2_errno[] = { 0, /* 0 */ IBCS2_EPERM, /* 1 */ IBCS2_ENOENT, /* 2 */ @@ -117,8 +116,5 @@ int bsd_to_ibcs2_errno[ELAST + 1] = { 0, /* 81 */ IBCS2_EIDRM, /* 82 */ IBCS2_ENOMSG, /* 83 */ - IBCS2_EOVERFLOW, /* 84 */ - 0, /* 85 */ - IBCS2_EILSEQ, /* 86 */ }; diff --git a/sys/i386/ibcs2/ibcs2_socksys.c b/sys/i386/ibcs2/ibcs2_socksys.c index c7f109a3cb9d0..e52bd2cdf7420 100644 --- a/sys/i386/ibcs2/ibcs2_socksys.c +++ b/sys/i386/ibcs2/ibcs2_socksys.c @@ -146,7 +146,7 @@ ibcs2_getipdomainname(p, uap) int len; /* Get the domain name */ - snprintf(hname, sizeof(hname), "%s", hostname); + strcpy(hname, hostname); dptr = index(hname, '.'); if ( dptr ) dptr++; @@ -177,7 +177,7 @@ ibcs2_setipdomainname(p, uap) return EINVAL; /* Get the host's unqualified name (strip off the domain) */ - snprintf(hname, sizeof(hname), "%s", hostname); + strcpy(hname, hostname); ptr = index(hname, '.'); if ( ptr != NULL ) { ptr++; diff --git a/sys/i386/ibcs2/ibcs2_stat.c b/sys/i386/ibcs2/ibcs2_stat.c index d3bf6ae077d27..febf4d2552d88 100644 --- a/sys/i386/ibcs2/ibcs2_stat.c +++ b/sys/i386/ibcs2/ibcs2_stat.c @@ -221,19 +221,20 @@ ibcs2_utssys(p, uap) struct ibcs2_utsname sut; bzero(&sut, ibcs2_utsname_len); - strncpy(sut.sysname, - IBCS2_UNAME_SYSNAME, sizeof(sut.sysname) - 1); - strncpy(sut.release, - IBCS2_UNAME_RELEASE, sizeof(sut.release) - 1); - strncpy(sut.version, - IBCS2_UNAME_VERSION, sizeof(sut.version) - 1); - strncpy(machine_name, hostname, sizeof(machine_name) - 1); - machine_name[sizeof(machine_name) - 1] = 0; + strncpy(sut.sysname, IBCS2_UNAME_SYSNAME, sizeof(sut.sysname)); + strncpy(sut.release, IBCS2_UNAME_RELEASE, sizeof(sut.release)); + strncpy(sut.version, IBCS2_UNAME_VERSION, sizeof(sut.version)); + strncpy(machine_name, hostname, sizeof(machine_name)); p = index(machine_name, '.'); if ( p ) *p = '\0'; - strncpy(sut.nodename, machine_name, sizeof(sut.nodename) - 1); - strncpy(sut.machine, machine, sizeof(sut.machine) - 1); + strncpy(sut.nodename, machine_name, sizeof(sut.nodename)); + strncpy(sut.machine, machine, sizeof(sut.machine)); + sut.sysname[sizeof(sut.sysname)-1] = '\0'; + sut.release[sizeof(sut.release)-1] = '\0'; + sut.version[sizeof(sut.version)-1] = '\0'; + sut.nodename[sizeof(sut.nodename)-1] = '\0'; + sut.machine[sizeof(sut.machine)-1] = '\0'; DPRINTF(("IBCS2 uname: sys=%s rel=%s ver=%s node=%s mach=%s\n", sut.sysname, sut.release, sut.version, sut.nodename, diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index bc0fa61e3bdeb..2a10b0e1eaae2 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -27,12 +27,10 @@ * (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: ibcs2_sysvec.c,v 1.12 1998/12/14 18:53:47 dt Exp $ + * $Id: ibcs2_sysvec.c,v 1.7 1998/04/28 18:15:05 eivind Exp $ */ #include <sys/param.h> -#include <sys/kernel.h> -#include <sys/module.h> #include <sys/sysent.h> #include <sys/signalvar.h> #include <i386/ibcs2/ibcs2_syscall.h> @@ -49,7 +47,7 @@ struct sysentvec ibcs2_svr3_sysvec = { 0xFF, NSIG, bsd_to_ibcs2_sig, - ELAST + 1, + ELAST, bsd_to_ibcs2_errno, 0, /* trap-to-signal translation function */ 0, /* fixup */ @@ -60,20 +58,3 @@ struct sysentvec ibcs2_svr3_sysvec = { "IBCS2 COFF", NULL /* we don't have a COFF coredump function */ }; - -/* - * Create an "ibcs2" module that does nothing but allow checking for - * the presence of the subsystem. - */ -static int -ibcs2_modevent(module_t mod, int type, void *unused) -{ - /* Do not care */ - return 0; -} -moduledata_t ibcs2_mod = { - "ibcs2", - ibcs2_modevent, - 0 -}; -DECLARE_MODULE(ibcs2, ibcs2_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); diff --git a/sys/i386/ibcs2/ibcs2_util.h b/sys/i386/ibcs2/ibcs2_util.h index 4ef390f64ffbe..e616234cb245c 100644 --- a/sys/i386/ibcs2/ibcs2_util.h +++ b/sys/i386/ibcs2/ibcs2_util.h @@ -61,7 +61,7 @@ static __inline caddr_t stackgap_init() { #define szsigcode (*(curproc->p_sysent->sv_szsigcode)) - return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE); + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); } static __inline void * diff --git a/sys/i386/ibcs2/ibcs2_xenix.c b/sys/i386/ibcs2/ibcs2_xenix.c index 8ab55563384e5..0677edec6a2f3 100644 --- a/sys/i386/ibcs2/ibcs2_xenix.c +++ b/sys/i386/ibcs2/ibcs2_xenix.c @@ -27,7 +27,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: ibcs2_xenix.c,v 1.16 1998/08/16 01:21:49 bde Exp $ + * $Id: ibcs2_xenix.c,v 1.15 1998/06/02 05:39:07 dyson Exp $ */ #include <sys/param.h> @@ -157,22 +157,14 @@ xenix_utsname(struct proc *p, struct xenix_utsname_args *uap) DPRINTF(("IBCS2: 'xenix sco_utsname'\n")); bzero(&ibcs2_sco_uname, sizeof(struct ibcs2_sco_utsname)); - strncpy(ibcs2_sco_uname.sysname, ostype, - sizeof(ibcs2_sco_uname.sysname) - 1); - strncpy(ibcs2_sco_uname.nodename, hostname, - sizeof(ibcs2_sco_uname.nodename) - 1); - strncpy(ibcs2_sco_uname.release, osrelease, - sizeof(ibcs2_sco_uname.release) - 1); - strncpy(ibcs2_sco_uname.kernelid, version, - sizeof(ibcs2_sco_uname.kernelid) - 1); - strncpy(ibcs2_sco_uname.machine, machine, - sizeof(ibcs2_sco_uname.machine) - 1); - strncpy(ibcs2_sco_uname.bustype, "ISA/EISA", - sizeof(ibcs2_sco_uname.bustype) - 1); - strncpy(ibcs2_sco_uname.sysserial, "no charge", - sizeof(ibcs2_sco_uname.sysserial) - 1); - strncpy(ibcs2_sco_uname.numusers, "unlim", - sizeof(ibcs2_sco_uname.numusers) - 1); + strncpy(ibcs2_sco_uname.sysname, ostype, 8); + strncpy(ibcs2_sco_uname.nodename, hostname, 8); + strncpy(ibcs2_sco_uname.release, osrelease, 15); + strncpy(ibcs2_sco_uname.kernelid, version, 19); + strncpy(ibcs2_sco_uname.machine, machine, 8); + bcopy("ISA/EISA", ibcs2_sco_uname.bustype, 8); + bcopy("no charge", ibcs2_sco_uname.sysserial, 9); + bcopy("unlim", ibcs2_sco_uname.numusers, 8); ibcs2_sco_uname.sysorigin = 0xFFFF; ibcs2_sco_uname.sysoem = 0xFFFF; ibcs2_sco_uname.numcpu = 1; diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c index 3632b7415e3d1..7793f4cc42a56 100644 --- a/sys/i386/ibcs2/imgact_coff.c +++ b/sys/i386/ibcs2/imgact_coff.c @@ -26,7 +26,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: imgact_coff.c,v 1.33 1998/10/16 03:55:00 peter Exp $ + * $Id: imgact_coff.c,v 1.32 1998/10/13 08:24:36 dg Exp $ */ #include <sys/param.h> @@ -475,7 +475,7 @@ exec_coff_imgact(imgp) /* * Tell kern_execve.c about it, with a little help from the linker. * Since `const' objects end up in the text segment, TEXT_SET is the - * correct directive to use. + * correct directive to use. Do not staticize; used by coff LKM. */ -static const struct execsw coff_execsw = { exec_coff_imgact, "coff" }; +const struct execsw coff_execsw = { exec_coff_imgact, "coff" }; EXEC_SET(coff, coff_execsw); diff --git a/sys/i386/include/ansi.h b/sys/i386/include/ansi.h index 9d7494e0fc120..52dad0bf856d6 100644 --- a/sys/i386/include/ansi.h +++ b/sys/i386/include/ansi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ansi.h 8.2 (Berkeley) 1/4/94 - * $Id: ansi.h,v 1.15 1998/06/14 14:00:47 bde Exp $ + * $Id: ansi.h,v 1.14 1998/01/08 00:27:30 alex Exp $ */ #ifndef _MACHINE_ANSI_H_ @@ -54,6 +54,9 @@ #define _BSD_SSIZE_T_ int /* byte count or error */ #define _BSD_TIME_T_ long /* time()... */ #define _BSD_TIMER_T_ int /* timer_gettime()... */ +#define _BSD_UINT8_T_ unsigned char /* unsigned exactly 8 bits */ +#define _BSD_UINT16_T_ unsigned short /* unsigned exactly 16 bits */ +#define _BSD_UINT32_T_ unsigned int /* unsigned exactly 32 bits */ #define _BSD_WCHAR_T_ _BSD_CT_RUNE_T_ /* wchar_t (see below) */ /* @@ -106,18 +109,5 @@ typedef unsigned int __attribute__((__mode__(__DI__))) __uint64_t; typedef long long __int64_t; typedef unsigned long long __uint64_t; #endif -/* - * Internal names for basic integral types. Omit the typedef if - * not possible for a machine/compiler combination. - */ -typedef __signed char __int8_t; -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; - -typedef int __intptr_t; -typedef unsigned int __uintptr_t; #endif /* !_MACHINE_ANSI_H_ */ diff --git a/sys/i386/include/apm_bios.h b/sys/i386/include/apm_bios.h index 43028b370113e..616e36a2e894d 100644 --- a/sys/i386/include/apm_bios.h +++ b/sys/i386/include/apm_bios.h @@ -12,7 +12,7 @@ * * Aug, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm_bios.h,v 1.20 1998/07/06 06:29:05 imp Exp $ + * $Id: apm_bios.h,v 1.19 1997/11/12 04:12:51 jdp Exp $ */ #ifndef _MACHINE_APM_BIOS_H_ @@ -160,6 +160,7 @@ struct apmhook *apm_hook_establish (int apmh, struct apmhook *); void apm_hook_disestablish (int apmh, struct apmhook *); void apm_cpu_idle(void); void apm_cpu_busy(void); +void apm_power_off(void); #endif /* KERNEL */ diff --git a/sys/i386/include/console.h b/sys/i386/include/console.h index c79759c356bd8..7f70bcaa052bb 100644 --- a/sys/i386/include/console.h +++ b/sys/i386/include/console.h @@ -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: console.h,v 1.42 1999/01/01 14:38:28 des Exp $ + * $Id: console.h,v 1.40 1998/09/23 09:58:45 yokota Exp $ */ #ifndef _MACHINE_CONSOLE_H_ @@ -52,7 +52,6 @@ #define KDSETLED _IO('K', 66 /*, int */) #define KDSETRAD _IO('K', 67 /*, int */) #define KDRASTER _IOW('K', 100, scr_size_t) -#define KDGKBINFO _IOR('K', 101, keyboard_info_t) #define GETFKEY _IOWR('k', 0, fkeyarg_t) #define SETFKEY _IOWR('k', 1, fkeyarg_t) @@ -62,8 +61,6 @@ #define PIO_KEYMAP _IOW('k', 7, keymap_t) #define GIO_DEADKEYMAP _IOR('k', 8, accentmap_t) #define PIO_DEADKEYMAP _IOW('k', 9, accentmap_t) -#define GIO_KEYMAPENT _IOWR('k', 10, keyarg_t) -#define PIO_KEYMAPENT _IOW('k', 11, keyarg_t) #define GIO_ATTR _IOR('a', 0, int) #define GIO_COLOR _IOR('c', 0, int) @@ -89,14 +86,11 @@ #define CONS_GETINFO _IOWR('c', 73, vid_info_t) #define CONS_GETVERS _IOR('c', 74, int) #define CONS_CURRENTADP _IOR('c', 100, int) -#define CONS_ADPINFO _IOWR('c', 101, video_adapter_info_t) +#define CONS_ADPINFO _IOWR('c', 101, video_adapter_t) #define CONS_MODEINFO _IOWR('c', 102, video_info_t) #define CONS_FINDMODE _IOWR('c', 103, video_info_t) #define CONS_SETWINORG _IO('c', 104 /* u_int */) -#define CONS_SETKBD _IO('c', 110 /* int */) -#define CONS_RELKBD _IO('c', 111) - /* CONS_SAVERMODE */ #define CONS_LKM_SAVER 0 #define CONS_USR_SAVER 1 @@ -195,11 +189,9 @@ struct mouse_info { #define NLKED 2 /* Num locked */ #define SLKED 4 /* Scroll locked */ #define ALKED 8 /* AltGr locked */ -#define LOCK_MASK (CLKED | NLKED | SLKED | ALKED) #define LED_CAP 1 /* Caps lock LED */ #define LED_NUM 2 /* Num lock LED */ #define LED_SCR 4 /* Scroll lock LED */ -#define LED_MASK (LED_CAP | LED_NUM | LED_SCR) /* possible flag values */ #define FLAG_LOCK_O 0 @@ -212,7 +204,7 @@ struct mouse_info { #ifndef _KEYMAP_DECLARED #define _KEYMAP_DECLARED -struct keyent_t { +struct key_t { u_char map[NUM_STATES]; u_char spcl; u_char flgs; @@ -220,17 +212,10 @@ struct keyent_t { struct keymap { u_short n_keys; - struct keyent_t key[NUM_KEYS]; + struct key_t key[NUM_KEYS]; }; typedef struct keymap keymap_t; - -struct keyarg { - u_short keynum; - struct keyent_t key; -}; - -typedef struct keyarg keyarg_t; #endif /* !_KEYMAP_DECLARED */ #define NUM_DEADKEYS 15 /* number of accent keys */ @@ -289,9 +274,6 @@ struct ssaver { struct video_adapter { int va_index; int va_type; - char *va_name; - int va_unit; - int va_minor; int va_flags; #define V_ADP_COLOR (1<<0) #define V_ADP_MODECHANGE (1<<1) @@ -301,14 +283,7 @@ struct video_adapter { #define V_ADP_PALETTE (1<<5) #define V_ADP_BORDER (1<<6) #define V_ADP_VESA (1<<7) -#define V_ADP_PROBED (1<<16) -#define V_ADP_INITIALIZED (1<<17) -#define V_ADP_REGISTERED (1<<18) - int va_io_base; - int va_io_size; int va_crtc_addr; - int va_mem_base; - int va_mem_size; u_int va_window; /* virtual address */ size_t va_window_size; size_t va_window_gran; @@ -317,30 +292,6 @@ struct video_adapter { int va_initial_mode; int va_initial_bios_mode; int va_mode; - int va_mode_flags; /* copy of vi_flags */ - void *va_token; -}; - -struct video_adapter_info { - int va_index; - int va_type; - char va_name[16]; - int va_unit; - int va_flags; - int va_io_base; - int va_io_size; - int va_crtc_addr; - int va_mem_base; - int va_mem_size; - 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; - int va_mode_flags; }; #define V_ADP_PRIMARY 0 @@ -352,7 +303,7 @@ struct video_info { int vi_flags; #define V_INFO_COLOR (1<<0) #define V_INFO_GRAPHICS (1<<1) -#define V_INFO_LINEAR (1<<2) +#define V_INFO_LENEAR (1<<2) #define V_INFO_VESA (1<<3) int vi_width; int vi_height; @@ -368,15 +319,6 @@ struct video_info { /* XXX pixel format, memory model,... */ }; -struct keyboard_info { - int kb_index; /* kbdio index# */ - char kb_name[16]; /* driver name */ - int kb_unit; /* unit# */ - int kb_type; /* KB_84, KB_101, KB_OTHER,... */ - int kb_config; /* device configuration flags */ - int kb_flags; /* internal flags */ -}; - typedef struct accentmap accentmap_t; typedef struct fkeytab fkeytab_t; typedef struct fkeyarg fkeyarg_t; @@ -388,9 +330,7 @@ typedef struct {char fnt8x14[14*256];} fnt14_t; typedef struct {char fnt8x16[16*256];} fnt16_t; typedef struct ssaver ssaver_t; typedef struct video_adapter video_adapter_t; -typedef struct video_adapter_info video_adapter_info_t; typedef struct video_info video_info_t; -typedef struct keyboard_info keyboard_info_t; typedef struct {int scr_size[3];} scr_size_t; /* defines for "special" keys (spcl bit set in keymap) */ @@ -448,13 +388,6 @@ typedef struct {int scr_size[3];} scr_size_t; #define MKEY 0x400 /* meta key marker (prepend ESC)*/ #define BKEY 0x800 /* backtab (ESC [ Z) */ -#define SPCLKEY 0x8000 /* special key */ -#define RELKEY 0x4000 /* key released */ -#define ERRKEY 0x2000 /* error */ - -#define KEYCHAR(c) ((c) & 0x00ff) -#define KEYFLAGS(c) ((c) & ~0x00ff) - /* video mode definitions */ #define M_B40x25 0 /* black & white 40 columns */ #define M_C40x25 1 /* color 40 columns */ diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index ce6bf05890017..977003cb5c238 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cpufunc.h,v 1.84 1999/01/08 19:51:02 bde Exp $ + * $Id: cpufunc.h,v 1.80 1998/07/11 04:58:25 bde Exp $ */ /* @@ -40,6 +40,15 @@ #ifndef _MACHINE_CPUFUNC_H_ #define _MACHINE_CPUFUNC_H_ +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <machine/lock.h> + +#if defined(SWTCH_OPTIM_STATS) +extern int tlb_flush_count; +#endif + #define readb(va) (*(volatile u_int8_t *) (va)) #define readw(va) (*(volatile u_int16_t *) (va)) #define readl(va) (*(volatile u_int32_t *) (va)) @@ -50,14 +59,6 @@ #ifdef __GNUC__ -#ifdef SMP -#include <machine/lock.h> /* XXX */ -#endif - -#ifdef SWTCH_OPTIM_STATS -extern int tlb_flush_count; /* XXX */ -#endif - static __inline void breakpoint(void) { @@ -68,17 +69,13 @@ static __inline void disable_intr(void) { __asm __volatile("cli" : : : "memory"); -#ifdef SMP MPINTR_LOCK(); -#endif } static __inline void enable_intr(void) { -#ifdef SMP MPINTR_UNLOCK(); -#endif __asm __volatile("sti"); } @@ -194,27 +191,24 @@ static __inline void insb(u_int port, void *addr, size_t cnt) { __asm __volatile("cld; rep; insb" - : "=D" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port) - : "memory"); + : : "d" (port), "D" (addr), "c" (cnt) + : "di", "cx", "memory"); } static __inline void insw(u_int port, void *addr, size_t cnt) { __asm __volatile("cld; rep; insw" - : "=D" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port) - : "memory"); + : : "d" (port), "D" (addr), "c" (cnt) + : "di", "cx", "memory"); } static __inline void insl(u_int port, void *addr, size_t cnt) { __asm __volatile("cld; rep; insl" - : "=D" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port) - : "memory"); + : : "d" (port), "D" (addr), "c" (cnt) + : "di", "cx", "memory"); } static __inline void @@ -223,11 +217,11 @@ invd(void) __asm __volatile("invd"); } -#if defined(SMP) && defined(KERNEL) +#ifdef KERNEL +#ifdef SMP /* - * When using APIC IPI's, invlpg() is not simply the invlpg instruction - * (this is a bug) and the inlining cost is prohibitive since the call + * When using APIC IPI's, the inlining cost is prohibitive since the call * executes into the IPI transmission system. */ void invlpg __P((u_int addr)); @@ -236,7 +230,7 @@ void invltlb __P((void)); static __inline void cpu_invlpg(void *addr) { - __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); + __asm __volatile("invlpg %0"::"m"(*(char *)addr):"memory"); } static __inline void @@ -253,15 +247,15 @@ cpu_invltlb(void) ++tlb_flush_count; #endif } - -#else /* !(SMP && KERNEL) */ +#else /* !SMP */ static __inline void invlpg(u_int addr) { - __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); + __asm __volatile("invlpg %0"::"m"(*(char *)addr):"memory"); } + static __inline void invltlb(void) { @@ -272,12 +266,13 @@ invltlb(void) */ __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp) : : "memory"); -#ifdef SWTCH_OPTIM_STATS +#if defined(SWTCH_OPTIM_STATS) ++tlb_flush_count; #endif } -#endif /* SMP && KERNEL */ +#endif /* SMP */ +#endif /* KERNEL */ static __inline u_short inw(u_int port) @@ -327,24 +322,24 @@ static __inline void outsb(u_int port, const void *addr, size_t cnt) { __asm __volatile("cld; rep; outsb" - : "=S" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port)); + : : "d" (port), "S" (addr), "c" (cnt) + : "si", "cx"); } static __inline void outsw(u_int port, const void *addr, size_t cnt) { __asm __volatile("cld; rep; outsw" - : "=S" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port)); + : : "d" (port), "S" (addr), "c" (cnt) + : "si", "cx"); } static __inline void outsl(u_int port, const void *addr, size_t cnt) { __asm __volatile("cld; rep; outsl" - : "=S" (addr), "=c" (cnt) - : "0" (addr), "1" (cnt), "d" (port)); + : : "d" (port), "S" (addr), "c" (cnt) + : "si", "cx"); } static __inline void @@ -399,7 +394,7 @@ rdtsc(void) } static __inline void -setbits(volatile u_int *addr, u_int bits) +setbits(volatile unsigned *addr, u_int bits) { __asm __volatile( #ifdef SMP @@ -452,7 +447,7 @@ u_int64_t rdmsr __P((u_int msr)); u_int64_t rdpmc __P((u_int pmc)); u_int64_t rdtsc __P((void)); u_int read_eflags __P((void)); -void setbits __P((volatile u_int *addr, u_int bits)); +void setbits __P((volatile unsigned *addr, u_int bits)); void wbinvd __P((void)); void write_eflags __P((u_int ef)); void wrmsr __P((u_int msr, u_int64_t newval)); @@ -466,5 +461,6 @@ void ltr __P((u_short sel)); u_int rcr0 __P((void)); u_int rcr3 __P((void)); u_int rcr4 __P((void)); +void i686_pagezero __P((void *addr)); #endif /* !_MACHINE_CPUFUNC_H_ */ diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h index 93f486bf2d021..5605b6fb3f84b 100644 --- a/sys/i386/include/elf.h +++ b/sys/i386/include/elf.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elf.h,v 1.4 1998/09/14 20:30:12 jdp Exp $ + * $Id: elf.h,v 1.3 1998/08/16 03:03:31 jdp Exp $ */ #ifndef _MACHINE_ELF_H_ @@ -40,8 +40,6 @@ #define ELF_ARCH EM_386 -#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) - /* * Auxiliary vector entries for passing information to the interpreter. * diff --git a/sys/i386/include/i4b_cause.h b/sys/i386/include/i4b_cause.h deleted file mode 100644 index 439db4e2bcc4b..0000000000000 --- a/sys/i386/include/i4b_cause.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *--------------------------------------------------------------------------- - * - * i4b_cause.h - causes and cause handling for i4b - * ----------------------------------------------- - * - * $Id: i4b_cause.h,v 1.8 1998/12/05 18:05:55 hm Exp $ - * - * last edit-date: [Sat Dec 5 18:36:30 1998] - * - *---------------------------------------------------------------------------*/ - -#ifndef _I4B_CAUSE_H_ -#define _I4B_CAUSE_H_ - -/*---------------------------------------------------------------------------* - * ISDN4BSD internal causes specification - *---------------------------------------------------------------------------*/ - -#define CAUSE_VAL 0x000000ff /* cause value */ -#define CAUSE_TYPE 0x0000ff00 /* cause type */ -#define CAUSET_Q850 0 /* value coded according to Q.850 */ -#define CAUSET_I4B 1 /* i4b protocol independent causes*/ - -#define GET_CAUSE_VAL(cause) ((cause) & 0xff) -#define SET_CAUSE_VAL(dest, val) ((dest) = ((dest & 0xffffff00) | \ - (val & 0x000000ff))) - -#define GET_CAUSE_TYPE(cause) (((cause) >> 8) & 0xff) -#define SET_CAUSE_TYPE(dest, type) ((dest) = ((dest & 0xffff00ff) | \ - ((type << 8) & 0x0000ff00))) - -#define SET_CAUSE_TV(dest, type, val) ((dest) = ((val & 0x000000ff) | \ - ((type << 8) & 0x0000ff00))) - -/* CAUSET_I4B - protocol independent cause values */ - -#define CAUSE_I4B_NORMAL 0 /* normal call clearing */ -#define CAUSE_I4B_BUSY 1 /* user busy */ -#define CAUSE_I4B_NOCHAN 2 /* circuit/channel not available*/ -#define CAUSE_I4B_INCOMP 3 /* incompatible source/dest */ -#define CAUSE_I4B_REJECT 4 /* call rejected */ -#define CAUSE_I4B_OOO 5 /* destination out of order */ -#define CAUSE_I4B_TMPFAIL 6 /* temporary failure */ -#define CAUSE_I4B_L1ERROR 7 /* L1 error / persistent deact */ -#define CAUSE_I4B_MAX 8 - -/* CAUSET_Q850 - causes defined in Q.850 */ - -#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */ -#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */ -#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */ -#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */ -#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */ -#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */ -#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */ -#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */ -#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */ -#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */ -#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */ -#define CAUSE_Q850_USRBSY 0x11 /* User busy */ -#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */ -#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */ -#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */ -#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */ -#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */ -#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */ -#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */ -#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */ -#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */ -#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */ -#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */ -#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */ -#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */ -#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */ -#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */ -#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */ -#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */ -#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */ -#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */ -#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */ -#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */ -#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */ -#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */ -#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */ -#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */ -#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */ -#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */ -#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */ -#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */ -#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */ -#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */ -#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */ -#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */ -#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */ -#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */ -#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */ -#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */ -#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */ -#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */ -#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */ -#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */ -#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */ -#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */ -#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */ -#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */ -#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */ -#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */ -#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */ -#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */ -#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */ -#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */ -#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */ -#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */ -#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */ -#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */ -#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */ - -#define CAUSE_Q850_MAX 128 - -#endif /* _I4B_CAUSE_H_ */ diff --git a/sys/i386/include/i4b_debug.h b/sys/i386/include/i4b_debug.h deleted file mode 100644 index 33e6315ba285a..0000000000000 --- a/sys/i386/include/i4b_debug.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *--------------------------------------------------------------------------- - * - * i4b_debug.h - i4b debug header file - * ----------------------------------- - * - * $Id: i4b_debug.h,v 1.14 1998/12/05 18:05:57 hm Exp $ - * - * last edit-date: [Sat Dec 5 18:36:47 1998] - * - *---------------------------------------------------------------------------*/ - -#define DO_I4B_DEBUG /* enable debugging code inclusion */ - -#undef DO_I4B_MAXDEBUG /* enable ALL debug messages by default */ - -#ifdef DO_I4B_DEBUG - -extern unsigned int i4b_l1_debug; -extern unsigned int i4b_l2_debug; -extern unsigned int i4b_l3_debug; -extern unsigned int i4b_l4_debug; - -#define DBGL1(bits, routine, what) \ - if(bits & i4b_l1_debug) \ - { \ - printf("i4b-L1-%s: ", routine); \ - printf what ; \ - } - -#define DBGL2(bits, routine, what) \ - if(bits & i4b_l2_debug) \ - { \ - printf("i4b-L2-%s: ", routine); \ - printf what ; \ - } - -#define DBGL3(bits, routine, what) \ - if(bits & i4b_l3_debug) \ - { \ - printf("i4b-L3-%s: ", routine); \ - printf what ; \ - } - -#define DBGL4(bits, routine, what) \ - if(bits & i4b_l4_debug) \ - { \ - printf("i4b-L4-%s: ", routine); \ - printf what ; \ - } -#else /* !DO_I4B_DEBUG */ - -#define DBGL1(bits, routine, what); -#define DBGL2(bits, routine, what); -#define DBGL3(bits, routine, what); -#define DBGL4(bits, routine, what); - -#endif /* DO_I4B_DEBUG */ - -/* Layer 1 */ - -#define L1_ERROR 0x0001 /* general error message*/ -#define L1_PRIM 0x0002 /* interlayer primitives*/ -#define L1_BCHAN 0x0004 /* B channel action */ -#define L1_H_ERR 0x0008 /* HSCX errors */ -#define L1_H_IRQ 0x0010 /* HSCX IRQ messages */ -#define L1_I_ERR 0x0020 /* ISAC errors */ -#define L1_I_MSG 0x0040 /* ISAC messages */ -#define L1_I_SETUP 0x0080 /* ISAC setup messages */ -#define L1_F_MSG 0x0100 /* FSM messages */ -#define L1_F_ERR 0x0200 /* FSM error messages */ -#define L1_T_MSG 0x0400 /* Timer messages */ -#define L1_T_ERR 0x0800 /* Timer error messages */ -#define L1_H_XFRERR 0x1000 /* HSCX data xfer error */ -#define L1_I_CICO 0x2000 /* ISAC command in/out */ - -#define L1_DEBUG_MAX 0x3fef /* all messages on except IRQ! */ -#define L1_DEBUG_ERR (L1_H_ERR | L1_I_ERR | L1_F_ERR | L1_T_ERR | L1_ERROR) - -#ifndef L1_DEBUG_DEFAULT -#ifdef DO_I4B_MAXDEBUG -#define L1_DEBUG_DEFAULT L1_DEBUG_MAX -#else -#define L1_DEBUG_DEFAULT L1_DEBUG_ERR -#endif -#endif - -/* Layer 2 */ - -#define L2_ERROR 0x0001 /* general error message */ -#define L2_PRIM 0x0002 /* interlayer primitives */ -#define L2_U_MSG 0x0004 /* U frame messages */ -#define L2_U_ERR 0x0008 /* U frame error messages */ -#define L2_S_MSG 0x0010 /* S frame messages */ -#define L2_S_ERR 0x0020 /* S frame error messages */ -#define L2_I_MSG 0x0040 /* I frame messages */ -#define L2_I_ERR 0x0080 /* I frame error messages */ -#define L2_F_MSG 0x0100 /* FSM messages */ -#define L2_F_ERR 0x0200 /* FSM error messages */ -#define L2_T_MSG 0x0400 /* timer messages */ -#define L2_T_ERR 0x0800 /* timer error messages */ -#define L2_TEI_MSG 0x1000 /* TEI messages */ -#define L2_TEI_ERR 0x2000 /* TEI error messages */ - -#define L2_DEBUG_MAX 0x3fff /* all messages on */ -#define L2_DEBUG_ERR (L2_ERROR | L2_I_ERR | L2_F_ERR | L2_T_ERR | L2_S_ERR | L2_TEI_ERR | L2_U_ERR ) - -#ifndef L2_DEBUG_DEFAULT -#ifdef DO_I4B_MAXDEBUG -#define L2_DEBUG_DEFAULT L2_DEBUG_MAX -#else -#define L2_DEBUG_DEFAULT L2_DEBUG_ERR -#endif -#endif - -/* Layer 3 */ - -#define L3_ERR 0x0001 /* general error message */ -#define L3_MSG 0x0002 /* general message */ -#define L3_F_MSG 0x0004 /* FSM messages */ -#define L3_F_ERR 0x0008 /* FSM error messages */ -#define L3_T_MSG 0x0010 /* timer messages */ -#define L3_T_ERR 0x0020 /* timer error messages */ -#define L3_P_MSG 0x0040 /* protocol messages */ -#define L3_P_ERR 0x0080 /* protocol error messages */ -#define L3_A_MSG 0x0100 /* AOC messages */ -#define L3_A_ERR 0x0200 /* AOC error messages */ -#define L3_PRIM 0x0400 /* messages exchanged */ - -#define L3_DEBUG_MAX 0x07ff /* all messages on */ -#define L3_DEBUG_ERR (L3_ERR | L3_F_ERR | L3_T_ERR | L3_P_ERR | L3_A_ERR) - -#ifndef L3_DEBUG_DEFAULT -#ifdef DO_I4B_MAXDEBUG -#define L3_DEBUG_DEFAULT L3_DEBUG_MAX -#else -#define L3_DEBUG_DEFAULT L3_DEBUG_ERR -#endif -#endif - -/* Layer 4 */ - -#define L4_ERR 0x0001 /* general error message */ -#define L4_MSG 0x0002 /* general message */ -#define L4_TIMO 0x0004 /* b channel idle timeout msgs */ -#define L4_DIALST 0x0008 /* network driver dial states */ -#define L4_IPRDBG 0x0010 /* ipr driver debug messages */ -#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */ - -#define L4_DEBUG_MAX 0x003f /* all messages on */ -#define L4_DEBUG_ERR (L4_ERR) - -#ifndef L4_DEBUG_DEFAULT -#ifdef DO_I4B_MAXDEBUG -#define L4_DEBUG_DEFAULT L4_DEBUG_MAX -#else -#define L4_DEBUG_DEFAULT L4_DEBUG_ERR -#endif -#endif - -/*---------------------------------------------------------------------------* - * ioctl via /dev/i4bctl: - * get/set current debug bits settings - *---------------------------------------------------------------------------*/ - -typedef struct { - unsigned int l1; - unsigned int l2; - unsigned int l3; - unsigned int l4; -} ctl_debug_t; - -#define I4B_CTL_GET_DEBUG _IOR('C', 0, ctl_debug_t) - -#define I4B_CTL_SET_DEBUG _IOW('C', 1, ctl_debug_t) - -/*---------------------------------------------------------------------------* - * get hscx statistics - *---------------------------------------------------------------------------*/ - -typedef struct { - int unit; /* controller number */ - int chan; /* channel number */ - int vfr; - int rdo; - int crc; - int rab; - int xdu; - int rfo; -} hscxstat_t; - -#define I4B_CTL_GET_HSCXSTAT _IOWR('C', 2, hscxstat_t) - -#define I4B_CTL_CLR_HSCXSTAT _IOW('C', 3, hscxstat_t) - -/* EOF */ diff --git a/sys/i386/include/i4b_ioctl.h b/sys/i386/include/i4b_ioctl.h deleted file mode 100644 index 17e945f173efa..0000000000000 --- a/sys/i386/include/i4b_ioctl.h +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *--------------------------------------------------------------------------- - * - * i4b_ioctl.h - messages kernel <--> userland - * ------------------------------------------- - * - * $Id: i4b_ioctl.h,v 1.58 1998/12/22 19:48:24 hm Exp $ - * - * last edit-date: [Tue Dec 22 20:33:46 1998] - * - *---------------------------------------------------------------------------*/ - -#ifndef _I4B_IOCTL_H_ -#define _I4B_IOCTL_H_ - -#if defined(__FreeBSD__) && __FreeBSD__ >= 3 -#ifndef _MACHINE_TYPES_H_ -#include <machine/types.h> -#endif /* _MACHINE_TYPES_H_ */ -#endif /* __FreeBSD__ */ - -/*---------------------------------------------------------------------------* - * version and release number for isdn4bsd package - *---------------------------------------------------------------------------*/ -#define VERSION 0 /* version number */ -#define REL 70 /* release number */ -#define STEP 00 /* release step */ - -/*---------------------------------------------------------------------------* - * date/time format in i4b log messages - * ------------------------------------ - * Being year 2000 clean is not easy with the current state of the - * ANSI C library standard and it's implementation for some locales. - * You might like to use the "%c" format of "strftime" sometimes, - * but this breaks Y2K in some locales. Also the old standard logfile - * format "%d.%m.%y %H:%M:%S" is non compliant. - * NetBSD's current toolset warns about this problems, and we compile - * with -Werror, so this problems need to be resolved. - *---------------------------------------------------------------------------*/ -#define I4B_TIME_FORMAT "%d.%m.%Y %H:%M:%S" - -/*---------------------------------------------------------------------------* - * max number of controllers in system - *---------------------------------------------------------------------------*/ -#define MAX_CONTROLLERS 8 /* max number of controllers */ - -/*---------------------------------------------------------------------------* - * controller types - *---------------------------------------------------------------------------*/ -#define CTRL_INVALID (-1) /* invalid, error */ -#define CTRL_UNKNOWN 0 /* unknown controller type */ -#define CTRL_PASSIVE 1 /* passive ISDN controller cards*/ -#define CTRL_DAIC 2 /* Diehl active controller cards*/ -#define CTRL_NUMTYPES 3 /* number of controller types */ - -/*---------------------------------------------------------------------------* - * card types for CTRL_PASSIVE - *---------------------------------------------------------------------------*/ -#define CARD_TYPEP_INVAL (-1) /* invalid, error */ -#define CARD_TYPEP_UNK 0 /* unknown */ -#define CARD_TYPEP_8 1 /* Teles, S0/8 */ -#define CARD_TYPEP_16 2 /* Teles, S0/16 */ -#define CARD_TYPEP_16_3 3 /* Teles, S0/16.3 */ -#define CARD_TYPEP_AVMA1 4 /* AVM A1 or AVM Fritz!Card */ -#define CARD_TYPEP_163P 5 /* Teles, S0/16.3 PnP */ -#define CARD_TYPEP_CS0P 6 /* Creatix, S0 PnP */ -#define CARD_TYPEP_USRTA 7 /* US Robotics ISDN TA internal */ -#define CARD_TYPEP_DRNNGO 8 /* Dr. Neuhaus Niccy GO@ */ -#define CARD_TYPEP_SWS 9 /* Sedlbauer Win Speed */ -#define CARD_TYPEP_DYNALINK 10 /* Dynalink IS64PH */ -#define CARD_TYPEP_BLMASTER 11 /* ISDN Blaster / ISDN Master */ -#define CARD_TYPEP_PCFRITZ 12 /* AVM PCMCIA Fritz!Card */ -#define CARD_TYPEP_ELSAQS1ISA 13 /* ELSA QuickStep 1000pro ISA */ -#define CARD_TYPEP_ELSAQS1PCI 14 /* ELSA QuickStep 1000pro PCI */ -#define CARD_TYPEP_SIEMENSITALK 15 /* Siemens I-Talk */ -#define CARD_TYPEP_ELSAMLIMC 16 /* ELSA MicroLink ISDN/MC */ -#define CARD_TYPEP_ELSAMLMCALL 17 /* ELSA MicroLink MCall */ -#define CARD_TYPEP_ITKIX1 18 /* ITK ix1 micro */ - -/* - * in case you add support for more cards, please update: - * - * isdnd: support.c, name_of_controller() - * diehl/diehlctl: main.c, listall() - * - * and adjust CARD_TYPEP_MAX below. - */ - -#define CARD_TYPEP_MAX 18 /* max type */ - -/*---------------------------------------------------------------------------* - * card types for CTRL_DAIC - *---------------------------------------------------------------------------*/ -#define CARD_TYPEA_DAIC_UNK 0 -#define CARD_TYPEA_DAIC_S 1 -#define CARD_TYPEA_DAIC_SX 2 -#define CARD_TYPEA_DAIC_SCOM 3 -#define CARD_TYPEA_DAIC_QUAD 4 - -/*---------------------------------------------------------------------------* - * max length of some strings - *---------------------------------------------------------------------------*/ -#define TELNO_MAX 41 /* max length of a telephone number (+ '\0') */ -#define DISPLAY_MAX 91 /* max length of display information (+ '\0') */ -#define DATETIME_MAX 21 /* max length of datetime information (+ '\0')*/ - -/*---------------------------------------------------------------------------* - * in case the src or dst telephone number is empty - *---------------------------------------------------------------------------*/ -#define TELNO_EMPTY "NotAvailable" - -/*---------------------------------------------------------------------------* - * B channel parameters - *---------------------------------------------------------------------------*/ -#define BCH_MAX_DATALEN 2048 /* max length of a B channel frame */ - -/*---------------------------------------------------------------------------* - * userland driver types - * --------------------- - * a "driver" is defined here as a piece of software interfacing an - * ISDN B channel with a userland service, such as IP, Telephony etc. - *---------------------------------------------------------------------------*/ -#define BDRV_RBCH 0 /* raw b-channel interface driver */ -#define BDRV_TEL 1 /* telephone (speech) interface driver */ -#define BDRV_IPR 2 /* IP over raw HDLC interface driver */ -#define BDRV_ISPPP 3 /* sync Kernel PPP interface driver */ - -/*---------------------------------------------------------------------------* - * B channel protocol - *---------------------------------------------------------------------------*/ -#define BPROT_NONE 0 /* no protocol at all, raw data */ -#define BPROT_RHDLC 1 /* raw HDLC: flag, data, crc, flag */ - -/*---------------------------------------------------------------------------* - * causes data type - *---------------------------------------------------------------------------*/ -typedef unsigned int cause_t; /* 32 bit unsigned int */ - -/*---------------------------------------------------------------------------* - * call descriptor id (cdid) definitions - *---------------------------------------------------------------------------*/ -#define CDID_UNUSED 0 /* cdid is invalid and unused */ -#define CDID_MAX 99999 /* highest valid cdid, wraparound to 1 */ - - -/**************************************************************************** - - outgoing call: - -------------- - - userland kernel - -------- ------ - - CDID_REQ -----------------> - - <------------------ cdid - - CONNECT_REQ --------------> - - <------------------ PROCEEDING_IND (if connect req ok) - - <------------------ CONNECT_ACTIVE_IND (if connection ok) - - or - - <------------------ DISCONNECT_IND (if connection failed) - - - - incoming call: - -------------- - - userland kernel - -------- ------ - - <------------------ CONNECT_IND - - CONNECT_RESP -------------> - - <------------------ CONNECT_ACTIVE_IND (if accepted) - - - - active disconnect: - ------------------ - - userland kernel - -------- ------ - - DISCONNECT_REQ ------------> - - <------------------ DISCONNECT_IND - - - passive disconnect: - ------------------- - - userland kernel - -------- ------ - - <------------------ DISCONNECT_IND - - -****************************************************************************/ - - -/*===========================================================================* - *===========================================================================* - * "read" messages from kernel -> userland - *===========================================================================* - *===========================================================================*/ - - -/*---------------------------------------------------------------------------* - * message header, included in every message - *---------------------------------------------------------------------------*/ -typedef struct { - char type; /* message identifier */ -#define MSG_CONNECT_IND 'a' -#define MSG_CONNECT_ACTIVE_IND 'b' -#define MSG_DISCONNECT_IND 'c' -#define MSG_DIALOUT_IND 'd' -#define MSG_IDLE_TIMEOUT_IND 'e' -#define MSG_ACCT_IND 'f' -#define MSG_CHARGING_IND 'g' -#define MSG_PROCEEDING_IND 'h' -#define MSG_ALERT_IND 'i' -#define MSG_DRVRDISC_REQ 'j' -#define MSG_L12STAT_IND 'k' -#define MSG_TEIASG_IND 'l' -#define MSG_PDEACT_IND 'm' -#define MSG_NEGCOMP_IND 'n' -#define MSG_IFSTATE_CHANGED_IND 'o' - int cdid; /* call descriptor id */ -} msg_hdr_t; - -/*---------------------------------------------------------------------------* - * connect indication - * indicates incoming connection - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller number */ - int channel; /* channel number */ -#define CHAN_B1 0 /* this _must_ be 0, HSCX B1 is also 0 */ -#define CHAN_B2 1 /* this _must_ be 1, HSCX B2 is also 1 */ -#define CHAN_ANY (-1) /* outgoing, not possible for incoming */ -#define CHAN_NO (-2) /* call waiting (CW) for incoming */ - int bprot; /* b channel protocot, see BPROT_XXX */ - char dst_telno[TELNO_MAX]; /* destination telno */ - char src_telno[TELNO_MAX]; /* source telno */ - int scr_ind;/* screening indicator */ -#define SCR_NONE 0 /* no screening indicator transmitted */ -#define SCR_USR_NOSC 1 /* screening user provided, not screened*/ -#define SCR_USR_PASS 2 /* screening user provided, verified & passed */ -#define SCR_USR_FAIL 3 /* screening user provided, verified & failed */ -#define SCR_NET 4 /* screening network provided */ - char display[DISPLAY_MAX]; /* content of display IE*/ -} msg_connect_ind_t; - -/*---------------------------------------------------------------------------* - * connect active indication - * indicates active connection - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller number actually used */ - int channel; /* channel number actually used */ - char datetime[DATETIME_MAX]; /* content of date/time IE */ -} msg_connect_active_ind_t; - -/*---------------------------------------------------------------------------* - * disconnect indication - * indicates a disconnect - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - cause_t cause; /* cause code */ -} msg_disconnect_ind_t; - -/*---------------------------------------------------------------------------* - * negotiation complete - * indicates an interface is completely up & running - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ -} msg_negcomplete_ind_t; - -/*---------------------------------------------------------------------------* - * interface changes internal state - * indicates an interface has somehow switched its FSM - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int state; /* new interface state */ -} msg_ifstatechg_ind_t; - -/*---------------------------------------------------------------------------* - * initiate a call to a remote site - * i.e. the IP driver got a packet and wants a connection - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int driver; /* driver type */ - int driver_unit; /* driver unit number */ -} msg_dialout_ind_t; - -/*---------------------------------------------------------------------------* - * idle timeout disconnect sent indication - * kernel has sent disconnect request because of b-ch idle - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ -} msg_idle_timeout_ind_t; - -/*---------------------------------------------------------------------------* - * accounting information from userland interface driver to daemon - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int accttype; /* accounting type */ -#define ACCT_DURING 0 -#define ACCT_FINAL 1 - int driver; /* driver type */ - int driver_unit; /* driver unit number */ - int ioutbytes; /* ISDN # of bytes sent */ - int iinbytes; /* ISDN # of bytes received */ - int outbps; /* bytes per sec out */ - int inbps; /* bytes per sec in */ - int outbytes; /* driver # of bytes sent */ - int inbytes; /* driver # of bytes received */ -} msg_accounting_ind_t; - -/*---------------------------------------------------------------------------* - * charging information from isdn driver to daemon - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int units; /* number of units */ - int units_type; /* type of units info */ -#define CHARGE_INVALID 0 /* invalid, unknown */ -#define CHARGE_AOCD 1 /* advice of charge during call */ -#define CHARGE_AOCE 2 /* advice of charge at end of call */ -#define CHARGE_CALC 3 /* locally calculated from rates information */ -} msg_charging_ind_t; - -/*---------------------------------------------------------------------------* - * call proceeding indication - * indicates outgoing SETUP has been acknowleged - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller number actually used */ - int channel; /* channel number actually used */ -} msg_proceeding_ind_t; - -/*---------------------------------------------------------------------------* - * alert indication - * indicates remote user side "rings" - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ -} msg_alert_ind_t; - -/*---------------------------------------------------------------------------* - * driver requests to disconnect line - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int driver; /* driver type */ - int driver_unit; /* driver unit number */ -} msg_drvrdisc_req_t; - -/*---------------------------------------------------------------------------* - * state of layer 1/2 - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller unit */ - int layer; /* layer number (1/2) */ -#define LAYER_ONE 1 -#define LAYER_TWO 2 - int state; /* state info */ -#define LAYER_IDLE 0 -#define LAYER_ACTIVE 1 -} msg_l12stat_ind_t; - -/*---------------------------------------------------------------------------* - * TEI assignment messages - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller unit */ - int tei; /* TEI or -1 if invalid */ -} msg_teiasg_ind_t; - -/*---------------------------------------------------------------------------* - * persistent deactivation state of stack - *---------------------------------------------------------------------------*/ -typedef struct { - msg_hdr_t header; /* common header */ - int controller; /* controller unit */ - int numactive; /* number of active connections */ -} msg_pdeact_ind_t; - - -/*===========================================================================* - *===========================================================================* - * "ioctl" messages from userland -> kernel - *===========================================================================* - *===========================================================================*/ - - -/*---------------------------------------------------------------------------* - * request a unique cdid (to setup an outgoing call) - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ -} msg_cdid_req_t; - -#define I4B_CDID_REQ _IOWR('4', 0, int) - -/*---------------------------------------------------------------------------* - * connect request - * requests an outgoing connection - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ - int controller; /* controller to use */ - int channel; /* channel to use */ - int txdelay; /* tx delay after connect */ - int bprot; /* b channel protocol */ - int driver; /* driver to route b channel data to */ - int driver_unit; /* unit number for above driver */ - int unitlen_time; /* length of a charging unit */ - int idle_time; /* time without activity on b ch */ - int earlyhup_time; /* safety area at end of unit */ - int unitlen_method; /* how to calculate the unitlength */ -#define ULEN_METHOD_STATIC 0 /* use unitlen_time value (see above) */ -#define ULEN_METHOD_DYNAMIC 1 /* use AOCD */ - char dst_telno[TELNO_MAX]; /* destination telephone no */ - char src_telno[TELNO_MAX]; /* source telephone number */ -} msg_connect_req_t; - -#define I4B_CONNECT_REQ _IOW('4', 1, msg_connect_req_t) - -/*---------------------------------------------------------------------------* - * connect response - * this is the answer to an incoming connect indication - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ - int response; /* what to do with incoming call */ -#define SETUP_RESP_DNTCRE 0 /* dont care, call is not for me */ -#define SETUP_RESP_REJECT 1 /* reject call */ -#define SETUP_RESP_ACCEPT 2 /* accept call */ - cause_t cause; /* cause for case SETUP_RESP_REJECT */ - /* the following are only used for SETUP_RESP_ACCEPT !! */ - int txdelay; /* tx delay after connect */ - int bprot; /* B chan protocol */ - int driver; /* driver to route b channel data to */ - int driver_unit; /* unit number for above driver */ - int max_idle_time; /* max time without activity on b ch */ -} msg_connect_resp_t; - -#define I4B_CONNECT_RESP _IOW('4', 2, msg_connect_resp_t) - -/*---------------------------------------------------------------------------* - * disconnect request - * active disconnect request - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ - cause_t cause; /* protocol independent cause */ -} msg_discon_req_t; - -#define I4B_DISCONNECT_REQ _IOW('4', 3, msg_discon_req_t) - -/*---------------------------------------------------------------------------* - * controller info request - *---------------------------------------------------------------------------*/ -typedef struct { - int controller; /* controller number */ - int ncontroller; /* number of controllers in system */ - int ctrl_type; /* controller type passive/active */ - int card_type; /* brand / version */ - int tei; /* tei controller probably has */ -} msg_ctrl_info_req_t; - -#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t) - -/*---------------------------------------------------------------------------* - * dialout response - * status report to driver who requested a dialout - *---------------------------------------------------------------------------*/ -typedef struct { - int driver; /* driver to route b channel data to */ - int driver_unit; /* unit number for above driver */ - int stat; /* state of dialout request */ -#define DSTAT_NONE 0 -#define DSTAT_TFAIL 1 /* transient failure */ -#define DSTAT_PFAIL 2 /* permanent failure */ -#define DSTAT_INONLY 3 /* no outgoing dials allowed */ -} msg_dialout_resp_t; - -#define I4B_DIALOUT_RESP _IOW('4', 5, msg_dialout_resp_t) - -/*---------------------------------------------------------------------------* - * timeout value update - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ - int unitlen_time; /* length of a charging unit */ - int idle_time; /* time without activity on b ch */ - int earlyhup_time; /* safety area at end of unit */ -} msg_timeout_upd_t; - -#define I4B_TIMEOUT_UPD _IOW('4', 6, msg_timeout_upd_t) - -/*---------------------------------------------------------------------------* - * soft enable/disable - *---------------------------------------------------------------------------*/ -typedef struct { - int driver; /* driver to route b channel data to */ - int driver_unit; /* unit number for above driver */ - int updown; /* what to do */ -#define SOFT_ENA 0 /* enable interface */ -#define SOFT_DIS 1 /* disable interface */ -} msg_updown_ind_t; - -#define I4B_UPDOWN_IND _IOW('4', 7, msg_updown_ind_t) - -/*---------------------------------------------------------------------------* - * send alert request - *---------------------------------------------------------------------------*/ -typedef struct { - int cdid; /* call descriptor id */ -} msg_alert_req_t; - -#define I4B_ALERT_REQ _IOW('4', 8, msg_alert_req_t) - -/*---------------------------------------------------------------------------* - * request version and release info from kernel part - *---------------------------------------------------------------------------*/ -typedef struct { - int version; /* version number */ - int release; /* release number */ - int step; /* release step number */ -} msg_vr_req_t; - -#define I4B_VR_REQ _IOR('4', 9, msg_vr_req_t) - -/*---------------------------------------------------------------------------* - * Protocol download to active cards - *---------------------------------------------------------------------------*/ -struct isdn_dr_prot { - size_t bytecount; /* length of code */ - u_int8_t *microcode; /* pointer to microcode */ -}; - -struct isdn_download_request { - int controller; /* controller number */ - int numprotos; /* number of protocols in 'protocols' */ - struct isdn_dr_prot *protocols; -}; - -#define I4B_CTRL_DOWNLOAD _IOW('4', 100, struct isdn_download_request) - -/*---------------------------------------------------------------------------* - * Generic diagnostic interface for active cards - *---------------------------------------------------------------------------*/ -struct isdn_diagnostic_request { - int controller; /* controller number */ - u_int32_t cmd; /* diagnostic command to execute */ - size_t in_param_len; /* length of additional input parameter */ - void *in_param; /* optional input parameter */ - size_t out_param_len; /* available output space */ - void *out_param; /* output data goes here */ -}; - -#define I4B_ACTIVE_DIAGNOSTIC _IOW('4', 102, struct isdn_diagnostic_request) - -#endif /* _I4B_IOCTL_H_ */ diff --git a/sys/i386/include/i4b_trace.h b/sys/i386/include/i4b_trace.h deleted file mode 100644 index 07e08daa075cb..0000000000000 --- a/sys/i386/include/i4b_trace.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *--------------------------------------------------------------------------- - * - * i4b_trace.h - header file for trace data read device - * ---------------------------------------------------- - * - * $Id: i4b_trace.h,v 1.5 1998/12/05 18:06:01 hm Exp $ - * - * last edit-date: [Sat Dec 5 18:37:49 1998] - * - *---------------------------------------------------------------------------*/ - -#ifndef _I4B_TRACE_H_ -#define _I4B_TRACE_H_ - -/*---------------------------------------------------------------------------* - * structure of the header at the beginning of every trace mbuf - *---------------------------------------------------------------------------*/ -typedef struct { - int length; /* length of the following mbuf */ - int unit; /* controller unit number */ - int type; /* type of channel */ -#define TRC_CH_I 0 /* Layer 1 INFO's */ -#define TRC_CH_D 1 /* D channel */ -#define TRC_CH_B1 2 /* B1 channel */ -#define TRC_CH_B2 3 /* B2 channel */ - int dir; /* direction */ -#define FROM_TE 0 /* user -> network */ -#define FROM_NT 1 /* network -> user */ - int trunc; /* # of truncated bytes (frame > MCLBYTES) */ - unsigned int count; /* frame count for this unit/type */ - struct timeval time; /* timestamp for this frame */ -} i4b_trace_hdr_t; - -#define INFO0 0 /* layer 1 */ -#define INFO1_8 1 -#define INFO1_10 2 -#define INFO2 3 -#define INFO3 4 -#define INFO4_8 5 -#define INFO4_10 6 - -/*---------------------------------------------------------------------------* - * ioctl via /dev/i4btrc device(s): - * get/set current trace flag settings - *---------------------------------------------------------------------------*/ - -#define I4B_TRC_GET _IOR('T', 0, int) /* get trace settings */ -#define I4B_TRC_SET _IOW('T', 1, int) /* set trace settings */ - -#define TRACE_OFF 0x00 /* tracing off */ -#define TRACE_I 0x01 /* trace L1 INFO's on */ -#define TRACE_D_TX 0x02 /* trace D channel on */ -#define TRACE_D_RX 0x04 /* trace D channel on */ -#define TRACE_B_TX 0x08 /* trace B channel on */ -#define TRACE_B_RX 0x10 /* trace B channel on */ - -typedef struct { - int rxunit; /* unit # for rx frames */ - int rxflags; /* d and/or b channel */ - int txunit; /* unit # for tx frames */ - int txflags; /* d and/or b channel */ -} i4b_trace_setupa_t; - -#define I4B_TRC_SETA _IOW('T', 2, i4b_trace_setupa_t) /* set analyze mode */ -#define I4B_TRC_RESETA _IOW('T', 3, int) /* reset analyze mode */ - -#endif /* _I4B_TRACE_H_ */ diff --git a/sys/i386/include/iic.h b/sys/i386/include/iic.h index 6649821e0240a..174432611c0c9 100644 --- a/sys/i386/include/iic.h +++ b/sys/i386/include/iic.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: iic.h,v 1.1 1998/09/03 21:00:08 nsouch Exp $ + * $Id: iic.h,v 1.1.2.1 1998/07/17 00:54:01 son Exp $ * */ #ifndef __IIC_H @@ -31,17 +31,10 @@ #include <sys/ioccom.h> -struct iiccmd { - u_char slave; - int count; - int last; - char *buf; -}; - -#define I2CSTART _IOW('i', 1, struct iiccmd) /* start condition */ -#define I2CSTOP _IO('i', 2) /* stop condition */ -#define I2CRSTCARD _IOW('i', 3, struct iiccmd) /* reset the card */ -#define I2CWRITE _IOW('i', 4, struct iiccmd) /* send data */ -#define I2CREAD _IOW('i', 5, struct iiccmd) /* receive data */ +#define I2CSTART _IO('i', 1) /* start condition */ +#define I2CSTOP _IO('i', 2) /* stop condition */ +#define I2CADDRESS _IOW('i', 3, long) /* address bus */ +#define I2CRSTCARD _IOW('i', 4, long) /* reset the card */ #endif + diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index fd7bcfd2c661f..a565266783452 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: md_var.h,v 1.27 1998/10/30 05:41:15 msmith Exp $ + * $Id: md_var.h,v 1.25 1998/09/14 22:43:40 jdp Exp $ */ #ifndef _MACHINE_MD_VAR_H_ @@ -38,12 +38,7 @@ extern int Maxmem; extern u_int atdevbase; /* offset in virtual memory of ISA io mem */ -extern void (*bcopy_vector) __P((const void *from, void *to, size_t len)); extern int busdma_swi_pending; -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)); extern u_int cpu_feature; extern u_int cpu_high; extern u_int cpu_id; @@ -56,7 +51,6 @@ extern int need_post_dma_flush; #endif extern void (*netisrs[32]) __P((void)); extern int nfs_diskless_valid; -extern void (*ovbcopy_vector) __P((const void *from, void *to, size_t len)); extern char sigcode[]; extern int szsigcode; @@ -68,6 +62,7 @@ struct fpreg; void bcopyb __P((const void *from, void *to, size_t len)); void busdma_swi __P((void)); void cpu_halt __P((void)); +void cpu_power_down __P((void)); void cpu_reset __P((void)); void cpu_switch_load_fs __P((void)) __asm(__STRING(cpu_switch_load_fs)); void cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs)); @@ -80,12 +75,6 @@ void doreti_popl_es_fault __P((void)) __asm(__STRING(doreti_popl_es_fault)); int fill_fpregs __P((struct proc *, struct fpreg *)); int fill_regs __P((struct proc *p, struct reg *regs)); void fillw __P((int /*u_short*/ pat, void *base, size_t cnt)); -void i486_bzero __P((void *buf, 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)); -void i686_pagezero __P((void *addr)); int is_physical_memory __P((vm_offset_t addr)); u_long kvtop __P((void *addr)); void setidt __P((int idx, alias_for_inthand_t *func, int typ, int dpl, diff --git a/sys/i386/include/mouse.h b/sys/i386/include/mouse.h index b6ecef777bee4..27ec8e1fe94ab 100644 --- a/sys/i386/include/mouse.h +++ b/sys/i386/include/mouse.h @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mouse.h,v 1.10 1998/06/14 20:05:22 ahasty Exp $ + * $Id: mouse.h,v 1.9 1997/12/07 08:08:50 yokota Exp $ */ #ifndef _MACHINE_MOUSE_H_ @@ -113,7 +113,6 @@ typedef struct mousehw { #define MOUSE_MODEL_THINK 5 #define MOUSE_MODEL_EASYSCROLL 6 #define MOUSE_MODEL_MOUSEMANPLUS 7 -#define MOUSE_MODEL_KIDSPAD 8 typedef struct mousemode { int protocol; /* MOUSE_PROTO_XXX */ @@ -141,7 +140,6 @@ typedef struct mousemode { #define MOUSE_PROTO_THINK 11 /* Kensignton Thinking Mouse, 3/4 bytes */ #define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ #define MOUSE_PROTO_X10MOUSEREM 13 /* X10 MouseRemote, 3 bytes */ -#define MOUSE_PROTO_KIDSPAD 14 /* Genius Kidspad */ #define MOUSE_RES_UNKNOWN (-1) #define MOUSE_RES_DEFAULT 0 diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h index ce0043945af6d..e03b9ad66f7b9 100644 --- a/sys/i386/include/param.h +++ b/sys/i386/include/param.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)param.h 5.8 (Berkeley) 6/28/91 - * $Id: param.h,v 1.47 1998/10/13 08:24:37 dg Exp $ + * $Id: param.h,v 1.46 1998/09/09 01:21:25 jdp Exp $ */ #ifndef _MACHINE_PARAM_H_ @@ -54,7 +54,11 @@ * that are supported on the architecture. */ #define OBJFORMAT_NAMES "elf", "aout" +#ifdef __ELF__ #define OBJFORMAT_DEFAULT "elf" +#else +#define OBJFORMAT_DEFAULT "aout" +#endif #ifdef SMP #define NCPUS 2 diff --git a/sys/i386/include/pc/vesa.h b/sys/i386/include/pc/vesa.h index 16b07098aad14..0f4dd6b931716 100644 --- a/sys/i386/include/pc/vesa.h +++ b/sys/i386/include/pc/vesa.h @@ -23,7 +23,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: vesa.h,v 1.3 1999/01/08 12:57:06 yokota Exp $ + * $Id: vesa.h,v 1.1 1998/09/15 18:16:37 sos Exp $ */ #ifndef _MACHINE_PC_VESA_H @@ -115,6 +115,10 @@ struct vesa_mode int vesa_load_ioctl(void); int vesa_unload_ioctl(void); +#ifndef VESA_MODULE +int vesa_load(void); +#endif + #endif /* KERNEL */ #endif /* !_MACHINE_PC_VESA_H */ diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h index 5251be3890c79..25bfc624c8eb4 100644 --- a/sys/i386/include/pmap.h +++ b/sys/i386/include/pmap.h @@ -42,7 +42,7 @@ * * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 - * $Id: pmap.h,v 1.56 1998/06/21 14:08:27 mckay Exp $ + * $Id: pmap.h,v 1.55 1998/05/11 01:05:59 dyson Exp $ */ #ifndef _MACHINE_PMAP_H_ @@ -237,10 +237,9 @@ typedef struct pv_entry { #define NPPROVMTRR 8 #define PPRO_VMTRRphysBase0 0x200 #define PPRO_VMTRRphysMask0 0x201 -struct ppro_vmtrr { +struct { u_int64_t base, mask; -}; -extern struct ppro_vmtrr PPro_vmtrr[NPPROVMTRR]; +} PPro_vmtrr[NPPROVMTRR]; extern caddr_t CADDR1; extern pt_entry_t *CMAP1; diff --git a/sys/i386/include/resource.h b/sys/i386/include/resource.h deleted file mode 100644 index 0307182216902..0000000000000 --- a/sys/i386/include/resource.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 1998 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. 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. - */ - -#ifndef _MACHINE_RESOURCE_H_ -#define _MACHINE_RESOURCE_H_ 1 - -/* - * Definitions of resource types for Intel Architecture machines - * with support for legacy ISA devices and drivers. - */ - -#define SYS_RES_IRQ 1 -#define SYS_RES_DRQ 2 -#define SYS_RES_MEMORY 3 -#define SYS_RES_IOPORT 4 - -#endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/sys/i386/include/smb.h b/sys/i386/include/smb.h index e0ebef8b2dd4c..1338a15658b7d 100644 --- a/sys/i386/include/smb.h +++ b/sys/i386/include/smb.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: smb.h,v 1.1 1998/09/03 21:00:08 nsouch Exp $ + * $Id: smb.h,v 1.1 1998/08/13 17:13:20 son Exp $ * */ #ifndef __SMB_H @@ -34,7 +34,6 @@ struct smbcmd { char cmd; int count; - u_char slave; union { char byte; short word; @@ -49,8 +48,8 @@ struct smbcmd { } data; }; -#define SMB_QUICK_WRITE _IOW('i', 1, struct smbcmd) -#define SMB_QUICK_READ _IOW('i', 2, struct smbcmd) +#define SMB_QUICK_WRITE _IO('i', 1) +#define SMB_QUICK_READ _IO('i', 2) #define SMB_SENDB _IOW('i', 3, struct smbcmd) #define SMB_RECVB _IOW('i', 4, struct smbcmd) #define SMB_WRITEB _IOW('i', 5, struct smbcmd) diff --git a/sys/i386/include/types.h b/sys/i386/include/types.h index f28d633cbd3c3..fa4d88f9cbc2a 100644 --- a/sys/i386/include/types.h +++ b/sys/i386/include/types.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)types.h 8.3 (Berkeley) 1/5/94 - * $Id: types.h,v 1.15 1998/07/14 05:09:43 bde Exp $ + * $Id: types.h,v 1.14 1998/07/10 02:27:15 bde Exp $ */ #ifndef _MACHINE_TYPES_H_ @@ -52,16 +52,33 @@ typedef __int64_t vm_ooffset_t; typedef unsigned int vm_pindex_t; typedef unsigned int vm_size_t; -typedef __int32_t register_t; +/* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +typedef __signed char int8_t; +typedef unsigned char u_int8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +typedef __int64_t int64_t; +typedef __uint64_t u_int64_t; + +typedef int32_t register_t; +typedef int32_t ufs_daddr_t; #ifdef KERNEL typedef int intfptr_t; typedef unsigned int uintfptr_t; +typedef int intptr_t; +typedef unsigned int uintptr_t; +typedef __uint64_t uoff_t; #endif /* Interrupt mask (spl, xxx_imask, etc) */ -typedef __uint32_t intrmask_t; +typedef u_int32_t intrmask_t; /* Interrupt handler function type. */ typedef void inthand2_t __P((void *_cookie)); diff --git a/sys/i386/isa/README.le b/sys/i386/isa/README.le index a8c33c194b3c3..52e4df590588f 100644 --- a/sys/i386/isa/README.le +++ b/sys/i386/isa/README.le @@ -1,4 +1,4 @@ -$Id: README.le,v 1.4 1997/02/22 09:35:49 peter Exp $ +$Id$ ---------------- @@ -38,7 +38,7 @@ i386/conf/files.i386 file. After that is done you will need to edit your config file (in i386/conf) and a line similar to: -device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 +device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr [The above line assumes the board is still at the factory defaults.] Change the port, irq, and iomem value if needed to your configuration. diff --git a/sys/i386/isa/README.stl b/sys/i386/isa/README.stl index 84e8ab66dd90d..20b62f701a913 100644 --- a/sys/i386/isa/README.stl +++ b/sys/i386/isa/README.stl @@ -328,7 +328,7 @@ i386/isa/stallion.c optional stl device-driver - enter a line for each board that you want to use. For stallion.c boards entries should look like: -device stl0 at isa? port 0x2a0 tty irq 10 +device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr For istallion.c boards, the entries should look like: diff --git a/sys/i386/isa/adv_isa.c b/sys/i386/isa/adv_isa.c index 7e9b84de9481a..09fe9f281926e 100644 --- a/sys/i386/isa/adv_isa.c +++ b/sys/i386/isa/adv_isa.c @@ -44,7 +44,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: adv_isa.c,v 1.7 1998/11/10 06:44:54 gibbs Exp $ + * $Id: adv_isa.c,v 1.5 1998/10/10 00:44:12 imp Exp $ */ #include <sys/param.h> @@ -71,9 +71,9 @@ * The overrun buffer shared amongst all ISA/VL adapters. */ static u_int8_t* overrun_buf; -static bus_dma_tag_t overrun_dmat; -static bus_dmamap_t overrun_dmamap; -static bus_addr_t overrun_physbase; +bus_dma_tag_t overrun_dmat; +bus_dmamap_t overrun_dmamap; +bus_addr_t overrun_physbase; /* Possible port addresses an ISA or VL adapter can live at */ u_int16_t adv_isa_ioports[] = @@ -122,7 +122,7 @@ advisaprobe(struct isa_device *id) if (id->id_iobase > 0) { for (;port_index <= max_port_index; port_index++) - if (id->id_iobase <= adv_isa_ioports[port_index]) + if (id->id_iobase >= adv_isa_ioports[port_index]) break; if ((port_index > max_port_index) || (id->id_iobase != adv_isa_ioports[port_index])) { diff --git a/sys/i386/isa/aha_isa.c b/sys/i386/isa/aha_isa.c index 94266790e87f6..5f81ea183bdaa 100644 --- a/sys/i386/isa/aha_isa.c +++ b/sys/i386/isa/aha_isa.c @@ -28,14 +28,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $ + * $Id: aha_isa.c,v 1.3 1998/10/10 00:44:12 imp Exp $ */ -#include "pnp.h" - #include <sys/param.h> #include <sys/systm.h> -#include <sys/kernel.h> #include <machine/bus_pio.h> #include <machine/bus.h> @@ -45,13 +42,9 @@ #include <cam/scsi/scsi_all.h> -#if NPNP > 0 -#include <i386/isa/pnp.h> -#endif - -static int aha_isa_probe(struct isa_device *dev); -static int aha_isa_attach(struct isa_device *dev); -static void aha_isa_intr(void *unit); +static int aha_isa_probe __P((struct isa_device *dev)); +static int aha_isa_attach __P((struct isa_device *dev)); +static void aha_isa_intr __P((void *unit)); struct isa_driver ahadriver = { @@ -75,18 +68,41 @@ aha_isa_probe(dev) */ struct aha_softc *aha; int port_index; - int max_port_index; + int max_port_index; - aha = NULL; + /* + * We ignore the unit number assigned by config to allow + * consistant numbering between PCI/EISA/ISA devices. + * This is a total kludge until we have a configuration + * manager. + */ + dev->id_unit = aha_unit; + aha = NULL; + port_index = 0; + max_port_index = AHA_NUM_ISAPORTS - 1; /* * Bound our board search if the user has * specified an exact port. */ - aha_find_probe_range(dev->id_iobase, &port_index, &max_port_index); - - if (port_index < 0) - return 0; + if (dev->id_iobase > 0) { + for (;port_index <= max_port_index; port_index++) + if (dev->id_iobase >= aha_isa_ports[port_index].addr) + break; + if ((port_index > max_port_index) + || (dev->id_iobase != aha_isa_ports[port_index].addr)) { + printf(" +aha_isa_probe: Invalid baseport of 0x%x specified. +aha_isa_probe: Nearest valid baseport is 0x%x. +aha_isa_probe: Failing probe.\n", + dev->id_iobase, + (port_index <= max_port_index) + ? aha_isa_ports[port_index].addr + : aha_isa_ports[max_port_index].addr); + return 0; + } + max_port_index = port_index; + } /* Attempt to find an adapter */ for (;port_index <= max_port_index; port_index++) { @@ -94,7 +110,7 @@ aha_isa_probe(dev) u_int ioport; int error; - ioport = aha_iop_from_bio(port_index); + ioport = aha_isa_ports[port_index].addr; /* * Ensure this port has not already been claimed already @@ -102,7 +118,7 @@ aha_isa_probe(dev) */ if (aha_check_probed_iop(ioport) != 0) continue; - dev->id_iobase = ioport; + dev->id_iobase = aha_isa_ports[port_index].addr; if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET)) continue; @@ -125,7 +141,7 @@ aha_isa_probe(dev) * Determine our IRQ, and DMA settings and * export them to the configuration system. */ - error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, + error = aha_cmd(aha, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, (u_int8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT); if (error != 0) { @@ -150,7 +166,6 @@ aha_isa_probe(dev) printf("aha_isa_probe: Invalid DMA setting " "detected for adapter at 0x%x. " "Failing probe\n", ioport); - return (0); } dev->id_irq = (config_data.irq << 9); dev->id_intr = aha_isa_intr; @@ -213,79 +228,3 @@ aha_isa_intr(void *unit) struct aha_softc* arg = aha_softcs[(int)unit]; aha_intr((void *)arg); } - -/* - * support PnP cards if we are using 'em - */ - -#if NPNP > 0 - -static char *ahapnp_probe(u_long csn, u_long vend_id); -static void ahapnp_attach(u_long csn, u_long vend_id, char *name, - struct isa_device *dev); -static u_long nahapnp = NAHA; - -static struct pnp_device ahapnp = { - "ahapnp", - ahapnp_probe, - ahapnp_attach, - &nahapnp, - &bio_imask -}; -DATA_SET (pnpdevice_set, ahapnp); - -static char * -ahapnp_probe(u_long csn, u_long vend_id) -{ - struct pnp_cinfo d; - char *s = NULL; - - if (vend_id != AHA1542_PNP && vend_id != AHA1542_PNPCOMPAT) - return (NULL); - - read_pnp_parms(&d, 0); - if (d.enable == 0 || d.flags & 1) { - printf("CSN %lu is disabled.\n", csn); - return (NULL); - } - s = "Adaptec 1542CP"; - - return (s); -} - -static void -ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) -{ - struct pnp_cinfo d; - struct isa_device *dvp; - - if (dev->id_unit >= NAHATOT) - return; - - if (read_pnp_parms(&d, 0) == 0) { - printf("failed to read pnp parms\n"); - return; - } - - write_pnp_parms(&d, 0); - - enable_pnp_card(); - - dev->id_iobase = d.port[0]; - dev->id_irq = (1 << d.irq[0]); - dev->id_intr = aha_intr; - dev->id_drq = d.drq[0]; - - if (dev->id_driver == NULL) { - dev->id_driver = &ahadriver; - dvp = find_isadev(isa_devtab_tty, &ahadriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; - } - - if ((dev->id_alive = aha_isa_probe(dev)) != 0) - aha_isa_attach(dev); - else - printf("aha%d: probe failed\n", dev->id_unit); -} -#endif diff --git a/sys/i386/isa/aic6360.c b/sys/i386/isa/aic6360.c index e0f946d3d993a..2b28abcebcd56 100644 --- a/sys/i386/isa/aic6360.c +++ b/sys/i386/isa/aic6360.c @@ -32,7 +32,7 @@ */ /* - * $Id: aic6360.c,v 1.42 1998/10/22 05:58:38 bde Exp $ + * $Id: aic6360.c,v 1.40 1998/04/15 17:45:12 bde Exp $ * * Acknowledgements: Many of the algorithms used in this driver are * inspired by the work of Julian Elischer (julian@tfs.com) and @@ -663,7 +663,6 @@ static int aic_find __P((struct aic_data *)); static void aic_done __P((struct acb *)); static void aic_dataout __P((struct aic_data *aic)); static void aic_datain __P((struct aic_data *aic)); -static ointhand2_t aicintr; static int32_t aic_scsi_cmd __P((struct scsi_xfer *)); static int aic_poll __P((struct aic_data *aic, struct acb *)); void aic_add_timeout __P((struct acb *, int)); @@ -715,7 +714,6 @@ static struct scsi_device aic_dev = { #include "card.h" #if NCARD > 0 #include <sys/select.h> -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> @@ -723,7 +721,16 @@ static int aic_card_intr __P((struct pccard_devinfo *)); static int aicinit __P((struct pccard_devinfo *)); static void aicunload __P((struct pccard_devinfo *)); -PCCARD_MODULE(aic, aicinit, aicunload, aic_card_intr, 0, bio_imask); +static struct pccard_device aic_info = { + "aic", + aicinit, + aicunload, + aic_card_intr, + 0, /* Attributes - presently unused */ + &bio_imask +}; + +DATA_SET(pccarddrv_set, aic_info); /* * Initialize the device - called from Slot manager. @@ -960,7 +967,6 @@ aicattach(dev) struct scsibus_data *scbus; AIC_TRACE(("aicattach\n")); - dev->id_ointr = aicintr; aic->state = 0; aic_scsi_reset(aic); aic_init(aic); /* Init chip and driver */ @@ -2129,7 +2135,7 @@ aic_datain(aic) * 2) doesn't support synchronous transfers properly (yet) */ -static void +void aicintr(int unit) { struct aic_data *aic = aicdata[unit]; diff --git a/sys/i386/isa/alog.c b/sys/i386/isa/alog.c new file mode 100644 index 0000000000000..8fbe5768811a9 --- /dev/null +++ b/sys/i386/isa/alog.c @@ -0,0 +1,663 @@ +/* + * Copyright (c) 1998 Scottibox + * 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 + * 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 + * + * 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. + * + * Industrial Computer Source model AIO8-P + * 8 channel, moderate speed analog to digital converter board with + * 128 channel MUX capability via daisy chained AT-16P units + * alog.c, character device driver, last revised January 6 1998 + * See http://www.scottibox.com + * http://www.indcompsrc.com/products/data/html/aio8g-p.html + * http://www.indcompsrc.com/products/data/html/at16-p.html + * + * Written by: Jamil J. Weatherbee <jamil@scottibox.com> + * + */ + + +/* Include Files */ + +#include "alog.h" +#if NALOG > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/poll.h> +#include <sys/vnode.h> +#include <sys/filio.h> +#include <i386/isa/isa_device.h> +#include <sys/alogio.h> +#include <sys/dataacq.h> + +#include "opt_devfs.h" +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +/* Local Defines */ + +/* Tests have shown that increasing the fifo size + * beyond 64 entries for this particular piece of hardware is + * unproductive */ + +#ifdef ALOG_FIFOSIZE +#define FIFOSIZE ALOG_FIFOSIZE +#else +#define FIFOSIZE 64 +#endif + +#ifdef ALOG_FIFO_TRIGGER +#define DEFAULT_FIFO_TRIGGER ALOG_FIFO_TRIGGER +#else +#define DEFAULT_FIFO_TRIGGER 1 +#endif + +#ifdef ALOG_CHANNELS +#define NUMCHANNELS ALOG_CHANNELS +#else +#define NUMCHANNELS 128 +#endif + +#ifdef ALOG_TIMO +#define READTIMO ALOG_TIMO +#else +#define READTIMO (MAX_MICRO_PERIOD*NUMCHANNELS/500000*hz) +#endif + +#define CDEV_MAJOR 86 +#define NUMPORTS 8 +#define MAXUNITS 2 +#define NUMIMUXES 8 + +#define ADLOW 0x0 +#define ADHIGH 0x1 +#define STATUS 0x2 +#define CNTR0 0x4 +#define CNTR1 0x5 +#define CNTR2 0x6 +#define CNTRCNTRL 0x7 + +#define DEVFORMAT "alog%d%c%d" +#define CLOCK2FREQ 4.165 +#define MIN_MICRO_PERIOD 25 +#define MAX_MICRO_PERIOD (65535/CLOCK2FREQ*PRIMARY_STATES) +#define DEFAULT_MICRO_PERIOD MAX_MICRO_PERIOD +#define READMAXTRIG 0.75*FIFOSIZE +#define ALOGPRI PRIBIO +#define ALOGMSG "alogio" + +#define PRIMARY_STATES 2 /* Setup and conversion are clock tick consuming */ +#define STATE_SETUP 0 +#define STATE_CONVERT 1 +#define STATE_READ 2 + +/* Notes on interrupt driven A/D conversion: + * On the AIO8-P, interrupt driven conversion (the only type supported by this + * driver) is facilitated through 8253 timer #2. In order for interrrupts to + * be generated you must connect line 6 to line 24 (counter 2 output to + * interrupt input) and line 23 to line 29 (counter 2 gate to +5VDC). + * Due to the design of the AIO8-P this precludes the use of programmable + * gain control. + */ + +/* mode bits for the status register */ + +#define EOC 0x80 +#define IEN 0x08 +#define IMUXMASK 0x07 +#define EMUXMASK 0xf0 + +/* mode bits for counter controller */ + +#define LD2MODE4 0xb8 + +/* Minor allocations: + * UCCCCMMM + * U: board unit (0-1) + * CCCC: external multiplexer channel (0-15) (on AT-16P units) + * MMM: internal multiplexer channel (0-7) (on AIO8-P card) + */ + +#define UNIT(dev) ((minor(dev) & 0x80) >> 7) +#define CHANNEL(dev) (minor(dev) & 0x7f) +#define EMUX(chan) ((chan & 0x78) >> 3) +#define EMUXMAKE(chan) ((chan & 0x78) << 1) +#define IMUX(chan) (chan & 0x07) +#define LMINOR(unit, chan) ((unit << 7)+chan) + +/* port statuses */ + +#define STATUS_UNUSED 0 +#define STATUS_INUSE 1 +#define STATUS_STOPPED 2 +#define STATUS_INIT 3 + +/* Type definitions */ + +typedef struct +{ + short status; /* the status of this chan */ + struct selinfo readpoll; /* the poll() info */ + u_short fifo[FIFOSIZE]; /* fifo for this chan */ + int fifostart, fifoend; /* the ptrs showing where info is stored in fifo */ + int fifosize, fifotrig; /* the current and trigger size of the fifo */ + void *devfs_token; /* the devfs token for this chan */ + int nextchan; +} talog_chan; + +typedef struct +{ + struct isa_device *isaunit; /* ptr to isa device information */ + talog_chan chan[NUMCHANNELS]; /* the device nodes */ + int curchan; /* the current chan being intr handled */ + int firstchan; /* the first chan to go to in list */ + int state; /* is the node in setup or convert mode */ + long microperiod; /* current microsecond period setting */ + u_char perlo, perhi; /* current values to send to clock 2 after every intr */ + +} talog_unit; + +/* Function Prototypes */ + +static int alog_probe (struct isa_device *idp); /* Check for alog board */ +static int alog_attach (struct isa_device *idp); /* Take alog board */ +static int sync_clock2 (int unit, long period); /* setup clock 2 period */ +static int putfifo (talog_chan *pchan, u_short fifoent); +static int alog_open (dev_t dev, int oflags, int devtype, struct proc *p); +static int alog_close (dev_t dev, int fflag, int devtype, struct proc *p); +static int alog_ioctl (dev_t dev, u_long cmd, caddr_t data, + int fflag, struct proc *p); +static int alog_read (dev_t dev, struct uio *uio, int ioflag); +static int alog_poll (dev_t dev, int events, struct proc *p); + +/* Global Data */ + +static int alog_devsw_installed = 0; /* Protect against reinit multiunit */ +static talog_unit *alog_unit[NALOG]; /* data structs for each unit */ + +/* Character device switching structure */ +static struct cdevsw alog_cdevsw = { alog_open, alog_close, alog_read, + nowrite, alog_ioctl, nostop, noreset, + nodevtotty, alog_poll, nommap, + nostrategy, "alog", NULL, -1 }; + +/* Structure expected to tell how to probe and attach the driver + * Must be published externally (cannot be static) */ +struct isa_driver alogdriver = { alog_probe, alog_attach, "alog", 0 }; + + +/* handle the ioctls */ +static int alog_ioctl (dev_t dev, u_long cmd, caddr_t data, + int fflag, struct proc *p) +{ + int unit = UNIT(dev); + int chan = CHANNEL(dev); + talog_unit *info = alog_unit[unit]; + int s; + + switch (cmd) + { + case FIONBIO: return 0; /* this allows for non-blocking ioctls */ + + case AD_NCHANS_GET: *(int *)data = NUMCHANNELS; + return 0; + case AD_FIFOSIZE_GET: *(int *)data = FIFOSIZE; + return 0; + + case AD_FIFO_TRIGGER_GET: s = spltty(); + *(int *)data = info->chan[chan].fifotrig; + splx(s); + return 0; + + case AD_FIFO_TRIGGER_SET: + s = spltty(); + if ((*(int *)data < 1) || (*(int *)data > FIFOSIZE)) + { + splx(s); + return EPERM; + } + info->chan[chan].fifotrig = *(int *)data; + splx(s); + return 0; + + case AD_STOP: s = spltty(); + info->chan[chan].status = STATUS_STOPPED; + splx(s); + return 0; + + case AD_START: s = spltty(); + info->chan[chan].status = STATUS_INUSE; + splx(s); + return 0; + + case AD_MICRO_PERIOD_SET: + s = spltty(); + if (sync_clock2 (unit, *(long *) data)) + { + splx(s); + return EPERM; + } + splx(s); + return 0; + + case AD_MICRO_PERIOD_GET: s = spltty(); + *(long *)data = info->microperiod; + splx(s); + return 0; + + } + + return ENOTTY; +} + + +/* handle poll() based read polling */ +static int alog_poll (dev_t dev, int events, struct proc *p) +{ + int unit = UNIT(dev); + int chan = CHANNEL(dev); + talog_unit *info = alog_unit[unit]; + int s; + + s = spltty(); + if (events & (POLLIN | POLLRDNORM)) /* if polling for any/normal data */ + if (info->chan[chan].fifosize >= info->chan[chan].fifotrig) + { + splx(s); + + return events & (POLLIN | POLLRDNORM); /* ready for any/read */ + } + else + { + /* record this request */ + selrecord (p, &(info->chan[chan].readpoll)); + splx(s); + return 0; /* not ready, yet */ + } + + splx(s); + return 0; /* not ready (any I never will be) */ +} + + +/* how to read from the board */ +static int alog_read (dev_t dev, struct uio *uio, int ioflag) +{ + int unit = UNIT(dev); + int chan = CHANNEL(dev); + talog_unit *info = alog_unit[unit]; + int s, oldtrig, toread, err = 0; + + s = spltty(); + + oldtrig = info->chan[chan].fifotrig; /* save official trigger value */ + while (uio->uio_resid >= sizeof(u_short)) /* while uio has space */ + { + if (!info->chan[chan].fifosize) /* if we have an empty fifo */ + { + if (ioflag & IO_NDELAY) /* exit if we are non-blocking */ + { err = EWOULDBLOCK; + break; + } + /* Start filling fifo on first blocking read */ + if (info->chan[chan].status == STATUS_INIT) + info->chan[chan].status = STATUS_INUSE; + /* temporarily adjust the fifo trigger to be optimal size */ + info->chan[chan].fifotrig = + min (READMAXTRIG, uio->uio_resid / sizeof(u_short)); + /* lets sleep until we have some io available or timeout */ + err = tsleep (&(info->chan[chan].fifo), ALOGPRI | PCATCH, ALOGMSG, + info->chan[chan].fifotrig*READTIMO); + if (err == EWOULDBLOCK) + { printf (DEVFORMAT ": read timeout\n", unit, + 'a'+EMUX(chan), IMUX(chan)); + } + if (err == ERESTART) err = EINTR; /* don't know how to restart */ + if (err) break; /* exit if any kind of error or signal */ + } + + /* ok, now if we got here there is something to read from the fifo */ + + /* calculate how many entries we can read out from the fifostart + * pointer */ + toread = min (uio->uio_resid / sizeof(u_short), + min (info->chan[chan].fifosize, + FIFOSIZE - info->chan[chan].fifostart)); + /* perform the move, if there is an error then exit */ + if (err = uiomove((caddr_t) + &(info->chan[chan].fifo[info->chan[chan].fifostart]), + toread * sizeof(u_short), uio)) break; + info->chan[chan].fifosize -= toread; /* fifo this much smaller */ + info->chan[chan].fifostart += toread; /* we got this many more */ + if (info->chan[chan].fifostart == FIFOSIZE) + info->chan[chan].fifostart = 0; /* wrap around fifostart */ + + } + info->chan[chan].fifotrig = oldtrig; /* restore trigger changes */ + splx(s); + return err; +} + + +/* open a channel */ +static int alog_open (dev_t dev, int oflags, int devtype, struct proc *p) +{ + int unit = UNIT(dev); /* get unit no */ + int chan = CHANNEL(dev); /* get channel no */ + talog_unit *info; + int s; /* priority */ + int cur; + + if ((unit >= NALOG) || (unit >= MAXUNITS) || (chan >= NUMCHANNELS)) + return ENXIO; /* unit and channel no ok ? */ + if (!alog_unit[unit]) return ENXIO; /* unit attached */ + info = alog_unit[unit]; /* ok, this is valid now */ + + if (info->chan[chan].status) return EBUSY; /* channel busy */ + if (oflags & FREAD) + { + s=spltty(); + info->chan[chan].status = STATUS_INIT; /* channel open, read waiting */ + info->chan[chan].fifostart = info->chan[chan].fifoend = + info->chan[chan].fifosize = 0;/* fifo empty */ + info->chan[chan].fifotrig = DEFAULT_FIFO_TRIGGER; + if (info->firstchan < 0) /* if empty chain */ + { + info->firstchan = info->curchan = chan; /* rev up the list */ + info->chan[chan].nextchan = -1; /* end of the list */ + } + else /* non empty list must insert */ + { + if (chan < info->firstchan) /* this one must become first in list */ + { + info->chan[chan].nextchan = info->firstchan; + info->firstchan = chan; + } + else /* insert this one as second - last in chan list */ + { + cur = info->firstchan; + + /* traverse list as long as cur is less than chan and cur is + * not last in list */ + while ((info->chan[cur].nextchan < chan) && + (info->chan[cur].nextchan >= 0)) + cur = info->chan[cur].nextchan; + + /* now cur should point to the entry right before yours */ + info->chan[chan].nextchan = info->chan[cur].nextchan; + info->chan[cur].nextchan = chan; /* insert yours in */ + } + } + splx(s); + return 0; /* open successful */ + } + return EPERM; /* this is a read only device */ +} + + +/* close a channel */ +static int alog_close (dev_t dev, int fflag, int devtype, struct proc *p) +{ + int unit = UNIT(dev); + int chan = CHANNEL(dev); + talog_unit *info = alog_unit[unit]; + int s; + int cur; + + s = spltty(); + info->chan[chan].status = STATUS_UNUSED; + + /* what if we are in the middle of a conversion ? + * then smoothly get us out of it: */ + if (info->curchan == chan) + { /* if we are last in list set curchan to first in list */ + if ((info->curchan = info->chan[chan].nextchan) < 0) + info->curchan = info->firstchan; + + info->state = STATE_SETUP; + } + + /* if this is the first channel, then make the second channel the first + * channel (note that if this is also the only channel firstchan becomes + * -1 and so the list is marked as empty */ + + if (chan == info->firstchan) + info->firstchan = info->chan[chan].nextchan; + else /* ok, so there must be at least 2 channels (and it is not the first) */ + { + cur = info->firstchan; + + /* find the entry before it (which must exist if you are closing) */ + while (info->chan[cur].nextchan < chan) + cur = info->chan[cur].nextchan; + /* at this point we must have the entry before ours */ + info->chan[cur].nextchan = info->chan[chan].nextchan; /* give our link */ + + } + + splx(s); + + return 0; /* close always successful */ +} + + +/* The probing routine - returns number of bytes needed */ +static int alog_probe (struct isa_device *idp) +{ + int unit = idp->id_unit; /* this device unit number */ + int iobase = idp->id_iobase; /* the base address of the unit */ + int addr; + + if ((unit < 0) || (unit >= NALOG) || (unit >= MAXUNITS)) + { + printf ("alog: invalid unit number (%d)\n", unit); + return 0; + } + + /* the unit number is ok, lets check if used */ + if (alog_unit[unit]) + { + printf ("alog: unit (%d) already attached\n", unit); + return 0; + } + + if (inb (iobase+STATUS) & EOC) return 0; /* End of conv bit should be 0 */ + for (addr=0; addr<NUMIMUXES; addr++) + { + outb (iobase+STATUS, EMUXMASK|addr);/* output ones to upper nibbl+addr */ + /* get back a zero in MSB and the addr where you put it */ + if ((inb (iobase+STATUS) & (EOC|IMUXMASK)) != addr) return 0; + } + + return NUMPORTS; /* this device needs this many ports */ +} + + +/* setup the info structure correctly for reloading clock 2 after interrupt */ +static int sync_clock2 (int unit, long period) +{ + int clockper; + talog_unit *info = alog_unit[unit]; + + if ((period > MAX_MICRO_PERIOD) || (period < MIN_MICRO_PERIOD)) + return -1; /* error period too long */ + info->microperiod = period; /* record the period */ + clockper = (CLOCK2FREQ * period) / PRIMARY_STATES; + info->perlo = clockper & 0xff; /* least sig byte of clock period */ + info->perhi = ((clockper & 0xff00) >> 8); /* most sig byte of clock period */ + return 0; +} + + +/* The attachment routine - returns true on success */ +static int alog_attach (struct isa_device *idp) +{ + int unit = idp->id_unit; /* this device unit number */ + int iobase = idp->id_iobase; /* the base address of the unit */ + talog_unit *info; /* pointer to driver specific info for unit */ + int chan; /* the channel used for creating devfs nodes */ + + if (!(info = malloc(sizeof(*info), M_DEVBUF, M_NOWAIT))) + { + printf ("alog%d: cannot allocate driver storage\n", unit); + return 0; + } + alog_unit[unit] = info; /* make sure to save the pointer */ + bzero (info, sizeof(*info)); /* clear info structure to all false */ + info->isaunit = idp; /* store ptr to isa device information */ + sync_clock2 (unit, DEFAULT_MICRO_PERIOD); /* setup perlo and perhi */ + info->firstchan = -1; /* channel lists are empty */ + + /* insert devfs nodes */ + +#ifdef DEVFS + for (chan=0; chan<NUMCHANNELS; chan++) + info->chan[chan].devfs_token = + devfs_add_devswf(&alog_cdevsw, LMINOR(unit, chan), DV_CHR, + UID_ROOT, GID_WHEEL, 0400, DEVFORMAT, + unit, 'a'+EMUX(chan), IMUX(chan)); +#endif + + printf ("alog%d: %d channels, %d bytes/FIFO, %d entry trigger\n", + unit, NUMCHANNELS, FIFOSIZE*sizeof(u_short), + DEFAULT_FIFO_TRIGGER); + alogintr (unit); /* start the periodic interrupting process */ + return 1; /* obviously successful */ +} + + +/* Unit interrupt handling routine (interrupts generated by clock 2) */ +void alogintr (int unit) +{ + talog_unit *info = alog_unit[unit]; + int iobase = info->isaunit->id_iobase; + u_short fifoent; + + + if (info->firstchan >= 0) /* ? is there even a chan list to traverse */ + switch (info->state) + { + case STATE_READ: + if (info->chan[info->curchan].status == STATUS_INUSE) + { + if (inb (iobase+STATUS) & EOC) /* check that conversion finished */ + printf (DEVFORMAT ": incomplete conversion\n", unit, + 'a'+EMUX(info->curchan), IMUX(info->curchan)); + else /* conversion is finished (should always be) */ + { + fifoent = (inb (iobase+ADHIGH) << 8) + + inb (iobase+ADLOW); + if (putfifo(&(info->chan[info->curchan]), fifoent)) + { + printf (DEVFORMAT ": fifo overflow\n", unit, + 'a'+EMUX(info->curchan), IMUX(info->curchan)); + } + if (info->chan[info->curchan].fifosize >= + info->chan[info->curchan].fifotrig) + { + /* if we've reached trigger levels */ + selwakeup (&(info->chan[info->curchan].readpoll)); + wakeup (&(info->chan[info->curchan].fifo)); + } + } + } + /* goto setup state for next channel on list */ + if ((info->curchan = info->chan[info->curchan].nextchan) < 0) + info->curchan = info->firstchan; + /* notice lack of break here this implys a STATE_SETUP */ + case STATE_SETUP: /* set the muxes and let them settle */ +#if NUMCHANNELS > NUMIMUXES /* only do this if using external muxes */ + outb (iobase+STATUS, + EMUXMAKE(info->curchan) | IMUX(info->curchan) | IEN); + info->state = STATE_CONVERT; + break; +#endif + case STATE_CONVERT: + outb (iobase+STATUS, + EMUXMAKE(info->curchan) | IMUX(info->curchan) | IEN); + outb (iobase+ADHIGH, 0); /* start the conversion */ + info->state = STATE_READ; + break; + } + else /* this is kind of like an idle mode */ + { + outb (iobase+STATUS, IEN); /* no list keep getting interrupts though */ + /* since we have no open channels spin clock rate down to + * minimum to save interrupt overhead */ + outb (iobase+CNTRCNTRL, LD2MODE4); /* counter 2 to mode 4 strobe */ + outb (iobase+CNTR2, 0xff); /* longest period we can generate */ + outb (iobase+CNTR2, 0xff); + return; + } + outb (iobase+CNTRCNTRL, LD2MODE4); /* counter 2 to mode 4 strobe */ + outb (iobase+CNTR2, info->perlo); /* low part of the period count */ + outb (iobase+CNTR2, info->perhi); /* high part of the period count */ +} + + +/* this will put an entry in fifo, returns 1 if the first item in + * fifo was wiped (overflow) or 0 if everything went fine */ +static int putfifo (talog_chan *pchan, u_short fifoent) +{ + pchan->fifo[pchan->fifoend] = fifoent; /* insert the entry in */ + pchan->fifoend++; /* one more in fifo */ + if (pchan->fifoend == FIFOSIZE) pchan->fifoend = 0; /* wrap around */ + /* note: I did intend to write over the oldest entry on overflow */ + if (pchan->fifosize == FIFOSIZE) /* overflowing state already */ + { + pchan->fifostart++; + if (pchan->fifostart == FIFOSIZE) pchan->fifostart = 0; + return 1; /* we overflowed */ + } + pchan->fifosize++; /* actually one bigger, else same size */ + return 0; /* went in just fine */ +} + + +/* Driver initialization */ +static void alog_drvinit (void *unused) +{ + dev_t dev; /* Type for holding device major/minor numbers (int) */ + + if (!alog_devsw_installed) + { + dev = makedev (CDEV_MAJOR, 0); /* description of device major */ + cdevsw_add (&dev, &alog_cdevsw, NULL); /* put driver in cdev table */ + alog_devsw_installed=1; + } +} + +/* System initialization call instance */ + +SYSINIT (alogdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, + alog_drvinit,NULL); + +#endif diff --git a/sys/i386/isa/asc.c b/sys/i386/isa/asc.c index 1a801b08fa69f..fe8dba69d73e4 100644 --- a/sys/i386/isa/asc.c +++ b/sys/i386/isa/asc.c @@ -34,7 +34,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * $Id: asc.c,v 1.31 1998/08/12 18:16:38 bde Exp $ + * $Id: asc.c,v 1.30 1998/06/07 17:10:13 dfr Exp $ */ #include "asc.h" @@ -188,8 +188,6 @@ static int ascprobe (struct isa_device *isdp); static int ascattach(struct isa_device *isdp); struct isa_driver ascdriver = { ascprobe, ascattach, "asc" }; -static ointhand2_t ascintr; - static d_open_t ascopen; static d_close_t ascclose; static d_read_t ascread; @@ -450,7 +448,6 @@ ascattach(struct isa_device *isdp) int unit = isdp->id_unit; struct asc_unit *scu = unittab + unit; - isdp->id_ointr = ascintr; scu->flags |= FLAG_DEBUG; printf("asc%d: [GI1904/Trust Ami-Scan Grey/Color]\n", unit); @@ -500,7 +497,7 @@ ascattach(struct isa_device *isdp) *** ascintr *** the interrupt routine, at the end of DMA... ***/ -static void +void ascintr(int unit) { struct asc_unit *scu = unittab + unit; diff --git a/sys/i386/isa/atapi-cd.c b/sys/i386/isa/atapi-cd.c index f475fa5083b83..62c168c8d2d37 100644 --- a/sys/i386/isa/atapi-cd.c +++ b/sys/i386/isa/atapi-cd.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: atapi-cd.c,v 1.6 1998/12/07 21:58:20 archie Exp $ + * $Id: atapi-cd.c,v 1.2 1998/10/08 06:41:44 sos Exp $ */ #include "wdc.h" @@ -94,6 +94,7 @@ static void acd_done(struct acd *, struct buf *, int, struct atapires); static int acd_read_toc(struct acd *); static int acd_request_wait(struct acd *, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, u_char, char *, int); static void acd_describe(struct acd *); +static int acd_open(dev_t, int, int); static int acd_setchan(struct acd *, u_char, u_char, u_char, u_char); static int acd_eject(struct acd *, int); static void acd_select_slot(struct acd *); @@ -261,11 +262,11 @@ acd_describe(struct acd *cdp) printf("acd%d: drive speed ", cdp->lun); if (cdp->cap.cur_speed != cdp->cap.max_speed) printf("%d - ", cdp->cap.cur_speed * 1000 / 1024); - printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024); + printf("%dKb/sec", cdp->cap.max_speed * 1000 / 1024); if (cdp->cap.buf_size) - printf(", %dKB cache\n", cdp->cap.buf_size); + printf(", %dKb cache\n", cdp->cap.buf_size); - printf("acd%d: supported read types:", cdp->lun); + printf("acd%d: supported read types:", cdp->lun); comma = 0; if (cdp->cap.read_cdr) { printf(" CD-R"); comma = 1; @@ -442,12 +443,16 @@ acdclose(dev_t dev, int flags, int fmt, struct proc *p) static int acdread(dev_t dev, struct uio *uio, int ioflag) { + struct acd *cdp = acdtab[dkunit(dev)]; + return physio(acdstrategy, NULL, dev, 1, minphys, uio); } static int acdwrite(dev_t dev, struct uio *uio, int ioflag) { + struct acd *cdp = acdtab[dkunit(dev)]; + return physio(acdstrategy, NULL, dev, 0, minphys, uio); } @@ -1147,7 +1152,7 @@ acd_read_toc(struct acd *cdp) else printf("%ld:%ld audio ", cdp->info.volsize / 75 / 60, cdp->info.volsize / 75 % 60); - printf("(%ld sectors (%ld bytes)), %d tracks\n", + printf("(%ld sectors (%d bytes)), %d tracks\n", cdp->info.volsize, cdp->info.blksize, cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1); } @@ -1284,6 +1289,7 @@ acd_open_track(struct acd *cdp, struct wormio_prepare_track *ptp) { struct write_param param; struct atapires result; + int error; result = atapi_request_wait(cdp->ata, cdp->unit, ATAPI_MODE_SENSE, 0, 0x05, 0, 0, 0, 0, @@ -1569,6 +1575,8 @@ static acd_devsw_installed = 0; static void acd_drvinit(void *unused) { + dev_t dev; + if (!acd_devsw_installed) { cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &acd_cdevsw); acd_devsw_installed = 1; diff --git a/sys/i386/isa/atapi.c b/sys/i386/isa/atapi.c index 9b3090d8bd203..44cdc4e235017 100644 --- a/sys/i386/isa/atapi.c +++ b/sys/i386/isa/atapi.c @@ -88,7 +88,7 @@ * You will need to make at least three routines: open(), close(), * strategy() and possibly ioctl(). * 2. Make attach() routine, which should allocate all the needed data - * structures and print the device description string (see xxxattach()). + * structures and print the device description string (see wcdattach()). * 3. Add an appropriate case to the switch in atapi_attach() routine, * call attach() routine of the new driver here. Add the appropriate * #include line at the top of attach.c. @@ -104,6 +104,7 @@ #ifndef ATAPI_MODULE # include "acd.h" +# include "wcd.h" # include "wfd.h" # include "wst.h" /* # include "wmd.h" -- add your driver here */ @@ -169,8 +170,11 @@ static int atapi_io (struct atapi *ata, struct atapicmd *ac); static int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac); static int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac); +static void atapi_poll_dsc(struct atapi *ata); + extern int wdstart (int ctrlr); extern int acdattach(struct atapi*, int, struct atapi_params*, int); +extern int wcdattach(struct atapi*, int, struct atapi_params*, int); extern int wfdattach(struct atapi*, int, struct atapi_params*, int); extern int wstattach(struct atapi*, int, struct atapi_params*, int); @@ -300,9 +304,17 @@ int atapi_attach (int ctlr, int unit, int port) ata->attached[unit] = 1; return (1); #else +#if NWCD > 0 + /* ATAPI CD-ROM drives */ + if (wcdattach (ata, unit, ap, ata->debug) < 0) + break; + ata->attached[unit] = 1; + return (1); +#else printf ("wdc%d: ATAPI CD-ROMs not configured\n", ctlr); break; #endif +#endif case AT_TYPE_TAPE: /* streaming tape */ #if NWST > 0 @@ -368,7 +380,7 @@ static char *cmdname (u_char cmd) case 0xbd: return ("ATAPI_MECH_STATUS"); case 0xbe: return ("READ_CD"); } - snprintf (buf, sizeof(buf), "[0x%x]", cmd); + sprintf (buf, "[0x%x]", cmd); return (buf); } @@ -652,8 +664,8 @@ int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac) */ int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac) { - /* Wait for DRQ from 100 usec to 3 msec for slow devices */ - int cnt = ata->intrcmd ? 10000 : ata->slow ? 3000 : 100; + /* Wait for DRQ from 50 usec to 3 msec for slow devices */ + int cnt = ata->intrcmd ? 10000 : ata->slow ? 3000 : 50; int ireason = 0, phase = 0; /* Wait for command phase. */ diff --git a/sys/i386/isa/atapi.h b/sys/i386/isa/atapi.h index 19733257f93c4..dce85fbc883bd 100644 --- a/sys/i386/isa/atapi.h +++ b/sys/i386/isa/atapi.h @@ -226,8 +226,8 @@ struct atapidrv { /* delayed attach info */ }; struct buf; -struct dmy; -typedef void atapi_callback_t(struct dmy *, struct buf *, int, struct atapires); +struct wcd; +typedef void atapi_callback_t(struct wcd *, struct buf *, int, struct atapires); struct atapicmd { /* ATAPI command block */ struct atapicmd *next; /* next command in queue */ diff --git a/sys/i386/isa/atkbd_isa.c b/sys/i386/isa/atkbd_isa.c deleted file mode 100644 index 9cd06297ef712..0000000000000 --- a/sys/i386/isa/atkbd_isa.c +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * Copyright (c) 1999 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 AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: atkbd_isa.c,v 1.1 1999/01/09 02:44:40 yokota Exp $ - */ - -#include "atkbd.h" -#include "opt_kbd.h" - -#if NATKBD > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/tty.h> - -#include <dev/kbd/kbdreg.h> -#include <dev/kbd/atkbdreg.h> - -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> - -static int atkbdprobe(struct isa_device *dev); -static int atkbdattach(struct isa_device *dev); -static ointhand2_t atkbd_isa_intr; - -struct isa_driver atkbddriver = { - atkbdprobe, - atkbdattach, - ATKBD_DRIVER_NAME, - 0, -}; - -static int -atkbdprobe(struct isa_device *dev) -{ - atkbd_softc_t *sc; - int error; - - sc = atkbd_get_softc(dev->id_unit); - if (sc == NULL) - return 0; - - /* try to find a keyboard */ - error = atkbd_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 = atkbd_isa_intr; - - return -1; -} - -static int -atkbdattach(struct isa_device *dev) -{ - atkbd_softc_t *sc; - - sc = atkbd_get_softc(dev->id_unit); - if (sc == NULL) - return 0; - - return ((atkbd_attach_unit(dev->id_unit, sc)) ? 0 : 1); -} - -static void -atkbd_isa_intr(int unit) -{ - keyboard_t *kbd; - - kbd = atkbd_get_softc(unit)->kbd; - (*kbdsw[kbd->kb_index]->intr)(kbd); -} - -#endif /* NATKBD > 0 */ diff --git a/sys/i386/isa/b004.c b/sys/i386/isa/b004.c new file mode 100644 index 0000000000000..5a9357da471ee --- /dev/null +++ b/sys/i386/isa/b004.c @@ -0,0 +1,669 @@ +/* + * FreeBSD device driver for B004-compatible Transputer boards. + * + * based on Linux version Copyright (C) 1993 by Christoph Niemann + * + * Rewritten for FreeBSD by + * Luigi Rizzo (luigi@iet.unipi.it) and + * Lorenzo Vicisano (l.vicisano@iet.unipi.it) + * Dipartimento di Ingegneria dell'Informazione + * Universita` di Pisa + * via Diotisalvi 2, 56126 Pisa, ITALY + * 14 september 1994 + * + * 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 Christoph Niemann, + * Luigi Rizzo and Lorenzo Vicisano - Dipartimento di Ingegneria + * dell'Informazione + * 4. The names of these contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + * + * NOTE NOTE NOTE + * The assembler version is still under development. + */ + +/* #define USE_ASM */ + +#include "bqu.h" +#if NBQU > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include "opt_devfs.h" + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif /*DEVFS*/ + +#include <machine/clock.h> + +#include <i386/isa/b004.h> +#include <i386/isa/isa_device.h> + +#define IOCTL_OUT(arg, ret) *(int*)arg = ret + +#define B004PRI (PZERO+8) + +#define B004_CHANCE 8 + +/* + * Define these symbols if you want to debug the code. + */ +#undef B004_DEBUG +#undef B004_DEBUG_2 + +#ifdef B004_DEBUG +static u_char d_inb(u_int port); +static void d_outb(u_int port, u_char data); + +#define out(port,data) d_outb(port, data) +#define in(a) d_inb(((u_int)a)) +#else +#define out(port, data) outb(port,data) +#define in(port) inb(((u_int)port)) +#endif B004_DEBUG + +#ifdef B004_DEBUG +#define DEB(x) x +#define NO_DEB(x) /* */ +#else +#define DEB(x) /* */ +#define NO_DEB(x) x +#endif + +#ifdef B004_DEBUG_2 +#define DEB2(x) x +#else +#define DEB2(x) +#endif + +static int bquprobe(struct isa_device *idp); +static int bquattach(struct isa_device *idp); + + +struct isa_driver bqudriver = { + bquprobe, bquattach, "bqu" +}; + +static d_open_t bquopen; +static d_close_t bquclose; +static d_read_t bquread; +static d_write_t bquwrite; +static d_ioctl_t bquioctl; +static d_poll_t bqupoll; + +#define CDEV_MAJOR 8 +static struct cdevsw bqu_cdevsw = + { bquopen, bquclose, bquread, bquwrite, /*8*/ + bquioctl, nostop, nullreset, nodevtotty,/* tputer */ + bqupoll, nommap, NULL, "bqu", NULL, -1 }; + +static int b004_sleep; /* wait address */ + +static struct b004_struct b004_table[NBQU]; + +static int first_time=1; + +/* + * At these addresses the driver will search for B004-compatible boards + */ +static int +b004_base_addresses[B004_CHANCE] = { + /* 0x150, 0x170, 0x190, 0x200, 0x300, 0x320, 0x340, 0x360 */ + 0x150, 0x190, 0, 0, 0, 0, 0, 0 +}; + +#ifdef B004_DEBUG +static void +d_outb(u_int port, u_char data) +{ + + printf("OUT 0x%x TO 0x%x\n",data,port); + outb(port,data); +} + +static u_char +d_inb(u_int port) +{ +u_char ap; + ap=inb(port); + printf("INPUT 0x%x FROM 0x%x\n",ap,port); + return(ap); +} +#endif + +static int +detected(int base) +{ + int i; + for(i=0;i<NBQU;i++) + if ((B004_F(i) & B004_EXIST) && (B004_BASE(i)==base)) return 1; + return (0); +} + +#define b004_delay(a) DELAY(10000) + +/* + * static void bqureset(): reset transputer network. + * + */ + +static void +bqureset( const int dev_min ) +{ + DEB(printf("B004 resetting transputer at link %d.\n", dev_min);) + out(B004_BASE(dev_min)+B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET); + b004_delay(dev_min); + + DEB(printf("B004 reset done.\n");) +} + +/* + * static void bquanalyse(): switch transputer network to analyse mode. + * + */ + +static void +bquanalyse( const int dev_min ) +{ + DEB(printf("B004 analysing transputer at link %d.\n", dev_min);) + + out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_ASSERT_ANALYSE); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET); + b004_delay(dev_min); + + out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE); + b004_delay(dev_min); + + DEB(printf("B004 switching to analyse-mode done.\n");) +} + + +/**************************************************************************** + * + * int bquread() - read bytes from the link interface. + * + * At first, the driver checks if the link-interface is ready to send a byte + * to the PC. If not, this check is repeated up to B004_MAXTRY times. + * If the link-interface is not ready after this loop, the driver sleeps for + * an NO=1 ticks and then checks the link-interface again. + * If the interface is still not ready, repeats as above incrementing NO. + * Once almost one byte is read N0 is set to 1. + * If B004_TIMEOUT != 0 and the link-interface is not ready for more than + * B004_TIMEOUT ticks read aborts returnig with the number of bytes read + * or with an error if no byte was read. + * + * By default, B004_TIMEOUT is = 0 (read is blocking) + * + *****************************************************************************/ + +static int +bquread(dev_t dev, struct uio *uio, int flag) +{ + unsigned int dev_min = minor(dev) & 7; + + int timeout=B004_TIMEOUT(dev_min); + int Timeout=timeout; + int idr=B004_IDR(dev_min); + int isr=B004_ISR(dev_min); + char buffer[B004_MAX_BYTES]; + + if ( uio->uio_resid < 0) { + DEB(printf("B004: invalid count for reading = %d.\n", uio->uio_resid);) + return EINVAL; + } + + while ( uio->uio_resid ) { + int sleep_ticks=0; + char *p, *last, *lim; + int i, end = min(B004_MAX_BYTES,uio->uio_resid); + lim= &buffer[end]; + for (p= buffer; p<lim;) { + last=p; + /*** try to read as much as possible ***/ +#ifdef USE_ASM + /* assembly code uses a very tight loop, with + * BX= data port, DX= address port, CX=count, ES:DI=p, AL=data, AH=1 + * SI=retry counter + */ + __asm__ ( + "movl %1, %%edx\n\t" /* isr */ + "movl %2, %%ebx\n\t" /* idr */ + "movl %3, %%edi\n" /* p */ + "movl %4, %%ecx\n\t" /* lim */ + "subl %%edi, %%ecx\n\t" + + "push %%es\n\t" + "movw %%ss, %%ax\n\t" /** prepare ES, DF for transfer */ + "movw %%ax, %%es\n\t" + "cld\n\t" + "movb $1, %%ah\n\t" + + "1:\tinb %%dx, %%al\n\t" + "testb %%ah, %%al\n\t" + "jz 2f\n\t" + "xchgl %%edx, %%ebx\n\t" + "insb\n\t" + "xchgl %%edx, %%ebx\n" + "2:\tloop 1b\n\t" + + "pop %%es\n\t" + "movl %%edi, %0\n\t" /* store p */ + : /* out */ "=g" (p) + : /* in */ "g" (isr), "g" (idr), "g" (p), "g" (lim) + : /* regs */ "eax", "ebx", "edx", "ecx", "edi"); +#else + for (i=lim - p; i-- ;) + if (inb(isr)&B004_READBYTE) *p++ =(char) inb(idr); +#endif + if (last!=p) { + sleep_ticks = 0; + } else { + /*** no new data read, must sleep ***/ + sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks); + if (Timeout) { + if (timeout <=0) { + DEB2(printf("Read : TIMEOUT OCCURRED XXXXXXXXXXX\n");) + break; + } + if (timeout < sleep_ticks) sleep_ticks=timeout; + timeout -= sleep_ticks; + } + DEB2(printf("Read: SLEEPING FOR %d TICKS XXXXX\n",sleep_ticks);) + if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH, + "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1; + } + } + if (p != buffer) { + uiomove((caddr_t)buffer, p - buffer, uio); + } + if( (Timeout) && (timeout <= 0) ) + break; + } + return 0; +} /* bquread() */ + + +/* + * int bquwrite() - write to the link interface. + */ + +static int +bquwrite(dev_t dev, struct uio *uio, int flag) +{ + unsigned int dev_min = minor(dev) & 7; + + int i, end; + int timeout=B004_TIMEOUT(dev_min); + int Timeout=timeout; + int odr=B004_ODR(dev_min); + int osr=B004_OSR(dev_min); + char buffer[B004_MAX_BYTES]; + + if ( uio->uio_resid < 0) { + DEB(printf("B004 invalid argument for writing: count = %d.\n", uio->uio_resid);) + return EINVAL; + } + + while ( uio->uio_resid ) { + int sleep_ticks=0; + char *p, *last, *lim; + end = min(B004_MAX_BYTES,uio->uio_resid); + uiomove((caddr_t)buffer, end, uio); + + lim= &buffer[end]; + for (p= &buffer[0]; p<lim;) { + last=p; +#ifdef USE_ASM + /* assembly code uses a very tight loop, with + * BX= data port, DX= address port, CX=count, DS:SI=p, AL=data, AH=1 + * DI= retry counter + * Unfortunately, C is almost as fast as this! + */ + __asm__ ( + "movl %1, %%edx\n\t" /* osr */ + "movl %2, %%ebx\n\t" /* odr */ + "movl %3, %%esi\n" /* p */ + "movl %4, %%ecx\n\t" /* lim */ + "subl %%esi, %%ecx\n\t" + + "push %%ds\n\t" + "movw %%ss, %%ax\n\t" /** prepare DS, DF for transfer */ + "movw %%ax, %%ds\n\t" + "cld\n\t" + "movb $1, %%ah\n\t" + "movw $100, %%di\n\t" + + "1:\tinb %%dx, %%al\n\t" + "testb %%ah, %%al\n\t" + "jz 2f\n\t" + "xchgl %%edx, %%ebx\n\t" + "outsb\n\t" + "xchgl %%edx, %%ebx\n\t" + "loop 1b\n\t" + "jmp 3f\n" + + "2:\tdec %%di\n\t" + "jnc 1b\n\t" + + "3:\tpop %%ds\n" + "movl %%esi, %0\n\t" /* store p */ + : /* out */ "=g" (p) + : /* in */ "g" (osr), "g" (odr), "g" (p), "g" (lim) + : /* regs */ "eax", "ebx", "edx", "ecx", "esi", "edi"); +#else + for (i=lim - p; i-- ; ) { + if (inb(osr)&B004_WRITEBYTE) outb(odr, *p++); + } +#endif + if (p != last ) { + sleep_ticks=0; + } else { + sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks); + if (Timeout) { + if (timeout <=0) { + DEB2(printf("Write : TIMEOUT OCCURRED XXXXXXXXXXX\n");) + uio->uio_resid += (lim - p); + break; + } + if (timeout < sleep_ticks) sleep_ticks=timeout; + timeout -= sleep_ticks; + } + DEB2(printf("Write: SLEEPING FOR %d TICKS XXXXXXX\n",sleep_ticks);) + if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH, + "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1; + } + } + if( (Timeout) && (timeout <= 0) ) + break; + } + return 0; +} /* bquwrite() */ + +/* + * int bquopen() -- open the link-device. + * + */ + +static int +bquopen(dev_t dev, int flags, int fmt, struct proc *p) +{ + unsigned int dev_min = minor(dev) & 7; + + if (dev_min >= NBQU) { + DEB(printf("B004 not opened, minor number >= %d.\n", NBQU);) + return ENXIO; + } + if ((B004_F(dev_min) & B004_EXIST) == 0) { + DEB(printf("B004 not opened, board %d does not exist.\n", dev_min);) + return ENXIO; + } + if (B004_F(dev_min) & B004_BUSY) { + DEB(printf("B004 not opened, board busy (minor = %d).\n", dev_min);) + return EBUSY; + } + B004_F(dev_min) |= B004_BUSY; + B004_TIMEOUT(dev_min) = 0; + DEB(printf( "B004 opened, minor = %d.\n", dev_min );) + return 0; +} /* bquopen() */ + + +/* + * int b004close() -- close the link device. + */ + +static int +bquclose(dev_t dev, int flags, int fmt, struct proc *p) +{ + unsigned int dev_min = minor(dev) & 7; + + if (dev_min >= NBQU) { + DEB(printf("B004 not released, minor number >= %d.\n", NBQU);) + return ENXIO; + } + B004_F(dev_min) &= ~B004_BUSY; + DEB(printf("B004(%d) released.\n", dev_min );) + return 0; +} + +static int +bqupoll(dev_t dev, int events, struct proc *p) +{ + /* still unimplemented */ + return(seltrue(dev, events, p)); +} + +/* + * int bquioctl() + * + * Supported functions: + * - reset + * - analyse + * - test error flag + * - set timeout + */ + +static int +bquioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) +{ + unsigned int dev_min = minor(dev) & 7; + int result = 0; + + if (dev_min >= NBQU) { + DEB(printf("B004 ioctl exit, minor >= %d.\n", NBQU );) + return ENODEV; + } + + if ((B004_F(dev_min) & B004_EXIST) == 0) { + DEB(printf("B004 ioctl exit, (B004_F & B004_EXIST) == 0.\n" );) + return ENODEV; + } + + switch ( cmd ) { + case B004RESET: /* reset transputer */ + bqureset(dev_min); + DEB(printf("B004 ioctl B004RESET, done\n" );) + break; + case B004WRITEABLE: /* can we write a byte to the C012 ? */ + IOCTL_OUT (addr, ((in(B004_OSR(dev_min))&B004_WRITEBYTE) != 0 )); + break; + case B004READABLE: /* can we read a byte from C012 ? */ + IOCTL_OUT (addr, ((in(B004_ISR(dev_min)) & B004_READBYTE) != 0 )); + break; + case B004ANALYSE: /* switch transputer to analyse mode */ + bquanalyse(dev_min); + break; + case B004ERROR: /* test error-flag */ + IOCTL_OUT (addr, + ((inb(B004_BASE(dev_min)+B004_ERROR_OFFSET) & + B004_TEST_ERROR) ? 0 : 1)); + break; + case B004TIMEOUT: /* set, retrieve timeout for writing & reading*/ + B004_TIMEOUT(dev_min) = *((int *)addr); + break; + default: result = EINVAL; + } + return result; +} /* bquioctl() */ + + +static int +bquattach(struct isa_device *idp) +{ + int unit = idp->id_unit; + struct b004_struct *bp; + int i; + +#ifdef DEVFS +#define BQU_UID 66 +#define BQU_GID 66 +#define BQU_PERM 0600 + bp = &b004_table[unit]; + for ( i = 0; i < 8; i++) { +#ifdef NOTYET + /* if (we've done all the ports found) break; */ +#endif + bp->devfs_token[i][0]= + devfs_add_devswf(&bqu_cdevsw, i, DV_CHR, BQU_UID, + BQU_GID, BQU_PERM, "ttyba%d", i); + bp->devfs_token[i][0]= + devfs_add_devswf(&bqu_cdevsw, i+64, DV_CHR, BQU_UID, + BQU_GID, BQU_PERM, "ttybb%d", i); + bp->devfs_token[i][0]= + devfs_add_devswf(&bqu_cdevsw, i+128, DV_CHR, BQU_UID, + BQU_GID, BQU_PERM, "ttybc%d", i); + bp->devfs_token[i][0]= + devfs_add_devswf(&bqu_cdevsw, i+192, DV_CHR, BQU_UID, + BQU_GID, BQU_PERM, "ttybd%d", unit); + } +#endif + return 1; +} + +/* + * int bquprobe + * + * Initializes the driver. It tries to detect the hardware + * and sets up all relevant data-structures. + */ + +static int +bquprobe(struct isa_device *idp) +{ + unsigned int test; + unsigned int dev_min = idp->id_unit; + int i,found = 0; + /* After a reset it should be possible to write a byte to + the B004. So let'S do a reset and then test the output status + register + */ +#ifdef undef + printf( + "bquprobe::\nIOBASE 0x%x\nIRQ %d\nDRQ %d\nMSIZE %d\nUNIT %d\nFLAGS" + "x0%x\nALIVE %d\n",idp->id_iobase,idp->id_irq, + idp->id_drq,idp->id_msize,idp->id_unit,idp->id_flags,idp->id_alive); +#endif + if(first_time){ + for(i=0;i<NBQU;i++) B004_F(i) &= ~B004_EXIST; + first_time=0; + } + + if(dev_min >= NBQU) return (0); /* No more descriptors */ + if ((idp->id_iobase < 0x100) || (idp->id_iobase >= 0x1000)) + idp->id_iobase=0; /* Dangerous isa addres ) */ + + for (test = 0; (test < B004_CHANCE); test++) { + if((idp->id_iobase==0)&&((!b004_base_addresses[test])|| + detected(b004_base_addresses[test]))) + continue; + idp->id_iobase=b004_base_addresses[test]; + + DEB(printf("Probing device %d at address 0x%x\n",dev_min, + idp->id_iobase); + ) + b004_delay(test); + B004_F(dev_min) = 0; + B004_TIMEOUT(dev_min) = B004_INIT_TIMEOUT; + B004_BASE(dev_min) = idp->id_iobase; + B004_ODR(dev_min) = B004_BASE(dev_min) + B004_ODR_OFFSET; + B004_ISR(dev_min) = B004_BASE(dev_min) + B004_ISR_OFFSET; + B004_OSR(dev_min) = B004_BASE(dev_min) + B004_OSR_OFFSET; + bqureset(dev_min); + + for (i = 0; i < B004_MAXTRY; i++) + if ( in(B004_OSR(dev_min)) == B004_WRITEBYTE) { + B004_F(dev_min) |= B004_EXIST; + out(B004_BASE(dev_min) + B008_INT_OFFSET, 0); + b004_delay(test); + if (in(B004_BASE(dev_min) + B008_INT_OFFSET) & 0x0f == 0) + B004_BOARDTYPE(dev_min) = B008; + else + B004_BOARDTYPE(dev_min) = B004; + printf("bqu%d at 0x0%x (polling) is a B00%s\n", + dev_min,B004_IDR(dev_min), + (B004_BOARDTYPE(dev_min) == B004) ? "4" : "8"); + found = 1; + break; + } + if(!found) { + idp->id_iobase=0; + } + else break; + + } + + if (!found){ + DEB(printf("b004probe(): no B004-board found.\n")); + return (0); + } + + idp->id_maddr=NULL; + idp->id_irq=0; + if(B004_BOARDTYPE(dev_min) == B004) + return(18); + else + return(20); +} /* bquprobe() */ + + +static bqu_devsw_installed = 0; + +static void +bqu_drvinit(void *unused) +{ + dev_t dev; + + if( ! bqu_devsw_installed ) { + dev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&dev,&bqu_cdevsw, NULL); + bqu_devsw_installed = 1; + } +} + +SYSINIT(bqudev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bqu_drvinit,NULL) + + +#endif /* NBQU */ diff --git a/sys/i386/isa/b004.h b/sys/i386/isa/b004.h new file mode 100644 index 0000000000000..8ae161f025277 --- /dev/null +++ b/sys/i386/isa/b004.h @@ -0,0 +1,154 @@ +/* + * b004.h + * + * Based on the Linux driver, by + * Christoph Niemann (niemann@swt.ruhr-uni-bochum.de) + * + * Ported to FreeBSD by Luigi Rizzo (luigi@iet.unipi.it) + * and Lorenzo Vicisano (l.vicisano@iet.unipi.it) + * + * 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 Christoph Niemann, + * Luigi Rizzo and Lorenzo Vicisano - Dipartimento di Ingegneria + * dell'Informazione + * 4. The names of these contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + * + * Works for FreeBSD 1.1.5 + */ + +#ifndef _I386_ISA_B004_H_ +#define _I386_ISA_B004_H_ + +#include <sys/ioccom.h> + +/* + * device status FLAGS + */ +#define B004_EXIST 0x0001 /* Is a B004-Board with at least one + Transputer present ? */ +#define B004_BUSY 0x0002 /* Is the B004-board in use ? */ + +/* + * IOCTL numbers + */ +#define B004RESET _IO ('Q', 0) + /* Reset transputer(s) */ +#define B004WRITEABLE _IOR ('Q', 1, int) + /* Return C012 Output Ready */ +#define B004READABLE _IOR ('Q', 2, int) + /* Return C012 Data Present */ +#define B004ANALYSE _IO ('Q', 3) + /* Switch transputer(s) to ANALYSE mode */ +#define B004ERROR _IOR ('Q', 4, int) + /* Return 1 on ERROR set */ +#define B004TIMEOUT _IOW ('Q', 5, int) + /* Set TIMEOUT for subsequent writing or + reading call, value in ticks, initial + 0 = no timeout (read/write blocking) + "open" sets timeout to 0 */ + + +#define B004_INIT_TIMEOUT 0 /* No timeout yet */ + +/* + * Registers DISPLACEMENT + */ +#define B004_IDR_OFFSET 0 /* Input Data Register */ +#define B004_ODR_OFFSET 1 /* Output Data Register */ +#define B004_ISR_OFFSET 2 /* Input Status Register */ +#define B004_OSR_OFFSET 3 /* Output Status Register */ +#define B004_RESET_OFFSET 16 /* Reset/Error Register */ +#define B004_ERROR_OFFSET B004_RESET_OFFSET +#define B004_ANALYSE_OFFSET 17 /* Analyse Register */ +#define B008_DMA_OFFSET 18 /* B008: DMA request register */ +#define B008_INT_OFFSET 19 /* B008: Interrupt control reg */ + +struct b004_struct { + int flags; /* various flags */ + int idr; /* address of the input data register */ + int odr; /* address if the output data register */ + int isr; /* address of the input status register */ + int osr; /* address of the output status register */ + unsigned int timeout; /* timeout for writing/reading the link */ + int boardtype; /* what kind of board is installed */ + void *devfs_token[8][4]; /* tokens for 4 types for 8 ports */ +}; + +/* + * Id's for the supported boards + */ +#define B004 1 +#define B008 2 + +/* + * Defines for easier access to the b004_table. + */ +#define B004_F(minor) b004_table[minor].flags +#define B004_TIMEOUT(minor) b004_table[minor].timeout +#define B004_BASE(minor) B004_IDR(minor) +#define B004_IDR(minor) b004_table[minor].idr +#define B004_ODR(minor) b004_table[minor].odr +#define B004_ISR(minor) b004_table[minor].isr +#define B004_OSR(minor) b004_table[minor].osr +#define B004_WAIT(minor) b004_table[minor].wait +#define B004_BOARDTYPE(minor) b004_table[minor].boardtype + +/* + * Additional defines for B008-boards + */ +#define B008_DMA(minor) b004_table[minor].int +#define B008_INT(minor) b004_table[minor].dma + +/* + * Number of tries to access isr or osr before reading or writing sleeps + */ +#define B004_MAXTRY 200 + +/* + * Maximum number of bytes to transfer at once + */ +#define B004_MAX_BYTES 2048 + +/* + * bit defines for C012 status ports at base + 2/3 + * accessed with B004_IS, B004_OS, which gets the byte... + */ +#define B004_READBYTE 1 +#define B004_WRITEBYTE 1 + +/* + * bit defines for C012 reset/error port at base + 16 + */ +#define B004_ASSERT_RESET 0x01 /* resetting the transputer */ +#define B004_DEASSERT_RESET 0x00 +#define B004_TEST_ERROR 0x01 /* for testing the transputer's error flag */ + +/* + * bit defines for C012 analyse port at base + 17 + */ +#define B004_ASSERT_ANALYSE 0x01 /* switch transputer to analyse-mode */ +#define B004_DEASSERT_ANALYSE 0x00 + +#endif /* !_I386_ISA_B004_H_ */ diff --git a/sys/i386/isa/bs/bs.c b/sys/i386/isa/bs/bs.c index 1f93746404328..fc543851f09da 100644 --- a/sys/i386/isa/bs/bs.c +++ b/sys/i386/isa/bs/bs.c @@ -39,30 +39,21 @@ #include <i386/isa/bs/bsif.h> #endif -#include <cam/cam.h> -#include <cam/cam_ccb.h> -#include <cam/cam_sim.h> -#include <cam/cam_xpt_sim.h> -#include <cam/cam_debug.h> - -#include <cam/scsi/scsi_all.h> -#include <cam/scsi/scsi_message.h> - /***************************************************************** * Inline phase funcs *****************************************************************/ /* static inline declare */ static BS_INLINE struct targ_info *bs_reselect __P((struct bs_softc *)); -static BS_INLINE void bs_sat_continue __P((struct bs_softc *, struct targ_info *, struct bsccb *)); -static BS_INLINE struct targ_info *bs_selected __P((struct bs_softc *, struct targ_info *, struct bsccb *)); +static BS_INLINE void bs_sat_continue __P((struct bs_softc *, struct targ_info *, struct ccb *)); +static BS_INLINE struct targ_info *bs_selected __P((struct bs_softc *, struct targ_info *, struct ccb *)); static BS_INLINE u_int8_t bs_read_1byte __P((struct bs_softc *)); static BS_INLINE void bs_write_1byte __P((struct bs_softc *, u_int8_t)); -static BS_INLINE void bs_commandout __P((struct bs_softc *, struct targ_info *, struct bsccb *)); +static BS_INLINE void bs_commandout __P((struct bs_softc *, struct targ_info *, struct ccb *)); static BS_INLINE void bs_status_check __P((struct bs_softc *, struct targ_info *)); static BS_INLINE void bs_msgin __P((struct bs_softc *, struct targ_info *)); -static BS_INLINE void bs_msgout __P((struct bs_softc *, struct targ_info *, struct bsccb *)); -static BS_INLINE void bs_disconnect_phase __P((struct bs_softc *, struct targ_info *, struct bsccb *)); -static void bs_phase_error __P((struct targ_info *, struct bsccb *)); +static BS_INLINE void bs_msgout __P((struct bs_softc *, struct targ_info *, struct ccb *)); +static BS_INLINE void bs_disconnect_phase __P((struct bs_softc *, struct targ_info *, struct ccb *)); +static void bs_phase_error __P((struct targ_info *, struct ccb *)); static int bs_scsi_cmd_poll_internal __P((struct targ_info *)); static int bs_xfer __P((struct bs_softc *, char *, int)); static void bs_io_xfer __P((struct targ_info *)); @@ -73,153 +64,99 @@ static void bs_msg_reject __P((struct targ_info *)); static void bshoststart __P((struct bs_softc *, struct targ_info *)); /***************************************************************** - * SIM interface + * Julian scsi interface *****************************************************************/ -void -bs_scsi_cmd(struct cam_sim *sim, union ccb *ccb) +XSBS_INT32T +bs_scsi_cmd(xs) + struct scsi_xfer *xs; { - struct bs_softc *bsc = (struct bs_softc *) cam_sim_softc(sim); - int s, target = (u_int) (ccb->ccb_h.target_id); + struct bs_softc *bsc = (struct bs_softc *) xs->sc_link->adapter_softc; + int s, target = (u_int) (xs->sc_link->target); struct targ_info *ti; - struct bsccb *cb; - - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - ti = bsc->sc_ti[target]; - if ((cb = bs_get_ccb()) == NULL) { - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - xpt_done(ccb); - return; + struct ccb *cb; + u_int flags = xs->flags; + + if (xs->bp == NULL && (bsc->sc_openf & (1 << target)) == 0) + { + s = splbio(); + xs->error = XS_DRIVER_STUFFUP; + xs->flags |= XSBS_ITSDONE; + scsi_done(xs); + splx(s); + return COMPLETE; + } + + ti = bsc->sc_ti[target]; + if ((cb = bs_get_ccb(flags & XSBS_SCSI_NOSLEEP)) == NULL) + return TRY_AGAIN_LATER; + + /* make up ccb! */ + cb->xs = xs; + cb->lun = xs->sc_link->lun; + cb->cmd = (u_int8_t *) xs->cmd; + cb->cmdlen = (int) xs->cmdlen; + cb->data = (u_int8_t *) xs->data; + cb->datalen = (int) xs->datalen; + cb->rcnt = 0; + cb->msgoutlen = 0; + cb->flags = (flags & XSBS_SCSI_POLL) ? BSFORCEIOPOLL : 0; + bs_targ_flags(ti, cb); + cb->tcmax = (xs->timeout >> 10); + if (cb->tcmax < BS_DEFAULT_TIMEOUT_SECOND) + cb->tcmax = BS_DEFAULT_TIMEOUT_SECOND; + +#ifdef BS_ADDRESS_CHECK + /* XXX: + * Sanity check, however this is critical! + * NetBSD 1.0: WRONG + * NetBSD 1.1: OK + * FreeBSD: WRONG + */ + if ((caddr_t) cb->data < (caddr_t) KERNBASE) + { + u_int8_t *altbp; + + altbp = (u_int8_t *) malloc(cb->datalen, M_DEVBUF, M_NOWAIT); + if (altbp == NULL) + { + bs_free_ccb(cb); + return TRY_AGAIN_LATER; } - /* make up ccb! */ - cb->ccb = ccb; - cb->lun = ccb->ccb_h.target_lun; - cb->cmd = ccb->csio.cdb_io.cdb_bytes; - cb->cmdlen = (int) ccb->csio.cdb_len; - cb->data = ccb->csio.data_ptr; - cb->datalen = (int) ccb->csio.dxfer_len; - cb->rcnt = 0; - cb->msgoutlen = 0; - cb->bsccb_flags = 0; - bs_targ_flags(ti, cb); - cb->tcmax = 0;/*(xs->timeout >> 10); default HN2*/ - if (cb->tcmax < BS_DEFAULT_TIMEOUT_SECOND) - cb->tcmax = BS_DEFAULT_TIMEOUT_SECOND; + if (flags & SCSI_DATA_OUT) + bcopy(cb->data, altbp, cb->datalen); + else + bzero(altbp, cb->datalen); - s = splbio(); + cb->data = (u_int8_t *) altbp; + cb->flags |= BSALTBUF; + } +#endif /* BS_ADDRESS_CHECK */ + + s = splbio(); - TAILQ_INSERT_TAIL(&ti->ti_ctab, cb, ccb_chain); + TAILQ_INSERT_TAIL(&ti->ti_ctab, cb, ccb_chain); - if (ti->ti_phase == FREE) { - if (ti->ti_state == BS_TARG_START) + if (ti->ti_phase == FREE) + { + if (ti->ti_state == BS_TARG_START) + { + if ((flags & XSBS_SCSI_POLL) == 0) bs_start_syncmsg(ti, NULL, BS_SYNCMSG_ASSERT); - bscmdstart(ti, BSCMDSTART); } + bscmdstart(ti, BSCMDSTART); + } + if ((flags & XSBS_SCSI_POLL) == 0) + { splx(s); - break; - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - case XPT_EN_LUN: /* Enable LUN as a target */ - case XPT_TARGET_IO: /* Execute target I/O request */ - case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ - case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ - case XPT_ABORT: /* Abort the specified CCB */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_SET_TRAN_SETTINGS: - /* XXX Implement */ - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; - case XPT_GET_TRAN_SETTINGS: { - struct ccb_trans_settings *cts; - struct targ_info *ti; - /*int s;*/ - - cts = &ccb->cts; - ti = bsc->sc_ti[ccb->ccb_h.target_id]; - /*s = splcam();*/ - if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { - if (ti->ti_cfgflags & BS_SCSI_DISC) - cts->flags = CCB_TRANS_DISC_ENB; - else - cts->flags = 0; - if (ti->ti_cfgflags & BS_SCSI_QTAG) - cts->flags |= CCB_TRANS_TAG_ENB; - cts->sync_period = ti->ti_syncnow.period; - cts->sync_offset = ti->ti_syncnow.offset; - cts->bus_width = 0;/*HN2*/ - - cts->valid = CCB_TRANS_SYNC_RATE_VALID - | CCB_TRANS_SYNC_OFFSET_VALID - | CCB_TRANS_BUS_WIDTH_VALID - | CCB_TRANS_DISC_VALID - | CCB_TRANS_TQ_VALID; - ccb->ccb_h.status = CAM_REQ_CMP; - } else - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - - /*splx(s);*/ - xpt_done(ccb); - break; - } - case XPT_CALC_GEOMETRY: { /* not yet HN2 */ - struct ccb_calc_geometry *ccg; - u_int32_t size_mb; - u_int32_t secs_per_cylinder; - - ccg = &ccb->ccg; - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - - ccg->heads = 8; - ccg->secs_per_track = 34; - - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - bshw_chip_reset(bsc); /* XXX need perfect RESET? */ - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - case XPT_TERM_IO: /* Terminate the I/O process */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_PATH_INQ: { /* Path routing inquiry */ - struct ccb_pathinq *cpi = &ccb->cpi; - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = NTARGETS - 1; - cpi->max_lun = 7; - cpi->initiator_id = bsc->sc_hostid; - cpi->bus_id = cam_sim_bus(sim); - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "NEC", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: -/*printf("bs: non support func_code = %d ", ccb->ccb_h.func_code);*/ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; + return SUCCESSFULLY_QUEUED; } + + bs_scsi_cmd_poll(ti, cb); + splx(s); + + return COMPLETE; } /************************************************** @@ -233,7 +170,7 @@ bscmdstart(ti, flags) struct targ_info *ti; int flags; { - struct bsccb *cb; + struct ccb *cb; struct bs_softc *bsc = ti->ti_bsc; if ((cb = ti->ti_ctab.tqh_first) == NULL) @@ -249,9 +186,9 @@ bscmdstart(ti, flags) ti->ti_scsp.datalen = cb->datalen; ti->ti_scsp.seglen = 0; if (cb->rcnt) - cb->bsccb_flags &= ~(BSSAT | BSLINK); + cb->flags &= ~(BSSAT | BSLINK); ti->ti_flags &= ~BSCFLAGSMASK; - ti->ti_flags |= cb->bsccb_flags & BSCFLAGSMASK; + ti->ti_flags |= cb->flags & BSCFLAGSMASK; cb->tc = cb->tcmax; /* GO GO */ @@ -274,13 +211,13 @@ bscmdstart(ti, flags) return 1; } -struct bsccb * +struct ccb * bscmddone(ti) struct targ_info *ti; { struct bs_softc *bsc = ti->ti_bsc; - struct bsccb *cb = ti->ti_ctab.tqh_first; - union ccb *ccb; + struct ccb *cb = ti->ti_ctab.tqh_first; + struct scsi_xfer *xs; int error; if (ti->ti_state == BS_TARG_SYNCH) @@ -296,12 +233,12 @@ bscmddone(ti) do { - ccb = cb->ccb; - error = CAM_REQ_CMP; + xs = cb->xs; + error = XS_NOERROR; - if (cb->bsccb_flags & (BSITSDONE | BSSENSECCB | BSCASTAT)) + if (cb->flags & (BSITSDONE | BSSENSECCB | BSCASTAT)) { - if (cb->bsccb_flags & BSSENSECCB) + if (cb->flags & BSSENSECCB) { cb->error &= ~BSDMAABNORMAL; if (cb->error == 0) @@ -309,17 +246,18 @@ bscmddone(ti) ti->ti_flags |= BSERROROK; } - else if (cb->bsccb_flags & BSCASTAT) + else if (cb->flags & BSCASTAT) { if (ti->ti_flags & BSCASTAT) { ti->ti_flags &= ~BSCASTAT; - error = CAM_AUTOSNS_VALID|CAM_SCSI_STATUS_ERROR; - if (ccb) - ccb->csio.sense_data = ti->sense;/* XXX may not be csio.... */ + error = XS_SENSE; + if (xs) + xs->sense = ti->sense; } else - error = CAM_AUTOSENSE_FAIL; + error = XS_DRIVER_STUFFUP; + ti->ti_flags |= BSERROROK; } else bs_panic(bsc, "internal error"); @@ -333,11 +271,11 @@ bscmddone(ti) if (cb->rcnt >= bsc->sc_retry || (cb->error & BSFATALIO)) { if (cb->error & (BSSELTIMEOUT | BSTIMEOUT)) - error = CAM_CMD_TIMEOUT; + error = XS_TIMEOUT; else if (cb->error & BSTARGETBUSY) - error = CAM_SCSI_STATUS_ERROR; + error = XS_BUSY; else - error = CAM_REQ_CMP_ERR; + error = XS_DRIVER_STUFFUP; break; } @@ -345,7 +283,7 @@ bscmddone(ti) { /* must clear the target's sense state */ cb->rcnt++; - cb->bsccb_flags |= (BSITSDONE | BSCASTAT); + cb->flags |= (BSITSDONE | BSCASTAT); cb->error &= ~BSREQSENSE; return bs_request_sense(ti); } @@ -357,15 +295,16 @@ bscmddone(ti) cb->error &= ~BSDMAABNORMAL; continue; } - if (/*(xs && xs->bp) || can't know whether bufferd i/o or not */ - (cb->error & BSSELTIMEOUT) == 0) + + if ((xs && xs->bp) || (cb->error & BSSELTIMEOUT) == 0) bs_debug_print(bsc, ti); + cb->rcnt++; return cb; } #ifdef BS_DIAG - cb->bsccb_flags |= BSITSDONE; + cb->flags |= BSITSDONE; #endif /* BS_DIAG */ if (bsc->sc_poll) { @@ -376,18 +315,28 @@ bscmddone(ti) TAILQ_REMOVE(&ti->ti_ctab, cb, ccb_chain); - if (ccb) + if (xs) { - ccb->ccb_h.status = error; - ccb->csio.scsi_status = ti->ti_status;/*XXX*/ - xpt_done(ccb); +#ifdef BS_ADDRESS_CHECK + if (cb->flags & BSALTBUF) + { + if (xs->flags & SCSI_DATA_IN) + bcopy(cb->data, xs->data, cb->datalen); + free(cb->data, M_DEVBUF); + } +#endif /* BS_ADDRESS_CHECK */ + + if ((xs->error = error) == XS_NOERROR) + xs->resid = 0; + xs->flags |= XSBS_ITSDONE; + scsi_done(xs); } bs_free_ccb(cb); cb = ti->ti_ctab.tqh_first; } - while (cb != NULL && (cb->bsccb_flags & BSITSDONE) != 0); + while (cb != NULL && (cb->flags & BSITSDONE) != 0); /* complete */ return NULL; @@ -404,7 +353,7 @@ bshoststart(bsc, ti) struct bs_softc *bsc; struct targ_info *ti; { - struct bsccb *cb; + struct ccb *cb; int s; if (bsc->sc_flags & BSINACTIVE) @@ -427,7 +376,7 @@ again: } #ifdef BS_DIAG - if (cb->bsccb_flags & BSITSDONE) + if (cb->flags & BSITSDONE) bs_panic(bsc, "bshoststart: already done"); if (bsc->sc_nexus || (ti->ti_flags & BSNEXUS)) @@ -546,7 +495,7 @@ static BS_INLINE struct targ_info * bs_selected(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { if (bsc->sc_busstat != BSR_SELECTED) @@ -638,7 +587,7 @@ static BS_INLINE void bs_sat_continue(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { BS_SETUP_PHASE(SATRESEL); @@ -771,7 +720,7 @@ static BS_INLINE void bs_commandout(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { u_int8_t scsi_cmd[16]; int len; @@ -831,7 +780,7 @@ bs_quick_abort(ti, msg) struct targ_info *ti; u_int msg; { - struct bsccb *cb; + struct ccb *cb; if ((cb = ti->ti_ctab.tqh_first) == NULL) return; @@ -867,7 +816,7 @@ bs_msgin_ext(ti) struct targ_info *ti; { struct bs_softc *bsc = ti->ti_bsc; - struct bsccb *cb = ti->ti_ctab.tqh_first; + struct ccb *cb = ti->ti_ctab.tqh_first; int count; u_int reqlen; u_int32_t *ptr; @@ -940,14 +889,14 @@ bs_msg_reject(ti) struct targ_info *ti; { struct bs_softc *bsc = ti->ti_bsc; - struct bsccb *cb = ti->ti_ctab.tqh_first; + struct ccb *cb = ti->ti_ctab.tqh_first; char *s = "unexpected msg reject"; switch (ti->ti_ophase) { case CMDPHASE: s = "cmd rejected"; - cb->bsccb_flags &= ~BSLINK; + cb->flags &= ~BSLINK; BS_SETUP_MSGPHASE(IOCOMPLETED); break; @@ -955,7 +904,7 @@ bs_msg_reject(ti) if (ti->ti_msgout & 0x80) { s = "identify msg rejected"; - cb->bsccb_flags &= ~BSDISC; + cb->flags &= ~BSDISC; BS_SETUP_MSGPHASE(IOCOMPLETED); } else if (ti->ti_msgout == MSG_EXTEND) @@ -1090,7 +1039,7 @@ static BS_INLINE void bs_msgout(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { u_int8_t msg[MAXMSGLEN + 1]; @@ -1165,7 +1114,7 @@ static BS_INLINE void bs_disconnect_phase(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { switch (bsc->sc_msgphase) @@ -1237,7 +1186,7 @@ struct bs_err bs_cmderr[] = { static void bs_phase_error(ti, cb) struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { struct bs_softc *bsc = ti->ti_bsc; struct bs_err *pep; @@ -1293,13 +1242,13 @@ bs_phase_error(ti, cb) /************************************************** * ### SCSI PHASE SEQUENCER ### **************************************************/ -static BS_INLINE void bs_ack_wait __P((struct bs_softc *, struct targ_info *, struct bsccb *)); +static BS_INLINE void bs_ack_wait __P((struct bs_softc *, struct targ_info *, struct ccb *)); static BS_INLINE void bs_ack_wait(bsc, ti, cb) struct bs_softc *bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { int wc = bsc->sc_wc; @@ -1338,7 +1287,7 @@ bs_sequencer(bsc) struct bs_softc *bsc; { register struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; /************************************************** * Check reset @@ -1423,7 +1372,7 @@ bs_sequencer(bsc) default: /* XXX: - * check check check for safety !! + * check check check for safty !! */ if (bsc->sc_selwait) { @@ -1582,7 +1531,7 @@ bs_scsi_cmd_poll_internal(cti) { struct bs_softc *bsc = cti->ti_bsc; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; int i, waits, delay_count; bsc->sc_poll++; @@ -1601,7 +1550,7 @@ bs_scsi_cmd_poll_internal(cti) { ti->ti_flags |= BSFORCEIOPOLL; if ((cb = ti->ti_ctab.tqh_first) != NULL) - cb->bsccb_flags |= BSFORCEIOPOLL; + cb->flags |= BSFORCEIOPOLL; } } @@ -1630,7 +1579,7 @@ bs_scsi_cmd_poll_internal(cti) int bs_scsi_cmd_poll(cti, targetcb) struct targ_info *cti; - struct bsccb *targetcb; + struct ccb *targetcb; { struct bs_softc *bsc = cti->ti_bsc; struct targ_info *ti; diff --git a/sys/i386/isa/bs/bs_isa.c b/sys/i386/isa/bs/bs_isa.c index 644dc0e8a14fb..7215de65cc480 100644 --- a/sys/i386/isa/bs/bs_isa.c +++ b/sys/i386/isa/bs/bs_isa.c @@ -59,8 +59,7 @@ bs_args_copy(bsc, ia, hw) bsc->sm_offset = 0; bsc->sc_cfgflags = DVCFG_MINOR(ia->ia_cfgflags); - snprintf(bsc->sc_dvname, sizeof(bsc->sc_dvname), - "%s", bsc->sc_dev.dv_xname); + strcpy(bsc->sc_dvname, bsc->sc_dev.dv_xname); } static int diff --git a/sys/i386/isa/bs/bsfunc.c b/sys/i386/isa/bs/bsfunc.c index c92b706769336..47dfe84788f80 100644 --- a/sys/i386/isa/bs/bsfunc.c +++ b/sys/i386/isa/bs/bsfunc.c @@ -51,7 +51,7 @@ int bs_debug_flag = 0; static void bs_print_syncmsg __P((struct targ_info *, char*)); static void bs_timeout_target __P((struct targ_info *)); -static void bs_kill_msg __P((struct bsccb *cb)); +static void bs_kill_msg __P((struct ccb *cb)); static int bs_start_target __P((struct targ_info *)); static int bs_check_target __P((struct targ_info *)); @@ -59,8 +59,8 @@ static int bs_check_target __P((struct targ_info *)); /************************************************************* * CCB ************************************************************/ -GENERIC_CCB_STATIC_ALLOC(bs, bsccb) -GENERIC_CCB(bs, bsccb, ccb_chain) +GENERIC_CCB_STATIC_ALLOC(bs, ccb) +GENERIC_CCB(bs, ccb, ccb_chain) /************************************************************* * TIMEOUT @@ -87,7 +87,7 @@ bstimeout(arg) { struct bs_softc *bsc = (struct bs_softc *) arg; struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; int s; s = splbio(); @@ -126,7 +126,7 @@ bstimeout(arg) *************************************************/ static u_int8_t cmd_unit_ready[6]; -struct bsccb * +struct ccb * bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout) struct targ_info *ti; u_int lun; @@ -137,19 +137,19 @@ bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout) u_int flags; int timeout; { - struct bsccb *cb; + struct ccb *cb; - if ((cb = bs_get_ccb()) == NULL) + if ((cb = bs_get_ccb(XSBS_SCSI_NOSLEEP)) == NULL) bs_panic(ti->ti_bsc, "can not get ccb mem"); - cb->ccb = NULL; + cb->xs = NULL; cb->lun = lun; cb->cmd = (cmd ? cmd : cmd_unit_ready); cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready)); cb->data = data; cb->datalen = (data ? datalen : 0); cb->msgoutlen = 0; - cb->bsccb_flags = flags & BSCFLAGSMASK; + cb->flags = flags & BSCFLAGSMASK; bs_targ_flags(ti, cb); cb->rcnt = 0; cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout : @@ -160,11 +160,11 @@ bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout) return cb; } -struct bsccb * +struct ccb * bs_make_msg_ccb(ti, lun, cb, msg, timex) struct targ_info *ti; u_int lun; - struct bsccb *cb; + struct ccb *cb; struct msgbase *msg; u_int timex; { @@ -175,7 +175,7 @@ bs_make_msg_ccb(ti, lun, cb, msg, timex) cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0, flags, timex); else - cb->bsccb_flags |= flags & BSCFLAGSMASK; + cb->flags |= flags & BSCFLAGSMASK; cb->msgoutlen = msg->msglen; bcopy(msg->msg, cb->msgout, msg->msglen); @@ -189,7 +189,7 @@ bs_send_msg(ti, lun, msg, timex) struct msgbase *msg; int timex; { - struct bsccb *cb; + struct ccb *cb; cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex); bscmdstart(ti, BSCMDSTART); @@ -198,7 +198,7 @@ bs_send_msg(ti, lun, msg, timex) static void bs_kill_msg(cb) - struct bsccb *cb; + struct ccb *cb; { cb->msgoutlen = 0; } @@ -206,11 +206,11 @@ bs_kill_msg(cb) /************************************************** * MAKE SENSE CCB **************************************************/ -struct bsccb * +struct ccb * bs_request_sense(ti) struct targ_info *ti; { - struct bsccb *cb; + struct ccb *cb; bzero(ti->scsi_cmd, sizeof(struct scsi_sense)); bzero(&ti->sense, sizeof(struct scsi_sense_data)); @@ -223,7 +223,7 @@ bs_request_sense(ti) sizeof(struct scsi_sense_data), BSFORCEIOPOLL, BS_DEFAULT_TIMEOUT_SECOND); - cb->bsccb_flags |= BSSENSECCB; + cb->flags |= BSSENSECCB; return cb; } @@ -234,7 +234,7 @@ bs_request_sense(ti) int bs_start_syncmsg(ti, cb, flag) struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; int flag; { struct syncdata *negp, *maxp; @@ -308,7 +308,7 @@ bs_print_syncmsg(ti, s) int bs_analyze_syncmsg(ti, cb) struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { struct bs_softc *bsc = ti->ti_bsc; u_int8_t ans = ti->ti_syncnow.state; @@ -411,13 +411,13 @@ bs_reset_device(ti) } /* send abort msg */ -struct bsccb * +struct ccb * bs_force_abort(ti) struct targ_info *ti; { struct bs_softc *bsc = ti->ti_bsc; struct msgbase msg; - struct bsccb *cb = ti->ti_ctab.tqh_first; + struct ccb *cb = ti->ti_ctab.tqh_first; u_int lun; if (cb) @@ -523,7 +523,7 @@ bs_reset_nexus(bsc) struct bs_softc *bsc; { struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; bsc->sc_flags &= ~(BSRESET | BSUNDERRESET); if (bsc->sc_poll) @@ -575,7 +575,7 @@ bs_reset_nexus(bsc) for ( ; cb; cb = cb->ccb_chain.tqe_next) { bs_kill_msg(cb); - cb->bsccb_flags &= ~(BSITSDONE | BSCASTAT); + cb->flags &= ~(BSITSDONE | BSCASTAT); cb->error = 0; } @@ -597,15 +597,19 @@ static int bs_start_target(ti) struct targ_info *ti; { - struct bsccb *cb; - struct scsi_start_stop_unit cmd; + struct ccb *cb; + struct scsi_start_stop cmd; - bzero(&cmd, sizeof(struct scsi_start_stop_unit)); + bzero(&cmd, sizeof(struct scsi_start_stop)); +#ifdef __NetBSD__ cmd.opcode = START_STOP; +#else + cmd.op_code = START_STOP; +#endif cmd.how = SSS_START; ti->ti_lun = 0; cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &cmd, - sizeof(struct scsi_start_stop_unit), + sizeof(struct scsi_start_stop), NULL, 0, BSFORCEIOPOLL, BS_MOTOR_TIMEOUT); bscmdstart(ti, BSCMDSTART); return bs_scsi_cmd_poll(ti, cb); @@ -619,7 +623,7 @@ bs_check_target(ti) struct bs_softc *bsc = ti->ti_bsc; struct scsi_inquiry scsi_cmd; struct scsi_inquiry_data scsi_inquiry_data; - struct bsccb *cb; + struct ccb *cb; int count, retry = bsc->sc_retry; int s, error = COMPLETE; @@ -629,7 +633,11 @@ bs_check_target(ti) /* inquiry */ bzero(&scsi_cmd, sizeof(scsi_cmd)); +#ifdef __NetBSD__ scsi_cmd.opcode = INQUIRY; +#else + scsi_cmd.op_code = INQUIRY; +#endif scsi_cmd.length = sizeof(struct scsi_inquiry_data); cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &scsi_cmd, sizeof(scsi_cmd), @@ -654,7 +662,7 @@ bs_check_target(ti) goto done; } - if (cb->bsccb_flags & BSCASTAT) + if (cb->flags & BSCASTAT) bs_printf(ti, "check", "could not clear CA state"); ti->ti_error = 0; @@ -889,7 +897,7 @@ bs_debug_print(bsc, ti) struct bs_softc *bsc; struct targ_info *ti; { - struct bsccb *cb; + struct ccb *cb; /* host stat */ printf("%s <DEBUG INFO> nexus %lx bs %lx bus status %lx \n", @@ -913,7 +921,7 @@ bs_debug_print(bsc, ti) sp->datalen, (u_long) sp->data, sp->seglen); if (cb) printf("odatalen %x flags %x\n", - cb->datalen, cb->bsccb_flags); + cb->datalen, cb->flags); else printf("\n"); printf("error flags %b\n", ti->ti_error, BSERRORBITS); diff --git a/sys/i386/isa/bs/bsfunc.h b/sys/i386/isa/bs/bsfunc.h index 13c06868d04cb..5658a27fd60a4 100644 --- a/sys/i386/isa/bs/bsfunc.h +++ b/sys/i386/isa/bs/bsfunc.h @@ -44,22 +44,22 @@ struct targ_info *bs_init_target_info __P((struct bs_softc *, int)); /* msg op */ int bs_send_msg __P((struct targ_info *, u_int, struct msgbase *, int)); -struct bsccb *bs_request_sense __P((struct targ_info *)); +struct ccb *bs_request_sense __P((struct targ_info *)); /* sync msg op */ -int bs_start_syncmsg __P((struct targ_info *, struct bsccb *, int)); +int bs_start_syncmsg __P((struct targ_info *, struct ccb *, int)); int bs_send_syncmsg __P((struct targ_info *)); -int bs_analyze_syncmsg __P((struct targ_info *, struct bsccb *)); +int bs_analyze_syncmsg __P((struct targ_info *, struct ccb *)); /* reset device */ void bs_scsibus_start __P((struct bs_softc *)); void bs_reset_nexus __P((struct bs_softc *)); -struct bsccb *bs_force_abort __P((struct targ_info *)); +struct ccb *bs_force_abort __P((struct targ_info *)); void bs_reset_device __P((struct targ_info *)); /* ccb */ -struct bsccb *bs_make_internal_ccb __P((struct targ_info *, u_int, u_int8_t *, u_int, u_int8_t *, u_int, u_int, int)); -struct bsccb *bs_make_msg_ccb __P((struct targ_info *, u_int, struct bsccb *, struct msgbase *, u_int)); +struct ccb *bs_make_internal_ccb __P((struct targ_info *, u_int, u_int8_t *, u_int, u_int8_t *, u_int, u_int, int)); +struct ccb *bs_make_msg_ccb __P((struct targ_info *, u_int, struct ccb *, struct msgbase *, u_int)); /* misc funcs */ void bs_printf __P((struct targ_info *, char *, char *)); @@ -77,9 +77,9 @@ void bs_debug_print __P((struct bs_softc *, struct targ_info *)); static BS_INLINE int bs_check_sat __P((struct targ_info *)); static BS_INLINE int bs_check_smit __P((struct targ_info *)); static BS_INLINE int bs_check_disc __P((struct targ_info *)); -static BS_INLINE int bs_check_link __P((struct targ_info *, struct bsccb *)); +static BS_INLINE int bs_check_link __P((struct targ_info *, struct ccb *)); static BS_INLINE u_int8_t bs_identify_msg __P((struct targ_info *)); -static BS_INLINE void bs_targ_flags __P((struct targ_info *, struct bsccb *)); +static BS_INLINE void bs_targ_flags __P((struct targ_info *, struct ccb *)); static BS_INLINE int bs_check_disc(ti) @@ -108,13 +108,13 @@ bs_check_smit(ti) static BS_INLINE int bs_check_link(ti, cb) struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { - struct bsccb *nextcb; + struct ccb *nextcb; return ((ti->ti_flags & BSLINK) && (nextcb = cb->ccb_chain.tqe_next) && - (nextcb->bsccb_flags & BSLINK)); + (nextcb->flags & BSLINK)); } static BS_INLINE u_int8_t @@ -128,17 +128,17 @@ bs_identify_msg(ti) static BS_INLINE void bs_targ_flags(ti, cb) struct targ_info *ti; - struct bsccb *cb; + struct ccb *cb; { u_int cmf = (u_int) bshw_cmd[cb->cmd[0]]; - cb->bsccb_flags |= ((cmf & (BSSAT | BSSMIT | BSLINK)) | BSDISC); - cb->bsccb_flags &= ti->ti_mflags; + cb->flags |= ((cmf & (BSSAT | BSSMIT | BSLINK)) | BSDISC); + cb->flags &= ti->ti_mflags; if (cb->datalen < DEV_BSIZE) - cb->bsccb_flags &= ~BSSMIT; - if (cb->bsccb_flags & BSFORCEIOPOLL) - cb->bsccb_flags &= ~(BSLINK | BSSMIT | BSSAT | BSDISC); + cb->flags &= ~BSSMIT; + if (cb->flags & BSFORCEIOPOLL) + cb->flags &= ~(BSLINK | BSSMIT | BSSAT | BSDISC); } /************************************************** diff --git a/sys/i386/isa/bs/bshw.c b/sys/i386/isa/bs/bshw.c index 2cfe06472eaef..9b6656916c0ec 100644 --- a/sys/i386/isa/bs/bshw.c +++ b/sys/i386/isa/bs/bshw.c @@ -385,7 +385,7 @@ bshw_setup_ctrl_reg(bsc, flags) void bshw_issue_satcmd(bsc, cb, link) struct bs_softc *bsc; - struct bsccb *cb; + struct ccb *cb; int link; { int i; diff --git a/sys/i386/isa/bs/bshw.h b/sys/i386/isa/bs/bshw.h index 8c698438a4ad8..384cb0b0988a6 100644 --- a/sys/i386/isa/bs/bshw.h +++ b/sys/i386/isa/bs/bshw.h @@ -97,7 +97,7 @@ int bshw_board_probe __P((struct bs_softc *, u_int *, u_int *)); void bshw_lock __P((struct bs_softc *)); void bshw_unlock __P((struct bs_softc *)); void bshw_get_syncreg __P((struct bs_softc *)); -void bshw_issue_satcmd __P((struct bs_softc *, struct bsccb *, int)); +void bshw_issue_satcmd __P((struct bs_softc *, struct ccb *, int)); void bshw_print_port __P((struct bs_softc *)); void bs_lc_smit_xfer __P((struct targ_info *, u_int)); diff --git a/sys/i386/isa/bs/bshw_dma.c b/sys/i386/isa/bs/bshw_dma.c index 5b32de740493a..b3683f6fb5fa3 100644 --- a/sys/i386/isa/bs/bshw_dma.c +++ b/sys/i386/isa/bs/bshw_dma.c @@ -101,7 +101,7 @@ bs_dma_xfer(ti, direction) /* setup segaddr */ sp->segaddr = (u_int8_t *) phys; /* setup seglen */ - endva = (vm_offset_t)round_page((unsigned long)(sp->data + sp->datalen)); + endva = (vm_offset_t)round_page(sp->data + sp->datalen); for (va = (vm_offset_t) sp->data; ; phys = nphys) { if ((va += BSHW_NBPG) >= endva) diff --git a/sys/i386/isa/bs/bsif.c b/sys/i386/isa/bs/bsif.c index 948d3b61fec2b..d9a8210c82319 100644 --- a/sys/i386/isa/bs/bsif.c +++ b/sys/i386/isa/bs/bsif.c @@ -42,15 +42,6 @@ #include <i386/isa/bs/bsif.h> #endif /* __FreeBSD__ */ -#include <cam/cam.h> -#include <cam/cam_ccb.h> -#include <cam/cam_sim.h> -#include <cam/cam_xpt_sim.h> -#include <cam/cam_debug.h> - -#include <cam/scsi/scsi_all.h> -#include <cam/scsi/scsi_message.h> - /************************************************** * DEVICE DECLARE **************************************************/ @@ -78,9 +69,7 @@ struct scsi_adapter pc98texa55bs = { #ifdef __FreeBSD__ static int bsprobe __P((struct isa_device *)); -static void bs_poll(struct cam_sim *sim); -static int bsattach(struct isa_device *); -static ointhand2_t bsintr; +static int bsattach __P((struct isa_device *)); static int bsprint __P((void *, const char *)); static void bs_scsi_minphys __P((struct buf *)); static int bs_dmarangecheck __P((caddr_t, unsigned)); @@ -90,7 +79,7 @@ struct isa_driver bsdriver = { bsattach, "bs" }; -#if 0 + struct scsi_device bs_dev = { NULL, /* Use default error handler */ NULL, /* have a queue, served by this */ @@ -99,14 +88,14 @@ struct scsi_device bs_dev = { "bs", 0, {0, 0} }; -#endif + u_int32_t bs_adapter_info(unit) int unit; { return (1); } -#if 0 + static struct scsi_adapter pc98texa55bs = { bs_scsi_cmd, bs_scsi_minphys, @@ -115,7 +104,7 @@ static struct scsi_adapter pc98texa55bs = { bs_adapter_info, "bs", {0, 0} }; -#endif + static u_short pc98_irq_ball[16] = { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15 @@ -168,7 +157,7 @@ bsprobe(dev) else bsc->sm_offset = (u_long) 0; - snprintf(bsc->sc_dvname, sizeof(bsc->sc_dvname), "bs%d", unit); + sprintf(bsc->sc_dvname, "bs%d", unit); if (dev->id_iobase == 0) { @@ -223,12 +212,6 @@ bsprint(aux, name) } #ifdef __FreeBSD__ -static void -bs_poll(struct cam_sim *sim) -{ - bs_sequencer(cam_sim_softc(sim)); -} - static int bsattach(dev) struct isa_device *dev; @@ -236,37 +219,27 @@ bsattach(dev) int unit = dev->id_unit; struct bs_softc *bsc = bscdata[unit]; struct scsibus_data *scbus; - struct cam_devq *devq; - dev->id_ointr = bsintr; + bsc->sc_link.adapter_unit = unit; + bsc->sc_link.adapter_targ = bsc->sc_hostid; + bsc->sc_link.flags = SDEV_BOUNCE; + bsc->sc_link.opennings = XSMAX; + bsc->sc_link.adapter_softc = bsc; + bsc->sc_link.adapter = &pc98texa55bs; + bsc->sc_link.device = &bs_dev; /* - * CAM support HN2 MAX_START, MAX_TAGS xxxx + * Prepare the scsibus_data area for the upperlevel + * scsi code. */ - devq = cam_simq_alloc(256/*MAX_START*/); - if (devq == NULL) - return 0; - - bsc->sim = cam_sim_alloc(bs_scsi_cmd, bs_poll, "bs", - bsc, unit, 1, 32/*MAX_TAGS*/, devq); - if (bsc->sim == NULL) { - cam_simq_free(devq); + scbus = scsi_alloc_bus(); + if (!scbus) return 0; - } - - if (xpt_bus_register(bsc->sim, 0) != CAM_SUCCESS) { - free(bsc->sim, M_DEVBUF); - return 0; - } - - if (xpt_create_path(&bsc->path, /*periph*/NULL, - cam_sim_path(bsc->sim), CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister(cam_sim_path(bsc->sim)); - cam_sim_free(bsc->sim, /*free_simq*/TRUE); - free(bsc->sim, M_DEVBUF); - return 0; - } + scbus->adapter_link = &bsc->sc_link; + /* + * ask the adapter what subunits are present + */ + scsi_attachdevs(scbus); bs_start_timeout(bsc); return 1; } @@ -283,7 +256,7 @@ bsintr(arg) #endif /* __NetBSD__ */ #ifdef __FreeBSD__ -static void +void bsintr(unit) int unit; { @@ -303,7 +276,7 @@ bs_scsi_minphys(bp) bp->b_bcount = BSDMABUFSIZ; minphys(bp); } -#if 0 + XSBS_INT32T bs_target_open(sc, cf) struct scsi_link *sc; @@ -323,7 +296,7 @@ bs_target_open(sc, cf) bs_setup_ctrl(ti, (u_int)sc->quirks, flags); return 0; } -#endif + /***************************************************************** * BS MEMORY ALLOCATION INTERFACE *****************************************************************/ @@ -386,7 +359,7 @@ static int bs_dmarangecheck(caddr_t va, unsigned length) { vm_offset_t phys, priorpage = 0, endva; - endva = (vm_offset_t)round_page((unsigned long)(va+length)); + endva = (vm_offset_t)round_page(va+length); for (; va < (caddr_t)endva; va += PAGE_SIZE) { phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); if (phys == 0) diff --git a/sys/i386/isa/bs/bsif.h b/sys/i386/isa/bs/bsif.h index 0c6347867656a..478944fcaea39 100644 --- a/sys/i386/isa/bs/bsif.h +++ b/sys/i386/isa/bs/bsif.h @@ -117,11 +117,9 @@ #include <machine/ipl.h> #include <machine/dvcfg.h> -#include <cam/scsi/scsi_all.h> -#if 0 -#include <cam/scsi/scsiconf.h> -#endif -#include <cam/scsi/scsi_da.h> +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <scsi/scsi_disk.h> #include <pc98/pc98/pc98.h> #include <i386/isa/isa_device.h> @@ -175,8 +173,8 @@ * xs flags's abstraction (all currently used) ***************************************************/ #define XSBS_ITSDONE ITSDONE -#ifdef __NetBSD__ #define XSBS_SCSI_NOSLEEP SCSI_NOSLEEP +#ifdef __NetBSD__ #define XSBS_SCSI_POLL SCSI_POLL #endif /* __NetBSD__ */ #ifdef __FreeBSD__ @@ -184,17 +182,20 @@ #endif /* __FreeBSD__ */ /*************************************************** + * Special operations + ***************************************************/ +#ifdef __FreeBSD__ +#define BS_ADDRESS_CHECK +#endif /* __FreeBSD__ */ + +/*************************************************** * declare ***************************************************/ /* (I) common declare */ void bs_alloc_buf __P((struct targ_info *)); -#ifdef __NetBSD__ XSBS_INT32T bs_target_open __P((struct scsi_link *, struct cfdata *)); XSBS_INT32T bs_scsi_cmd __P((struct scsi_xfer *)); -#endif -#ifdef __FreeBSD__ -void bs_scsi_cmd(struct cam_sim *sim, union ccb *ccb); -#endif + extern int delaycount; /* (II) os depend declare */ diff --git a/sys/i386/isa/bs/bsvar.h b/sys/i386/isa/bs/bsvar.h index 9eea57a6065a8..9167c2d156183 100644 --- a/sys/i386/isa/bs/bsvar.h +++ b/sys/i386/isa/bs/bsvar.h @@ -92,7 +92,7 @@ * PARAMETER **************************************************/ #define NTARGETS 8 -#define RETRIES 0 /* number of retries before giving up */ +#define RETRIES 4 /* number of retries before giving up */ #define HARDRETRIES 3 #define XSMAX 4 #define BSDMABUFSIZ 0x10000 @@ -240,7 +240,7 @@ struct sc_p { #define BSERRORBITS "\020\014busy\013abnormal\012retry\011msgerr\010fatal\007seltimeout\006sense\005timeout\004statuserr\003parity\002cmderr\001dmaerr" -/* bsccb bsccb_flags & targ_info flags & cmd flags*/ +/* ccb & targ_info flags & cmd flags*/ #define BSREAD 0x0001 #define BSSAT 0x0002 #define BSLINK 0x0004 @@ -258,14 +258,14 @@ struct sc_p { #define BSCFLAGSMASK (0xffff) -struct bsccb { - TAILQ_ENTRY(bsccb) ccb_chain; +struct ccb { + TAILQ_ENTRY(ccb) ccb_chain; - union ccb *ccb; /* upper drivers info */ + struct scsi_xfer *xs; /* upper drivers info */ u_int lun; /* lun */ - u_int bsccb_flags; /* control flags */ + u_int flags; /* control flags */ int rcnt; /* retry counter of this ccb */ @@ -290,75 +290,75 @@ struct bsccb { int tcmax; }; -GENERIC_CCB_ASSERT(bs, bsccb) +GENERIC_CCB_ASSERT(bs, ccb) /* target info */ struct targ_info { -/*0*/ TAILQ_ENTRY(targ_info) ti_tchain; /* targ_info link */ + TAILQ_ENTRY(targ_info) ti_tchain; /* targ_info link */ -/*4*/ TAILQ_ENTRY(targ_info) ti_wchain; /* wait link */ + TAILQ_ENTRY(targ_info) ti_wchain; /* wait link */ -/*8*/ struct bs_softc *ti_bsc; /* our controller */ -/*c*/ u_int ti_id; /* scsi id */ -/*10*/ u_int ti_lun; /* current lun */ + struct bs_softc *ti_bsc; /* our controller */ + u_int ti_id; /* scsi id */ + u_int ti_lun; /* current lun */ -/*14*/ struct bsccbtab ti_ctab, ti_bctab; /* ccb */ + struct ccbtab ti_ctab, ti_bctab; /* ccb */ #define BS_TARG_NULL 0 #define BS_TARG_CTRL 1 #define BS_TARG_START 2 #define BS_TARG_SYNCH 3 #define BS_TARG_RDY 4 -/*24*/ int ti_state; /* target state */ + int ti_state; /* target state */ -/*28*/ u_int ti_cfgflags; /* target cfg flags */ + u_int ti_cfgflags; /* target cfg flags */ -/*2c*/ u_int ti_flags; /* flags */ -/*30*/ u_int ti_mflags; /* flags masks */ + u_int ti_flags; /* flags */ + u_int ti_mflags; /* flags masks */ -/*34*/ u_int ti_error; /* error flags */ -/*38*/ u_int ti_herrcnt; /* hardware err retry counter */ + u_int ti_error; /* error flags */ + u_int ti_herrcnt; /* hardware err retry counter */ /***************************************** * scsi phase data *****************************************/ -/*3c*/ struct sc_p ti_scsp; /* saved scsi data pointer */ + struct sc_p ti_scsp; /* saved scsi data pointer */ -/*50*/ enum scsi_phase ti_phase; /* scsi phase */ -/*54*/ enum scsi_phase ti_ophase; /* previous scsi phase */ + enum scsi_phase ti_phase; /* scsi phase */ + enum scsi_phase ti_ophase; /* previous scsi phase */ -/*58*/ u_int8_t ti_status; /* status in */ + u_int8_t ti_status; /* status in */ -/*59*/ u_int8_t ti_msgin[MAXMSGLEN]; /* msgin buffer */ -/*64*/ int ti_msginptr; + u_int8_t ti_msgin[MAXMSGLEN]; /* msgin buffer */ + int ti_msginptr; -/*68*/ u_int8_t ti_msgout; /* last msgout byte */ -/*69*/ u_int8_t ti_emsgout; /* last msgout byte */ -/*6c*/ u_int ti_omsgoutlen; /* for retry msgout */ + u_int8_t ti_msgout; /* last msgout byte */ + u_int8_t ti_emsgout; /* last msgout byte */ + u_int ti_omsgoutlen; /* for retry msgout */ -/*70*/ struct syncdata ti_syncmax; /* synch data (scsi) */ -/*72*/ struct syncdata ti_syncnow; -/*74*/ u_int8_t ti_sync; /* synch val (chip) */ + struct syncdata ti_syncmax; /* synch data (scsi) */ + struct syncdata ti_syncnow; + u_int8_t ti_sync; /* synch val (chip) */ /***************************************** * bounce buffer & smit data pointer *****************************************/ -/*75*/ u_int8_t *bounce_phys; -/*76*/ u_int8_t *bounce_addr; -/*78*/ u_int bounce_size; + u_int8_t *bounce_phys; + u_int8_t *bounce_addr; + u_int bounce_size; -/*7c*/ u_long sm_offset; + u_long sm_offset; /***************************************** * target inq data *****************************************/ -/*79*/ u_int8_t targ_type; -/*7a*/ u_int8_t targ_support; + u_int8_t targ_type; + u_int8_t targ_support; /***************************************** * generic scsi cmd buffer for this target *****************************************/ -/*7b*/ u_int8_t scsi_cmd[12]; + u_int8_t scsi_cmd[12]; struct scsi_sense_data sense; }; @@ -371,6 +371,8 @@ struct bs_softc { *****************************************/ OS_DEPEND_DEVICE_HEADER + OS_DEPEND_SCSI_HEADER + OS_DEPEND_MISC_HEADER /***************************************** @@ -431,7 +433,7 @@ struct bs_softc { u_int sc_wc; /* weight count */ int sc_poll; - struct bsccb *sc_outccb; + struct ccb *sc_outccb; /***************************************** * wd33c93 chip depend section @@ -460,12 +462,6 @@ struct bs_softc { *****************************************/ #define BS_DVNAME_LEN 16 u_char sc_dvname[BS_DVNAME_LEN]; - - /***************************************** - * CAM support - *****************************************/ - struct cam_sim *sim; - struct cam_path *path; }; /************************************************* @@ -500,10 +496,10 @@ extern int bs_debug_flag; /************************************************* * Function declare *************************************************/ -int bs_scsi_cmd_internal __P((struct bsccb *, u_int)); -struct bsccb *bscmddone __P((struct targ_info *)); +int bs_scsi_cmd_internal __P((struct ccb *, u_int)); +struct ccb *bscmddone __P((struct targ_info *)); int bscmdstart __P((struct targ_info *, int)); -int bs_scsi_cmd_poll __P((struct targ_info *, struct bsccb *)); +int bs_scsi_cmd_poll __P((struct targ_info *, struct ccb *)); int bs_sequencer __P((struct bs_softc *)); void bs_poll_timeout __P((struct bs_softc *, char *)); @@ -511,9 +507,8 @@ void bs_poll_timeout __P((struct bs_softc *, char *)); * XXX *************************************************/ /* misc error */ -#define COMPLETE 2 -#define NOTARGET (-2) -#define HASERROR (-1) +#define NOTARGET -2 +#define HASERROR -1 /* XXX: use scsi_message.h */ /* status */ diff --git a/sys/i386/isa/bt_isa.c b/sys/i386/isa/bt_isa.c index f646f85bf1580..8009a36569d86 100644 --- a/sys/i386/isa/bt_isa.c +++ b/sys/i386/isa/bt_isa.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bt_isa.c,v 1.4 1998/10/12 18:53:33 imp Exp $ + * $Id: bt_isa.c,v 1.3 1998/10/10 00:44:12 imp Exp $ */ #include <sys/param.h> @@ -86,10 +86,24 @@ bt_isa_probe(dev) * Bound our board search if the user has * specified an exact port. */ - bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index); - - if (port_index < 0) - return 0; + if (dev->id_iobase > 0) { + for (;port_index <= max_port_index; port_index++) + if (dev->id_iobase >= bt_isa_ports[port_index].addr) + break; + if ((port_index > max_port_index) + || (dev->id_iobase != bt_isa_ports[port_index].addr)) { + printf(" +bt_isa_probe: Invalid baseport of 0x%x specified. +bt_isa_probe: Nearest valid baseport is 0x%x. +bt_isa_probe: Failing probe.\n", + dev->id_iobase, + (port_index <= max_port_index) + ? bt_isa_ports[port_index].addr + : bt_isa_ports[max_port_index].addr); + return 0; + } + max_port_index = port_index; + } /* Attempt to find an adapter */ for (;port_index <= max_port_index; port_index++) { @@ -97,7 +111,7 @@ bt_isa_probe(dev) u_int ioport; int error; - ioport = bt_iop_from_bio(port_index); + ioport = bt_isa_ports[port_index].addr; /* * Ensure this port has not already been claimed already @@ -105,7 +119,7 @@ bt_isa_probe(dev) */ if (bt_check_probed_iop(ioport) != 0) continue; - dev->id_iobase = ioport; + dev->id_iobase = bt_isa_ports[port_index].addr; if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET)) continue; @@ -155,7 +169,6 @@ bt_isa_probe(dev) printf("bt_isa_probe: Invalid DMA setting " "detected for adapter at 0x%x. " "Failing probe\n", ioport); - return (0); } } else { /* VL DMA */ diff --git a/sys/i386/isa/ccbque.h b/sys/i386/isa/ccbque.h index 0d9eeecb9f550..7530068d13954 100644 --- a/sys/i386/isa/ccbque.h +++ b/sys/i386/isa/ccbque.h @@ -36,6 +36,7 @@ #define _CCBQUE_H_ #define CCB_MWANTED 0x01 +#define CCB_WOK(fl) (((fl) == 0) ? M_WAITOK : M_NOWAIT) /* (I) structure and prototype */ #define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \ @@ -48,7 +49,7 @@ struct CCBTYPE##que { \ }; \ \ void DEV##_init_ccbque __P((int)); \ -struct CCBTYPE *DEV##_get_ccb __P((void)); \ +struct CCBTYPE *DEV##_get_ccb __P((int)); \ void DEV##_free_ccb __P((register struct CCBTYPE *)); /* (II) static allocated memory */ @@ -68,7 +69,8 @@ DEV##_init_ccbque(count) \ } \ \ struct CCBTYPE * \ -DEV##_get_ccb() \ +DEV##_get_ccb(flags) \ + int flags; \ { \ register struct CCBTYPE *cb; \ int s = splbio(); \ @@ -85,7 +87,7 @@ again: \ } \ else \ { \ - cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT); \ + cb = malloc(sizeof(*cb), M_DEVBUF, CCB_WOK(flags));\ if (cb != NULL) \ { \ bzero(cb, sizeof(*cb)); \ @@ -95,6 +97,12 @@ again: \ CCBTYPE##que.count --; \ } \ \ + if (flags == 0) \ + { \ + CCBTYPE##que.flags |= CCB_MWANTED; \ + tsleep((caddr_t) &CCBTYPE##que.count, PRIBIO, "ccbwait", 0);\ + goto again; \ + } \ cb = NULL; \ \ out: \ diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index d9bca71ad7c16..7515141cb1f6f 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.128 1998/10/23 10:46:20 phk Exp $ + * $Id: clock.c,v 1.126 1998/09/20 03:47:54 bde Exp $ */ /* @@ -126,7 +126,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; @@ -137,7 +137,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; @@ -173,7 +173,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 */ @@ -182,9 +182,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 */ @@ -193,7 +193,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) @@ -751,8 +751,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) { @@ -801,16 +801,16 @@ 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) */ } /* - * 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) @@ -829,17 +829,17 @@ inittodr(time_t base) splx(s); } - /* 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) @@ -847,21 +847,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 */ sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); @@ -877,12 +877,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() @@ -900,7 +900,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); @@ -908,7 +908,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; @@ -1118,7 +1118,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); } @@ -1138,7 +1138,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/i386/isa/ctx.c b/sys/i386/isa/ctx.c index 413302d504718..3e094ee8a6b53 100644 --- a/sys/i386/isa/ctx.c +++ b/sys/i386/isa/ctx.c @@ -8,7 +8,7 @@ * of this software, nor does the author assume any responsibility * for damages incurred with its use. * - * $Id: ctx.c,v 1.28 1998/06/14 10:52:52 bde Exp $ + * $Id: ctx.c,v 1.27 1998/06/07 17:10:15 dfr Exp $ */ /* @@ -196,12 +196,12 @@ ctxattach(struct isa_device * devp) sr->iobase = devp->id_iobase; sr->maddr = devp->id_maddr; sr->msize = devp->id_msize; + return (1); #ifdef DEVFS sr->devfs_token = devfs_add_devswf(&ctx_cdevsw, 0, DV_CHR, 0, 0, 0600, "ctx%d", devp->id_unit); #endif /* DEVFS */ - return (1); } static int diff --git a/sys/i386/isa/cx.c b/sys/i386/isa/cx.c index 9b00dabb8d638..b4fb32460fb7b 100644 --- a/sys/i386/isa/cx.c +++ b/sys/i386/isa/cx.c @@ -417,8 +417,7 @@ int cxioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case 8: o->iftype = c->board->if8type; break; } if (c->master != c->ifp) - snprintf (o->master, sizeof(o->master), - "%s%d", c->master->if_name, + sprintf (o->master, "%s%d", c->master->if_name, c->master->if_unit); else *o->master = 0; @@ -846,7 +845,7 @@ int cxrinta (cx_chan_t *c) } /* Discard exception characters. */ - if ((risr & RISA_SCMASK) && tp && (tp->t_iflag & IXON)) + if ((risr & RISA_SCMASK) && (tp->t_iflag & IXON)) reoir |= REOI_DISCEXC; /* Handle received data. */ diff --git a/sys/i386/isa/cy.c b/sys/i386/isa/cy.c index 794d4d690b929..3f765678f0c1b 100644 --- a/sys/i386/isa/cy.c +++ b/sys/i386/isa/cy.c @@ -27,7 +27,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: cy.c,v 1.82 1998/12/24 14:17:57 bde Exp $ + * $Id: cy.c,v 1.70 1998/08/20 05:21:50 bde Exp $ */ #include "opt_compat.h" @@ -37,6 +37,8 @@ /* * TODO: + * Implement BREAK. + * Fix overflows when closing line. * Atomic COR change. * Consoles. */ @@ -86,9 +88,6 @@ #include <machine/clock.h> #include <machine/ipl.h> -#ifndef SMP -#include <machine/lock.h> -#endif #include <i386/isa/isa_device.h> #include <i386/isa/cyreg.h> @@ -153,16 +152,6 @@ #define CD1400_xIVR_CHAN_SHIFT 3 #define CD1400_xIVR_CHAN 0x1F -/* - * ETC states. com->etc may also contain a hardware ETC command value, - * meaning that execution of that command is pending. - */ -#define ETC_NONE 0 /* we depend on bzero() setting this */ -#define ETC_BREAK_STARTING 1 -#define ETC_BREAK_STARTED 2 -#define ETC_BREAK_ENDING 3 -#define ETC_BREAK_ENDED 4 - #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ #define RS_IBUFSIZE 256 @@ -211,7 +200,6 @@ #define CS_DTR_OFF 0x10 /* DTR held off */ #define CS_ODONE 4 /* output completed */ #define CS_RTS_IFLOW 8 /* use RTS input flow control */ -#define CSE_ODONE 1 /* output transmitted */ static char const * const error_desc[] = { #define CE_OVERRUN 0 @@ -243,10 +231,6 @@ struct com_s { bool_t active_out; /* nonzero if the callout device is open */ #if 0 u_char cfcr_image; /* copy of value written to CFCR */ -#endif - u_char etc; /* pending Embedded Transmit Command */ - u_char extra_state; /* more flag bits, separate for order trick */ -#if 0 u_char fifo_image; /* copy of value written to FIFO */ #endif u_char gfrcr_image; /* copy of value read from GFRCR */ @@ -321,7 +305,6 @@ struct com_s { u_int start_count; /* no. of calls to comstart() */ u_int start_real; /* no. of calls that did something */ #endif - u_char car; /* CD1400 CAR shadow (if first unit in cd) */ u_char channel_control;/* CD1400 CCR control command shadow */ u_char cor[3]; /* CD1400 COR1-3 shadows */ u_char intr_enable; /* CD1400 SRER shadow */ @@ -352,15 +335,10 @@ struct com_s { /* PCI driver entry point. */ int cyattach_common __P((cy_addr cy_iobase, int cy_align)); -ointhand2_t siointr; static int cy_units __P((cy_addr cy_iobase, int cy_align)); static int sioattach __P((struct isa_device *dev)); -static void cd1400_channel_cmd __P((struct com_s *com, int cmd)); -static void cd1400_channel_cmd_wait __P((struct com_s *com)); -static void cd_etc __P((struct com_s *com, int etc)); -static int cd_getreg __P((struct com_s *com, int reg)); -static void cd_setreg __P((struct com_s *com, int reg, int val)); +static void cd1400_channel_cmd __P((cy_addr iobase, int cmd, int cy_align)); static timeout_t siodtrwakeup; static void comhardclose __P((struct com_s *com)); #if 0 @@ -450,11 +428,11 @@ sioprobe(dev) iobase = (cy_addr)dev->id_maddr; /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ - cy_inb(iobase, CY16_RESET, 0); /* XXX? */ + cd_inb(iobase, CY16_RESET, 0); /* XXX? */ DELAY(500); /* wait for the board to get its act together */ /* this is needed to get the board out of reset */ - cy_outb(iobase, CY_CLEAR_INTR, 0, 0); + cd_outb(iobase, CY_CLEAR_INTR, 0, 0); DELAY(500); return (cy_units(iobase, 0) == 0 ? 0 : -1); @@ -528,7 +506,6 @@ sioattach(isdp) printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter); isdp->id_unit = adapter; /* XXX */ } - isdp->id_ointr = siointr; isdp->id_ri_flags |= RI_FAST; return (1); } @@ -601,7 +578,6 @@ cyattach_common(cy_iobase, cy_align) com->cy_align = cy_align; com->cy_iobase = cy_iobase; com->iobase = iobase; - com->car = ~CD1400_CAR_CHAN; /* * We don't use all the flags from <sys/ttydefaults.h> since they @@ -664,7 +640,7 @@ cyattach_common(cy_iobase, cy_align) } /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); + cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); return (adapter); } @@ -678,6 +654,7 @@ sioopen(dev, flag, mode, p) { struct com_s *com; int error; + cy_addr iobase; int mynor; int s; struct tty *tp; @@ -747,25 +724,48 @@ open_top: tp->t_ififosize = 2 * RS_IBUFSIZE; tp->t_ispeedwat = (speed_t)-1; tp->t_ospeedwat = (speed_t)-1; - - /* Encode per-board unit in LIVR for access in intr routines. */ - cd_setreg(com, CD1400_LIVR, - (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); - - (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); #if 0 + (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); com->poll = com->no_irq; com->poll_output = com->loses_outints; #endif ++com->wopeners; + iobase = com->iobase; + + /* reset this channel */ + cd_outb(iobase, CD1400_CAR, com->cy_align, + unit & CD1400_CAR_CHAN); + cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align); + + /* + * Resetting disables the transmitter and receiver as well as + * flushing the fifos so some of our cached state becomes + * invalid. The documentation suggests that all registers + * for the current channel are reset to defaults, but + * apparently none are. We wouldn't want DTR cleared. + */ + com->channel_control = 0; + + /* Encode per-board unit in LIVR for access in intr routines. */ + cd_outb(iobase, CD1400_LIVR, com->cy_align, + (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); + + /* + * raise dtr and generally set things up correctly. this + * has the side-effect of selecting the appropriate cd1400 + * channel, to help us with subsequent channel control stuff + */ error = comparam(tp, &tp->t_termios); --com->wopeners; if (error != 0) goto out; + /* + * XXX we should goto open_top if comparam() slept. + */ #if 0 if (com->hasfifo) { /* - * (Re)enable and flush fifos. + * (Re)enable and drain fifos. * * Certain SMC chips cause problems if the fifos * are enabled while input is ready. Turn off the @@ -797,21 +797,14 @@ open_top: | IER_EMSC); enable_intr(); #else /* !0 */ - /* - * Flush fifos. This requires a full channel reset which - * also disables the transmitter and receiver. Recover - * from this. - */ - cd1400_channel_cmd(com, - CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); - cd1400_channel_cmd(com, com->channel_control); - + /* XXX raise RTS too */ + (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); disable_intr(); com->prev_modem_status = com->last_modem_status - = cd_getreg(com, CD1400_MSVR2); - cd_setreg(com, CD1400_SRER, - com->intr_enable - = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); + = cd_inb(iobase, CD1400_MSVR2, com->cy_align); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable + = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); enable_intr(); #endif /* 0 */ /* @@ -872,7 +865,6 @@ sioclose(dev, flag, mode, p) com = com_addr(MINOR_TO_UNIT(mynor)); tp = com->tp; s = spltty(); - cd_etc(com, CD1400_ETC_STOPBREAK); (*linesw[tp->t_line].l_close)(tp, flag); disc_optim(tp, &tp->t_termios, com); siostop(tp, FREAD | FWRITE); @@ -904,15 +896,9 @@ comhardclose(com) com->poll_output = FALSE; #endif com->do_timestamp = 0; + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); #if 0 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#else - /* XXX */ - disable_intr(); - com->etc = ETC_NONE; - cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); - enable_intr(); - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); #endif { @@ -920,7 +906,8 @@ comhardclose(com) outb(iobase + com_ier, 0); #else disable_intr(); - cd_setreg(com, CD1400_SRER, com->intr_enable = 0); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable = 0); enable_intr(); #endif tp = com->tp; @@ -942,9 +929,10 @@ comhardclose(com) com->channel_control = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | CD1400_CCR_RCVDIS; - cd1400_channel_cmd(com, com->channel_control); + cd1400_channel_cmd(iobase, com->channel_control, + com->cy_align); - if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { + if (com->dtr_wait != 0) { timeout(siodtrwakeup, com, com->dtr_wait); com->state |= CS_DTR_OFF; } @@ -1064,16 +1052,16 @@ siointr(unit) u_char recv_data; u_char serv_type; #ifdef PollMode + u_char save_car; u_char save_rir; #endif #ifdef PollMode save_rir = cd_inb(iobase, CD1400_RIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter rx service */ cd_outb(iobase, CD1400_CAR, cy_align, save_rir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_rir & CD1400_CAR_CHAN; serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); com = com_addr(baseu @@ -1081,7 +1069,7 @@ siointr(unit) & CD1400_xIVR_CHAN)); #else /* ack receive service */ - serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); + serv_type = cy_inb(iobase, CY8_SVCACKR); com = com_addr(baseu + + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) @@ -1229,6 +1217,7 @@ cont: cd_outb(iobase, CD1400_RIR, cy_align, save_rir & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif @@ -1237,6 +1226,7 @@ cont: struct com_s *com; u_char modem_status; #ifdef PollMode + u_char save_car; u_char save_mir; #else u_char vector; @@ -1244,17 +1234,16 @@ cont: #ifdef PollMode save_mir = cd_inb(iobase, CD1400_MIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter modem service */ cd_outb(iobase, CD1400_CAR, cy_align, save_mir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_mir & CD1400_CAR_CHAN; com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS + (save_mir & CD1400_MIR_CHAN)); #else /* ack modem service */ - vector = cy_inb(iobase, CY8_SVCACKM, cy_align); + vector = cy_inb(iobase, CY8_SVCACKM); com = com_addr(baseu + ((vector >> CD1400_xIVR_CHAN_SHIFT) @@ -1293,9 +1282,7 @@ cont: cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); + |= CD1400_SRER_TXRDY); } else { com->state &= ~CS_ODEVREADY; if (com->intr_enable @@ -1303,9 +1290,7 @@ cont: cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); + &= ~CD1400_SRER_TXRDY); } } #endif @@ -1316,6 +1301,7 @@ cont: cd_outb(iobase, CD1400_MIR, cy_align, save_mir & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif @@ -1323,6 +1309,7 @@ cont: if (status & CD1400_SVRR_TXRDY) { struct com_s *com; #ifdef PollMode + u_char save_car; u_char save_tir; #else u_char vector; @@ -1330,106 +1317,22 @@ cont: #ifdef PollMode save_tir = cd_inb(iobase, CD1400_TIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter tx service */ cd_outb(iobase, CD1400_CAR, cy_align, save_tir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_tir & CD1400_CAR_CHAN; - com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS + (save_tir & CD1400_TIR_CHAN)); #else /* ack transmit service */ - vector = cy_inb(iobase, CY8_SVCACKT, cy_align); + vector = cy_inb(iobase, CY8_SVCACKT); com = com_addr(baseu + ((vector >> CD1400_xIVR_CHAN_SHIFT) & CD1400_xIVR_CHAN)); #endif - if (com->etc != ETC_NONE) { - if (com->intr_enable & CD1400_SRER_TXRDY) { - /* - * Here due to sloppy SRER_TXRDY - * enabling. Ignore. Come back when - * tx is empty. - */ - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } - switch (com->etc) { - case CD1400_ETC_SENDBREAK: - case CD1400_ETC_STOPBREAK: - /* - * Start the command. Come back on - * next tx empty interrupt, hopefully - * after command has been executed. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] |= CD1400_COR2_ETC); - cd_outb(iobase, CD1400_TDR, cy_align, - CD1400_ETC_CMD); - cd_outb(iobase, CD1400_TDR, cy_align, - com->etc); - if (com->etc == CD1400_ETC_SENDBREAK) - com->etc = ETC_BREAK_STARTING; - else - com->etc = ETC_BREAK_ENDING; - goto terminate_tx_service; - case ETC_BREAK_STARTING: - /* - * BREAK is now on. Continue with - * SRER_TXMPTY processing, hopefully - * don't come back. - */ - com->etc = ETC_BREAK_STARTED; - break; - case ETC_BREAK_STARTED: - /* - * Came back due to sloppy SRER_TXMPTY - * enabling. Hope again. - */ - break; - case ETC_BREAK_ENDING: - /* - * BREAK is now off. Continue with - * SRER_TXMPTY processing and don't - * come back. The SWI handler will - * restart tx interrupts if necessary. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] - &= ~CD1400_COR2_ETC); - com->etc = ETC_BREAK_ENDED; - if (!(com->state & CS_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - setsofttty(); - } - break; - case ETC_BREAK_ENDED: - /* - * Shouldn't get here. Hope again. - */ - break; - } - } - if (com->intr_enable & CD1400_SRER_TXMPTY) { - if (!(com->extra_state & CSE_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->extra_state |= CSE_ODONE; - setsofttty(); - } - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - &= ~CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { u_char *ioptr; u_int ocount; @@ -1457,24 +1360,9 @@ cont: } else { /* output just completed */ com->state &= ~CS_BUSY; - - /* - * The setting of CSE_ODONE may be - * stale here. We currently only - * use it when CS_BUSY is set, and - * fixing it when we clear CS_BUSY - * is easiest. - */ - if (com->extra_state & CSE_ODONE) { - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - } - cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); + &= ~CD1400_SRER_TXRDY); } if (!(com->state & CS_ODONE)) { com_events += LOTS_OF_EVENTS; @@ -1487,11 +1375,11 @@ cont: } /* terminate service context */ -terminate_tx_service: #ifdef PollMode cd_outb(iobase, CD1400_TIR, cy_align, save_tir & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif @@ -1499,7 +1387,7 @@ terminate_tx_service: } /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); + cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); schedsofttty(); @@ -1524,6 +1412,7 @@ sioioctl(dev, cmd, data, flag, p) { struct com_s *com; int error; + cy_addr iobase; int mynor; int s; struct tty *tp; @@ -1534,6 +1423,7 @@ sioioctl(dev, cmd, data, flag, p) mynor = minor(dev); com = com_addr(MINOR_TO_UNIT(mynor)); + iobase = com->iobase; if (mynor & CONTROL_MASK) { struct termios *ct; @@ -1609,21 +1499,17 @@ sioioctl(dev, cmd, data, flag, p) splx(s); return (error); } + cd_outb(iobase, CD1400_CAR, com->cy_align, + MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); switch (cmd) { - case TIOCSBRK: #if 0 + case TIOCSBRK: outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); -#else - cd_etc(com, CD1400_ETC_SENDBREAK); -#endif break; case TIOCCBRK: -#if 0 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#else - cd_etc(com, CD1400_ETC_STOPBREAK); -#endif break; +#endif /* 0 */ case TIOCSDTR: (void)commctl(com, TIOCM_DTR, DMBIS); break; @@ -1689,6 +1575,7 @@ repeat: u_char *buf; struct com_s *com; u_char *ibuf; + cy_addr iobase; int incc; struct tty *tp; @@ -1747,8 +1634,11 @@ repeat: outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); + iobase = com->iobase, + cd_outb(iobase, CD1400_CAR, com->cy_align, + unit & CD1400_CAR_CHAN), + cd_outb(iobase, com->mcr_rts_reg, com->cy_align, + com->mcr_image |= com->mcr_rts); #endif enable_intr(); com->ibuf = ibuf; @@ -1768,25 +1658,12 @@ repeat: (*linesw[tp->t_line].l_modem) (tp, com->prev_modem_status & MSR_DCD); } - if (com->extra_state & CSE_ODONE) { - disable_intr(); - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - enable_intr(); - if (!(com->state & CS_BUSY)) { - tp->t_state &= ~TS_BUSY; - ttwwakeup(com->tp); - } - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup(&com->etc); - } - } if (com->state & CS_ODONE) { disable_intr(); com_events -= LOTS_OF_EVENTS; com->state &= ~CS_ODONE; + if (!(com->state & CS_BUSY)) + com->tp->t_state &= ~TS_BUSY; enable_intr(); (*linesw[tp->t_line].l_start)(tp); } @@ -1858,6 +1735,7 @@ comparam(tp, t) u_long cy_clock; int idivisor; int iflag; + cy_addr iobase; int iprescaler; int itimeout; int odivisor; @@ -1883,19 +1761,21 @@ comparam(tp, t) return (EINVAL); /* parameters are OK, convert them to the com struct and the device */ + iobase = com->iobase; s = spltty(); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); if (odivisor == 0) (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ else (void)commctl(com, TIOCM_DTR, DMBIS); if (idivisor != 0) { - cd_setreg(com, CD1400_RBPR, idivisor); - cd_setreg(com, CD1400_RCOR, iprescaler); + cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor); + cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler); } if (odivisor != 0) { - cd_setreg(com, CD1400_TBPR, odivisor); - cd_setreg(com, CD1400_TCOR, oprescaler); + cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor); + cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler); } /* @@ -1908,20 +1788,20 @@ comparam(tp, t) | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); if (opt != com->channel_control) { com->channel_control = opt; - cd1400_channel_cmd(com, opt); + cd1400_channel_cmd(iobase, opt, com->cy_align); } #ifdef Smarts /* set special chars */ /* XXX if one is _POSIX_VDISABLE, can't use some others */ if (t->c_cc[VSTOP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); + cd_outb(iobase, CD1400_SCHR1, com->cy_align, t->c_cc[VSTOP]); if (t->c_cc[VSTART] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); + cd_outb(iobase, CD1400_SCHR2, com->cy_align, t->c_cc[VSTART]); if (t->c_cc[VINTR] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); + cd_outb(iobase, CD1400_SCHR3, com->cy_align, t->c_cc[VINTR]); if (t->c_cc[VSUSP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]); #endif /* @@ -1968,14 +1848,14 @@ comparam(tp, t) cor_change = 0; if (opt != com->cor[0]) { cor_change |= CD1400_CCR_COR1; - cd_setreg(com, CD1400_COR1, com->cor[0] = opt); + cd_outb(iobase, CD1400_COR1, com->cy_align, com->cor[0] = opt); } /* * Set receive time-out period, normally to max(one char time, 5 ms). */ if (t->c_ispeed == 0) - itimeout = cd_getreg(com, CD1400_RTPR); + itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align); else { itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; #ifdef SOFT_HOTCHAR @@ -1991,7 +1871,7 @@ comparam(tp, t) itimeout = t->c_cc[VTIME] * 10; if (itimeout > 255) itimeout = 255; - cd_setreg(com, CD1400_RTPR, itimeout); + cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout); /* * set channel option register 2 - @@ -2008,12 +1888,10 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_COR2_CCTS_OFLOW; #endif - disable_intr(); if (opt != com->cor[1]) { cor_change |= CD1400_CCR_COR2; - cd_setreg(com, CD1400_COR2, com->cor[1] = opt); + cd_outb(iobase, CD1400_COR2, com->cy_align, com->cor[1] = opt); } - enable_intr(); /* * set channel option register 3 - @@ -2030,12 +1908,13 @@ comparam(tp, t) #endif if (opt != com->cor[2]) { cor_change |= CD1400_CCR_COR3; - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); + cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt); } /* notify the CD1400 if COR1-3 have changed */ if (cor_change) - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); + cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change, + com->cy_align); /* * set channel option register 4 - @@ -2058,12 +1937,8 @@ comparam(tp, t) opt |= CD1400_COR4_INLCR; #endif if (iflag & IGNBRK) - opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; - /* - * The `-ignbrk -brkint parmrk' case is not handled by the hardware, - * so only tell the hardware about -brkint if -parmrk. - */ - if (!(iflag & (BRKINT | PARMRK))) + opt |= CD1400_COR4_IGNBRK; + if (!(iflag & BRKINT)) opt |= CD1400_COR4_NOBRKINT; #if 0 /* XXX using this "intelligence" breaks reporting of overruns. */ @@ -2078,7 +1953,7 @@ comparam(tp, t) #else opt |= CD1400_COR4_PFO_EXCEPTION; #endif - cd_setreg(com, CD1400_COR4, opt); + cd_outb(iobase, CD1400_COR4, com->cy_align, opt); /* * set channel option register 5 - @@ -2095,7 +1970,7 @@ comparam(tp, t) if (t->c_oflag & OCRNL) opt |= CD1400_COR5_OCRNL; #endif - cd_setreg(com, CD1400_COR5, opt); + cd_outb(iobase, CD1400_COR5, com->cy_align, opt); /* * We always generate modem status change interrupts for CD changes. @@ -2117,7 +1992,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR1_CTSzd; #endif - cd_setreg(com, CD1400_MCOR1, opt); + cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt); /* * set modem change option register 2 @@ -2128,7 +2003,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR2_CTSod; #endif - cd_setreg(com, CD1400_MCOR2, opt); + cd_outb(iobase, CD1400_MCOR2, com->cy_align, opt); /* * XXX should have done this long ago, but there is too much state @@ -2156,8 +2031,8 @@ comparam(tp, t) #if 0 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); + cd_outb(iobase, com->mcr_rts_reg, com->cy_align, + com->mcr_image |= com->mcr_rts); #endif } @@ -2188,16 +2063,12 @@ comparam(tp, t) #endif if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { if (!(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable |= CD1400_SRER_TXRDY); } else { if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable &= ~CD1400_SRER_TXRDY); } enable_intr(); @@ -2211,6 +2082,7 @@ comstart(tp) struct tty *tp; { struct com_s *com; + cy_addr iobase; int s; #ifdef CyDebug bool_t started; @@ -2219,6 +2091,7 @@ comstart(tp) unit = DEV_TO_UNIT(tp->t_dev); com = com_addr(unit); + iobase = com->iobase; s = spltty(); #ifdef CyDebug @@ -2227,29 +2100,26 @@ comstart(tp) #endif disable_intr(); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); if (tp->t_state & TS_TTSTOP) { com->state &= ~CS_TTGO; if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable &= ~CD1400_SRER_TXRDY); } else { com->state |= CS_TTGO; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); + cd_outb(iobase, CD1400_SRER, com->cy_align, + com->intr_enable |= CD1400_SRER_TXRDY); } if (tp->t_state & TS_TBLOCK) { if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) #if 0 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image &= ~com->mcr_rts); + cd_outb(iobase, com->mcr_rts_reg, com->cy_align, + com->mcr_image &= ~com->mcr_rts); #endif } else { if (!(com->mcr_image & com->mcr_rts) @@ -2258,8 +2128,8 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); + cd_outb(iobase, com->mcr_rts_reg, com->cy_align, + com->mcr_image |= com->mcr_rts); #endif } enable_intr(); @@ -2294,11 +2164,10 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); + cd_outb(iobase, CD1400_SRER, + com->cy_align, + com->intr_enable + |= CD1400_SRER_TXRDY); } enable_intr(); } @@ -2324,11 +2193,10 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); + cd_outb(iobase, CD1400_SRER, + com->cy_align, + com->intr_enable + |= CD1400_SRER_TXRDY); } enable_intr(); } @@ -2354,39 +2222,25 @@ siostop(tp, rw) int rw; { struct com_s *com; - bool_t wakeup_etc; com = com_addr(DEV_TO_UNIT(tp->t_dev)); - wakeup_etc = FALSE; disable_intr(); if (rw & FWRITE) { com->obufs[0].l_queued = FALSE; com->obufs[1].l_queued = FALSE; - if (com->extra_state & CSE_ODONE) { - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup_etc = TRUE; - } - } - com->tp->t_state &= ~TS_BUSY; if (com->state & CS_ODONE) com_events -= LOTS_OF_EVENTS; com->state &= ~(CS_ODONE | CS_BUSY); + com->tp->t_state &= ~TS_BUSY; } if (rw & FREAD) { - /* XXX no way to reset only input fifo. */ com_events -= (com->iptr - com->ibuf); com->iptr = com->ibuf; } enable_intr(); - if (wakeup_etc) - wakeup(&com->etc); - if (rw & FWRITE && com->etc == ETC_NONE) - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); comstart(tp); + + /* XXX should clear h/w fifos too. */ } static struct tty * @@ -2411,9 +2265,11 @@ commctl(com, bits, how) int bits; int how; { + cy_addr iobase; int mcr; int msr; + iobase = com->iobase; if (how == DMGET) { if (com->channel_control & CD1400_CCR_RCVEN) bits |= TIOCM_LE; @@ -2432,7 +2288,7 @@ commctl(com, bits, how) * reading the status register doesn't clear pending modem * status change interrupts. */ - msr = cd_getreg(com, CD1400_MSVR2); + msr = cd_inb(iobase, CD1400_MSVR2, com->cy_align); if (msr & MSR_CTS) bits |= TIOCM_CTS; @@ -2454,18 +2310,18 @@ commctl(com, bits, how) switch (how) { case DMSET: com->mcr_image = mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIS: com->mcr_image = mcr = com->mcr_image | mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIC: com->mcr_image = mcr = com->mcr_image & ~mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; } enable_intr(); @@ -2574,6 +2430,7 @@ disc_optim(tp, t, com) struct com_s *com; { #ifndef SOFT_HOTCHAR + cy_addr iobase; u_char opt; #endif @@ -2593,15 +2450,19 @@ disc_optim(tp, t, com) tp->t_state &= ~TS_CAN_BYPASS_L_RINT; com->hotchar = linesw[tp->t_line].l_hotchar; #ifndef SOFT_HOTCHAR + iobase = com->iobase; + cd_outb(iobase, CD1400_CAR, com->cy_align, com->unit & CD1400_CAR_CHAN); opt = com->cor[2] & ~CD1400_COR3_SCD34; if (com->hotchar != 0) { - cd_setreg(com, CD1400_SCHR3, com->hotchar); - cd_setreg(com, CD1400_SCHR4, com->hotchar); + cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar); opt |= CD1400_COR3_SCD34; } if (opt != com->cor[2]) { - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); + cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt); + cd1400_channel_cmd(com->iobase, + CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, + com->cy_align); } #endif } @@ -2668,129 +2529,27 @@ comspeed(speed, cy_clock, prescaler_io) } static void -cd1400_channel_cmd(com, cmd) - struct com_s *com; - int cmd; -{ - cd1400_channel_cmd_wait(com); - cd_setreg(com, CD1400_CCR, cmd); - cd1400_channel_cmd_wait(com); -} - -static void -cd1400_channel_cmd_wait(com) - struct com_s *com; -{ - struct timeval start; - struct timeval tv; - long usec; - - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&start); - for (;;) { - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&tv); - usec = 1000000 * (tv.tv_sec - start.tv_sec) + - tv.tv_usec - start.tv_usec; - if (usec >= 5000) { - log(LOG_ERR, - "cy%d: channel command timeout (%ld usec)\n", - com->unit, usec); - return; - } - } -} - -static void -cd_etc(com, etc) - struct com_s *com; - int etc; -{ - /* - * We can't change the hardware's ETC state while there are any - * characters in the tx fifo, since those characters would be - * interpreted as commands! Unputting characters from the fifo - * is difficult, so we wait up to 12 character times for the fifo - * to drain. The command will be delayed for up to 2 character - * times for the tx to become empty. Unputting characters from - * the tx holding and shift registers is impossible, so we wait - * for the tx to become empty so that the command is sure to be - * executed soon after we issue it. - */ - disable_intr(); - if (com->etc == etc) { - enable_intr(); - goto wait; - } - if (etc == CD1400_ETC_SENDBREAK - && (com->etc == ETC_BREAK_STARTING - || com->etc == ETC_BREAK_STARTED) - || etc == CD1400_ETC_STOPBREAK - && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED - || com->etc == ETC_NONE)) { - enable_intr(); - return; - } - com->etc = etc; - cd_setreg(com, CD1400_SRER, - com->intr_enable - = com->intr_enable & ~CD1400_SRER_TXRDY | CD1400_SRER_TXMPTY); - enable_intr(); -wait: - while (com->etc == etc - && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) - continue; -} - -static int -cd_getreg(com, reg) - struct com_s *com; - int reg; -{ - struct com_s *basecom; - u_char car; - int cy_align; - u_long ef; +cd1400_channel_cmd(iobase, cmd, cy_align) cy_addr iobase; - int val; - - basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - ef = read_eflags(); - disable_intr(); - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - val = cd_inb(iobase, reg, cy_align); - write_eflags(ef); - return (val); -} - -static void -cd_setreg(com, reg, val) - struct com_s *com; - int reg; - int val; -{ - struct com_s *basecom; - u_char car; + int cmd; int cy_align; - u_long ef; - cy_addr iobase; - - basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - ef = read_eflags(); - disable_intr(); - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - cd_outb(iobase, reg, cy_align, val); - write_eflags(ef); +{ + /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, + as the card is probed every round? Replaced delaycount with 8k. + Either delaycount has to be implemented in FreeBSD or more sensible + way of doing these should be implemented. DELAY isn't enough here. + */ + u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ + + /* wait for processing of previous command to complete */ + while (cd_inb(iobase, CD1400_CCR, cy_align) && maxwait--) + ; + + if (!maxwait) + log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", + 5 * 8 * 1024); + + cd_outb(iobase, CD1400_CCR, cy_align, cmd); } #ifdef CyDebug @@ -2814,15 +2573,17 @@ cystatus(unit) iobase = com->iobase; printf("\n"); printf("cd1400 base address:\\tt%p\n", iobase); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); printf("saved channel_control:\t\t0x%02x\n", com->channel_control); printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", com->cor[0], com->cor[1], com->cor[2]); printf("service request enable reg:\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_SRER), com->intr_enable); + cd_inb(iobase, CD1400_SRER, com->cy_align), com->intr_enable); printf("service request register:\t0x%02x\n", cd_inb(iobase, CD1400_SVRR, com->cy_align)); printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); + cd_inb(iobase, CD1400_MSVR2, com->cy_align), + com->prev_modem_status); printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", cd_inb(iobase, CD1400_RIR, com->cy_align), cd_inb(iobase, CD1400_TIR, com->cy_align), diff --git a/sys/i386/isa/cyreg.h b/sys/i386/isa/cyreg.h index baedda4175b2f..d98cfd80ece0a 100644 --- a/sys/i386/isa/cyreg.h +++ b/sys/i386/isa/cyreg.h @@ -26,50 +26,32 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cyreg.h,v 1.7 1998/08/13 19:03:22 bde Exp $ + * $Id: cyreg.h,v 1.6 1998/08/13 13:54:10 bde Exp $ */ /* * Definitions for Cyclades Cyclom-Y serial boards. */ -/* - * Cyclades register offsets. These are physical offsets for ISA boards - * and physical offsets divided by 2 for PCI boards. - */ -#define CY8_SVCACKR 0x100 /* (r) */ -#define CY8_SVCACKT 0x200 /* (r) */ -#define CY8_SVCACKM 0x300 /* (r) */ -#define CY16_RESET 0x1400 /* (r) */ -#define CY_CLEAR_INTR 0x1800 /* intr ack address (w) */ +#define CY8_SVCACKR 0x100 +#define CY8_SVCACKT 0x200 +#define CY8_SVCACKM 0x300 +#define CY16_RESET 0x0a00 +#define CY_CLEAR_INTR 0x0c00 /* intr ack address */ #define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ #define CY_CLOCK(version) ((version) >= 0x48 ? 60000000 : 25000000) #define CY_RTS_DTR_SWAPPED(version) ((version) >= 0x48) -/* - * The `cd' macros are for access to cd1400 registers. The `cy' macros - * are for access to Cyclades registers. Both sets of macros scale the - * register number to get an offset, but the scales are different for - * mostly historical reasons. - */ #ifdef CyDebug -#define cd_inb(iobase, reg, cy_align) \ - (++cd_inbs, *((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (++cy_inbs, *((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - (++cd_outbs, (void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - (++cy_outbs, (void)(*((iobase) + ((reg) << (cy_align))) = (val))) +#define cd_inb(iobase, reg, cy_align) (++cd_inbs, *((iobase) + ((reg)*2 << (cy_align)))) +#define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg))) +#define cd_outb(iobase, reg, cy_align, val) (++cd_outbs, (void)(*((iobase) + ((reg)*2 << (cy_align))) = (val))) +#define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val))) #else -#define cd_inb(iobase, reg, cy_align) \ - (*((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (*((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + ((reg) << (cy_align))) = (val))) +#define cd_inb(iobase, reg, cy_align) (*((iobase) + ((reg)*2 << (cy_align)))) +#define cy_inb(iobase, reg) (*((iobase) + (reg))) +#define cd_outb(iobase, reg, cy_align, val) ((void)(*((iobase) + ((reg)*2 << (cy_align))) = (val))) +#define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val))) #endif diff --git a/sys/i386/isa/diskslice_machdep.c b/sys/i386/isa/diskslice_machdep.c index adfd39c52e949..ab9d4bac6948d 100644 --- a/sys/i386/isa/diskslice_machdep.c +++ b/sys/i386/isa/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.31 1998/08/10 07:22:14 phk Exp $ + * $Id: diskslice_machdep.c,v 1.30 1998/07/25 16:35:06 bde Exp $ */ #include <sys/param.h> @@ -405,7 +405,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, diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index 9972a38f5c358..d04f98a1f388c 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/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.131 1999/01/15 09:15:27 bde Exp $ + * $Id: fd.c,v 1.122 1998/09/15 08:15:28 gibbs Exp $ * */ +#include "ft.h" +#if NFT < 1 +#undef NFDC +#endif #include "fd.h" #include "opt_devfs.h" #include "opt_fdc.h" @@ -76,6 +76,10 @@ #include <i386/isa/fdc.h> #include <i386/isa/rtc.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 */ @@ -85,10 +89,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 @@ -190,9 +190,15 @@ static struct fd_data { * 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 */ @@ -215,7 +221,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 *); @@ -238,9 +243,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[] = @@ -258,9 +260,6 @@ static char const * const fdstates[] = "MOTORWAIT", "IOTIMEDOUT", "RESETCOMPLETE", -#ifdef FDC_YE -"PIOREAD", -#endif }; /* CAUTION: fd_debug causes huge amounts of logging output */ @@ -272,91 +271,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 = { @@ -395,7 +309,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; @@ -425,7 +339,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); @@ -438,7 +352,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); @@ -600,14 +514,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); } @@ -623,6 +529,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 @@ -631,7 +540,6 @@ fdattach(struct isa_device *dev) int typesize; #endif - dev->id_ointr = fdintr; fdc->fdcu = fdcu; fdc->flags |= FDC_ATTACHED; fdc->dmachan = dev->id_drq; @@ -649,7 +557,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 */ @@ -666,8 +574,26 @@ fdattach(struct isa_device *dev) } /* is there a unit? */ if ((fdt == RTCFDT_NONE) +#if NFT > 0 + || (fdsu >= DRVS_PER_CTLR)) { +#else ) { 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; } @@ -713,7 +639,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) && @@ -856,10 +782,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 */ @@ -878,138 +804,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 */ @@ -1216,6 +1010,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); @@ -1289,6 +1088,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; @@ -1326,18 +1131,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)) { @@ -1467,46 +1275,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 * @@ -1514,6 +1297,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; @@ -1522,15 +1306,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, * @@ -1704,11 +1481,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) } fd->track = b_cylinder; -#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; @@ -1750,12 +1524,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, @@ -1776,24 +1544,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 */ @@ -1814,37 +1564,9 @@ 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 */ -#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 */ untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); @@ -1863,11 +1585,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ case IOTIMEDOUT: -#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); if (fdc->status[0] & NE7_ST0_IC) { if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT @@ -1902,7 +1621,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, @@ -2022,10 +1741,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; @@ -2069,7 +1790,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, @@ -2178,6 +1899,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; switch (cmd) diff --git a/sys/i386/isa/fdc.h b/sys/i386/isa/fdc.h index 43bf9f8f5f4c4..fdaf694f8d35c 100644 --- a/sys/i386/isa/fdc.h +++ b/sys/i386/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.12 1998/12/12 08:16:01 imp Exp $ + * $Id: fdc.h,v 1.10 1998/07/11 06:35:39 bde Exp $ * */ @@ -56,10 +56,6 @@ struct fdc_data #define FDC_STAT_VALID 0x08 #define FDC_HAS_FIFO 0x10 #define FDC_NEEDS_RESET 0x20 -#ifdef FDC_YE -#define FDC_PCMCIA 0x40 -#define FDC_UNLOADED 0x80 -#endif struct fd_data *fd; int fdu; /* the active drive */ int state; @@ -68,8 +64,7 @@ struct fdc_data u_int status[7]; /* copy of the registers */ enum fdc_type fdct; /* chip version of FDC */ int fdc_errs; /* number of logged errors */ - struct buf_queue_head head; - struct buf *bp; /* active buffer */ + struct buf_queue_head head; /* Head of buf chain */ }; /***********************************************************************\ diff --git a/sys/i386/isa/ft.c b/sys/i386/isa/ft.c new file mode 100644 index 0000000000000..2b7fd5fa90e88 --- /dev/null +++ b/sys/i386/isa/ft.c @@ -0,0 +1,2580 @@ +/* + * Copyright (c) 1993, 1994 Steve Gerakines + * + * This is freely redistributable software. You may do anything you + * wish with it, so long as the above notice stays intact. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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. + * + * ft.c - QIC-40/80 floppy tape driver + * $Id: ft.c,v 1.37 1998/04/17 22:36:32 des Exp $ + * + * 01/19/95 ++sg + * Cleaned up recalibrate/seek code at attach time for FreeBSD 2.x. + * + * 06/07/94 v0.9 ++sg + * Tape stuck on segment problem should be gone. Re-wrote buffering + * scheme. Added support for drives that do not automatically perform + * seek load point. Can handle more wakeup types now and should correctly + * report most manufacturer names. Fixed places where unit 0 was being + * sent to the fdc instead of the actual unit number. Added ioctl support + * for an in-core badmap. + * + * 01/26/94 v0.3b - Jim Babb + * Got rid of the hard coded device selection. Moved (some of) the + * static variables into a structure for support of multiple devices. + * ( still has a way to go for 2 controllers - but closer ) + * Changed the interface with fd.c so we no longer 'steal' its + * driver routine vectors. + * + * 10/30/93 v0.3 + * Fixed a couple more bugs. Reading was sometimes looping when an + * an error such as address-mark-missing was encountered. Both + * reading and writing was having more backup-and-retries than was + * necessary. Added support to get hardware info. Updated for use + * with FreeBSD. + * + * 09/15/93 v0.2 pl01 + * Fixed a bunch of bugs: extra isa_dmadone() in async_write() (shouldn't + * matter), fixed double buffering in async_req(), changed tape_end() in + * set_fdcmode() to reduce unexpected interrupts, changed end of track + * processing in async_req(), protected more of ftreq_rw() with an + * splbio(). Changed some of the ftreq_*() functions so that they wait + * for inactivity and then go, instead of aborting immediately. + * + * 08/07/93 v0.2 release + * Shifted from ftstrat to ioctl support for I/O. Streaming is now much + * more reliable. Added internal support for error correction, QIC-40, + * and variable length tapes. Random access of segments greatly + * improved. Formatting and verification support is close but still + * incomplete. + * + * 06/03/93 v0.1 Alpha release + * Hopefully the last re-write. Many bugs fixed, many remain. + */ + +#include "ft.h" +#if NFT > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/disklabel.h> /* temp. for dkunit() in fdc.h */ +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/ftape.h> +#include <sys/kernel.h> + +#include <machine/clock.h> + +#include <i386/isa/isa_device.h> +#ifdef PC98 +#include <pc98/pc98/fdreg.h> +#else +#include <i386/isa/fdreg.h> +#endif +#include <i386/isa/fdc.h> +#include <i386/isa/ftreg.h> + +extern int ftintr __P((ftu_t ftu)); + +/* Enable or disable debugging messages. */ +#define FTDBGALL 0 /* 1 if you want everything */ +/*#define DPRT(a) printf a */ +#define DPRT(a) + +/* Constants private to the driver */ +#define FTPRI (PRIBIO) /* sleep priority */ +#define FTNBUFF 9 /* 8 for buffering, 1 for header */ + +/* The following items are needed from the fd driver. */ +extern int in_fdc(int); /* read fdc registers */ +extern int out_fdc(int, int); /* write fdc registers */ + +/* Flags in isadev struct */ +#define FT_PROBE 0x1 /* allow for "dangerous" tape probes */ + +/* Type of tape attached */ +/* use numbers that don't interfere with the possible floppy types */ +#define NO_TYPE 0 /* (same as NO_TYPE in fd.c) */ + +/* F_TAPE_TYPE must match value in fd.c */ +#define F_TAPE_TYPE 0x020 /* bit for ft->types to indicate tape */ +#define FT_NONE (F_TAPE_TYPE | 0) /* no method required */ +#define FT_MOUNTAIN (F_TAPE_TYPE | 1) /* mountain */ +#define FT_COLORADO (F_TAPE_TYPE | 2) /* colorado */ +#define FT_INSIGHT (F_TAPE_TYPE | 3) /* insight */ + +/* Mode FDC is currently in: tape or disk */ +enum { FDC_TAPE_MODE, FDC_DISK_MODE }; + +/* Command we are awaiting completion of */ +enum { FTCMD_NONE, FTCMD_RESET, FTCMD_RECAL, FTCMD_SEEK, FTCMD_READID }; + +/* Tape interrupt status of current request */ +enum { FTSTS_NONE, FTSTS_SNOOZE, FTSTS_INTERRUPT, FTSTS_TIMEOUT }; + +/* Tape I/O status */ +enum { + FTIO_READY, /* No I/O activity */ + FTIO_READING, /* Currently reading blocks */ + FTIO_RDAHEAD, /* Currently reading ahead */ + FTIO_WRITING /* Buffers are being written */ +}; + +/* Current tape mode */ +enum { + FTM_PRIMARY, /* Primary mode */ + FTM_VERIFY, /* Verify mode */ + FTM_FORMAT, /* Format mode */ + FTM_DIAG1, /* Diagnostic mode 1 */ + FTM_DIAG2 /* Diagnostic mode 2 */ +}; + +/* Tape geometries table */ +static QIC_Geom ftgtbl[] = { + { 0, 0, "Unformatted", "Unknown", 0, 0, 0, 0, 0 }, /* XXX */ + { 1, 1, "QIC-40", "205/550", 20, 68, 2176, 128, 21760 }, + { 1, 2, "QIC-40", "307.5/550", 20, 102, 3264, 128, 32640 }, + { 1, 3, "QIC-40", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ + { 1, 4, "QIC-40", "1100/550", 20, 365, 11680, 128, 32512 }, + { 1, 5, "QIC-40", "1100/900", 0, 0, 0, 0, 0 }, /* ??? */ + { 2, 1, "QIC-80", "205/550", 28, 100, 3200, 128, 19200 }, + { 2, 2, "QIC-80", "307.5/550", 28, 150, 4800, 128, 19200 }, + { 2, 3, "QIC-80", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ + { 2, 4, "QIC-80", "1100/550", 28, 537, 17184, 128, 32512 }, + { 2, 5, "QIC-80", "1100/900", 0, 0, 0, 0, 0 }, /* ??? */ + { 3, 1, "QIC-500", "205/550", 0, 0, 0, 0, 0 }, /* ??? */ + { 3, 2, "QIC-500", "307.5/550", 0, 0, 0, 0, 0 }, /* ??? */ + { 3, 3, "QIC-500", "295/900", 0, 0, 0, 0, 0 }, /* ??? */ + { 3, 4, "QIC-500", "1100/550", 0, 0, 0, 0, 0 }, /* ??? */ + { 3, 5, "QIC-500", "1100/900", 0, 0, 0, 0, 0 } /* ??? */ +}; +#define NGEOM (sizeof(ftgtbl) / sizeof(QIC_Geom)) + +static QIC_Geom *ftg = NULL; /* Current tape's geometry */ + +/* + * things relating to asynchronous commands + */ +static int awr_state; /* state of async write */ +static int ard_state; /* state of async read */ +static int arq_state; /* state of async request */ +static int async_retries; /* retries, one per invocation */ +static int async_func; /* function to perform */ +static int async_state; /* state current function is at */ +static int async_arg0; /* up to 3 arguments for async cmds */ +static int async_arg1; /**/ +static int async_arg2; /**/ +static int async_ret; /* return value */ +static struct _astk { + int over_func; + int over_state; + int over_retries; + int over_arg0; + int over_arg1; + int over_arg2; +} astk[10]; +static struct _astk *astk_ptr = &astk[0]; /* Pointer to stack position */ + +/* List of valid async (interrupt driven) tape support functions. */ +enum { + ACMD_NONE, /* no command */ + ACMD_SEEK, /* command seek */ + ACMD_STATUS, /* report status */ + ACMD_STATE, /* wait for state bits to be true */ + ACMD_SEEKSTS, /* perform command and wait for status */ + ACMD_READID, /* read id */ + ACMD_RUNBLK /* ready tape for I/O on the given block */ +}; + +/* Call another asyncronous command from within async_cmd(). */ +#define CALL_ACMD(r,f,a,b,c) \ + astk_ptr->over_retries = async_retries; \ + astk_ptr->over_func = async_func; \ + astk_ptr->over_state = (r); \ + astk_ptr->over_arg0 = async_arg0; \ + astk_ptr->over_arg1 = async_arg1; \ + astk_ptr->over_arg2 = async_arg2; \ + async_func = (f); async_state = 0; async_retries = 0; \ + async_arg0=(a); async_arg1=(b); async_arg2=(c); \ + astk_ptr++; \ + goto restate + +/* Perform an asyncronous command from outside async_cmd(). */ +#define ACMD_FUNC(r,f,a,b,c) over_async = (r); astk_ptr = &astk[0]; \ + async_func = (f); async_state = 0; async_retries = 0; \ + async_arg0=(a); async_arg1=(b); async_arg2=(c); \ + async_cmd(ftu); \ + return + +/* Various wait channels */ +static char *wc_buff_avail = "bavail"; +static char *wc_buff_done = "bdone"; +static char *wc_iosts_change = "iochg"; +static char *wc_long_delay = "ldelay"; +static char *wc_intr_wait = "intrw"; +#define ftsleep(wc,to) tsleep((caddr_t)(wc),FTPRI,(wc),(to)) + +/***********************************************************************\ +* Per controller structure. * +\***********************************************************************/ +extern struct fdc_data fdc_data[NFDC]; + +/***********************************************************************\ +* Per tape drive structure. * +\***********************************************************************/ +static struct ft_data { + struct fdc_data *fdc; /* pointer to controller structure */ + int ftsu; /* this units number on this controller */ + int type; /* Drive type (Mountain, Colorado) */ +/* QIC_Geom *ftg; */ /* pointer to Current tape's geometry */ + int flags; + int cmd_wait; /* Command we are awaiting completion of */ + int sts_wait; /* Tape interrupt status of current request */ + int io_sts; /* Tape I/O status */ + int mode; + int pcn; /* present cylinder number */ + int attaching; /* true when ft is attaching */ + unsigned char *xptr; /* pointer to buffer blk to xfer */ + int xcnt; /* transfer count */ + int xblk; /* block number to transfer */ + int xseg; /* segment being transferred */ + SegReq *segh; /* Current I/O request */ + SegReq *segt; /* Tail of queued I/O requests */ + SegReq *doneh; /* Completed I/O request queue */ + SegReq *donet; /* Completed I/O request tail */ + SegReq *segfree; /* Free segments */ + SegReq *hdr; /* Current tape header */ + int nsegq; /* Segments on request queue */ + int ndoneq; /* Segments on completed queue */ + int nfreelist; /* Segments on free list */ + + /* the next 3 should be defines in 'flags' */ + int active; /* TRUE if transfer is active */ + int rdonly; /* TRUE if tape is read-only */ + int newcart; /* TRUE if new cartridge detected */ + int laststs; /* last reported status code */ + int lastcfg; /* last reported QIC config */ + int lasterr; /* last QIC error code */ + int lastpos; /* last known segment number */ + int moving; /* TRUE if tape is moving */ + int rid[7]; /* read_id return values */ + struct callout_handle tohandle; +} *ft_data[NFT]; + +/***********************************************************************\ +* Throughout this file the following conventions will be used: * +* ft is a pointer to the ft_data struct for the drive in question * +* fdc is a pointer to the fdc_data struct for the controller * +* ftu is the tape drive unit number * +* fdcu is the floppy controller unit number * +* ftsu is the tape drive unit number on that controller. (sub-unit) * +\***********************************************************************/ + + + +#define id_physid id_scsiid /* this biotab field doubles as a field */ + /* for the physical unit number on the controller */ + +int ftopen(dev_t, int); +int ftclose(dev_t, int); +int ftioctl(dev_t, unsigned long, caddr_t, int, struct proc *); +int ftattach(struct isa_device *, struct isa_device *, int); +static timeout_t ft_timeout; +static void async_cmd(ftu_t); +static void async_req(ftu_t, int); +static void async_read(ftu_t, int); +static void async_write(ftu_t, int); +static void tape_start(ftu_t, int); +static void tape_end(ftu_t); +static void tape_inactive(ftu_t); +static int tape_cmd(ftu_t, int); +static int tape_status(ftu_t); +static int qic_status(ftu_t, int, int); +static int ftreq_rewind(ftu_t); +static int ftreq_hwinfo(ftu_t, QIC_HWInfo *); + +/*****************************************************************************/ + + +/* + * Allocate a segment I/O buffer from the free list. + */ +static SegReq * +segio_alloc(ft_p ft) +{ + SegReq *r; + + /* Grab first item from free list */ + if ((r = ft->segfree) != NULL) { + ft->segfree = ft->segfree->next; + ft->nfreelist--; + } + DPRT(("segio_alloc: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); + return(r); +} + + +/* + * Queue a segment I/O request. + */ +static void +segio_queue(ft_p ft, SegReq *sp) +{ + /* Put request on in process queue. */ + if (ft->segt == NULL) + ft->segh = sp; + else + ft->segt->next = sp; + sp->next = NULL; + ft->segt = sp; + ft->nsegq++; + DPRT(("segio_queue: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); +} + + +/* + * Segment I/O completed, place on correct queue. + */ +static void +segio_done(ft_p ft, SegReq *sp) +{ + /* First remove from current I/O queue */ + ft->segh = sp->next; + if (ft->segh == NULL) ft->segt = NULL; + ft->nsegq--; + + if (sp->reqtype == FTIO_WRITING) { + /* Place on free list */ + sp->next = ft->segfree; + ft->segfree = sp; + ft->nfreelist++; + wakeup((caddr_t)wc_buff_avail); + DPRT(("segio_done: (w) nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); + } else { + /* Put on completed I/O queue */ + if (ft->donet == NULL) + ft->doneh = sp; + else + ft->donet->next = sp; + sp->next = NULL; + ft->donet = sp; + ft->ndoneq++; + wakeup((caddr_t)wc_buff_done); + DPRT(("segio_done: (r) nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); + } +} + + +/* + * Take I/O request from finished queue to free queue. + */ +static void +segio_free(ft_p ft, SegReq *sp) +{ + /* First remove from done queue */ + ft->doneh = sp->next; + if (ft->doneh == NULL) ft->donet = NULL; + ft->ndoneq--; + + /* Place on free list */ + sp->next = ft->segfree; + ft->segfree = sp; + ft->nfreelist++; + wakeup((caddr_t)wc_buff_avail); + DPRT(("segio_free: nfree=%d ndone=%d nreq=%d\n", ft->nfreelist, ft->ndoneq, ft->nsegq)); +} + +/* + * Probe/attach floppy tapes. + */ +int +ftattach(isadev, fdup, unithasfd) + struct isa_device *isadev, *fdup; + int unithasfd; +{ + fdcu_t fdcu = isadev->id_unit; /* fdc active unit */ + fdc_p fdc = fdc_data + fdcu; /* pointer to controller structure */ + ftu_t ftu = fdup->id_unit; + ft_p ft; + ftsu_t ftsu = fdup->id_physid; + QIC_HWInfo hw; + char *manu; + + if (ftu >= NFT) return 0; + ft = ft_data[ftu] = malloc(sizeof *ft, M_DEVBUF, M_NOWAIT); + bzero(ft, sizeof *ft); + callout_handle_init(&ft->tohandle); + + /* Probe for tape */ + ft->attaching = 1; + ft->type = NO_TYPE; + ft->fdc = fdc; + ft->ftsu = ftsu; + + /* + * FT_NONE - no method, just do it + */ + tape_start(ftu, 0); + if (tape_status(ftu) >= 0) { + ft->type = FT_NONE; + ftreq_hwinfo(ftu, &hw); + goto out; + } + + /* + * FT_COLORADO - colorado style + */ + tape_start(ftu, 0); + tape_cmd(ftu, QC_COL_ENABLE1); + tape_cmd(ftu, QC_COL_ENABLE2 + ftu); + if (tape_status(ftu) >= 0) { + ft->type = FT_COLORADO; + ftreq_hwinfo(ftu, &hw); + tape_cmd(ftu, QC_COL_DISABLE); + goto out; + } + + /* + * FT_MOUNTAIN - mountain style + */ + tape_start(ftu, 0); + tape_cmd(ftu, QC_MTN_ENABLE1); + tape_cmd(ftu, QC_MTN_ENABLE2); + if (tape_status(ftu) >= 0) { + ft->type = FT_MOUNTAIN; + ftreq_hwinfo(ftu, &hw); + tape_cmd(ftu, QC_MTN_DISABLE); + goto out; + } + + if(isadev->id_flags & FT_PROBE) { + /* + * Insight probe is dangerous, since it requires the motor being + * enabled and therefore risks attached floppy disk drives to jam. + * Probe only if explicitly requested by a flag 0x1 from config + */ + + /* + * FT_INSIGHT - insight style + * + * Since insight requires turning the drive motor on, we will not + * perform this probe if a floppy drive was already found with the + * the given unit and controller. + */ + if (unithasfd) goto out; + tape_start(ftu, 1); + if (tape_status(ftu) >= 0) { + ft->type = FT_INSIGHT; + ftreq_hwinfo(ftu, &hw); + goto out; + } + } + +out: + tape_end(ftu); + if (ft->type != NO_TYPE) { + fdc->flags |= FDC_HASFTAPE; + switch(hw.hw_make) { + case 0x0000: + if (ft->type == FT_COLORADO) { + manu = "Colorado"; + } else if (ft->type == FT_INSIGHT) { + manu = "Insight"; + } else if (ft->type == FT_MOUNTAIN && hw.hw_model == 0x05) { + manu = "Archive"; + } else if (ft->type == FT_MOUNTAIN) { + manu = "Mountain"; + } else { + manu = "Unknown"; + } + break; + case 0x0001: + manu = "Colorado"; + break; + case 0x0005: + if (hw.hw_model >= 0x09) { + manu = "Conner"; + } else { + manu = "Archive"; + } + break; + case 0x0006: + manu = "Mountain"; + break; + case 0x0007: + manu = "Wangtek"; + break; + case 0x0222: + manu = "IOMega"; + break; + default: + manu = "Unknown"; + break; + } + printf("ft%d: %s tape\n", fdup->id_unit, manu); + } + ft->attaching = 0; + return(ft->type); +} + + +/* + * Perform common commands asynchronously. + */ +static void +async_cmd(ftu_t ftu) { + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; + int cmd, i, st0, st3, pcn; + static int bitn, retval, retpos, nbits, newcn; + static int wanttrk, wantblk, wantdir; + static int curtrk, curblk, curdir, curdiff; + static int errcnt = 0; + +restate: +#if FTDBGALL + DPRT(("async_cmd state: func: %d state: %d\n", async_func, async_state)); +#endif + switch(async_func) { + case ACMD_SEEK: + /* + * Arguments: + * 0 - command to perform + */ + switch (async_state) { + case 0: + cmd = async_arg0; +#if FTDBGALL + DPRT(("===>async_seek cmd = %d\n", cmd)); +#endif + newcn = (cmd <= ft->pcn) ? ft->pcn - cmd : ft->pcn + cmd; + async_state = 1; + i = 0; + if (out_fdc(fdcu, NE7CMD_SEEK) < 0) i = 1; + if (!i && out_fdc(fdcu, ftu) < 0) i = 1; + if (!i && out_fdc(fdcu, newcn) < 0) i = 1; + if (i) { + if (++async_retries >= 10) { + DPRT(("ft%d: async_cmd command seek failed!!\n", ftu)); + goto complete; + } + DPRT(("ft%d: async_cmd command seek retry...\n",ftu)); + async_state = 0; + goto restate; + } + break; + case 1: + out_fdc(fdcu, NE7CMD_SENSEI); + st0 = in_fdc(fdcu); + pcn = in_fdc(fdcu); + if (st0 < 0 || pcn < 0 || newcn != pcn) { + if (++async_retries >= 10) { + DPRT(("ft%d: async_cmd seek retries exceeded\n",ftu)); + goto complete; + } + DPRT(("ft%d: async_cmd command bad st0=$%02x pcn=$%02x\n", + ftu, st0, pcn)); + async_state = 0; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); + break; + } + if (st0 & 0x20) { /* seek done */ + ft->pcn = pcn; + } +#if FTDBGALL + else + DPRT(("ft%d: async_seek error st0 = $%02x pcn = %d\n", + ftu, st0, pcn)); +#endif + if (async_arg1) goto complete; + async_state = 2; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/50); + break; + case 2: + goto complete; + /* NOTREACHED */ + } + break; + + case ACMD_STATUS: + /* + * Arguments: + * 0 - command to issue report from + * 1 - number of bits + * modifies: bitn, retval, st3 + */ + switch (async_state) { + case 0: + bitn = 0; + retval = 0; + cmd = async_arg0; + nbits = async_arg1; + DPRT(("async_status got cmd = %d nbits = %d\n", cmd,nbits)); + CALL_ACMD(5, ACMD_SEEK, QC_NEXTBIT, 0, 0); + /* NOTREACHED */ + case 1: + out_fdc(fdcu, NE7CMD_SENSED); + out_fdc(fdcu, ftu); + st3 = in_fdc(fdcu); + if (st3 < 0) { + DPRT(("ft%d: async_status timed out on bit %d r=$%02x\n", + ftu,bitn,retval)); + async_ret = -1; + goto complete; + } + if ((st3 & 0x10) != 0) retval |= (1 << bitn); + bitn++; + if (bitn >= (nbits+2)) { + if ((retval & 1) && (retval & (1 << (nbits+1)))) { + async_ret = (retval & ~(1<<(nbits+1))) >> 1; + if (async_arg0 == QC_STATUS && async_arg2 == 0 && + (async_ret & (QS_ERROR|QS_NEWCART))) { + async_state = 2; + goto restate; + } + DPRT(("async status got $%04x ($%04x)\n", async_ret,retval)); + } else { + DPRT(("ft%d: async_status failed: retval=$%04x nbits=%d\n", + ftu, retval,nbits)); + async_ret = -2; + } + goto complete; + } + CALL_ACMD(1, ACMD_SEEK, QC_NEXTBIT, 0, 0); + /* NOTREACHED */ + case 2: + if (async_ret & QS_NEWCART) ft->newcart = 1; + CALL_ACMD(3, ACMD_STATUS, QC_ERRCODE, 16, 1); + case 3: + ft->lasterr = async_ret; + if ((ft->lasterr & QS_NEWCART) == 0 && ft->lasterr) { + DPRT(("ft%d: QIC error %d occurred on cmd %d\n", + ftu, ft->lasterr & 0xff, ft->lasterr >> 8)); + } + cmd = async_arg0; + nbits = async_arg1; + CALL_ACMD(4, ACMD_STATUS, QC_STATUS, 8, 1); + case 4: + goto complete; + case 5: + CALL_ACMD(6, ACMD_SEEK, QC_NEXTBIT, 0, 0); + case 6: + CALL_ACMD(7, ACMD_SEEK, QC_NEXTBIT, 0, 0); + case 7: + CALL_ACMD(8, ACMD_SEEK, QC_NEXTBIT, 0, 0); + case 8: + cmd = async_arg0; + CALL_ACMD(1, ACMD_SEEK, cmd, 0, 0); + } + break; + + case ACMD_STATE: + /* + * Arguments: + * 0 - status bits to check + */ + switch(async_state) { + case 0: + CALL_ACMD(1, ACMD_STATUS, QC_STATUS, 8, 0); + case 1: + if ((async_ret & async_arg0) != 0) goto complete; + async_state = 0; + if (++async_retries == 360) { /* 90 secs. */ + DPRT(("ft%d: acmd_state exceeded retry count\n", ftu)); + goto complete; + } + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/4); + break; + } + break; + + case ACMD_SEEKSTS: + /* + * Arguments: + * 0 - command to perform + * 1 - status bits to check + * 2 - (optional) seconds to wait until completion + */ + switch(async_state) { + case 0: + cmd = async_arg0; + async_retries = (async_arg2) ? (async_arg2 * 4) : 10; + CALL_ACMD(1, ACMD_SEEK, cmd, 0, 0); + case 1: + CALL_ACMD(2, ACMD_STATUS, QC_STATUS, 8, 0); + case 2: + if ((async_ret & async_arg1) != 0) goto complete; + if (--async_retries == 0) { + DPRT(("ft%d: acmd_seeksts retries exceeded\n", ftu)); + goto complete; + } + async_state = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/4); + break; + } + break; + + case ACMD_READID: + /* + * Arguments: (none) + */ + switch(async_state) { + case 0: + if (!ft->moving) { + CALL_ACMD(4, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + /* NOTREACHED */ + } + async_state = 1; + out_fdc(fdcu, 0x4a); /* READ_ID */ + out_fdc(fdcu, ftu); + break; + case 1: + for (i = 0; i < 7; i++) ft->rid[i] = in_fdc(fdcu); + async_ret = (ft->rid[3]*ftg->g_fdtrk) + + (ft->rid[4]*ftg->g_fdside) + ft->rid[5] - 1; + DPRT(("readid st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d\n", + ft->rid[0], ft->rid[1], ft->rid[2], ft->rid[3], + ft->rid[4], ft->rid[5], async_ret)); + if ((ft->rid[0] & 0xc0) != 0 || async_ret < 0) { + /* + * Method for retry: + * errcnt == 1 regular retry + * 2 microstep head 1 + * 3 microstep head 2 + * 4 microstep head back to 0 + * 5 fail + */ + if (++errcnt >= 5) { + DPRT(("ft%d: acmd_readid errcnt exceeded\n", fdcu)); + async_ret = -2; + errcnt = 0; + goto complete; + } + if (errcnt == 1) { + ft->moving = 0; + CALL_ACMD(4, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + } else { + ft->moving = 0; + CALL_ACMD(4, ACMD_SEEKSTS, QC_STPAUSE, QS_READY, 0); + } + DPRT(("readid retry %d...\n", errcnt)); + async_state = 0; + goto restate; + } + if ((async_ret % ftg->g_blktrk) == (ftg->g_blktrk-1)) { + DPRT(("acmd_readid detected last block on track\n")); + retpos = async_ret; + CALL_ACMD(2, ACMD_STATE, QS_BOT|QS_EOT, 0, 0); + /* NOTREACHED */ + } + ft->lastpos = async_ret; + errcnt = 0; + goto complete; + /* NOTREACHED */ + case 2: + CALL_ACMD(3, ACMD_STATE, QS_READY, 0, 0); + case 3: + ft->moving = 0; + async_ret = retpos+1; + goto complete; + case 4: + CALL_ACMD(5, ACMD_SEEK, QC_FORWARD, 0, 0); + case 5: + ft->moving = 1; + async_state = 0; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ + break; + } + break; + + case ACMD_RUNBLK: + /* + * Arguments: + * 0 - block number I/O will be performed on + * + * modifies: curpos + */ + switch (async_state) { + case 0: + wanttrk = async_arg0 / ftg->g_blktrk; + wantblk = async_arg0 % ftg->g_blktrk; + wantdir = wanttrk & 1; + ft->moving = 0; + CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + case 1: + curtrk = wanttrk; + curdir = curtrk & 1; + DPRT(("Changing to track %d\n", wanttrk)); + CALL_ACMD(2, ACMD_SEEK, QC_SEEKTRACK, 0, 0); + case 2: + cmd = wanttrk+2; + CALL_ACMD(3, ACMD_SEEKSTS, cmd, QS_READY, 0); + case 3: + CALL_ACMD(4, ACMD_STATUS, QC_STATUS, 8, 0); + case 4: + ft->laststs = async_ret; + if (wantblk == 0) { + curblk = 0; + cmd = (wantdir) ? QC_SEEKEND : QC_SEEKSTART; + CALL_ACMD(6, ACMD_SEEKSTS, cmd, QS_READY, 90); + } + if (ft->laststs & QS_BOT) { + DPRT(("Tape is at BOT\n")); + curblk = (wantdir) ? 4800 : 0; + async_state = 6; + goto restate; + } + if (ft->laststs & QS_EOT) { + DPRT(("Tape is at EOT\n")); + curblk = (wantdir) ? 0 : 4800; + async_state = 6; + goto restate; + } + CALL_ACMD(5, ACMD_READID, 0, 0, 0); + case 5: + if (async_ret < 0) { + ft->moving = 0; + ft->lastpos = -2; + if (async_ret == -2) { + CALL_ACMD(9, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + } + CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + } + curtrk = (async_ret+1) / ftg->g_blktrk; + curblk = (async_ret+1) % ftg->g_blktrk; + DPRT(("gotid: curtrk=%d wanttrk=%d curblk=%d wantblk=%d\n", + curtrk, wanttrk, curblk, wantblk)); + if (curtrk != wanttrk) { /* oops! */ + DPRT(("oops!! wrong track!\n")); + CALL_ACMD(1, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + } + async_state = 6; + goto restate; + case 6: + DPRT(("curtrk = %d nextblk = %d\n", curtrk, curblk)); + if (curblk == wantblk) { + ft->lastpos = curblk - 1; + async_ret = ft->lastpos; + if (ft->moving) goto complete; + CALL_ACMD(7, ACMD_STATE, QS_READY, 0, 0); + } + if (curblk > wantblk) { /* passed it */ + ft->moving = 0; + CALL_ACMD(10, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + } + if ((wantblk - curblk) <= 256) { /* approaching it */ + CALL_ACMD(5, ACMD_READID, 0, 0, 0); + } + /* way up ahead */ + ft->moving = 0; + CALL_ACMD(14, ACMD_SEEKSTS, QC_STOP, QS_READY, 0); + break; + case 7: + ft->moving = 1; + CALL_ACMD(8, ACMD_SEEK, QC_FORWARD, 0, 0); + break; + case 8: + async_state = 9; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ + break; + case 9: + goto complete; + case 10: + curdiff = ((curblk - wantblk) / QCV_BLKSEG) + 2; + if (curdiff >= ftg->g_segtrk) curdiff = ftg->g_segtrk - 1; + DPRT(("pos %d past %d, reverse %d\n", curblk, wantblk, curdiff)); + CALL_ACMD(11, ACMD_SEEK, QC_SEEKREV, 0, 0); + case 11: + DPRT(("reverse 1 done\n")); + CALL_ACMD(12, ACMD_SEEK, (curdiff & 0xf)+2, 0, 0); + case 12: + DPRT(("reverse 2 done\n")); + CALL_ACMD(13, ACMD_SEEKSTS, ((curdiff>>4)&0xf)+2, QS_READY, 90); + case 13: + CALL_ACMD(5, ACMD_READID, 0, 0, 0); + case 14: + curdiff = ((wantblk - curblk) / QCV_BLKSEG) - 2; + if (curdiff < 0) curdiff = 0; + DPRT(("pos %d before %d, forward %d\n", curblk, wantblk, curdiff)); + CALL_ACMD(15, ACMD_SEEK, QC_SEEKFWD, 0, 0); + case 15: + DPRT(("forward 1 done\n")); + CALL_ACMD(16, ACMD_SEEK, (curdiff & 0xf)+2, 0, 0); + case 16: + DPRT(("forward 2 done\n")); + CALL_ACMD(13, ACMD_SEEKSTS, ((curdiff>>4)&0xf)+2, QS_READY, 90); + } + break; + } + + return; + +complete: + if (astk_ptr != &astk[0]) { + astk_ptr--; + async_retries = astk_ptr->over_retries; + async_func = astk_ptr->over_func; + async_state = astk_ptr->over_state; + async_arg0 = astk_ptr->over_arg0; + async_arg1 = astk_ptr->over_arg1; + async_arg2 = astk_ptr->over_arg2; + goto restate; + } + async_func = ACMD_NONE; + async_state = 0; + switch (ft->io_sts) { + case FTIO_READY: + async_req(ftu, 2); + break; + case FTIO_READING: + case FTIO_RDAHEAD: + async_read(ftu, 2); + break; + case FTIO_WRITING: + async_write(ftu, 2); + break; + default: + DPRT(("ft%d: bad async_cmd ending I/O state!\n", ftu)); + break; + } +} + + +/* + * Entry point for the async request processor. + */ +static void +async_req(ftu_t ftu, int from) +{ + ft_p ft = ft_data[ftu]; + SegReq *sp; + static int over_async, lastreq; + int cmd; + + if (from == 2) arq_state = over_async; + +restate: + switch (arq_state) { + case 0: /* Process segment */ + sp = ft->segh; + ft->io_sts = (sp == NULL) ? FTIO_READY : sp->reqtype; + + if (ft->io_sts == FTIO_WRITING) + async_write(ftu, from); + else + async_read(ftu, from); + if (ft->io_sts != FTIO_READY) return; + + /* Pull buffer from current I/O queue */ + if (sp != NULL) { + lastreq = sp->reqtype; + segio_done(ft, sp); + + /* If I/O cancelled, clear finished queue. */ + if (sp->reqcan) { + while (ft->doneh != NULL) + segio_free(ft, ft->doneh); + lastreq = FTIO_READY; + } + } else + lastreq = FTIO_READY; + + /* Detect end of track */ + if (((ft->xblk / QCV_BLKSEG) % ftg->g_segtrk) == 0) { + ACMD_FUNC(2, ACMD_STATE, QS_BOT|QS_EOT, 0, 0); + } + arq_state = 1; + goto restate; + + case 1: /* Next request */ + /* If we have another request queued, start it running. */ + if (ft->segh != NULL) { + sp = ft->segh; + sp->reqcrc = 0; + arq_state = ard_state = awr_state = 0; + ft->xblk = sp->reqblk; + ft->xseg = sp->reqseg; + ft->xcnt = 0; + ft->xptr = sp->buff; + DPRT(("I/O reqblk = %d\n", ft->xblk)); + goto restate; + } + + /* If the last request was reading, do read ahead. */ + if ((lastreq == FTIO_READING || lastreq == FTIO_RDAHEAD) && + (sp = segio_alloc(ft)) != NULL) { + sp->reqtype = FTIO_RDAHEAD; + sp->reqblk = ft->xblk; + sp->reqseg = ft->xseg+1; + sp->reqcrc = 0; + sp->reqcan = 0; + segio_queue(ft, sp); + bzero(sp->buff, QCV_SEGSIZE); + arq_state = ard_state = awr_state = 0; + ft->xblk = sp->reqblk; + ft->xseg = sp->reqseg; + ft->xcnt = 0; + ft->xptr = sp->buff; + DPRT(("Processing readahead reqblk = %d\n", ft->xblk)); + goto restate; + } + + if (ft->moving) { + DPRT(("No more I/O.. Stopping.\n")); + ft->moving = 0; + ACMD_FUNC(7, ACMD_SEEKSTS, QC_PAUSE, QS_READY, 0); + break; + } + arq_state = 7; + goto restate; + + case 2: /* End of track */ + ft->moving = 0; + ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); + break; + + case 3: + DPRT(("async_req seek head to track %d\n", ft->xblk / ftg->g_blktrk)); + ACMD_FUNC(4, ACMD_SEEK, QC_SEEKTRACK, 0, 0); + break; + + case 4: + cmd = (ft->xblk / ftg->g_blktrk) + 2; + if (ft->segh != NULL) { + ACMD_FUNC(5, ACMD_SEEKSTS, cmd, QS_READY, 0); + } else { + ACMD_FUNC(7, ACMD_SEEKSTS, cmd, QS_READY, 0); + } + break; + + case 5: + ft->moving = 1; + ACMD_FUNC(6, ACMD_SEEK, QC_FORWARD, 0, 0); + break; + + case 6: + arq_state = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ + break; + + case 7: + /* Time to rest. */ + ft->active = 0; + ft->lastpos = -2; + + /* wakeup those who want an i/o chg */ + wakeup((caddr_t)wc_iosts_change); + break; + } +} + + +/* + * Entry for async read. + */ +static void +async_read(ftu_t ftu, int from) +{ + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + int i, rddta[7]; + int where; + static int over_async; + static int retries = 0; + + if (from == 2) ard_state = over_async; + +restate: +#if FTDBGALL + DPRT(("async_read: state: %d from = %d\n", ard_state, from)); +#endif + switch (ard_state) { + case 0: /* Start off */ + /* If tape is not at desired position, stop and locate */ + if (ft->lastpos != (ft->xblk-1)) { + DPRT(("ft%d: position unknown: lastpos:%d ft->xblk:%d\n", + ftu, ft->lastpos, ft->xblk)); + ACMD_FUNC(1, ACMD_RUNBLK, ft->xblk, 0, 0); + } + + /* Tape is in position but stopped. */ + if (!ft->moving) { + DPRT(("async_read ******STARTING TAPE\n")); + ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); + } + ard_state = 1; + goto restate; + + case 1: /* Start DMA */ + /* Tape is now moving and in position-- start DMA now! */ + isa_dmastart(B_READ, ft->xptr, QCV_BLKSIZE, 2); + out_fdc(fdcu, 0x66); /* read */ + out_fdc(fdcu, ftu); /* unit */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdside) / ftg->g_fdtrk); /* cylinder */ + out_fdc(fdcu, ft->xblk / ftg->g_fdside); /* head */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* sector */ + out_fdc(fdcu, 0x03); /* 1K sectors */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* count */ + out_fdc(fdcu, 0x74); /* gap length */ + out_fdc(fdcu, 0xff); /* transfer size */ + ard_state = 2; + break; + + case 2: /* DMA completed */ + /* Transfer complete, get status */ + for (i = 0; i < 7; i++) rddta[i] = in_fdc(fdcu); + isa_dmadone(B_READ, ft->xptr, QCV_BLKSIZE, 2); + +#if FTDBGALL + /* Compute where the controller thinks we are */ + where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) + + rddta[5]-1; + DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", + rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], + where, ft->xblk)); +#endif + + /* Check for errors */ + if ((rddta[0] & 0xc0) != 0x00) { +#if !FTDBGALL + where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) + + rddta[5]-1; + DPRT(("xd: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", + rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], + where, ft->xblk)); +#endif + if ((rddta[1] & 0x04) == 0x04 && retries < 2) { + /* Probably wrong position */ + DPRT(("async_read: doing retry %d\n", retries)); + ft->lastpos = ft->xblk; + ard_state = 0; + retries++; + goto restate; + } else { + /* CRC/Address-mark/Data-mark, et. al. */ + DPRT(("ft%d: CRC error on block %d\n", fdcu, ft->xblk)); + ft->segh->reqcrc |= (1 << ft->xcnt); + } + } + + /* Otherwise, transfer completed okay. */ + retries = 0; + ft->lastpos = ft->xblk; + ft->xblk++; + ft->xcnt++; + ft->xptr += QCV_BLKSIZE; + if (ft->xcnt < QCV_BLKSEG && ft->segh->reqcan == 0) { + ard_state = 0; + goto restate; + } + DPRT(("Read done.. Cancel = %d\n", ft->segh->reqcan)); + ft->io_sts = FTIO_READY; + break; + + case 3: + ft->moving = 1; + ACMD_FUNC(4, ACMD_SEEK, QC_FORWARD, 0, 0); + break; + + case 4: + ard_state = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ + break; + + default: + DPRT(("ft%d: bad async_read state %d!!\n", ftu, ard_state)); + break; + } +} + + +/* + * Entry for async write. If from is 0, this came from the interrupt + * routine, if it's 1 then it was a timeout, if it's 2, then an + * async_cmd completed. + */ +static void +async_write(ftu_t ftu, int from) +{ + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + int i, rddta[7]; + int where; + static int over_async; + static int retries = 0; + + if (from == 2) awr_state = over_async; + +restate: +#if FTDBGALL + DPRT(("async_write: state: %d from = %d\n", awr_state, from)); +#endif + switch (awr_state) { + case 0: /* Start off */ + /* If tape is not at desired position, stop and locate */ + if (ft->lastpos != (ft->xblk-1)) { + DPRT(("ft%d: position unknown: lastpos:%d ft->xblk:%d\n", + ftu, ft->lastpos, ft->xblk)); + ACMD_FUNC(1, ACMD_RUNBLK, ft->xblk, 0, 0); + } + + /* Tape is in position but stopped. */ + if (!ft->moving) { + DPRT(("async_write ******STARTING TAPE\n")); + ACMD_FUNC(3, ACMD_STATE, QS_READY, 0, 0); + } + awr_state = 1; + goto restate; + + case 1: /* Start DMA */ + /* Tape is now moving and in position-- start DMA now! */ + isa_dmastart(B_WRITE, ft->xptr, QCV_BLKSIZE, 2); + out_fdc(fdcu, 0x45); /* write */ + out_fdc(fdcu, ftu); /* unit */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdside) / ftg->g_fdtrk); /* cyl */ + out_fdc(fdcu, ft->xblk / ftg->g_fdside); /* head */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* sector */ + out_fdc(fdcu, 0x03); /* 1K sectors */ + out_fdc(fdcu, (ft->xblk % ftg->g_fdtrk) + 1); /* count */ + out_fdc(fdcu, 0x74); /* gap length */ + out_fdc(fdcu, 0xff); /* transfer size */ + awr_state = 2; + break; + + case 2: /* DMA completed */ + /* Transfer complete, get status */ + for (i = 0; i < 7; i++) rddta[i] = in_fdc(fdcu); + isa_dmadone(B_WRITE, ft->xptr, QCV_BLKSIZE, 2); + +#if FTDBGALL + /* Compute where the controller thinks we are */ + where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) + rddta[5]-1; + DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", + rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], + where, ft->xblk)); +#endif + + /* Check for errors */ + if ((rddta[0] & 0xc0) != 0x00) { +#if !FTDBGALL + where = (rddta[3]*ftg->g_fdtrk) + (rddta[4]*ftg->g_fdside) + + rddta[5]-1; + DPRT(("xfer done: st0:%02x st1:%02x st2:%02x c:%d h:%d s:%d pos:%d want:%d\n", + rddta[0], rddta[1], rddta[2], rddta[3], rddta[4], rddta[5], + where, ft->xblk)); +#endif + if (retries < 3) { + /* Something happened -- try again */ + DPRT(("async_write: doing retry %d\n", retries)); + ft->lastpos = ft->xblk; + awr_state = 0; + retries++; + goto restate; + } else { + /* + * Retries failed. Note the unrecoverable error. + * Marking the block as bad is useless right now. + */ + printf("ft%d: unrecoverable write error on block %d\n", + ftu, ft->xblk); + ft->segh->reqcrc |= (1 << ft->xcnt); + } + } + + /* Otherwise, transfer completed okay. */ + retries = 0; + ft->lastpos = ft->xblk; + ft->xblk++; + ft->xcnt++; + ft->xptr += QCV_BLKSIZE; + if (ft->xcnt < QCV_BLKSEG) { + awr_state = 0; /* next block */ + goto restate; + } +#if FTDBGALL + DPRT(("Write done.\n")); +#endif + ft->io_sts = FTIO_READY; + break; + + case 3: + ft->moving = 1; + ACMD_FUNC(4, ACMD_SEEK, QC_FORWARD, 0, 0); + break; + + case 4: + awr_state = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, hz/10); /* XXX */ + break; + + default: + DPRT(("ft%d: bad async_write state %d!!\n", ftu, awr_state)); + break; + } +} + + +/* + * Interrupt handler for active tape. Bounced off of fdintr(). + */ +int +ftintr(ftu_t ftu) +{ + int st0, pcn, i; + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + int s = splbio(); + + st0 = 0; + pcn = 0; + + /* I/O segment transfer completed */ + if (ft->active) { + if (async_func != ACMD_NONE) { + async_cmd(ftu); + splx(s); + return(1); + } +#if FTDBGALL + DPRT(("Got request interrupt\n")); +#endif + async_req(ftu, 0); + splx(s); + return(1); + } + + /* Get interrupt status */ + if (ft->cmd_wait != FTCMD_READID) { + out_fdc(fdcu, NE7CMD_SENSEI); + st0 = in_fdc(fdcu); + pcn = in_fdc(fdcu); + } + + if (ft->cmd_wait == FTCMD_NONE || ft->sts_wait != FTSTS_SNOOZE) { +huh_what: + printf("ft%d: unexpected interrupt; st0 = $%02x pcn = %d\n", + ftu, st0, pcn); + splx(s); + return(1); + } + + switch (ft->cmd_wait) { + case FTCMD_RESET: + ft->sts_wait = FTSTS_INTERRUPT; + wakeup((caddr_t)wc_intr_wait); + break; + case FTCMD_RECAL: + case FTCMD_SEEK: + if (st0 & 0x20) { /* seek done */ + ft->sts_wait = FTSTS_INTERRUPT; + ft->pcn = pcn; + wakeup((caddr_t)wc_intr_wait); + } +#if FTDBGALL + else + DPRT(("ft%d: seek error st0 = $%02x pcn = %d\n", + ftu, st0, pcn)); +#endif + break; + case FTCMD_READID: + for (i = 0; i < 7; i++) ft->rid[i] = in_fdc(fdcu); + ft->sts_wait = FTSTS_INTERRUPT; + wakeup((caddr_t)wc_intr_wait); + break; + + default: + goto huh_what; + } + + splx(s); + return(1); +} + + +/* + * Interrupt timeout routine. + */ +static void +ft_timeout(void *arg1) +{ + int s; + ftu_t ftu = (ftu_t)arg1; + ft_p ft = ft_data[ftu]; + + s = splbio(); + if (ft->active) { + if (async_func != ACMD_NONE) { + async_cmd(ftu); + splx(s); + return; + } + async_req(ftu, 1); + } else { + ft->sts_wait = FTSTS_TIMEOUT; + wakeup((caddr_t)wc_intr_wait); + } + splx(s); +} + + +/* + * Wait for a particular interrupt to occur. ftintr() will wake us up + * if it sees what we want. Otherwise, time out and return error. + * Should always disable ints before trigger is sent and calling here. + */ +static int +ftintr_wait(ftu_t ftu, int cmd, int ticks) +{ + int retries, st0, pcn; + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + + ft->cmd_wait = cmd; + ft->sts_wait = FTSTS_SNOOZE; + + /* At attach time, we can't rely on having interrupts serviced */ + if (ft->attaching) { + switch (cmd) { + case FTCMD_RESET: + DELAY(100); + ft->sts_wait = FTSTS_INTERRUPT; + goto intrdone; + case FTCMD_RECAL: + case FTCMD_SEEK: + for (retries = 0; retries < 10000; retries++) { + DELAY(150); + out_fdc(fdcu, NE7CMD_SENSEI); + st0 = in_fdc(fdcu); + if ((st0 & 0xc0) == 0x80) continue; + pcn = in_fdc(fdcu); + if (st0 & 0x20) { + ft->sts_wait = FTSTS_INTERRUPT; + ft->pcn = pcn; + goto intrdone; + } + } + break; + } + ft->sts_wait = FTSTS_TIMEOUT; + goto intrdone; + } + + ftsleep(wc_intr_wait, ticks); + +intrdone: + if (ft->sts_wait == FTSTS_TIMEOUT) { /* timeout */ +#if FTDBGALL + if (ft->cmd_wait != FTCMD_RESET) + DPRT(("ft%d: timeout on command %d\n", ftu, ft->cmd_wait)); +#endif + ft->cmd_wait = FTCMD_NONE; + ft->sts_wait = FTSTS_NONE; + return(1); + } + + /* got interrupt */ + if (ft->attaching == 0 && ticks) + untimeout(ft_timeout, (caddr_t)ftu, ft->tohandle); + ft->cmd_wait = FTCMD_NONE; + ft->sts_wait = FTSTS_NONE; + return(0); +} + + +/* + * Recalibrate tape drive. Parameter totape is true, if we should + * recalibrate to tape drive settings. + */ +static int +tape_recal(ftu_t ftu, int totape) +{ + int s; + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + + DPRT(("tape_recal start\n")); + +#ifdef PC98 + outb(0xbe, FDP_FDDEXC | FDP_PORTEXC); +#endif + out_fdc(fdcu, NE7CMD_SPECIFY); +#ifdef PC98 + out_fdc(fdcu, (totape) ? 0xEF : 0xCF); + out_fdc(fdcu, 0x02); +#else + out_fdc(fdcu, (totape) ? 0xAD : 0xDF); + out_fdc(fdcu, 0x02); +#endif + + s = splbio(); + out_fdc(fdcu, NE7CMD_RECAL); + out_fdc(fdcu, ftu); + + if (ftintr_wait(ftu, FTCMD_RECAL, hz)) { + splx(s); + DPRT(("ft%d: recalibrate timeout\n", ftu)); + return(1); + } + splx(s); + + out_fdc(fdcu, NE7CMD_SPECIFY); +#ifdef PC98 + out_fdc(fdcu, (totape) ? 0xEF : 0xCF); + out_fdc(fdcu, 0x02); +#else + out_fdc(fdcu, (totape) ? 0xFD : 0xDF); + out_fdc(fdcu, 0x02); +#endif + + DPRT(("tape_recal end\n")); + return(0); +} + +/* + * Wait for a particular tape status to be met. If all is TRUE, then + * all states must be met, otherwise any state can be met. + */ +static int +tape_state(ftu_t ftu, int all, int mask, int seconds) +{ + int r, tries, maxtries; + + maxtries = (seconds) ? (4 * seconds) : 1; + for (tries = 0; tries < maxtries; tries++) { + r = tape_status(ftu); + if (r >= 0) { + if (all && (r & mask) == mask) return(r); + if ((r & mask) != 0) return(r); + } + if (seconds) ftsleep(wc_long_delay, hz/4); + } + DPRT(("ft%d: tape_state failed on mask=$%02x maxtries=%d\n", + ftu, mask, maxtries)); + return(-1); +} + + +/* + * Send a QIC command to tape drive, wait for completion. + */ +static int +tape_cmd(ftu_t ftu, int cmd) +{ + int newcn; + int retries = 0; + int s; + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + + DPRT(("===> tape_cmd: %d\n",cmd)); + newcn = (cmd <= ft->pcn) ? ft->pcn - cmd : ft->pcn + cmd; + +retry: + + /* Perform seek */ + s = splbio(); + out_fdc(fdcu, NE7CMD_SEEK); + out_fdc(fdcu, ftu); + out_fdc(fdcu, newcn); + + if (ftintr_wait(ftu, FTCMD_SEEK, hz)) { + DPRT(("ft%d: tape_cmd seek timeout\n", ftu)); +redo: + splx(s); + if (++retries < 5) goto retry; + DPRT(("ft%d: tape_cmd seek failed!\n", ftu)); + return(1); + } + splx(s); + + if (ft->pcn != newcn) { + DPRT(("ft%d: bad seek in tape_cmd; pcn = %d newcn = %d\n", + ftu, ft->pcn, newcn)); + goto redo; + } + DELAY(2500); + return(0); +} + + +/* + * Return status of tape drive + */ +static int +tape_status(ftu_t ftu) +{ + int r, err, tries; + ft_p ft = ft_data[ftu]; + int max = (ft->attaching) ? 2 : 3; + + for (r = -1, tries = 0; r < 0 && tries < max; tries++) + r = qic_status(ftu, QC_STATUS, 8); + if (tries == max) return(-1); + +recheck: + DPRT(("tape_status got $%04x\n",r)); + ft->laststs = r; + + if (r & (QS_ERROR|QS_NEWCART)) { + err = qic_status(ftu, QC_ERRCODE, 16); + ft->lasterr = err; + if (r & QS_NEWCART) { + ft->newcart = 1; + /* If tape not referenced, do a seek load point. */ + if ((r & QS_FMTOK) == 0 && !ft->attaching) { + tape_cmd(ftu, QC_SEEKLP); + do { + ftsleep(wc_long_delay, hz); + } while ((r = qic_status(ftu, QC_STATUS, 8)) < 0 || + (r & (QS_READY|QS_CART)) == QS_CART); + goto recheck; + } + } else if (err && !ft->attaching) { + DPRT(("ft%d: QIC error %d occurred on cmd %d\n", + ftu, err & 0xff, err >> 8)); + } + r = qic_status(ftu, QC_STATUS, 8); + ft->laststs = r; + DPRT(("tape_status got error code $%04x new sts = $%02x\n",err,r)); + } + + ft->rdonly = (r & QS_RDONLY); + return(r); +} + + +/* + * Transfer control to tape drive. + */ +static void +tape_start(ftu_t ftu, int motor) +{ + ft_p ft = ft_data[ftu]; + fdc_p fdc = ft->fdc; + int s, mbits; +#ifndef PC98 + static int mbmotor[] = { FDO_MOEN0, FDO_MOEN1, FDO_MOEN2, FDO_MOEN3 }; +#endif + + s = splbio(); + DPRT(("tape_start start\n")); + + /* reset, dma disable */ +#ifdef PC98 + outb(fdc->baseport+FDOUT, FDO_RST | FDO_FRY | FDO_AIE | FDO_MTON); +#else + outb(fdc->baseport+FDOUT, 0x00); +#endif + (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); + + /* raise reset, enable DMA, motor on if needed */ +#ifdef PC98 + outb(fdc->baseport+FDOUT, FDO_DMAE | FDO_MTON); +#else + mbits = ftu & 3; + if (motor && ftu < 4) + mbits |= mbmotor[ftu]; + + outb(fdc->baseport+FDOUT, FDO_FRST | FDO_FDMAEN | mbits); +#endif + (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); + + splx(s); + + tape_recal(ftu, 1); + + /* set transfer speed */ +#ifndef PC98 + outb(fdc->baseport+FDCTL, FDC_500KBPS); + DELAY(10); +#endif + + DPRT(("tape_start end\n")); +} + + +/* + * Transfer control back to floppy disks. + */ +static void +tape_end(ftu_t ftu) +{ + ft_p ft = ft_data[ftu]; + fdc_p fdc = ft->fdc; + int s; + + DPRT(("tape_end start\n")); + tape_recal(ftu, 0); + + s = splbio(); + + /* reset, dma disable */ +#ifdef PC98 + outb(fdc->baseport+FDOUT, FDO_RST | FDO_FRY | FDO_AIE | FDO_MTON); +#else + outb(fdc->baseport+FDOUT, 0x00); +#endif + (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); + + /* raise reset, enable DMA */ +#ifdef PC98 + outb(fdc->baseport+FDOUT, FDO_DMAE | FDO_MTON); +#else + outb(fdc->baseport+FDOUT, FDO_FRST | FDO_FDMAEN); +#endif + (void)ftintr_wait(ftu, FTCMD_RESET, hz/10); + + splx(s); + + /* set transfer speed */ +#ifndef PC98 + outb(fdc->baseport+FDCTL, FDC_500KBPS); + DELAY(10); +#endif + fdc->flags &= ~FDC_TAPE_BUSY; + + DPRT(("tape_end end\n")); +} + + +/* + * Wait for the driver to go inactive, cancel readahead if necessary. + */ +static void +tape_inactive(ftu_t ftu) +{ + ft_p ft = ft_data[ftu]; + int s = splbio(); + + if (ft->segh != NULL) { + if (ft->segh->reqtype == FTIO_RDAHEAD) { + /* cancel read-ahead */ + ft->segh->reqcan = 1; + } else if (ft->segh->reqtype == FTIO_WRITING && !ft->active) { + /* flush out any remaining writes */ + DPRT(("Flushing write I/O chain\n")); + arq_state = ard_state = awr_state = 0; + ft->xblk = ft->segh->reqblk; + ft->xseg = ft->segh->reqseg; + ft->xcnt = 0; + ft->xptr = ft->segh->buff; + ft->active = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); + } + } + while (ft->active) ftsleep(wc_iosts_change, 0); + splx(s); +} + + +/* + * Get the geometry of the tape currently in the drive. + */ +static int +ftgetgeom(ftu_t ftu) +{ + int r, i, tries; + int cfg, qic80, ext; + int sts, fmt, len; + ft_p ft = ft_data[ftu]; + + r = tape_status(ftu); + + /* XXX fix me when format mode is finished */ + if (r < 0 || (r & QS_CART) == 0 || (r & QS_FMTOK) == 0) { + DPRT(("ftgetgeom: no cart or not formatted 0x%04x\n",r)); + ftg = NULL; + ft->newcart = 1; + return(0); + } + + /* Report drive configuration */ + for (cfg = -1, tries = 0; cfg < 0 && tries < 3; tries++) + cfg = qic_status(ftu, QC_CONFIG, 8); + if (tries == 3) { + DPRT(("ftgetgeom report config failed\n")); + ftg = NULL; + return(-1); + } + DPRT(("ftgetgeom report config got $%04x\n", cfg)); + ft->lastcfg = cfg; + + qic80 = cfg & QCF_QIC80; + ext = cfg & QCF_EXTRA; + +/* + * XXX - This doesn't seem to work on my Colorado Jumbo 250... + * if it works on your drive, I'd sure like to hear about it. + */ +#if 0 + /* Report drive status */ + for (sts = -1, tries = 0; sts < 0 && tries < 3; tries++) + sts = qic_status(ftu, QC_TSTATUS, 8); + if (tries == 3) { + DPRT(("ftgetgeom report tape status failed\n")); + ftg = NULL; + return(-1); + } + DPRT(("ftgetgeom report tape status got $%04x\n", sts)); +#else + /* + * XXX - Forge a fake tape status based upon the returned + * configuration, since the above command or code is broken + * for my drive and probably other older drives. + */ + sts = 0; + sts = (qic80) ? QTS_QIC80 : QTS_QIC40; + sts |= (ext) ? QTS_LEN2 : QTS_LEN1; +#endif + + fmt = sts & QTS_FMMASK; + len = (sts & QTS_LNMASK) >> 4; + + if (fmt > QCV_NFMT) { + ftg = NULL; + printf("ft%d: unsupported tape format\n", ftu); + return(-1); + } + if (len > QCV_NLEN) { + ftg = NULL; + printf("ft%d: unsupported tape length\n", ftu); + return(-1); + } + + /* Look up geometry in the table */ + for (i = 1; i < NGEOM; i++) + if (ftgtbl[i].g_fmtno == fmt && ftgtbl[i].g_lenno == len) break; + if (i == NGEOM) { + printf("ft%d: unknown tape geometry\n", ftu); + ftg = NULL; + return(-1); + } + ftg = &ftgtbl[i]; + if (!ftg->g_trktape) { + printf("ft%d: unsupported format %s w/len %s\n", + ftu, ftg->g_fmtdesc, ftg->g_lendesc); + ftg = NULL; + return(-1); + } + DPRT(("Tape format is %s, length is %s\n", ftg->g_fmtdesc, ftg->g_lendesc)); + ft->newcart = 0; + return(0); +} + + +/* + * Switch between tape/floppy. This will send the tape enable/disable + * codes for this drive's manufacturer. + */ +static int +set_fdcmode(dev_t dev, int newmode) +{ + ftu_t ftu = FDUNIT(minor(dev)); + ft_p ft = ft_data[ftu]; + fdc_p fdc = ft->fdc; + static int havebufs = 0; + int i; + SegReq *sp, *rsp; + + if (newmode == FDC_TAPE_MODE) { + /* Wake up the tape drive */ + switch (ft->type) { + case NO_TYPE: + fdc->flags &= ~FDC_TAPE_BUSY; + return(ENXIO); + case FT_NONE: + tape_start(ftu, 0); + break; + case FT_COLORADO: + tape_start(ftu, 0); + if (tape_cmd(ftu, QC_COL_ENABLE1)) { + tape_end(ftu); + return(EIO); + } + if (tape_cmd(ftu, QC_COL_ENABLE2 + ftu)) { + tape_end(ftu); + return(EIO); + } + break; + case FT_MOUNTAIN: + tape_start(ftu, 0); + if (tape_cmd(ftu, QC_MTN_ENABLE1)) { + tape_end(ftu); + return(EIO); + } + if (tape_cmd(ftu, QC_MTN_ENABLE2)) { + tape_end(ftu); + return(EIO); + } + break; + case FT_INSIGHT: + tape_start(ftu, 1); + break; + default: + DPRT(("ft%d: bad tape type\n", ftu)); + return(ENXIO); + } + if (tape_status(ftu) < 0) { + if (ft->type == FT_COLORADO) + tape_cmd(ftu, QC_COL_DISABLE); + else if (ft->type == FT_MOUNTAIN) + tape_cmd(ftu, QC_MTN_DISABLE); + tape_end(ftu); + return(EIO); + } + + /* Grab buffers from memory. */ + if (!havebufs) { + ft->segh = ft->segt = NULL; + ft->doneh = ft->donet = NULL; + ft->segfree = NULL; + ft->hdr = NULL; + ft->nsegq = ft->ndoneq = ft->nfreelist = 0; + for (i = 0; i < FTNBUFF; i++) { + sp = malloc(sizeof(SegReq), M_DEVBUF, M_WAITOK); + if (sp == NULL) { + printf("ft%d: not enough memory for buffers\n", ftu); + for (sp=ft->segfree; sp != NULL; sp=sp->next) + free(sp, M_DEVBUF); + if (ft->type == FT_COLORADO) + tape_cmd(ftu, QC_COL_DISABLE); + else if (ft->type == FT_MOUNTAIN) + tape_cmd(ftu, QC_MTN_DISABLE); + tape_end(ftu); + return(ENOMEM); + } + sp->reqtype = FTIO_READY; + sp->next = ft->segfree; + ft->segfree = sp; + ft->nfreelist++; + } + /* take one buffer for header */ + ft->hdr = ft->segfree; + ft->segfree = ft->segfree->next; + ft->nfreelist--; + havebufs = 1; + } + ft->io_sts = FTIO_READY; /* tape drive is ready */ + ft->active = 0; /* interrupt driver not active */ + ft->moving = 0; /* tape not moving */ + ft->rdonly = 0; /* tape read only */ + ft->newcart = 0; /* new cartridge flag */ + ft->lastpos = -1; /* tape is rewound */ + async_func = ACMD_NONE; /* No async function */ + tape_state(ftu, 0, QS_READY, 60); + tape_cmd(ftu, QC_RATE); + tape_cmd(ftu, QCF_RT500+2); /* 500K bps */ + tape_state(ftu, 0, QS_READY, 60); + ft->mode = FTM_PRIMARY; + tape_cmd(ftu, QC_PRIMARY); /* Make sure we're in primary mode */ + tape_state(ftu, 0, QS_READY, 60); + ftg = NULL; /* No geometry yet */ + ftgetgeom(ftu); /* Get tape geometry */ + ftreq_rewind(ftu); /* Make sure tape is rewound */ + } else { + if (ft->type == FT_COLORADO) + tape_cmd(ftu, QC_COL_DISABLE); + else if (ft->type == FT_MOUNTAIN) + tape_cmd(ftu, QC_MTN_DISABLE); + tape_end(ftu); + ft->newcart = 0; /* clear new cartridge */ + if (ft->hdr != NULL) free(ft->hdr, M_DEVBUF); + if (havebufs) { + for (sp = ft->segfree; sp != NULL;) { + rsp = sp; sp = sp->next; + free(rsp, M_DEVBUF); + } + for (sp = ft->segh; sp != NULL;) { + rsp = sp; sp = sp->next; + free(rsp, M_DEVBUF); + } + for (sp = ft->doneh; sp != NULL;) { + rsp = sp; sp = sp->next; + free(rsp, M_DEVBUF); + } + } + havebufs = 0; + } + return(0); +} + + +/* + * Perform a QIC status function. + */ +static int +qic_status(ftu_t ftu, int cmd, int nbits) +{ + int st3, r, i; + ft_p ft = ft_data[ftu]; + fdcu_t fdcu = ft->fdc->fdcu; /* fdc active unit */ + + if (tape_cmd(ftu, cmd)) { + DPRT(("ft%d: QIC status timeout\n", ftu)); + return(-1); + } + + /* Sense drive status */ + out_fdc(fdcu, NE7CMD_SENSED); + out_fdc(fdcu, ftu); + st3 = in_fdc(fdcu); + + if ((st3 & 0x10) == 0) { /* track 0 */ + DPRT(("qic_status has dead drive... st3 = $%02x\n", st3)); + return(-1); + } + + for (i = r = 0; i <= nbits; i++) { + if (tape_cmd(ftu, QC_NEXTBIT)) { + DPRT(("ft%d: QIC status bit timed out on %d\n", ftu, i)); + return(-1); + } + + out_fdc(fdcu, NE7CMD_SENSED); + out_fdc(fdcu, ftu); + st3 = in_fdc(fdcu); + if (st3 < 0) { + DPRT(("ft%d: controller timed out on bit %d r=$%02x\n", + ftu, i, r)); + return(-1); + } + + r >>= 1; + if (i < nbits) + r |= ((st3 & 0x10) ? 1 : 0) << nbits; + else if ((st3 & 0x10) == 0) { + DPRT(("ft%d: qic status stop bit missing at %d, st3=$%02x r=$%04x\n", + ftu,i,st3,r)); + return(-1); + } + } + + DPRT(("qic_status returned $%02x\n", r)); + return(r); +} + + +/* + * Open tape drive for use. Bounced off of Fdopen if tape minor is + * detected. + */ +int +ftopen(dev_t dev, int arg2) { + ftu_t ftu = FDUNIT(minor(dev)); + fdc_p fdc; + + /* check bounds */ + if (ftu >= NFT) + return(ENXIO); + if (!ft_data[ftu]) + return(ENXIO); + fdc = ft_data[ftu]->fdc; + if ((fdc == NULL) || (ft_data[ftu]->type == NO_TYPE)) + return(ENXIO); + /* check for controller already busy with tape */ + if (fdc->flags & FDC_TAPE_BUSY) + return(EBUSY); + /* make sure we found a tape when probed */ + if (!(fdc->flags & FDC_HASFTAPE)) + return(ENODEV); + fdc->fdu = ftu; + fdc->flags |= FDC_TAPE_BUSY; + return(set_fdcmode(dev, FDC_TAPE_MODE)); /* try to switch to tape */ +} + + +/* + * Close tape and return floppy controller to disk mode. + */ +int +ftclose(dev_t dev, int flags) +{ + ftu_t ftu = FDUNIT(minor(dev)); + ft_p ft = ft_data[ftu]; + + + /* Wait for any remaining I/O activity to complete. */ + tape_inactive(ftu); + + ft->mode = FTM_PRIMARY; + tape_cmd(ftu, QC_PRIMARY); + tape_state(ftu, 0, QS_READY, 60); + ftreq_rewind(ftu); + return(set_fdcmode(dev, FDC_DISK_MODE)); /* Otherwise, close tape */ +} + +/* + * Read or write a segment. + */ +static int +ftreq_rw(ftu_t ftu, unsigned long cmd, QIC_Segment *sr, struct proc *p) +{ + int r, i; + SegReq *sp; + int s; + long blk, bad, seg; + unsigned char *cp, *cp2; + ft_p ft = ft_data[ftu]; + + if (!ft->active && ft->segh == NULL) { + r = tape_status(ftu); + if ((r & QS_CART) == 0) + return(ENXIO); /* No cartridge */ + if ((r & QS_FMTOK) == 0) + return(ENXIO); /* Not formatted */ + tape_state(ftu, 0, QS_READY, 90); + } + + if (ftg == NULL || ft->newcart) { + tape_inactive(ftu); + tape_state(ftu, 0, QS_READY, 90); + if (ftgetgeom(ftu) < 0) + return(ENXIO); + } + + /* Write not allowed on a read-only tape. */ + if (cmd == QIOWRITE && ft->rdonly) + return(EROFS); + + /* Quick check of request and buffer. */ + if (sr == NULL || sr->sg_data == NULL) + return(EINVAL); + + /* Make sure requested track and segment is in range. */ + if (sr->sg_trk >= ftg->g_trktape || sr->sg_seg >= ftg->g_segtrk) + return(EINVAL); + + blk = sr->sg_trk * ftg->g_blktrk + sr->sg_seg * QCV_BLKSEG; + seg = sr->sg_trk * ftg->g_segtrk + sr->sg_seg; + + s = splbio(); + if (cmd == QIOREAD) { + /* + * See if the driver is reading ahead. + */ + if (ft->doneh != NULL || + (ft->segh != NULL && ft->segh->reqtype == FTIO_RDAHEAD)) { + /* + * Eat the completion queue and see if the request + * is already there. + */ + while (ft->doneh != NULL) { + if (blk == ft->doneh->reqblk) { + sp = ft->doneh; + sp->reqtype = FTIO_READING; + sp->reqbad = sr->sg_badmap; + goto rddone; + } + segio_free(ft, ft->doneh); + } + + /* + * Not on the completed queue, in progress maybe? + */ + if (ft->segh != NULL && ft->segh->reqtype == FTIO_RDAHEAD && + blk == ft->segh->reqblk) { + sp = ft->segh; + sp->reqtype = FTIO_READING; + sp->reqbad = sr->sg_badmap; + goto rdwait; + } + } + + /* Wait until we're ready. */ + tape_inactive(ftu); + + /* Set up a new read request. */ + sp = segio_alloc(ft); + sp->reqcrc = 0; + sp->reqbad = sr->sg_badmap; + sp->reqblk = blk; + sp->reqseg = seg; + sp->reqcan = 0; + sp->reqtype = FTIO_READING; + segio_queue(ft, sp); + + /* Start the read request off. */ + DPRT(("Starting read I/O chain\n")); + arq_state = ard_state = awr_state = 0; + ft->xblk = sp->reqblk; + ft->xseg = sp->reqseg; + ft->xcnt = 0; + ft->xptr = sp->buff; + ft->active = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); + +rdwait: + ftsleep(wc_buff_done, 0); + +rddone: + bad = sp->reqbad; + sr->sg_crcmap = sp->reqcrc & ~bad; + + /* Copy out segment and discard bad mapped blocks. */ + cp = sp->buff; cp2 = sr->sg_data; + for (i = 0; i < QCV_BLKSEG; cp += QCV_BLKSIZE, i++) { + if (bad & (1 << i)) continue; + copyout(cp, cp2, QCV_BLKSIZE); + cp2 += QCV_BLKSIZE; + } + segio_free(ft, sp); + } else { + if (ft->segh != NULL && ft->segh->reqtype != FTIO_WRITING) + tape_inactive(ftu); + + /* Allocate a buffer and start tape if we're running low. */ + sp = segio_alloc(ft); + if (!ft->active && (sp == NULL || ft->nfreelist <= 1)) { + DPRT(("Starting write I/O chain\n")); + arq_state = ard_state = awr_state = 0; + ft->xblk = ft->segh->reqblk; + ft->xseg = ft->segh->reqseg; + ft->xcnt = 0; + ft->xptr = ft->segh->buff; + ft->active = 1; + ft->tohandle = timeout(ft_timeout, (caddr_t)ftu, 1); + } + + /* Sleep until a buffer becomes available. */ + while (sp == NULL) { + ftsleep(wc_buff_avail, 0); + sp = segio_alloc(ft); + } + + /* Copy in segment and expand bad blocks. */ + bad = sr->sg_badmap; + cp = sr->sg_data; cp2 = sp->buff; + for (i = 0; i < QCV_BLKSEG; cp2 += QCV_BLKSIZE, i++) { + if (bad & (1 << i)) continue; + copyin(cp, cp2, QCV_BLKSIZE); + cp += QCV_BLKSIZE; + } + sp->reqblk = blk; + sp->reqseg = seg; + sp->reqcan = 0; + sp->reqtype = FTIO_WRITING; + segio_queue(ft, sp); + } + splx(s); + return(0); +} + + +/* + * Rewind to beginning of tape + */ +static int +ftreq_rewind(ftu_t ftu) +{ + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + tape_cmd(ftu, QC_STOP); + tape_state(ftu, 0, QS_READY, 90); + tape_cmd(ftu, QC_SEEKSTART); + tape_state(ftu, 0, QS_READY, 90); + tape_cmd(ftu, QC_SEEKTRACK); + tape_cmd(ftu, 2); + tape_state(ftu, 0, QS_READY, 90); + ft->lastpos = -1; + ft->moving = 0; + return(0); +} + + +/* + * Move to logical beginning or end of track + */ +static int +ftreq_trkpos(ftu_t ftu, int req) +{ + int curtrk, r, cmd; + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + tape_cmd(ftu, QC_STOP); + tape_state(ftu, 0, QS_READY, 90); + + r = tape_status(ftu); + if ((r & QS_CART) == 0) return(ENXIO); /* No cartridge */ + if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ + + if (ftg == NULL || ft->newcart) { + if (ftgetgeom(ftu) < 0) return(ENXIO); + } + + curtrk = (ft->lastpos < 0) ? 0 : ft->lastpos / ftg->g_blktrk; + if (req == QIOBOT) + cmd = (curtrk & 1) ? QC_SEEKEND : QC_SEEKSTART; + else + cmd = (curtrk & 1) ? QC_SEEKSTART : QC_SEEKEND; + tape_cmd(ftu, cmd); + tape_state(ftu, 0, QS_READY, 90); + return(0); +} + + +/* + * Seek tape head to a particular track. + */ +static int +ftreq_trkset(ftu_t ftu, int *trk) +{ + int r; + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + tape_cmd(ftu, QC_STOP); + tape_state(ftu, 0, QS_READY, 90); + + r = tape_status(ftu); + if ((r & QS_CART) == 0) return(ENXIO); /* No cartridge */ + if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ + if (ftg == NULL || ft->newcart) { + if (ftgetgeom(ftu) < 0) return(ENXIO); + } + + tape_cmd(ftu, QC_SEEKTRACK); + tape_cmd(ftu, *trk + 2); + tape_state(ftu, 0, QS_READY, 90); + return(0); +} + + +/* + * Start tape moving forward. + */ +static int +ftreq_lfwd(ftu_t ftu) +{ + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + tape_cmd(ftu, QC_STOP); + tape_state(ftu, 0, QS_READY, 90); + tape_cmd(ftu, QC_FORWARD); + ft->moving = 1; + return(0); +} + + +/* + * Stop the tape + */ +static int +ftreq_stop(ftu_t ftu) +{ + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + tape_cmd(ftu, QC_STOP); + tape_state(ftu, 0, QS_READY, 90); + ft->moving = 0; + return(0); +} + + +/* + * Set the particular mode the drive should be in. + */ +static int +ftreq_setmode(ftu_t ftu, int cmd) +{ + int r; + ft_p ft = ft_data[ftu]; + + tape_inactive(ftu); + r = tape_status(ftu); + + switch(cmd) { + case QIOPRIMARY: + ft->mode = FTM_PRIMARY; + tape_cmd(ftu, QC_PRIMARY); + break; + case QIOFORMAT: + if (r & QS_RDONLY) return(ENXIO); + if ((r & QS_BOT) == 0) return(ENXIO); + tape_cmd(ftu, QC_FORMAT); + break; + case QIOVERIFY: + if ((r & QS_FMTOK) == 0) return(ENXIO); /* Not formatted */ + tape_cmd(ftu, QC_VERIFY); + break; + } + tape_state(ftu, 0, QS_READY, 60); + return(0); +} + + +/* + * Return drive status bits + */ +static int +ftreq_status(ftu_t ftu, unsigned long cmd, int *sts, struct proc *p) +{ + ft_p ft = ft_data[ftu]; + + if (ft->active) + *sts = ft->laststs & ~QS_READY; + else + *sts = tape_status(ftu); + return(0); +} + + +/* + * Return drive configuration bits + */ +static int +ftreq_config(ftu_t ftu, unsigned long cmd, int *cfg, struct proc *p) +{ + int r, tries; + ft_p ft = ft_data[ftu]; + + if (ft->active) + r = ft->lastcfg; + else { + for (r = -1, tries = 0; r < 0 && tries < 3; tries++) + r = qic_status(ftu, QC_CONFIG, 8); + if (tries == 3) return(ENXIO); + } + *cfg = r; + return(0); +} + + +/* + * Return current tape's geometry. + */ +static int +ftreq_geom(ftu_t ftu, QIC_Geom *g) +{ + tape_inactive(ftu); + if (ftg == NULL && ftgetgeom(ftu) < 0) return(ENXIO); + bcopy(ftg, g, sizeof(QIC_Geom)); + return(0); +} + + +/* + * Return drive hardware information + */ +static int +ftreq_hwinfo(ftu_t ftu, QIC_HWInfo *hwp) +{ + int tries; + int rom, vend; + + tape_inactive(ftu); + bzero(hwp, sizeof(QIC_HWInfo)); + + for (rom = -1, tries = 0; rom < 0 && tries < 3; tries++) + rom = qic_status(ftu, QC_VERSION, 8); + if (rom > 0) { + hwp->hw_rombeta = (rom >> 7) & 0x01; + hwp->hw_romid = rom & 0x7f; + } + + for (vend = -1, tries = 0; vend < 0 && tries < 3; tries++) + vend = qic_status(ftu, QC_VENDORID, 16); + if (vend > 0) { + hwp->hw_make = (vend >> 6) & 0x3ff; + hwp->hw_model = vend & 0x3f; + } + + return(0); +} + + +/* + * Receive or Send the in-core header segment. + */ +static int +ftreq_hdr(ftu_t ftu, unsigned long cmd, QIC_Segment *sp) +{ + ft_p ft = ft_data[ftu]; + QIC_Header *h = (QIC_Header *)ft->hdr->buff; + + if (sp == NULL || sp->sg_data == NULL) return(EINVAL); + if (cmd == QIOSENDHDR) { + copyin(sp->sg_data, ft->hdr->buff, QCV_SEGSIZE); + } else { + if (h->qh_sig != QCV_HDRMAGIC) return(EIO); + copyout(ft->hdr->buff, sp->sg_data, QCV_SEGSIZE); + } + return(0); +} + +/* + * I/O functions. + */ +int +ftioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag, struct proc *p) +{ + ftu_t ftu = FDUNIT(minor(dev)); + + switch(cmd) { + case QIOREAD: /* Request reading a segment from tape. */ + case QIOWRITE: /* Request writing a segment to tape. */ + return(ftreq_rw(ftu, cmd, (QIC_Segment *)data, p)); + + case QIOREWIND: /* Rewind tape. */ + return(ftreq_rewind(ftu)); + + case QIOBOT: /* Seek to logical beginning of track. */ + case QIOEOT: /* Seek to logical end of track. */ + return(ftreq_trkpos(ftu, cmd)); + + case QIOTRACK: /* Seek tape head to specified track. */ + return(ftreq_trkset(ftu, (int *)data)); + + case QIOSEEKLP: /* Seek load point. */ + goto badreq; + + case QIOFORWARD: /* Move tape in logical forward direction. */ + return(ftreq_lfwd(ftu)); + + case QIOSTOP: /* Causes tape to stop. */ + return(ftreq_stop(ftu)); + + case QIOPRIMARY: /* Enter primary mode. */ + case QIOFORMAT: /* Enter format mode. */ + case QIOVERIFY: /* Enter verify mode. */ + return(ftreq_setmode(ftu, cmd)); + + case QIOWRREF: /* Write reference burst. */ + goto badreq; + + case QIOSTATUS: /* Get drive status. */ + return(ftreq_status(ftu, cmd, (int *)data, p)); + + case QIOCONFIG: /* Get tape configuration. */ + return(ftreq_config(ftu, cmd, (int *)data, p)); + + case QIOGEOM: + return(ftreq_geom(ftu, (QIC_Geom *)data)); + + case QIOHWINFO: + return(ftreq_hwinfo(ftu, (QIC_HWInfo *)data)); + + case QIOSENDHDR: + case QIORECVHDR: + return(ftreq_hdr(ftu, cmd, (QIC_Segment *)data)); + } +badreq: + DPRT(("ft%d: unknown ioctl(%#lx) request\n", ftu, cmd)); + return(ENXIO); +} + +#endif diff --git a/sys/i386/isa/ftreg.h b/sys/i386/isa/ftreg.h new file mode 100644 index 0000000000000..eea78ec9ea5a0 --- /dev/null +++ b/sys/i386/isa/ftreg.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1993, 1994 Steve Gerakines + * + * This is freely redistributable software. You may do anything you + * wish with it, so long as the above notice stays intact. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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. + * + * ftreg.h - QIC-40/80 floppy tape driver header + * 06/03/94 v0.9 + * Changed seek load point to QC_SEEKLP, added reqseg to SegReq structure. + * + * 10/30/93 v0.3 + * More things will end up here. QC_VENDORID and QC_VERSION now used. + * + * 08/07/93 v0.2 release + * Things that should've been here in the first place were moved. + * Tape geometry and segment request types were added. + * + * 06/03/93 v0.1 Alpha release + * Initial revision. Many more things should be moved here. + */ + +/* QIC-117 command set. */ +#define QC_RESET 1 /* reset */ +#define QC_NEXTBIT 2 /* report next bit */ +#define QC_PAUSE 3 /* pause */ +#define QC_STPAUSE 4 /* step pause */ +#define QC_TIMEOUT 5 /* alt timeout */ +#define QC_STATUS 6 /* report status */ +#define QC_ERRCODE 7 /* report error code */ +#define QC_CONFIG 8 /* report config */ +#define QC_VERSION 9 /* report version */ +#define QC_FORWARD 10 /* logical forward */ +#define QC_SEEKSTART 11 /* seek to track start */ +#define QC_SEEKEND 12 /* seek to track end */ +#define QC_SEEKTRACK 13 /* seek head to track */ +#define QC_SEEKLP 14 /* seek load point */ +#define QC_FORMAT 15 /* format mode */ +#define QC_WRITEREF 16 /* write reference */ +#define QC_VERIFY 17 /* verify mode */ +#define QC_STOP 18 /* stop tape */ +#define QC_STEPUP 21 /* step head up */ +#define QC_STEPDOWN 22 /* step head down */ +#define QC_SEEKREV 25 /* seek reverse */ +#define QC_SEEKFWD 26 /* seek forward */ +#define QC_RATE 27 /* select data rate */ +#define QC_DIAG1 28 /* diagnostic mode 1 */ +#define QC_DIAG2 29 /* diagnostic mode 2 */ +#define QC_PRIMARY 30 /* primary mode */ +#define QC_VENDORID 32 /* vendor id */ +#define QC_TSTATUS 33 /* report tape status */ +#define QC_EXTREV 34 /* extended skip reverse */ +#define QC_EXTFWD 35 /* extended skip forward */ + +/* Colorado enable/disable. */ +#define QC_COL_ENABLE1 46 /* enable */ +#define QC_COL_ENABLE2 2 /* unit+2 */ +#define QC_COL_DISABLE 47 /* disable */ + +/* Mountain enable/disable. */ +#define QC_MTN_ENABLE1 23 /* enable 1 */ +#define QC_MTN_ENABLE2 20 /* enable 2 */ +#define QC_MTN_DISABLE 24 /* disable */ + +/* Segment I/O request. */ +typedef struct segq { + unsigned char buff[QCV_SEGSIZE];/* Segment data; first for alignment */ + int reqtype; /* Request type */ + long reqcrc; /* CRC Errors found */ + long reqbad; /* Bad sector map */ + long reqblk; /* Block request starts at */ + long reqseg; /* Segment request is at */ + int reqcan; /* Cancel read-ahead */ + struct segq *next; /* Next request */ +} SegReq; + +typedef int ftu_t; +typedef int ftsu_t; +typedef struct ft_data *ft_p; diff --git a/sys/i386/isa/gsc.c b/sys/i386/isa/gsc.c index 1fa83761b8535..44a97ea7c72e8 100644 --- a/sys/i386/isa/gsc.c +++ b/sys/i386/isa/gsc.c @@ -71,13 +71,9 @@ #define DMA1_READY 0x08 #ifdef GSCDEBUG -#define lprintf(args) \ - do { \ - if (scu->flags & FLAG_DEBUG) \ - printf args; \ - } while (0) +#define lprintf if(scu->flags & FLAG_DEBUG) printf #else -#define lprintf(args) +#define lprintf (void) #endif #define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -230,16 +226,16 @@ lookup_geometry(struct gsc_geom geom, const struct gsc_unit *scu) ( ( geom.g_res != INVALID ) && ( tab.g_res == geom.g_res ) ) || ( ( geom.s_res != INVALID ) && ( tab.s_res == geom.s_res ) ) ) { - lprintf(("gsc.lookup_geometry: " + lprintf("gsc.lookup_geometry: " "geometry lookup found: %ddpi, %ddpl\n", - tab.dpi, tab.dpl)); + tab.dpi, tab.dpl); return i; } } - lprintf(("gsc.lookup_geometry: " + lprintf("gsc.lookup_geometry: " "geometry lookup failed on {%d, %d, 0x%02x, 0x%02x}\n", - geom.dpi, geom.dpl, geom.g_res, geom.s_res)); + geom.dpi, geom.dpl, geom.g_res, geom.s_res); return INVALID; } @@ -257,7 +253,7 @@ get_geometry(const struct gsc_unit *scu) { struct gsc_geom geom = NEW_GEOM; - lprintf(("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat)); + lprintf("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat); if ( ( geom.g_res = inb(scu->stat) ) == FAIL ) return INVALID; @@ -280,18 +276,18 @@ buffer_allocate(struct gsc_unit *scu) size = scu->blen * geomtab[scu->geometry].dpl / 8; - lprintf(("gsc.buffer_allocate: need 0x%x bytes\n", size)); + lprintf("gsc.buffer_allocate: need 0x%x bytes\n", size); if ( size > MAX_BUFSIZE ) { - lprintf(("gsc.buffer_allocate: 0x%x bytes are too much\n", size)); + lprintf("gsc.buffer_allocate: 0x%x bytes are too much\n", size); return ENOMEM; } scu->sbuf.size = size; scu->sbuf.poi = size; - lprintf(("gsc.buffer_allocate: ok\n")); + lprintf("gsc.buffer_allocate: ok\n"); return SUCCESS; } @@ -311,11 +307,11 @@ buffer_read(struct gsc_unit *scu) int sps; int delay; - lprintf(("gsc.buffer_read: begin\n")); + lprintf("gsc.buffer_read: begin\n"); if (scu->ctrl_byte == INVALID) { - lprintf(("gsc.buffer_read: invalid ctrl_byte\n")); + lprintf("gsc.buffer_read: invalid ctrl_byte\n"); return EIO; } @@ -334,7 +330,7 @@ buffer_read(struct gsc_unit *scu) if(delay >= scu->btime) { splx(sps); - lprintf(("gsc.buffer_read: timeout\n")); + lprintf("gsc.buffer_read: timeout\n"); res = EWOULDBLOCK; break; } @@ -350,16 +346,16 @@ buffer_read(struct gsc_unit *scu) if(res != SUCCESS) { - lprintf(("gsc.buffer_read: aborted with %d\n", res)); + lprintf("gsc.buffer_read: aborted with %d\n", res); return res; } - lprintf(("gsc.buffer_read: invert buffer\n")); + lprintf("gsc.buffer_read: invert buffer\n"); for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--) *p = ~*p; scu->sbuf.poi = 0; - lprintf(("gsc.buffer_read: ok\n")); + lprintf("gsc.buffer_read: ok\n"); return SUCCESS; } @@ -388,25 +384,25 @@ gscprobe (struct isa_device *isdp) scu->flags = FLAG_DEBUG; - lprintf(("gsc%d.probe " - "on iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n", + lprintf("gsc%d.probe " + "on iobase 0x%03x, irq %d, drq %d, addr %d, size %d\n", unit, isdp->id_iobase, isdp->id_irq, isdp->id_drq, isdp->id_maddr, - isdp->id_msize)); + isdp->id_msize); if ( isdp->id_iobase < 0 ) { - lprintf(("gsc%d.probe: no iobase given\n", unit)); + lprintf("gsc%d.probe: no iobase given\n", unit); return PROBE_FAIL; } stb = inb( GSC_STAT(isdp->id_iobase) ); if (stb == FAIL) { - lprintf(("gsc%d.probe: get status byte failed\n", unit)); + lprintf("gsc%d.probe: get status byte failed\n", unit); return PROBE_FAIL; } @@ -420,25 +416,25 @@ gscprobe (struct isa_device *isdp) switch(stb & GSC_CNF_MASK) { case GSC_CNF_DMA1: - lprintf(("gsc%d.probe: DMA 1\n", unit)); + lprintf("gsc%d.probe: DMA 1\n", unit); scu->channel = 1; break; case GSC_CNF_DMA3: - lprintf(("gsc%d.probe: DMA 3\n", unit)); + lprintf("gsc%d.probe: DMA 3\n", unit); scu->channel = 3; break; case GSC_CNF_IRQ3: - lprintf(("gsc%d.probe: IRQ 3\n", unit)); + lprintf("gsc%d.probe: IRQ 3\n", unit); goto probe_noirq; case GSC_CNF_IRQ5: - lprintf(("gsc%d.probe: IRQ 5\n", unit)); + lprintf("gsc%d.probe: IRQ 5\n", unit); probe_noirq: - lprintf(("gsc%d.probe: sorry, can't use IRQ yet\n", unit)); + lprintf("gsc%d.probe: sorry, can't use IRQ yet\n", unit); return PROBE_FAIL; default: - lprintf(("gsc%d.probe: invalid status byte 0x%02x\n", unit, (u_char) stb)); + lprintf("gsc%d.probe: invalid status byte\n", unit, stb); return PROBE_FAIL; } @@ -446,8 +442,8 @@ gscprobe (struct isa_device *isdp) isdp->id_drq = scu->channel; if (scu->channel != isdp->id_drq) { - lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n", - unit, isdp->id_drq, scu->channel)); + lprintf("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n", + unit, isdp->id_drq, scu->channel); return PROBE_FAIL; } @@ -455,7 +451,7 @@ gscprobe (struct isa_device *isdp) scu->geometry = lookup_geometry(geom, scu); if (scu->geometry == INVALID) { - lprintf(("gsc%d.probe: geometry lookup failed\n", unit)); + lprintf("gsc%d.probe: geometry lookup failed\n", unit); return PROBE_FAIL; } else @@ -463,13 +459,13 @@ gscprobe (struct isa_device *isdp) scu->ctrl_byte = geomtab[scu->geometry].s_res; outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON); - lprintf(("gsc%d.probe: status 0x%02x, %ddpi\n", - unit, stb, geomtab[scu->geometry].dpi)); + lprintf("gsc%d.probe: status 0x%02x, %ddpi\n", + unit, stb, geomtab[scu->geometry].dpi); outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON); } - lprintf(("gsc%d.probe: ok\n", unit)); + lprintf("gsc%d.probe: ok\n", unit); scu->flags &= ~FLAG_DEBUG; @@ -492,14 +488,14 @@ gscattach(struct isa_device *isdp) scu->flags |= FLAG_DEBUG; - lprintf(("gsc%d.attach: " - "iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n", + lprintf("gsc%d.attach: " + "iobase 0x%03x, irq %d, drq %d, addr %d, size %d\n", unit, isdp->id_iobase, isdp->id_irq, isdp->id_drq, isdp->id_maddr, - isdp->id_msize)); + isdp->id_msize); printf("gsc%d: GeniScan GS-4500 at %ddpi\n", unit, geomtab[scu->geometry].dpi); @@ -513,7 +509,7 @@ gscattach(struct isa_device *isdp) 0ul, 0xfffffful, 1ul, 0x10000ul); if ( scu->sbuf.base == NULL ) { - lprintf(("gsc%d.attach: buffer allocation failed\n", unit)); + lprintf("gsc%d.attach: buffer allocation failed\n", unit); return ATTACH_FAIL; /* XXX attach must not fail */ } scu->sbuf.size = INVALID; @@ -523,7 +519,7 @@ gscattach(struct isa_device *isdp) scu->btime = TIMEOUT; scu->flags |= ATTACHED; - lprintf(("gsc%d.attach: ok\n", unit)); + lprintf("gsc%d.attach: ok\n", unit); scu->flags &= ~FLAG_DEBUG; #ifdef DEVFS #define GSC_UID 0 @@ -573,8 +569,8 @@ gscopen (dev_t dev, int flags, int fmt, struct proc *p) scu = unittab + unit; if ( !( scu->flags & ATTACHED ) ) { - lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n", - unit, scu->flags)); + lprintf("gsc%d.open: unit was not attached successfully 0x04x\n", + unit, scu->flags); return ENXIO; } @@ -586,23 +582,23 @@ gscopen (dev_t dev, int flags, int fmt, struct proc *p) switch(minor(dev) & FRMT_MASK) { case FRMT_PBM: scu->flags |= PBM_MODE; - lprintf(("gsc%d.open: pbm mode\n", unit)); + lprintf("gsc%d.open: pbm mode\n", unit); break; case FRMT_RAW: - lprintf(("gsc%d.open: raw mode\n", unit)); + lprintf("gsc%d.open: raw mode\n", unit); scu->flags &= ~PBM_MODE; break; default: - lprintf(("gsc%d.open: gray maps are not yet supported", unit)); + lprintf("gsc%d.open: gray maps are not yet supported", unit); return ENXIO; } - lprintf(("gsc%d.open: minor %d\n", - unit, minor(dev))); + lprintf("gsc%d.open: minor %d\n", + unit, minor(dev)); if ( scu->flags & OPEN ) { - lprintf(("gsc%d.open: already open", unit)); + lprintf("gsc%d.open: already open", unit); return EBUSY; } @@ -628,13 +624,13 @@ gscclose (dev_t dev, int flags, int fmt, struct proc *p) int unit = UNIT(minor(dev)); struct gsc_unit *scu = unittab + unit; - lprintf(("gsc%d.close: minor %d\n", - unit, minor(dev))); + lprintf("gsc%d.close: minor %d\n", + unit, minor(dev)); if ( unit >= NGSC || !( scu->flags & ATTACHED ) ) { - lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n", - unit, scu->flags)); + lprintf("gsc%d.read: unit was not attached successfully 0x04x\n", + unit, scu->flags); return ENXIO; } @@ -663,12 +659,12 @@ gscread (dev_t dev, struct uio *uio, int ioflag) size_t nbytes; int res; - lprintf(("gsc%d.read: minor %d\n", unit, minor(dev))); + lprintf("gsc%d.read: minor %d\n", unit, minor(dev)); if ( unit >= NGSC || !( scu->flags & ATTACHED ) ) { - lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n", - unit, scu->flags)); + lprintf("gsc%d.read: unit was not attached successfully 0x04x\n", + unit, scu->flags); return ENXIO; } @@ -691,8 +687,8 @@ gscread (dev_t dev, struct uio *uio, int ioflag) sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height); scu->bcount = scu->height * width / 8; - lprintf(("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n", - unit, scu->sbuf.base, scu->bcount)); + lprintf("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n", + unit, scu->sbuf.base, scu->bcount); /* move header to end of sbuf */ for(p=scu->sbuf.base; *p; p++); @@ -704,37 +700,37 @@ gscread (dev_t dev, struct uio *uio, int ioflag) } } - lprintf(("gsc%d.read(before buffer_read): " + lprintf("gsc%d.read(before buffer_read): " "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n", - unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount)); + unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount); if ( scu->sbuf.poi == scu->sbuf.size ) if ( (res = buffer_read(scu)) != SUCCESS ) return res; - lprintf(("gsc%d.read(after buffer_read): " + lprintf("gsc%d.read(after buffer_read): " "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n", - unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount)); + unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount); nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi ); if ( (scu->flags & PBM_MODE) ) nbytes = MIN( nbytes, scu->bcount ); - lprintf(("gsc%d.read: transferring 0x%x bytes", unit, nbytes)); + lprintf("gsc%d.read: transferring 0x%x bytes", nbytes); res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio); if ( res != SUCCESS ) { - lprintf(("gsc%d.read: uiomove failed %d", unit, res)); + lprintf("gsc%d.read: uiomove failed %d", unit, res); return res; } scu->sbuf.poi += nbytes; if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes; - lprintf(("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n", - unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount)); + lprintf("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n", + unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount); return SUCCESS; } @@ -751,38 +747,38 @@ gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) int unit = UNIT(minor(dev)); struct gsc_unit *scu = unittab + unit; - lprintf(("gsc%d.ioctl: minor %d\n", - unit, minor(dev))); + lprintf("gsc%d.ioctl: minor %d\n", + unit, minor(dev)); if ( unit >= NGSC || !( scu->flags & ATTACHED ) ) { - lprintf(("gsc%d.ioctl: unit was not attached successfully 0x%04x\n", - unit, scu->flags)); + lprintf("gsc%d.ioctl: unit was not attached successfully 0x04x\n", + unit, scu->flags); return ENXIO; } switch(cmd) { case GSC_SRESSW: - lprintf(("gsc%d.ioctl:GSC_SRESSW\n", unit)); + lprintf("gsc%d.ioctl:GSC_SRESSW\n", unit); if ( scu->flags & READING ) { - lprintf(("gsc%d:ioctl on already reading unit\n", unit)); + lprintf("gsc%d:ioctl on already reading unit\n", unit); return EBUSY; } scu->geometry = get_geometry(scu); return SUCCESS; case GSC_GRES: *(int *)data=geomtab[scu->geometry].dpi; - lprintf(("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data); return SUCCESS; case GSC_GWIDTH: *(int *)data=geomtab[scu->geometry].dpl; - lprintf(("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data); return SUCCESS; case GSC_SRES: case GSC_SWIDTH: - lprintf(("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n", - unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n", + unit, *(int *)data); { int g; struct gsc_geom geom = NEW_GEOM; if ( cmd == GSC_SRES ) @@ -796,37 +792,37 @@ gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) } case GSC_GHEIGHT: *(int *)data=scu->height; - lprintf(("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data); return SUCCESS; case GSC_SHEIGHT: - lprintf(("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data); if ( scu->flags & READING ) { - lprintf(("gsc%d:ioctl on already reading unit\n", unit)); + lprintf("gsc%d:ioctl on already reading unit\n", unit); return EBUSY; } scu->height=*(int *)data; return SUCCESS; case GSC_GBLEN: *(int *)data=scu->blen; - lprintf(("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data); return SUCCESS; case GSC_SBLEN: - lprintf(("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data); if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE) { - lprintf(("gsc%d:ioctl buffer size too high\n", unit)); + lprintf("gsc%d:ioctl buffer size too high\n", unit); return ENOMEM; } scu->blen=*(int *)data; return SUCCESS; case GSC_GBTIME: *(int *)data = scu->btime / hz; - lprintf(("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data); return SUCCESS; case GSC_SBTIME: scu->btime = *(int *)data * hz; - lprintf(("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data)); + lprintf("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data); return SUCCESS; default: return ENOTTY; } diff --git a/sys/i386/isa/ic/cd1400.h b/sys/i386/isa/ic/cd1400.h index ee9b9f27a4ddb..52081fe9b8368 100644 --- a/sys/i386/isa/ic/cd1400.h +++ b/sys/i386/isa/ic/cd1400.h @@ -27,7 +27,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: cd1400.h,v 1.4 1997/02/22 09:37:59 peter Exp $ + * $Id$ */ /* @@ -99,7 +99,6 @@ #define CD1400_CCR_CMDRESET (1<<7) /* enables following: */ #define CD1400_CCR_FTF (1<<1) /* flush tx fifo */ #define CD1400_CCR_FULLRESET (1<<0) /* full reset */ -#define CD1400_CCR_CHANRESET 0 /* current channel */ #define CD1400_CCR_CMDCORCHG (1<<6) /* enables following: */ #define CD1400_CCR_COR3 (1<<3) /* COR3 changed */ #define CD1400_CCR_COR2 (1<<2) /* COR2 changed */ @@ -134,10 +133,6 @@ #define CD1400_COR2_IXANY (1<<7) /* implied XON mode */ #define CD1400_COR2_IXOFF (1<<6) /* in-band tx flow control */ #define CD1400_COR2_ETC (1<<5) /* embedded tx command */ -#define CD1400_ETC_CMD 0x00 /* start an ETC */ -#define CD1400_ETC_SENDBREAK 0x81 -#define CD1400_ETC_INSERTDELAY 0x82 -#define CD1400_ETC_STOPBREAK 0x83 #define CD1400_COR2_LLM (1<<4) /* local loopback mode */ #define CD1400_COR2_RLM (1<<3) /* remote loopback mode */ #define CD1400_COR2_RTSAO (1<<2) /* RTS auto output */ diff --git a/sys/i386/isa/ic/esp.h b/sys/i386/isa/ic/esp.h index cc74b0b67720a..6621e6503917c 100644 --- a/sys/i386/isa/ic/esp.h +++ b/sys/i386/isa/ic/esp.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: esp.h,v 1.4 1999/01/03 05:03:46 kato Exp $ + * $Id$ */ #ifndef _IC_ESP_H_ @@ -59,9 +59,6 @@ #define ESP_SETFLOWTYPE 0x08 /* set type of flow-control (2 bytes) */ #define ESP_SETRXFLOW 0x0a /* set Rx FIFO flow control levels (4 bytes) */ #define ESP_SETMODE 0x10 /* set board mode (1 byte) */ -#ifdef PC98 -#define ESP_SETCLOCK 0x23 /* set UART clock prescaler */ -#endif /* Mode bits (ESP_SETMODE). */ #define ESP_MODE_FIFO 0x02 /* act like a 16550 (compatibility mode) */ diff --git a/sys/i386/isa/ic/ncr53400.h b/sys/i386/isa/ic/ncr53400.h new file mode 100644 index 0000000000000..4a60f018826f4 --- /dev/null +++ b/sys/i386/isa/ic/ncr53400.h @@ -0,0 +1,49 @@ +/* + * Definitions for 53C400 SCSI-controller chip. + * + * Derived from Linux NCR-5380 generic driver sources (by Drew Eckhardt). + * + * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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. + */ + +#ifndef _IC_NCR_53C400_H_ +#define _IC_NCR_53C400_H_ + +#define C400_CSR 0 /* rw - Control and Status Reg. */ +#define CSR_5380_ENABLE 0x80 +#define CSR_TRANSFER_DIRECTION 0x40 +#define CSR_TRANSFER_READY_INTR 0x20 +#define CSR_5380_INTR 0x10 +#define CSR_SHARED_INTR 0x08 +#define CSR_HOST_BUF_NOT_READY 0x04 /* read only */ +#define CSR_SCSI_BUF_READY 0x02 /* read only */ +#define CSR_5380_GATED_IRQ 0x01 /* read only */ +#define CSR_BITS "\20\1irq\2sbrdy\3hbrdy\4shintr\5intr\6tintr\7tdir\10enable" + +#define C400_CCR 1 /* rw - Clock Counter Reg. */ +#define C400_HBR 4 /* rw - Host Buffer Reg. */ + +#define C400_5380_REG_OFFSET 8 /* Offset of 5380 registers. */ + +#endif /* _IC_NCR_53C400_H_ */ diff --git a/sys/i386/isa/ic/ncr5380.h b/sys/i386/isa/ic/ncr5380.h new file mode 100644 index 0000000000000..ce14fec3da2f9 --- /dev/null +++ b/sys/i386/isa/ic/ncr5380.h @@ -0,0 +1,90 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * Modified by Serge Vakulenko (vak@cronyx.ru) + * + * ncr_5380.h,v 1.2 1994/09/11 20:29:18 phk Exp + * + * Definitions for 5380 SCSI-controller chip. + * + * Derived from "NCR 53C80 Family SCSI Protocol Controller Data Manual" + */ + +#ifndef _IC_NCR_5380_H_ +#define _IC_NCR_5380_H_ + +#define C80_CSDR 0 /* ro - Current SCSI Data Reg. */ +#define C80_ODR 0 /* wo - Output Data Reg. */ + +#define C80_ICR 1 /* rw - Initiator Command Reg. */ +#define ICR_ASSERT_RST 0x80 +#define ICR_ARBITRATION_IN_PROGRESS 0x40 /* read only */ +#define ICR_TRI_STATE_MODE 0x40 /* write only */ +#define ICR_LOST_ARBITRATION 0x20 /* read only */ +#define ICR_DIFF_ENABLE 0x20 /* write only */ +#define ICR_ASSERT_ACK 0x10 +#define ICR_ASSERT_BSY 0x08 +#define ICR_ASSERT_SEL 0x04 +#define ICR_ASSERT_ATN 0x02 +#define ICR_ASSERT_DATA_BUS 0x01 +#define ICR_BITS "\20\1dbus\2atn\3sel\4bsy\5ack\6arblost\7arb\10rst" + +/* + * The mask to use when doing read_modify_write on ICR. + */ +#define ICR_MASK (~(ICR_DIFF_ENABLE | ICR_TRI_STATE_MODE)) + +#define C80_MR 2 /* rw - Mode Reg. */ +#define MR_BLOCK_MODE_DMA 0x80 +#define MR_TARGET_MODE 0x40 +#define MR_ENABLE_PARITY_CHECKING 0x20 +#define MR_ENABLE_PARITY_INTERRUPT 0x10 +#define MR_ENABLE_EOP_INTERRUPT 0x08 +#define MR_MONITOR_BUSY 0x04 +#define MR_DMA_MODE 0x02 +#define MR_ARBITRATE 0x01 +#define MR_BITS "\20\1arb\2dma\3mbusy\4eopintr\5parintr\6pcheck\7targ\10blk" + +#define C80_TCR 3 /* rw - Target Command Reg. */ +#define TCR_LAST_BYTE_SENT 0x80 /* read only */ +#define TCR_ASSERT_REQ 0x08 +#define TCR_ASSERT_MSG 0x04 +#define TCR_ASSERT_CD 0x02 +#define TCR_ASSERT_IO 0x01 +#define TCR_BITS "\20\1i/o\2c/d\3msg\4req\10lastbyte" + +#define C80_CSBR 4 /* ro - Current SCSI Bus Status Reg. */ +#define CSBR_RST 0x80 +#define CSBR_BSY 0x40 +#define CSBR_REQ 0x20 +#define CSBR_MSG 0x10 +#define CSBR_CD 0x08 +#define CSBR_IO 0x04 +#define CSBR_SEL 0x02 +#define CSBR_ACK 0x01 +#define CSBR_BITS "\20\1ack\2sel\3i/o\4c/d\5msg\6req\7bsy\10rst" + +#define C80_SER 4 /* wo - Select Enable Reg. */ + +#define C80_BSR 5 /* ro - Bus and Status Reg. */ +#define BSR_END_OF_DMA_XFER 0x80 +#define BSR_DMA_REQUEST 0x40 +#define BSR_PARITY_ERROR 0x20 +#define BSR_INTERRUPT_REQUEST_ACTIVE 0x10 +#define BSR_PHASE_MISMATCH 0x08 +#define BSR_BUSY_ERROR 0x04 +#define BSR_ATN 0x02 +#define BSR_ACK 0x01 +#define BSR_BITS "\20\1ack\2atn\3busyerr\4pherr\5irq\6parerr\7drq\10dend" + +#define C80_SDSR 5 /* wo - Start DMA Send Reg. */ +#define C80_IDR 6 /* ro - Input Data Reg. */ +#define C80_SDTR 6 /* wo - Start DMA Target Receive Reg. */ +#define C80_RPIR 7 /* ro - Reset Parity/Interrupt Reg. */ +#define C80_SDIR 7 /* wo - Start DMA Initiator Receive Reg. */ + +#endif /* _IC_NCR_5380_H_ */ diff --git a/sys/i386/isa/ic/ns16550.h b/sys/i386/isa/ic/ns16550.h index b91f5fd2a8395..ba338886c764b 100644 --- a/sys/i386/isa/ic/ns16550.h +++ b/sys/i386/isa/ic/ns16550.h @@ -31,12 +31,25 @@ * SUCH DAMAGE. * * from: @(#)ns16550.h 7.1 (Berkeley) 5/9/91 - * $Id: ns16550.h,v 1.6 1999/01/03 05:03:46 kato Exp $ + * $Id$ */ /* * NS16550 UART registers */ +#ifdef PC98 +#define com_data 0x000 /* data register (R/W) */ +#define com_dlbl 0x000 /* divisor latch low (W) */ +#define com_dlbh 0x100 /* divisor latch high (W) */ +#define com_ier 0x100 /* interrupt enable (W) */ +#define com_iir 0x200 /* interrupt identification (R) */ +#define com_fifo 0x200 /* FIFO control (W) */ +#define com_lctl 0x300 /* line control register (R/W) */ +#define com_cfcr 0x300 /* line control register (R/W) */ +#define com_mcr 0x400 /* modem control register (R/W) */ +#define com_lsr 0x500 /* line status register (R/W) */ +#define com_msr 0x600 /* modem status register (R/W) */ +#else /* IBM-PC */ #define com_data 0 /* data register (R/W) */ #define com_dlbl 0 /* divisor latch low (W) */ #define com_dlbh 1 /* divisor latch high (W) */ @@ -48,3 +61,4 @@ #define com_mcr 4 /* modem control register (R/W) */ #define com_lsr 5 /* line status register (R/W) */ #define com_msr 6 /* modem status register (R/W) */ +#endif /* PC98 */ diff --git a/sys/i386/isa/ic/rsa.h b/sys/i386/isa/ic/rsa.h deleted file mode 100644 index e760e306cacc9..0000000000000 --- a/sys/i386/isa/ic/rsa.h +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: $ - */ - -/* - * RSA Mode Driver Data Sheet - * - * <<Register Map>> - * Base + 0x00 - * Mode Select Register(Read/Write) - * bit4=interrupt type(1: level, 0: edge) - * bit3=Auto RTS-CTS Flow Control Enable - * bit2=External FIFO Enable - * bit1=Reserved(Default 0)Don't Change!! - * bit0=Swap Upper 8byte and Lower 8byte in 16byte space. - * - * Base + 0x01 - * Interrupt Enable Register(Read/Write) - * bit4=Hardware Timer Interrupt Enable - * bit3=Character Time-Out Interrupt Enable - * bit2=Tx FIFO Empty Interrupt Enable - * bit1=Tx FIFO Half Full Interrupt Enable - * bit0=Rx FIFO Half Full Interrupt Enable - * - * Base + 0x02 - * Status Read Register(Read) - * bit7=Hardware Time Out Interrupt Status(1: True, 0: False) - * bit6=Character Time Out Interrupt Status - * bit5=Rx FIFO Full Flag(0: True, 1: False) - * bit4=Rx FIFO Half Full Flag - * bit3=Rx FIFO Empty Flag - * bit2=Tx FIFO Full Flag - * bit1=Tx FIFO Half Full Flag - * bit0=Tx FIFO Empty Flag - * - * Base + 0x02 - * FIFO Reset Register(Write) - * Reset Extrnal FIFO - * - * Base + 0x03 - * Timer Interval Value Set Register(Read/Write) - * Range of n: 1-255 - * Interval Value: n * 0.2ms - * - * Base + 0x04 - * Timer Control Register(Read/Write) - * bit0=Timer Enable - * - * Base + 0x08 - 0x0f - * Same as UART 16550 - * - * Special Regisgter in RSA Mode - * UART Data Register(Base + 0x08) - * Data transfer between Extrnal FIFO - * - * UART MCR(Base + 0x0c) - * bit3(OUT2[MCR_IENABLE])=1: Diable 16550 to Rx FIFO transfer - * bit2(OUT1[MCR_DRS])=1: Diable Tx FIFO to 16550 transfer - * - * <<Intrrupt and Intrrupt Reset>> - * o Reciver Line Status(from UART16550) - * Reset: Read LSR - * - * o Modem Status(from UART16550) - * Reset: Read MSR - * - * o Rx FIFO Half Full(from Extrnal FIFO) - * Reset: Read Rx FIFO under Hall Full - * - * o Character Time Out(from Extrnal FIFO) - * Reset: Read Rx FIFO or SRR - * - * o Tx FIFO Empty(from Extrnal FIFO) - * Reset: Write Tx FIFO or Read SRR - * - * o Tx FIFO Half Full(from Extrnal FIFO) - * Reset: Write Tx FIFO until Hall Full or Read SRR - * - * o Hardware Timer(from Extrnal FIFO) - * Reset: Disable Timer in TCR - * Notes: If you want to use Timer for next intrrupt, - * you must enable Timer in TCR - * - * <<Used Setting>> - * Auto RTS-CTS: Enable or Disable - * External FIFO: Enable - * Swap 8bytes: Disable - * Haredware Timer: Disable - * interrupt type: edge - * interrupt source: - * Hareware Timer - * Character Time Out - * Tx FIFO Empty - * Rx FIFO Half Full - * - */ - -/* I/O-DATA RSA Serise Exrension Register */ -#define rsa_msr 0 /* Mode Status Register (R/W) */ -#define rsa_ier 1 /* Interrupt Enable Register (R/W) */ -#define rsa_srr 2 /* Status Read Register (R) */ -#define rsa_frr 2 /* FIFO Reset Register (W) */ -#define rsa_tivsr 3 /* Timer Interval Value Set Register (R/W) */ -#define rsa_tcr 4 /* Timer Control Register (W) */ diff --git a/sys/i386/isa/if_ar.c b/sys/i386/isa/if_ar.c index a3fa4a28b37de..adebd22e54891 100644 --- a/sys/i386/isa/if_ar.c +++ b/sys/i386/isa/if_ar.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ar.c,v 1.23 1998/10/22 05:58:38 bde Exp $ + * $Id: if_ar.c,v 1.21 1998/06/21 14:53:10 bde Exp $ */ /* @@ -178,7 +178,6 @@ static int irqtable[16] = { struct isa_driver ardriver = {arprobe, arattach, "arc"}; -static ointhand2_t arintr; static void ar_xmit(struct ar_softc *sc); static void arstart(struct ifnet *ifp); static int arioctl(struct ifnet *ifp, u_long cmd, caddr_t data); @@ -297,7 +296,6 @@ arattach(struct isa_device *id) int unit; char *iface; - id->id_ointr = arintr; switch(hc->interface) { default: iface = "UNKNOWN"; break; case AR_IFACE_EIA_232: iface = "EIA-232"; break; @@ -357,6 +355,13 @@ arattach(struct isa_device *id) sppp_attach((struct ifnet *)&sc->ifsppp); if_attach(ifp); + /* + * Shortcut the sppp tls/tlf actions to up/down events + * since our lower layer is always ready. + */ + sc->ifsppp.pp_tls = sc->ifsppp.pp_up; + sc->ifsppp.pp_tlf = sc->ifsppp.pp_down; + #if NBPFILTER > 0 bpfattach(ifp, DLT_PPP, PPP_HEADER_LEN); #endif @@ -373,7 +378,7 @@ arattach(struct isa_device *id) * See if there is other interrupts pending. * Repeat until there is no more interrupts. */ -static void +void arintr(int unit) { struct ar_hardc *hc = &ar_hardc[unit]; diff --git a/sys/i386/isa/if_cs.c b/sys/i386/isa/if_cs.c index 1ddfbca1888fb..1d044deaa36d1 100644 --- a/sys/i386/isa/if_cs.c +++ b/sys/i386/isa/if_cs.c @@ -27,7 +27,7 @@ */ /* - * $Id: if_cs.c,v 1.7 1998/12/07 21:58:21 archie Exp $ + * $Id: if_cs.c,v 1.4 1998/08/27 22:41:18 msmith Exp $ * * Device driver for Crystal Semiconductor CS8920 based ethernet * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997 @@ -100,9 +100,7 @@ static struct cs_softc { } cs_softc[NCS]; -#if NPNP > 0 static u_long cs_unit = NCS; -#endif static int cs_recv_delay = 570; SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, ""); @@ -110,7 +108,6 @@ SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, "") static int cs_attach __P((struct cs_softc *, int, int)); static int cs_attach_isa __P((struct isa_device *)); static void cs_init __P((void *)); -static ointhand2_t csintr; static int cs_ioctl __P((struct ifnet *, u_long, caddr_t)); static int cs_probe __P((struct isa_device *)); static int cs_cs89x0_probe __P((struct cs_softc *, @@ -192,6 +189,7 @@ get_eeprom_cksum(int off, int len, int *buffer) static int wait_eeprom_ready(struct cs_softc *sc) { + int timeout=1000; DELAY ( 30000 ); /* XXX should we do some checks here ? */ return 0; } @@ -234,6 +232,7 @@ cs_duplex_auto(struct cs_softc *sc) static int enable_tp(struct cs_softc *sc) { + int i; int unit = sc->arpcom.ac_if.if_unit; cs_writereg(sc->nic_addr, PP_LineCTL, sc->line_ctl & ~AUI_ONLY); @@ -254,6 +253,7 @@ enable_tp(struct cs_softc *sc) static int send_test_pkt(struct cs_softc *sc) { + int unit = sc->arpcom.ac_if.if_unit; char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 0, 46, /* A 46 in network order */ 0, 0, /* DSAP=0 & SSAP=0 fields */ @@ -342,7 +342,7 @@ cs_cs89x0_probe(struct cs_softc *sc, u_int *dev_irq, int *dev_drq, int iobase, int unit, int flags) { unsigned rev_type = 0; - int i, irq=0; + int i, irq=0, result; int eeprom_buff[CHKSUM_LEN]; int chip_type, pp_isaint, pp_isadma; char chip_revision; @@ -633,7 +633,6 @@ cs_attach_isa(struct isa_device *dev) struct cs_softc *sc=&cs_softc[unit]; int flags=dev->id_flags; - dev->id_ointr = csintr; return cs_attach(sc, unit, flags); } @@ -645,7 +644,7 @@ cs_init(void *xsc) { struct cs_softc *sc=(struct cs_softc *)xsc; struct ifnet *ifp = &sc->arpcom.ac_if; - int i, s, rx_cfg; + int i, s, result, rx_cfg; /* address not known */ if (TAILQ_EMPTY(&ifp->if_addrhead)) /* unlikely? XXX */ @@ -815,7 +814,7 @@ static void csintr_sc(struct cs_softc *sc, int unit) { struct ifnet *ifp = &(sc->arpcom.ac_if); - int status; + int status, s; #ifdef CS_DEBUG printf(CS_NAME"%1d: Interrupt.\n", unit); @@ -872,7 +871,7 @@ csintr_sc(struct cs_softc *sc, int unit) /* * Handle interrupts */ -static void +void csintr(int unit) { struct cs_softc *sc = &cs_softc[unit]; @@ -1305,6 +1304,7 @@ csintr_pnp_add(struct cs_softc *sc, int unit) static void csintr_pnp(int unit) { + struct cs_softc *sc; struct csintr_list *intr; for (intr=csintr_head; intr; intr=intr->next) { @@ -1350,8 +1350,8 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, struct pnp_cinfo d; int ldn = 0; int iobase, unit, flags; - u_int irq; - int drq; + u_short irq; + short drq; struct isa_device *dvp; struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); @@ -1367,7 +1367,7 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, irq = dev->id_irq = (1 << d.irq[0] ); drq = dev->id_drq = d.drq[0]; dev->id_maddr = 0; - dev->id_ointr = csintr_pnp; + dev->id_intr = csintr_pnp; flags = dev->id_flags = 0; unit = dev->id_unit; diff --git a/sys/i386/isa/if_cx.c b/sys/i386/isa/if_cx.c index d8e5999b97d5d..ded05ec339795 100644 --- a/sys/i386/isa/if_cx.c +++ b/sys/i386/isa/if_cx.c @@ -62,7 +62,6 @@ static int cxattach __P((struct isa_device *id)); static void cxput __P((cx_chan_t *c, char b)); static void cxsend __P((cx_chan_t *c)); static void cxrinth __P((cx_chan_t *c)); -static ointhand2_t cxintr; static int cxtinth __P((cx_chan_t *c)); #ifdef DEBUG @@ -231,8 +230,6 @@ cxattach (struct isa_device *id) int i; struct sppp *sp; - id->id_ointr = cxintr; - /* Initialize the board structure. */ cx_init (b, unit, iobase, ffs(irq)-1, drq); @@ -284,7 +281,13 @@ cxattach (struct isa_device *id) /* Init routine is never called by upper level? */ sppp_attach (c->ifp); if_attach (c->ifp); + /* + * Shortcut the sppp tls/tlf actions to up/down + * events since our lower layer is always ready. + */ sp = (struct sppp*) c->ifp; + sp->pp_tls = sp->pp_up; + sp->pp_tlf = sp->pp_down; #if NBPFILTER > 0 /* If BPF is in the kernel, call the attach for it. */ bpfattach (c->ifp, DLT_PPP, PPP_HEADER_LEN); @@ -704,7 +707,7 @@ cxtinth (cx_chan_t *c) return (teoir); } -static void +void cxintr (int bnum) { cx_board_t *b = cxboard + bnum; diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index 9133a485e758d..0fed19a155267 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/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.147 1998/12/13 23:00:48 eivind Exp $ + * $Id: if_ed.c,v 1.144 1998/08/24 02:28:15 bde Exp $ */ /* @@ -138,7 +138,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 *)); @@ -194,7 +193,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> @@ -205,7 +203,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. @@ -1731,7 +1739,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); } @@ -2560,7 +2567,7 @@ edintr_sc(sc) } } -static void +void edintr(unit) int unit; { @@ -3459,7 +3466,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/i386/isa/if_eg.c b/sys/i386/isa/if_eg.c new file mode 100644 index 0000000000000..7f68aa6429c75 --- /dev/null +++ b/sys/i386/isa/if_eg.c @@ -0,0 +1,789 @@ +/* + * Copyright (c) 1993 Dean Huxley <dean@fsa.ca> + * 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 Dean Huxley. + * 4. The name of Dean Huxley 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: if_eg.c,v 1.27 1998/03/28 13:23:56 bde Exp $ + * + * Support for 3Com 3c505 Etherlink+ card. + */ + +/* To do: + * - multicast + * - promiscuous + */ +#include "eg.h" +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/sockio.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/syslog.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/if_arp.h> + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#include <machine/clock.h> + +#include <i386/isa/isa_device.h> +#include <i386/isa/if_egreg.h> + +/* for debugging convenience */ +#ifdef EGDEBUG +#define dprintf(x) printf x +#else +#define dprintf(x) +#endif + +#define EG_INLEN 10 +#define EG_BUFLEN 0x0670 + +/* + * Ethernet software status per interface. + */ +static struct eg_softc { + struct arpcom sc_arpcom; /* Ethernet common part */ + int eg_cmd; /* Command register R/W */ + int eg_ctl; /* Control register R/W (EG_CTL_*) */ + int eg_stat; /* Status register R/O (EG_STAT_*) */ + int eg_data; /* Data register R/W (16 bits) */ + u_char eg_rom_major; /* Cards ROM version (major number) */ + u_char eg_rom_minor; /* Cards ROM version (minor number) */ + short eg_ram; /* Amount of RAM on the card */ + u_char eg_pcb[64]; /* Primary Command Block buffer */ + u_char eg_incount; /* Number of buffers currently used */ + u_char *eg_inbuf; /* Incoming packet buffer */ + u_char *eg_outbuf; /* Outgoing packet buffer */ +} eg_softc[NEG]; + +static int egprobe (struct isa_device *); +static int egattach (struct isa_device *); + +struct isa_driver egdriver = { + egprobe, egattach, "eg", 0 +}; + +static void egprintpcb __P((struct eg_softc *sc)); +static void egprintstat __P((int b)); +static int egoutPCB __P((struct eg_softc *sc, int b)); +static int egreadPCBstat __P((struct eg_softc *sc, int statb)); +static int egreadPCBready __P((struct eg_softc *sc)); +static int egwritePCB __P((struct eg_softc *sc)); +static int egreadPCB __P((struct eg_softc *sc)); +static void eginit __P((struct eg_softc *sc)); +static int egioctl (struct ifnet *, u_long, caddr_t); +static void egrecv(struct eg_softc *); +static void egstart(struct ifnet *); +static void egread __P((struct eg_softc *, caddr_t, int)); +static void egstop __P((struct eg_softc *)); + +static void egwatchdog __P((struct ifnet *)); +static void egreset __P((struct eg_softc *)); +static struct mbuf *egget __P((struct eg_softc *, caddr_t, int)); + +/* + * Support stuff + */ + +static void +egprintpcb(sc) + struct eg_softc *sc; +{ + int i; + + for (i = 0; i < sc->eg_pcb[1] + 2; i++) + dprintf(("eg#: pcb[%2d] = %x\n", i, sc->eg_pcb[i])); +} + + +static void +egprintstat(b) + u_char b; +{ + dprintf(("eg#: %s %s %s %s %s %s %s\n", + (b & EG_STAT_HCRE)?"HCRE":"", + (b & EG_STAT_ACRF)?"ACRF":"", + (b & EG_STAT_DIR )?"DIR ":"", + (b & EG_STAT_DONE)?"DONE":"", + (b & EG_STAT_ASF3)?"ASF3":"", + (b & EG_STAT_ASF2)?"ASF2":"", + (b & EG_STAT_ASF1)?"ASF1":"")); +} + +static int +egoutPCB(sc, b) + struct eg_softc *sc; + u_char b; +{ + int i; + + for (i=0; i < 4000; i++) { + if (inb(sc->eg_stat) & EG_STAT_HCRE) { + outb(sc->eg_cmd, b); + return 0; + } + DELAY(10); + } + dprintf(("eg#: egoutPCB failed\n")); + return 1; +} + +static int +egreadPCBstat(sc, statb) + struct eg_softc *sc; + u_char statb; +{ + int i; + + for (i=0; i < 5000; i++) { + if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) + break; + DELAY(10); + } + if ((inb(sc->eg_stat) & EG_PCB_STAT) == statb) + return 0; + return 1; +} + +static int +egreadPCBready(sc) + struct eg_softc *sc; +{ + int i; + + for (i=0; i < 10000; i++) { + if (inb(sc->eg_stat) & EG_STAT_ACRF) + return 0; + DELAY(5); + } + dprintf(("eg#: PCB read not ready\n")); + return 1; +} + +static int +egwritePCB(sc) + struct eg_softc *sc; +{ + int i; + u_char len; + + outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL); + + len = sc->eg_pcb[1] + 2; + for (i = 0; i < len; i++) + egoutPCB(sc, sc->eg_pcb[i]); + + for (i=0; i < 4000; i++) { + if (inb(sc->eg_stat) & EG_STAT_HCRE) + break; + DELAY(10); + } + + outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_DONE); + + egoutPCB(sc, len); + + if (egreadPCBstat(sc, EG_PCB_ACCEPT)) + return 1; + return 0; +} + +static int +egreadPCB(sc) + struct eg_softc *sc; +{ + int i; + u_char b; + + outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_NULL); + + bzero(sc->eg_pcb, sizeof(sc->eg_pcb)); + + if (egreadPCBready(sc)) + return 1; + + sc->eg_pcb[0] = inb(sc->eg_cmd); + + if (egreadPCBready(sc)) + return 1; + + sc->eg_pcb[1] = inb(sc->eg_cmd); + + if (sc->eg_pcb[1] > 62) { + dprintf(("eg#: len %d too large\n", sc->eg_pcb[1])); + return 1; + } + + for (i = 0; i < sc->eg_pcb[1]; i++) { + if (egreadPCBready(sc)) + return 1; + sc->eg_pcb[2+i] = inb(sc->eg_cmd); + } + if (egreadPCBready(sc)) + return 1; + if (egreadPCBstat(sc, EG_PCB_DONE)) + return 1; + if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1] + 2) { + dprintf(("eg#: %d != %d\n", b, sc->eg_pcb[1] + 2)); + return 1; + } + + outb(sc->eg_ctl, (inb(sc->eg_ctl) & ~EG_PCB_STAT) | EG_PCB_ACCEPT); + + return 0; +} + +/* + * Real stuff + */ + +static int +egprobe(struct isa_device * id) +{ + struct eg_softc *sc = &eg_softc[id->id_unit]; + int i; + + if (id->id_iobase & ~0x07f0 != 0) { + dprintf(("eg#: Weird iobase %x\n", ia->ia_iobase)); + return 0; + } + + sc->eg_cmd = id->id_iobase + EG_COMMAND; + sc->eg_ctl = id->id_iobase + EG_CONTROL; + sc->eg_stat = id->id_iobase + EG_STATUS; + sc->eg_data = id->id_iobase + EG_DATA; + + /* hard reset card */ + outb(sc->eg_ctl, EG_CTL_RESET); + outb(sc->eg_ctl, 0); + for (i = 0; i < 1600; i++) { + DELAY(10000); + if ((inb(sc->eg_stat) & EG_PCB_STAT) == EG_PCB_NULL) + break; + } + if ((inb(sc->eg_stat) & EG_PCB_STAT) != EG_PCB_NULL) { + dprintf(("eg#: eg: Reset failed\n")); + return 0; + } + sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */ + sc->eg_pcb[1] = 0; + if (egwritePCB(sc) != 0) + return 0; + + if (egreadPCB(sc) != 0) { + egprintpcb(sc); + return 0; + } + + if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */ + sc->eg_pcb[1] != 0x0a) { + egprintpcb(sc); + return 0; + } + sc->eg_rom_major = sc->eg_pcb[3]; + sc->eg_rom_minor = sc->eg_pcb[2]; + sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8); + + return 8; +} + +static int +egattach(struct isa_device *id) +{ + struct eg_softc *sc = &eg_softc[id->id_unit]; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + egstop(sc); + + sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */ + sc->eg_pcb[1] = 0; + if (egwritePCB(sc) != 0) { + dprintf(("eg#: write error\n")); + return 0; + } + if (egreadPCB(sc) != 0) { + dprintf(("eg#: read error\n")); + egprintpcb(sc); + return 0; + } + + /* check Get station address response */ + if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) { + dprintf(("eg#: parse error\n")); + egprintpcb(sc); + return 0; + } + bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); + + printf("eg%d: address %6D, type=3COM 3c505 (v%d.%02d, %dk)\n", + id->id_unit, sc->sc_arpcom.ac_enaddr, ":", + sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram); + + sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */ + if (egwritePCB(sc) != 0) { + dprintf(("eg#: write error2\n")); + return 0; + } + if (egreadPCB(sc) != 0) { + dprintf(("eg#: read error2\n")); + egprintpcb(sc); + return 0; + } + if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 || + sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) { + dprintf(("eg#: parse error2\n")); + egprintpcb(sc); + return 0; + } + + /* Initialize ifnet structure. */ + ifp->if_softc = sc; + ifp->if_unit = id->id_unit; + ifp->if_name = "eg"; + ifp->if_output = ether_output; + ifp->if_start = egstart; + ifp->if_ioctl = egioctl; + ifp->if_init = (if_init_f_t*)eginit; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + ifp->if_watchdog = egwatchdog; + + /* Now we can attach the interface. */ + if_attach(ifp); + ether_ifattach(ifp); + +#if NBPFILTER > 0 + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + + return 1; +} + +static void +eginit(struct eg_softc *sc) +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + /* soft reset the board */ + outb(sc->eg_ctl, EG_CTL_FLSH); + DELAY(100); + outb(sc->eg_ctl, EG_CTL_ATTN); + DELAY(100); + outb(sc->eg_ctl, 0); + DELAY(200); + + sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */ + sc->eg_pcb[1] = 2; + sc->eg_pcb[2] = 3; /* receive broadcast & multicast */ + sc->eg_pcb[3] = 0; +#ifdef EGDEBUG + if (egwritePCB(sc) != 0) + dprintf(("eg#: write error3\n")); +#endif + + if (egreadPCB(sc) != 0) { + dprintf(("eg#: read error\n")); + egprintpcb(sc); + } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) + printf("eg%d: configure card command failed\n", ifp->if_unit); + + if (sc->eg_inbuf == NULL) + sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); + sc->eg_incount = 0; + + if (sc->eg_outbuf == NULL) + sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); + + outb(sc->eg_ctl, EG_CTL_CMDE); + + sc->eg_incount = 0; + egrecv(sc); + + /* Interface is now `running', with no output active. */ + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + /* Attempt to start output, if any. */ + egstart(ifp); +} + +static void +egrecv(sc) + struct eg_softc *sc; +{ + + while (sc->eg_incount < EG_INLEN) { + sc->eg_pcb[0] = EG_CMD_RECVPACKET; + sc->eg_pcb[1] = 0x08; + sc->eg_pcb[2] = 0; /* address not used.. we send zero */ + sc->eg_pcb[3] = 0; + sc->eg_pcb[4] = 0; + sc->eg_pcb[5] = 0; + sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */ + sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff; + sc->eg_pcb[8] = 0; /* timeout, 0 == none */ + sc->eg_pcb[9] = 0; + if (egwritePCB(sc) != 0) + break; + sc->eg_incount++; + } +} + +static void +egstart(ifp) + struct ifnet *ifp; +{ + register struct eg_softc *sc = ifp->if_softc; + struct mbuf *m0, *m; + caddr_t buffer; + int len; + u_short *ptr; + + /* Don't transmit if interface is busy or not running */ + if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) + return; + +loop: + /* Dequeue the next datagram. */ + IF_DEQUEUE(&ifp->if_snd, m0); + if (m0 == 0) + return; + + ifp->if_flags |= IFF_OACTIVE; + + /* We need to use m->m_pkthdr.len, so require the header */ + if ((m0->m_flags & M_PKTHDR) == 0) + panic("egstart: no header mbuf"); + len = max(m0->m_pkthdr.len, ETHER_MIN_LEN); + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp, m0); +#endif + + sc->eg_pcb[0] = EG_CMD_SENDPACKET; + sc->eg_pcb[1] = 0x06; + sc->eg_pcb[2] = 0; /* address not used, we send zero */ + sc->eg_pcb[3] = 0; + sc->eg_pcb[4] = 0; + sc->eg_pcb[5] = 0; + sc->eg_pcb[6] = len; /* length of packet */ + sc->eg_pcb[7] = len >> 8; + if (egwritePCB(sc) != 0) { + dprintf(("eg#: egwritePCB in egstart failed\n")); + ifp->if_oerrors++; + ifp->if_flags &= ~IFF_OACTIVE; + goto loop; + } + + buffer = sc->eg_outbuf; + for (m = m0; m != 0; m = m->m_next) { + bcopy(mtod(m, caddr_t), buffer, m->m_len); + buffer += m->m_len; + } + + /* set direction bit: host -> adapter */ + outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR); + + for (ptr = (u_short *) sc->eg_outbuf; len > 0; len -= 2) { + outw(sc->eg_data, *ptr++); + while (!(inb(sc->eg_stat) & EG_STAT_HRDY)) + ; /* XXX need timeout here */ + } + + m_freem(m0); +} + +void +egintr(int unit) +{ + register struct eg_softc *sc = &eg_softc[unit]; + int i, len; + u_short *ptr; + + while (inb(sc->eg_stat) & EG_STAT_ACRF) { + egreadPCB(sc); + switch (sc->eg_pcb[0]) { + case EG_RSP_RECVPACKET: + len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8); + + /* Set direction bit : Adapter -> host */ + outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR); + + for (ptr = (u_short *) sc->eg_inbuf; len > 0; len -= 2) { + while (!(inb(sc->eg_stat) & EG_STAT_HRDY)) + ; + *ptr++ = inw(sc->eg_data); + } + + len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8); + egread(sc, sc->eg_inbuf, len); + + sc->eg_incount--; + egrecv(sc); + break; + + case EG_RSP_SENDPACKET: + if (sc->eg_pcb[6] || sc->eg_pcb[7]) { + dprintf(("eg#: packet dropped\n")); + sc->sc_arpcom.ac_if.if_oerrors++; + } else + sc->sc_arpcom.ac_if.if_opackets++; + sc->sc_arpcom.ac_if.if_collisions += sc->eg_pcb[8] & 0xf; + sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + egstart(&sc->sc_arpcom.ac_if); + break; + + case EG_RSP_GETSTATS: + dprintf(("eg#: Card Statistics\n")); + bcopy(&sc->eg_pcb[2], &i, sizeof(i)); + dprintf(("eg#: Receive Packets %d\n", i)); + bcopy(&sc->eg_pcb[6], &i, sizeof(i)); + dprintf(("eg#: Transmit Packets %d\n", i)); + dprintf(("eg#: CRC errors %d\n", *(short*) &sc->eg_pcb[10])); + dprintf(("eg#: alignment errors %d\n", *(short*) &sc->eg_pcb[12])); + dprintf(("eg#: no resources errors %d\n", *(short*) &sc->eg_pcb[14])); + dprintf(("eg#: overrun errors %d\n", *(short*) &sc->eg_pcb[16])); + break; + + default: + dprintf(("eg#: egintr: Unknown response %x??\n", + sc->eg_pcb[0])); + egprintpcb(sc); + break; + } + } + + return; +} + +/* + * Pass a packet up to the higher levels. + */ +static void +egread(sc, buf, len) + struct eg_softc *sc; + caddr_t buf; + int len; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct mbuf *m; + struct ether_header *eh; + + if (len <= sizeof(struct ether_header) || + len > ETHER_MAX_LEN) { + printf("eg#: invalid packet size %d; dropping\n", len); + ifp->if_ierrors++; + return; + } + + /* Pull packet off interface. */ + m = egget(sc, buf, len); + if (m == 0) { + ifp->if_ierrors++; + return; + } + + ifp->if_ipackets++; + + /* We assume the header fit entirely in one mbuf. */ + eh = mtod(m, struct ether_header *); + +#if NBPFILTER > 0 + /* + * Check if there's a BPF listener on this interface. + * If so, hand off the raw packet to BPF. + */ + if (ifp->if_bpf) { + bpf_mtap(ifp, m); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no BPF listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + */ + if ((ifp->if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + return; + } + } +#endif + + /* We assume the header fit entirely in one mbuf. */ + m_adj(m, sizeof(struct ether_header)); + ether_input(ifp, eh, m); +} + +/* + * convert buf into mbufs + */ +static struct mbuf * +egget(sc, buf, totlen) + struct eg_softc *sc; + caddr_t buf; + int totlen; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct mbuf *top, **mp, *m; + int len; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return 0; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + len = MHLEN; + top = 0; + mp = ⊤ + + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return 0; + } + len = MLEN; + } + if (totlen >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + len = MCLBYTES; + } + m->m_len = len = min(totlen, len); + bcopy((caddr_t)buf, mtod(m, caddr_t), len); + buf += len; + totlen -= len; + *mp = m; + mp = &m->m_next; + } + + return top; +} + +static int +egioctl(ifp, command, data) + register struct ifnet *ifp; + u_long command; + caddr_t data; +{ + struct eg_softc *sc = ifp->if_softc; + int s, error = 0; + + s = splnet(); + + switch (command) { + + case SIOCSIFADDR: + case SIOCGIFADDR: + case SIOCSIFMTU: + error = ether_ioctl(ifp, command, data); + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + egstop(sc); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + eginit(sc); + } else { + sc->eg_pcb[0] = EG_CMD_GETSTATS; + sc->eg_pcb[1] = 0; +#ifdef EGDEBUG + if (egwritePCB(sc) != 0) + dprintf(("eg#: write error\n")); +#endif + /* + * XXX deal with flags changes: + * IFF_MULTICAST, IFF_PROMISC, + * IFF_LINK0, IFF_LINK1, + */ + } + break; + + default: + error = EINVAL; + break; + } + + splx(s); + return error; +} + +static void +egreset(sc) + struct eg_softc *sc; +{ + int s; + + dprintf(("eg#: egreset()\n")); + s = splnet(); + egstop(sc); + eginit(sc); + splx(s); +} + +static void +egwatchdog(ifp) + struct ifnet *ifp; +{ + struct eg_softc *sc = ifp->if_softc; + + log(LOG_ERR, "%s: device timeout\n", "eg#"); + sc->sc_arpcom.ac_if.if_oerrors++; + + egreset(sc); +} + +static void +egstop(sc) + register struct eg_softc *sc; +{ + + outb(sc->eg_ctl, 0); +} diff --git a/sys/i386/isa/if_egreg.h b/sys/i386/isa/if_egreg.h new file mode 100644 index 0000000000000..9067a58383d94 --- /dev/null +++ b/sys/i386/isa/if_egreg.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1993 Dean Huxley (dean@fsa.ca) + * 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 Dean Huxley. + * 4. The name of Dean Huxley 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. + */ + +/* + * Register offsets from base. + */ +#define EG_COMMAND 0x00 +#define EG_STATUS 0x02 +#define EG_DATA 0x04 +#define EG_CONTROL 0x06 + +/* + * Host Control Register bits + * EG_CTL_ATTN - does a soft reset + * EG_CTL_FLSH - flushes the data register + * EG_CTL_RESET - does a hard reset + * EG_CTL_DMAE - Used with DIR bit, enables DMA transfers to/from data reg. + * EG_CTL_DIR - if clear then host -> adapter, if set then adapter -> host + * EG_CTL_TCEN - terminal count enable. enables host interrupt after DMA. + * EG_CTL_CMDE - command reg interrupt enable. (when it is written) + * EG_CTL_HSF1 - Host status flag 1 + * EG_CTL_HSF2 - Host status flag 2 + */ + +#define EG_CTL_ATTN 0x80 +#define EG_CTL_FLSH 0x40 +#define EG_CTL_RESET (EG_CTL_ATTN|EG_CTL_FLSH) +#define EG_CTL_DMAE 0x20 +#define EG_CTL_DIR 0x10 +#define EG_CTL_TCEN 0x08 +#define EG_CTL_CMDE 0x04 +#define EG_CTL_HSF2 0x02 +#define EG_CTL_HSF1 0x01 + +/* + * Host Status Register bits + * EG_STAT_HRDY - Data Register ready + * EG_STAT_HCRE - Host Command Register empty + * EG_STAT_ACRF - Adapter Command register full + * EG_STAT_DIR - Direction flag, 0 = host -> adapter, 1 = adapter -> host + * EG_STAT_DONE - DMA done + * EG_STAT_ASF1 - Adapter status flag 1 + * EG_STAT_ASF2 - Adapter status flag 2 + * EG_STAT_ASF3 - Adapter status flag 3 + */ + +#define EG_STAT_HRDY 0x80 +#define EG_STAT_HCRE 0x40 +#define EG_STAT_ACRF 0x20 +#define EG_STAT_DIR 0x10 +#define EG_STAT_DONE 0x08 +#define EG_STAT_ASF3 0x04 +#define EG_STAT_ASF2 0x02 +#define EG_STAT_ASF1 0x01 + +#define EG_PCB_NULL 0x00 +#define EG_PCB_ACCEPT 0x01 +#define EG_PCB_REJECT 0x02 +#define EG_PCB_DONE 0x03 +#define EG_PCB_STAT 0x03 + +#define EG_CMD_CONFIG82586 0x02 +#define EG_CMD_GETEADDR 0x03 +#define EG_CMD_RECVPACKET 0x08 +#define EG_CMD_SENDPACKET 0x09 +#define EG_CMD_GETSTATS 0x0a +#define EG_CMD_SETEADDR 0x10 +#define EG_CMD_GETINFO 0x11 + +#define EG_RSP_CONFIG82586 0x32 +#define EG_RSP_GETEADDR 0x33 +#define EG_RSP_RECVPACKET 0x38 +#define EG_RSP_SENDPACKET 0x39 +#define EG_RSP_GETSTATS 0x3a +#define EG_RSP_SETEADDR 0x40 +#define EG_RSP_GETINFO 0x41 diff --git a/sys/i386/isa/if_el.c b/sys/i386/isa/if_el.c index f8aad8e4d020f..6a3c32d1b83bd 100644 --- a/sys/i386/isa/if_el.c +++ b/sys/i386/isa/if_el.c @@ -6,7 +6,7 @@ * * Questions, comments, bug reports and fixes to kimmel@cs.umass.edu. * - * $Id: if_el.c,v 1.39 1998/12/07 21:58:21 archie Exp $ + * $Id: if_el.c,v 1.36 1998/06/07 17:10:28 dfr Exp $ */ /* Except of course for the portions of code lifted from other FreeBSD * drivers (mainly elread, elget and el_ioctl) @@ -82,7 +82,6 @@ static void el_watchdog(struct ifnet *); static void el_stop(int); static int el_xmit(struct el_softc *,int); -static ointhand2_t elintr; static __inline void elread(struct el_softc *,caddr_t,int); static struct mbuf *elget(caddr_t,int,int,struct ifnet *); static __inline void el_hardreset(int); @@ -146,29 +145,6 @@ el_probe(struct isa_device *idev) } } -/* Do a hardware reset of the 3c501. Do not call until after el_probe()! */ -static __inline void -el_hardreset(int unit) -{ - register struct el_softc *sc; - register int base; - register int j; - - sc = &el_softc[unit]; - base = sc->el_base; - - /* First reset the board */ - outb(base+EL_AC,EL_AC_RESET); - DELAY(5); - outb(base+EL_AC,0); - - /* Then give it back its ethernet address. Thanks to the mach - * source code for this undocumented goodie... - */ - for(j=0;j<ETHER_ADDR_LEN;j++) - outb(base+j,sc->arpcom.ac_enaddr[j]); -} - /* Attach the interface to the kernel data structures. By the time * this is called, we know that the card exists at the given I/O address. * We still assume that the IRQ given is correct. @@ -178,12 +154,13 @@ el_attach(struct isa_device *idev) { struct el_softc *sc; struct ifnet *ifp; + struct ifaddr *ifa; + struct sockaddr_dl *sdl; u_short base; dprintf(("Attaching el%d...\n",idev->id_unit)); /* Get things pointing to the right places. */ - idev->id_ointr = elintr; sc = &el_softc[idev->id_unit]; ifp = &sc->arpcom.ac_if; base = sc->el_base; @@ -243,6 +220,28 @@ static void el_stop(int unit) outb(sc->el_base+EL_AC,0); } +/* Do a hardware reset of the 3c501. Do not call until after el_probe()! */ +static __inline void el_hardreset(int unit) +{ + register struct el_softc *sc; + register int base; + register int j; + + sc = &el_softc[unit]; + base = sc->el_base; + + /* First reset the board */ + outb(base+EL_AC,EL_AC_RESET); + DELAY(5); + outb(base+EL_AC,0); + + /* Then give it back its ethernet address. Thanks to the mach + * source code for this undocumented goodie... + */ + for(j=0;j<ETHER_ADDR_LEN;j++) + outb(base+j,sc->arpcom.ac_enaddr[j]); +} + /* Initialize interface. */ static void el_init(int unit) @@ -406,8 +405,7 @@ el_start(struct ifnet *ifp) * to the board. Call at splimp or interrupt, after downloading data! * Returns 0 on success, non-0 on failure */ -static int -el_xmit(struct el_softc *sc,int len) +static int el_xmit(struct el_softc *sc,int len) { int gpl; int i; @@ -429,53 +427,8 @@ el_xmit(struct el_softc *sc,int len) return(0); } -/* Pass a packet up to the higher levels. */ -static __inline void -elread(struct el_softc *sc,caddr_t buf,int len) -{ - register struct ether_header *eh; - struct mbuf *m; - - eh = (struct ether_header *)buf; - -#if NBPFILTER > 0 - /* - * Check if there's a bpf filter listening on this interface. - * If so, hand off the raw packet to bpf. - */ - if(sc->arpcom.ac_if.if_bpf) { - bpf_tap(&sc->arpcom.ac_if, buf, - len + sizeof(struct ether_header)); - - /* - * Note that the interface cannot be in promiscuous mode if - * there are no bpf listeners. And if el are in promiscuous - * mode, el have to check if this packet is really ours. - * - * This test does not support multicasts. - */ - if((sc->arpcom.ac_if.if_flags & IFF_PROMISC) - && bcmp(eh->ether_dhost,sc->arpcom.ac_enaddr, - sizeof(eh->ether_dhost)) != 0 - && bcmp(eh->ether_dhost,etherbroadcastaddr, - sizeof(eh->ether_dhost)) != 0) - return; - } -#endif - - /* - * Pull packet off interface. - */ - m = elget(buf,len,0,&sc->arpcom.ac_if); - if(m == 0) - return; - - ether_input(&sc->arpcom.ac_if,eh,m); -} - /* controller interrupt */ -static void -elintr(int unit) +void elintr(int unit) { register struct el_softc *sc; register int base; @@ -570,6 +523,49 @@ elintr(int unit) return; } +/* Pass a packet up to the higher levels. */ +static __inline void elread(struct el_softc *sc,caddr_t buf,int len) +{ + register struct ether_header *eh; + struct mbuf *m; + + eh = (struct ether_header *)buf; + +#if NBPFILTER > 0 + /* + * Check if there's a bpf filter listening on this interface. + * If so, hand off the raw packet to bpf. + */ + if(sc->arpcom.ac_if.if_bpf) { + bpf_tap(&sc->arpcom.ac_if, buf, + len + sizeof(struct ether_header)); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no bpf listeners. And if el are in promiscuous + * mode, el have to check if this packet is really ours. + * + * This test does not support multicasts. + */ + if((sc->arpcom.ac_if.if_flags & IFF_PROMISC) + && bcmp(eh->ether_dhost,sc->arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0 + && bcmp(eh->ether_dhost,etherbroadcastaddr, + sizeof(eh->ether_dhost)) != 0) + return; + } +#endif + + /* + * Pull packet off interface. + */ + m = elget(buf,len,0,&sc->arpcom.ac_if); + if(m == 0) + return; + + ether_input(&sc->arpcom.ac_if,eh,m); +} + /* * Pull read data off a interface. * Len is length of data, with local net header stripped. diff --git a/sys/i386/isa/if_ep.c b/sys/i386/isa/if_ep.c index e325ada5b316c..80b8db4c3ca23 100644 --- a/sys/i386/isa/if_ep.c +++ b/sys/i386/isa/if_ep.c @@ -38,7 +38,7 @@ */ /* - * $Id: if_ep.c,v 1.77 1998/10/22 05:58:39 bde Exp $ + * $Id: if_ep.c,v 1.75 1998/06/07 17:10:28 dfr Exp $ * * Promiscuous mode added and interrupt logic slightly changed * to reduce the number of adapter failures. Transceiver select @@ -118,7 +118,6 @@ static int ep_isa_attach __P((struct isa_device *)); static int epioctl __P((struct ifnet * ifp, u_long, caddr_t)); static void epinit __P((struct ep_softc *)); -static ointhand2_t epintr; static void epread __P((struct ep_softc *)); void epreset __P((int)); static void epstart __P((struct ifnet *)); @@ -149,7 +148,6 @@ struct isa_driver epdriver = { #if NCARD > 0 #include <sys/select.h> -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> @@ -161,7 +159,16 @@ static int ep_pccard_attach __P((struct pccard_devinfo *)); static void ep_unload __P((struct pccard_devinfo *)); static int card_intr __P((struct pccard_devinfo *)); -PCCARD_MODULE(ep, ep_pccard_init, ep_unload, card_intr, 0, net_imask); +static struct pccard_device ep_info = { + "ep", + ep_pccard_init, + ep_unload, + card_intr, + 0, /* Attributes - presently unused */ + &net_imask +}; + +DATA_SET(pccarddrv_set, ep_info); /* * Initialize the device - called from Slot manager. @@ -531,7 +538,6 @@ ep_isa_attach(is) u_short config; int irq; - is->id_ointr = epintr; sc->ep_connectors = 0; config = inw(IS_BASE + EP_W0_CONFIG_CTRL); if (config & IS_AUI) { @@ -894,7 +900,7 @@ readcheck: goto startagain; } -static void +void epintr(unit) int unit; { diff --git a/sys/i386/isa/if_ex.c b/sys/i386/isa/if_ex.c index 2508bd735e225..f64ef74269b49 100644 --- a/sys/i386/isa/if_ex.c +++ b/sys/i386/isa/if_ex.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ex.c,v 1.12 1998/06/07 17:10:30 dfr Exp $ + * $Id: if_ex.c,v 1.11 1998/03/28 13:24:06 bde Exp $ */ /* @@ -119,7 +119,6 @@ static int ex_attach __P((struct isa_device *)); static void ex_init __P((void *)); static void ex_start __P((struct ifnet *)); static void ex_stop __P((int)); -static ointhand2_t exintr; static int ex_ioctl __P((struct ifnet *, u_long, caddr_t)); static void ex_reset __P((int)); static void ex_watchdog __P((struct ifnet *)); @@ -255,8 +254,6 @@ int ex_attach(struct isa_device *dev) DODEBUG(Start_End, printf("ex_attach%d: start\n", unit);); - dev->id_ointr = exintr; - /* * Initialize the ifnet structure. */ @@ -568,7 +565,7 @@ void ex_stop(int unit) } -static void exintr(int unit) +void exintr(int unit) { struct ex_softc *sc = &ex_sc[unit]; struct ifnet *ifp = &sc->arpcom.ac_if; diff --git a/sys/i386/isa/if_fe.c b/sys/i386/isa/if_fe.c index 94e4bef130944..85e948d88d207 100644 --- a/sys/i386/isa/if_fe.c +++ b/sys/i386/isa/if_fe.c @@ -21,10 +21,10 @@ */ /* - * $Id: if_fe.c,v 1.47 1999/01/12 00:36:29 eivind Exp $ + * $Id: if_fe.c,v 1.41 1998/06/07 17:10:31 dfr Exp $ * * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. - * To be used with FreeBSD 3.x + * 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 @@ -36,13 +36,12 @@ * other types of Ethernet cards, but the author is not sure whether * they are useful. * - * This version also includes some alignments to support RE1000, - * C-NET(98)P2 and so on. These cards are not for AT-compatibles, - * but for NEC PC-98 bus -- a proprietary bus architecture available - * only in Japan. Confusingly, it is different from the Microsoft's - * PC98 architecture. :-{ - * Further work for PC-98 version will be available as a part of - * FreeBSD(98) project. + * 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. @@ -59,14 +58,16 @@ /* * 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. - * o To test FreeBSD3.0-current. - * o To test BRIDGE codes. */ #include "fe.h" @@ -79,12 +80,10 @@ #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> -#include <net/if_mib.h> -#include <net/if_media.h> -#include <net/if_types.h> #ifdef INET #include <netinet/in.h> @@ -113,10 +112,6 @@ #include <net/bpf.h> #endif -#ifdef BRIDGE -#include <net/bridge.h> -#endif - #include <machine/clock.h> #include <i386/isa/isa_device.h> @@ -127,7 +122,6 @@ #if NCARD > 0 #include <sys/kernel.h> #include <sys/select.h> -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> #endif @@ -136,31 +130,36 @@ #include <i386/isa/if_fereg.h> /* - * Default settings for fe driver specific options. - * They can be set in config file by "options" statements. + * 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 /* - * Transmit just one packet per a "send" command to 86960. - * This option is intended for performance test. An EXPERIMENTAL option. + * Default settings for fe driver specific options. + * They can be set in config file by "options" statements. */ -#ifndef FE_SINGLE_TRANSMISSION -#define FE_SINGLE_TRANSMISSION 0 -#endif /* - * Maximum loops when interrupt. - * This option prevents an infinite loop due to hardware failure. - * (Some laptops make an infinite loop after PC-Card is ejected.) + * 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_MAX_LOOP -#define FE_MAX_LOOP 0x800 +#ifndef FE_DEBUG +#define FE_DEBUG 1 #endif /* - * If you define this option, 8-bit cards are also supported. + * Transmit just one packet per a "send" command to 86960. + * This option is intended for performance test. An EXPERIMENTAL option. */ -/*#define FE_8BIT_SUPPORT*/ +#ifndef FE_SINGLE_TRANSMISSION +#define FE_SINGLE_TRANSMISSION 0 +#endif /* * Device configuration flags. @@ -201,43 +200,32 @@ static struct fe_softc { /* Used by config codes. */ /* Set by probe() and not modified in later phases. */ - char const * typestr; /* printable name of the interface. */ + 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 registers. */ + 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 stability; /* How stable is this? */ - u_short priv_info; /* info specific to a vendor/model. */ - /* Vendor/model specific hooks. */ - void (*init)(struct fe_softc *); /* Just before fe_init(). */ - void (*stop)(struct fe_softc *); /* Just after fe_stop(). */ + /* 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.) */ + /* 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. */ - /* Network management. */ - struct ifmib_iso_8802_3 mibdata; - - /* Media information. */ - struct ifmedia media; /* used by if_media. */ - u_short mbitmap; /* bitmap for supported media; see bit2media */ - int defmedia; /* default media */ - void (* msel)(struct fe_softc *); /* media selector. */ - } fe_softc[NFE]; #define sc_if arpcom.ac_if @@ -247,40 +235,36 @@ static struct fe_softc { /* 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 ( void * ); -static ointhand2_t feintr; +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 * ); -static int fe_medchange ( struct ifnet * ); -static void fe_medstat ( struct ifnet *, struct ifmediareq * ); /* Local functions. Order of declaration is confused. FIXME. */ -static int fe_probe_ssi ( struct isa_device *, struct fe_softc * ); -static int fe_probe_jli ( struct isa_device *, struct fe_softc * ); -static int fe_probe_fmv ( struct isa_device *, struct fe_softc * ); -static int fe_probe_lnx ( struct isa_device *, struct fe_softc * ); -static int fe_probe_gwy ( struct isa_device *, struct fe_softc * ); -static int fe_probe_ubn ( struct isa_device *, struct fe_softc * ); -#ifdef PC98 -static int fe_probe_re1000 ( struct isa_device *, struct fe_softc * ); -static int fe_probe_cnet9ne( struct isa_device *, struct fe_softc * ); -#endif +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 * ); +static int fe_probe_gwy ( DEVICE *, struct fe_softc * ); #if NCARD > 0 -static int fe_probe_mbh ( struct isa_device *, struct fe_softc * ); -static int fe_probe_tdk ( struct isa_device *, struct fe_softc * ); +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 ( struct fe_softc * ); +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 * ); - -#ifdef DIAGNOSTIC -static void fe_emptybuffer ( 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.) */ @@ -313,62 +297,6 @@ struct isa_driver fedriver = */ /* - * Miscellaneous definitions not directly related to hardware. - */ - -/* Flags for stability. */ -#define UNSTABLE_IRQ 0x01 /* IRQ setting may be incorrect. */ -#define UNSTABLE_MAC 0x02 /* Probed MAC address may be incorrect. */ -#define UNSTABLE_TYPE 0x04 /* Probed vendor/model may be incorrect. */ - -/* The following line must be delete when "net/if_media.h" support it. */ -#ifndef IFM_10_FL -#define IFM_10_FL /* 13 */ IFM_10_5 -#endif - -#if 0 -/* Mapping between media bitmap (in fe_softc.mbitmap) and ifm_media. */ -static int const bit2media [] = { -#define MB_HA 0x0001 - IFM_HDX | IFM_ETHER | IFM_AUTO, -#define MB_HM 0x0002 - IFM_HDX | IFM_ETHER | IFM_MANUAL, -#define MB_HT 0x0004 - IFM_HDX | IFM_ETHER | IFM_10_T, -#define MB_H2 0x0008 - IFM_HDX | IFM_ETHER | IFM_10_2, -#define MB_H5 0x0010 - IFM_HDX | IFM_ETHER | IFM_10_5, -#define MB_HF 0x0020 - IFM_HDX | IFM_ETHER | IFM_10_FL, -#define MB_FT 0x0040 - IFM_FDX | IFM_ETHER | IFM_10_T, - /* More can be come here... */ - 0 -}; -#else -/* Mapping between media bitmap (in fe_softc.mbitmap) and ifm_media. */ -static int const bit2media [] = { -#define MB_HA 0x0001 - IFM_ETHER | IFM_AUTO, -#define MB_HM 0x0002 - IFM_ETHER | IFM_MANUAL, -#define MB_HT 0x0004 - IFM_ETHER | IFM_10_T, -#define MB_H2 0x0008 - IFM_ETHER | IFM_10_2, -#define MB_H5 0x0010 - IFM_ETHER | IFM_10_5, -#define MB_HF 0x0020 - IFM_ETHER | IFM_10_FL, -#define MB_FT 0x0040 - IFM_ETHER | IFM_10_T, - /* More can be come here... */ - 0 -}; -#endif - -/* * Routines to access contiguous I/O ports. */ @@ -393,50 +321,65 @@ outblk ( struct fe_softc * sc, int offs, u_char const * mem, int len ) /* * 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 int feinit ( struct pccard_devinfo * ); +static void feunload ( struct pccard_devinfo * ); +static int fe_card_intr ( struct pccard_devinfo * ); -PCCARD_MODULE(fe, feinit, feunload, fe_card_intr, 0, net_imask); +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. + * 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; - - /* Prepare for the device probe process. */ + /* 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; - /* - * When the feinit() is called, the devi->misc holds a - * six-byte value set by the pccard daemon. If the - * corresponding entry in /etc/pccard.conf has an "ether" - * keyword, the value is the Ethernet MAC address extracted - * from CIS area of the card. If the entry has no "ether" - * keyword, the daemon fills the field with binary zero, - * instead. We passes the value (either MAC address or zero) - * to model-specific sub-probe routines through sc->sc_enaddr - * (it actually is sc->sc_arpcom.ar_enaddr, BTW) so that the - * sub-probe routies can use that info. - */ - bcopy(devi->misc, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Probe for supported cards. */ - if (fe_probe_mbh(&devi->isahd, sc) == 0 - && fe_probe_tdk(&devi->isahd, sc) == 0) return ENXIO; + /* 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); + } - /* We've got a supported card. Attach it, then. */ - if (fe_attach(&devi->isahd) == 0) return ENXIO; + /* 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; + return (0); } /* @@ -452,9 +395,8 @@ static void feunload(struct pccard_devinfo *devi) { struct fe_softc *sc = &fe_softc[devi->isahd.id_unit]; - printf("fe%d: unload\n", sc->sc_unit); - fe_stop(sc); - if_down(&sc->arpcom.ac_if); + printf("fe%d: unload\n", devi->isahd.id_unit); + fe_stop(devi->isahd.id_unit); } /* @@ -472,58 +414,117 @@ fe_card_intr(struct pccard_devinfo *devi) /* * Hardware probe routines. - * - * In older versions of this driver, we provided an automatic I/O - * address detection. The features is, however, removed from this - * version, for simplicity. Any comments? */ +/* 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. */ +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 }; + +static struct fe_probe_list const fe_probe_list [] = +{ + { fe_probe_fmv, fe_fmv_addr }, + { fe_probe_ati, fe_ati_addr }, + { fe_probe_gwy, NULL }, /* GWYs cannot be auto detected. */ + { NULL, NULL } +}; + + /* - * Determine if the device is present at a specified I/O address. The - * main entry to the driver. + * 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 (struct isa_device * dev) +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 ]; -#ifdef DIAGNOSTIC - if (dev->id_unit >= NFE) { - printf("fe%d: too large unit number for the current config\n", - dev->id_unit); - return 0; - } -#endif - - /* Prepare for the softc struct. */ - sc = &fe_softc[dev->id_unit]; + /* Initialize "minimum" parts of our softc. */ + sc = &fe_softc[ dev->id_unit ]; sc->sc_unit = dev->id_unit; - sc->iobase = dev->id_iobase; - /* Probe for supported boards. */ - nports = 0; -#ifdef PC98 - if (!nports) nports = fe_probe_re1000(dev, sc); - if (!nports) nports = fe_probe_cnet9ne(dev, sc); + /* 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 - if (!nports) nports = fe_probe_ssi(dev, sc); - if (!nports) nports = fe_probe_jli(dev, sc); - if (!nports) nports = fe_probe_fmv(dev, sc); - if (!nports) nports = fe_probe_lnx(dev, sc); - if (!nports) nports = fe_probe_ubn(dev, sc); - if (!nports) nports = fe_probe_gwy(dev, sc); - - /* We found supported board. */ - return nports; + + /* 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. - * A common utility function called from various sub-probe routines. */ - struct fe_simple_probe_struct { u_char port; /* Offset from the base I/O address. */ @@ -538,11 +539,9 @@ fe_simple_probe ( struct fe_softc const * sc, struct fe_simple_probe_struct const * p; for ( p = sp; p->mask != 0; p++ ) { -#ifdef FE_DEBUG - unsigned a = sc->ioaddr[p->port]; - printf("fe%d: Probing %02x (%04x): %02x (%02x, %02x): %s\n", - sc->sc_unit, p->port, a, inb(a), p->mask, p->bits, - (inb(a) & p->mask) == p->bits ? "OK" : "NG"); +#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 ) { @@ -552,167 +551,40 @@ fe_simple_probe ( struct fe_softc const * sc, return ( 1 ); } -/* Test if a given 6 byte value is a valid Ethernet station (MAC) - address. "Vendor" is an expected vendor code (first three bytes,) - or a zero when nothing expected. */ -static int -valid_Ether_p (u_char const * addr, unsigned vendor) -{ -#ifdef FE_DEBUG - printf("fe?: validating %6D against %06x\n", addr, ":", vendor); -#endif - - /* All zero is not allowed as a vendor code. */ - if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0) return 0; - - switch (vendor) { - case 0x000000: - /* Legal Ethernet address (stored in ROM) must have - its Group and Local bits cleared. */ - if ((addr[0] & 0x03) != 0) return 0; - break; - case 0x020000: - /* Same as above, but a local address is allowed in - this context. */ - if ((addr[0] & 0x01) != 0) return 0; - break; - default: - /* Make sure the vendor part matches if one is given. */ - if ( addr[0] != ((vendor >> 16) & 0xFF) - || addr[1] != ((vendor >> 8) & 0xFF) - || addr[2] != ((vendor ) & 0xFF)) return 0; - break; - } - - /* Host part must not be all-zeros nor all-ones. */ - if (addr[3] == 0xFF && addr[4] == 0xFF && addr[5] == 0xFF) return 0; - if (addr[3] == 0x00 && addr[4] == 0x00 && addr[5] == 0x00) return 0; - - /* Given addr looks like an Ethernet address. */ - return 1; -} - -/* Fill our softc struct with default value. */ -static void -fe_softc_defaults (struct fe_softc *sc) -{ - int i; - - /* Initialize I/O address re-mapping table for the standard - (contiguous) register layout. This routine doesn't use - ioaddr[], so the caller can safely override it after - calling fe_softc_defaults, if needed. */ - for (i = 0; i < MAXREGISTERS; i++) sc->ioaddr[i] = sc->iobase + i; - - /* Prepare for typical register prototypes. We assume a - "typical" board has <32KB> of <fast> SRAM connected with a - <byte-wide> data lines. */ - 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; - sc->proto_bmpr13 = 0; - - /* Assume the probe process (to be done later) is stable. */ - sc->stability = 0; - - /* A typical board needs no hooks. */ - sc->init = NULL; - sc->stop = NULL; - - /* Assume the board has no software-controllable media selection. */ - sc->mbitmap = MB_HM; - sc->defmedia = MB_HM; - sc->msel = NULL; -} - -/* Common error reporting routine used in probe routines for - "soft configured IRQ"-type boards. */ -static void -fe_irq_failure (char const *name, int unit, int irq, char const *list) -{ - printf("fe%d: %s board is detected, but %s IRQ was given\n", - unit, name, (irq == NO_IRQ ? "no" : "invalid")); - if (list != NULL) { - printf("fe%d: specify an IRQ from %s in kernel config\n", - unit, list); - } -} - -/* - * Hardware (vendor) specific probe routines and hooks. - */ - -/* - * Machine independent routines. - */ - -/* - * Generic media selection scheme for MB86965 based boards. - */ -static void -fe_msel_965 (struct fe_softc *sc) -{ - u_char b13; - - /* Find the appropriate bits for BMPR13 tranceiver control. */ - switch (IFM_SUBTYPE(sc->media.ifm_media)) { - case IFM_AUTO: b13 = FE_B13_PORT_AUTO | FE_B13_TPTYPE_UTP; break; - case IFM_10_T: b13 = FE_B13_PORT_TP | FE_B13_TPTYPE_UTP; break; - default: b13 = FE_B13_PORT_AUI; break; - } - - /* Write it into the register. It takes effect immediately. */ - outb(sc->ioaddr[FE_BMPR13], sc->proto_bmpr13 | b13); -} - -/* - * Fujitsu MB86965 JLI mode support routines. - */ - -/* Datasheet for 86965 explicitly states that it only supports serial - * EEPROM with 16 words (32 bytes) capacity. (I.e., 93C06.) However, - * ones with 64 words (128 bytes) are available in the marked, namely - * 93C46, and are also fully compatible with 86965. It is known that - * some boards (e.g., ICL) actually have 93C46 on them and use extra - * storage to keep various config info. */ -#define JLI_EEPROM_SIZE 128 - /* * Routines to read all bytes from the config EEPROM through MB86965A. - * It is a MicroWire (3-wire) serial EEPROM with 6-bit address. - * (93C06 or 93C46.) + * 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_jli ( u_short bmpr16 ) +fe_strobe_eeprom ( u_short bmpr16 ) { /* - * We must guarantee 1us (or more) interval to access slow + * 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_jli ( struct fe_softc * sc, u_char * data ) +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; - u_char save16, save17; - - /* Save the current value of the EEPROM interface registers. */ - save16 = inb(bmpr16); - save17 = inb(bmpr17); /* Read bytes from EEPROM; two bytes per an iteration. */ - for ( n = 0; n < JLI_EEPROM_SIZE / 2; n++ ) { + for ( n = 0; n < FE_EEPROM_SIZE / 2; n++ ) { /* Reset the EEPROM interface. */ outb( bmpr16, 0x00 ); @@ -721,20 +593,20 @@ fe_read_eeprom_jli ( struct fe_softc * sc, u_char * data ) /* Start EEPROM access. */ outb( bmpr16, FE_B16_SELECT ); outb( bmpr17, FE_B17_DATA ); - fe_strobe_eeprom_jli( bmpr16 ); + fe_strobe_eeprom( bmpr16 ); - /* Pass the iteration count as well as a READ command. */ + /* 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_jli( bmpr16 ); + fe_strobe_eeprom( bmpr16 ); } outb( bmpr17, 0x00 ); /* Read a byte. */ val = 0; for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { - fe_strobe_eeprom_jli( bmpr16 ); + fe_strobe_eeprom( bmpr16 ); if ( inb( bmpr17 ) & FE_B17_DATA ) { val |= bit; } @@ -744,7 +616,7 @@ fe_read_eeprom_jli ( struct fe_softc * sc, u_char * data ) /* Read one more byte. */ val = 0; for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { - fe_strobe_eeprom_jli( bmpr16 ); + fe_strobe_eeprom( bmpr16 ); if ( inb( bmpr17 ) & FE_B17_DATA ) { val |= bit; } @@ -752,476 +624,278 @@ fe_read_eeprom_jli ( struct fe_softc * sc, u_char * data ) *data++ = val; } -#if 0 /* Reset the EEPROM interface, again. */ outb( bmpr16, 0x00 ); outb( bmpr17, 0x00 ); -#else - /* Make sure to restore the original value of EEPROM interface - registers, since we are not yet sure we have MB86965A on - the address. */ - outb(bmpr17, save17); - outb(bmpr16, save16); -#endif -#if 1 +#if FE_DEBUG >= 3 /* Report what we got. */ - if (bootverbose) { - int i; - data -= JLI_EEPROM_SIZE; - for (i = 0; i < JLI_EEPROM_SIZE; i += 16) { - printf("fe%d: EEPROM(JLI):%3x: %16D\n", - sc->sc_unit, i, data + i, " "); - } - } + 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 } -static void -fe_init_jli (struct fe_softc * sc) -{ - /* "Reset" by writing into a magic location. */ - DELAY(200); - outb(sc->ioaddr[0x1E], inb(sc->ioaddr[0x1E])); - DELAY(300); -} - /* - * SSi 78Q8377A support routines. + * Hardware (vendor) specific probe routines. */ -#define SSI_EEPROM_SIZE 512 -#define SSI_DIN 0x01 -#define SSI_DAT 0x01 -#define SSI_CSL 0x02 -#define SSI_CLK 0x04 -#define SSI_EEP 0x10 - /* - * Routines to read all bytes from the config EEPROM through 78Q8377A. - * It is a MicroWire (3-wire) serial EEPROM with 8-bit address. (I.e., - * 93C56 or 93C66.) - * - * As I don't have SSi manuals, (hmm, an old song again!) I'm not exactly - * sure the following code is correct... It is just stolen from the - * C-NET(98)P2 support routine in FreeBSD(98). + * Probe and initialization for Fujitsu FMV-180 series boards */ - -static void -fe_read_eeprom_ssi (struct fe_softc *sc, u_char *data) +static int +fe_probe_fmv ( DEVICE * dev, struct fe_softc * sc ) { - u_short bmpr12 = sc->ioaddr[FE_DLCR12]; - u_char val, bit; - int n; - u_char save6, save7, save12; - - /* Save the current value for the DLCR registers we are about - to destroy. */ - save6 = inb(sc->ioaddr[FE_DLCR6]); - save7 = inb(sc->ioaddr[FE_DLCR7]); - - /* Put the 78Q8377A into a state that we can access the EEPROM. */ - 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); - - /* Save the current value for the BMPR12 register, too. */ - save12 = inb(bmpr12); - - /* Read bytes from EEPROM; two bytes per an iteration. */ - for ( n = 0; n < SSI_EEPROM_SIZE / 2; n++ ) { - - /* Start EEPROM access */ - outb(bmpr12, SSI_EEP); - outb(bmpr12, SSI_EEP | SSI_CSL); - - /* Send the following four bits to the EEPROM in the - specified order: a dummy bit, a start bit, and - command bits (10) for READ. */ - outb(bmpr12, SSI_EEP | SSI_CSL ); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK ); /* 0 */ - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_DAT); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK | SSI_DAT); /* 1 */ - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_DAT); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK | SSI_DAT); /* 1 */ - outb(bmpr12, SSI_EEP | SSI_CSL ); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK ); /* 0 */ - - /* Pass the iteration count to the chip. */ - for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { - val = ( n & bit ) ? SSI_DAT : 0; - outb(bmpr12, SSI_EEP | SSI_CSL | val); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK | val); - } - - /* Read a byte. */ - val = 0; - for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { - outb(bmpr12, SSI_EEP | SSI_CSL); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK); - if (inb(bmpr12) & SSI_DIN) val |= bit; - } - *data++ = val; - - /* Read one more byte. */ - val = 0; - for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { - outb(bmpr12, SSI_EEP | SSI_CSL); - outb(bmpr12, SSI_EEP | SSI_CSL | SSI_CLK); - if (inb(bmpr12) & SSI_DIN) val |= bit; - } - *data++ = val; - - outb(bmpr12, SSI_EEP); - } + int i, n; - /* Reset the EEPROM interface. (For now.) */ - outb( bmpr12, 0x00 ); + static u_short const baseaddr [ 8 ] = + { 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340 }; + static u_short const irqmap [ 4 ] = + { IRQ3, IRQ7, IRQ10, IRQ15 }; - /* Restore the saved register values, for the case that we - didn't have 78Q8377A at the given address. */ - outb(sc->ioaddr[FE_BMPR12], save12); - outb(sc->ioaddr[FE_DLCR7], save7); - outb(sc->ioaddr[FE_DLCR6], save6); + 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 - /* Report what we got. */ - if (bootverbose) { - int i; - data -= SSI_EEPROM_SIZE; - for (i = 0; i < SSI_EEPROM_SIZE; i += 16) { - printf("fe%d: EEPROM(SSI):%3x: %16D\n", - sc->sc_unit, i, data + i, " "); - } - } + /* + * 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 -} - -#define FE_SSI_EEP_IRQ 9 /* Irq ??? */ -#define FE_SSI_EEP_ADDR 16 /* Station(MAC) address */ -#define FE_SSI_EEP_DUPLEX 25 /* Duplex mode ??? */ - -/* - * TDK/LANX boards support routines. - */ - -/* AX012/AX013 equips an X24C01 chip, which has 128 bytes of memory cells. */ -#define LNX_EEPROM_SIZE 128 - -/* Bit assignments and command definitions for the serial EEPROM - interface register in LANX ASIC. */ -#define LNX_SDA_HI 0x08 /* Drive SDA line high (logical 1.) */ -#define LNX_SDA_LO 0x00 /* Drive SDA line low (logical 0.) */ -#define LNX_SDA_FL 0x08 /* Float (don't drive) SDA line. */ -#define LNX_SDA_IN 0x01 /* Mask for reading SDA line. */ -#define LNX_CLK_HI 0x04 /* Drive clock line high (active.) */ -#define LNX_CLK_LO 0x00 /* Drive clock line low (inactive.) */ - -/* It is assumed that the CLK line is low and SDA is high (float) upon entry. */ -#define LNX_PH(D,K,N) \ - ((LNX_SDA_##D | LNX_CLK_##K) << N) -#define LNX_CYCLE(D1,D2,D3,D4,K1,K2,K3,K4) \ - (LNX_PH(D1,K1,0)|LNX_PH(D2,K2,8)|LNX_PH(D3,K3,16)|LNX_PH(D4,K4,24)) - -#define LNX_CYCLE_START LNX_CYCLE(HI,LO,LO,HI, HI,HI,LO,LO) -#define LNX_CYCLE_STOP LNX_CYCLE(LO,LO,HI,HI, LO,HI,HI,LO) -#define LNX_CYCLE_HI LNX_CYCLE(HI,HI,HI,HI, LO,HI,LO,LO) -#define LNX_CYCLE_LO LNX_CYCLE(LO,LO,LO,HI, LO,HI,LO,LO) -#define LNX_CYCLE_INIT LNX_CYCLE(LO,HI,HI,HI, LO,LO,LO,LO) - -static void -fe_eeprom_cycle_lnx (u_short reg20, u_long cycle) -{ - outb(reg20, (cycle ) & 0xFF); - DELAY(15); - outb(reg20, (cycle >> 8) & 0xFF); - DELAY(15); - outb(reg20, (cycle >> 16) & 0xFF); - DELAY(15); - outb(reg20, (cycle >> 24) & 0xFF); - DELAY(15); -} + { 0 } + }; -static u_char -fe_eeprom_receive_lnx (u_short reg20) -{ - u_char dat; - - outb(reg20, LNX_CLK_HI | LNX_SDA_FL); - DELAY(15); - dat = inb(reg20); - outb(reg20, LNX_CLK_LO | LNX_SDA_FL); - DELAY(15); - return (dat & LNX_SDA_IN); -} + /* "Hardware revision ID" */ + int revision; -static void -fe_read_eeprom_lnx (struct fe_softc *sc, u_char *data) -{ - int i; - u_char n, bit, val; - u_char save20; - u_short reg20 = sc->ioaddr[0x14]; + /* + * 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; - save20 = inb(sc->ioaddr[0x14]); + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; + } - /* NOTE: DELAY() timing constants are approximately three - times longer (slower) than the required minimum. This is - to guarantee a reliable operation under some tough - conditions... Fortunately, this routine is only called - during the boot phase, so the speed is less important than - stability. */ + /* Simple probe. */ + if ( !fe_simple_probe( sc, probe_table ) ) return 0; -#if 1 - /* Reset the X24C01's internal state machine and put it into - the IDLE state. We usually don't need this, but *if* - someone (e.g., probe routine of other driver) write some - garbage into the register at 0x14, synchronization will be - lost, and the normal EEPROM access protocol won't work. - Moreover, as there are no easy way to reset, we need a - _manoeuvre_ here. (It even lacks a reset pin, so pushing - the RESET button on the PC doesn't help!) */ - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_INIT); - for (i = 0; i < 10; i++) { - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_START); - } - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_STOP); - DELAY(10000); + /* 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 + } - /* Issue a start condition. */ - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_START); + /* Find the "hardware revision." */ + revision = inb( sc->ioaddr[ FE_FMV1 ] ) & FE_FMV1_REV; - /* Send seven bits of the starting address (zero, in this - case) and a command bit for READ. */ - val = 0x01; - for (bit = 0x80; bit != 0x00; bit >>= 1) { - if (val & bit) { - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_HI); - } else { - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_LO); + /* 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; } - } - - /* Receive an ACK bit. */ - if (fe_eeprom_receive_lnx(reg20)) { - /* ACK was not received. EEPROM is not present (i.e., - this board was not a TDK/LANX) or not working - properly. */ - if (bootverbose) { - printf("fe%d: no ACK received from EEPROM(LNX)\n", - sc->sc_unit); + 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; } - /* Clear the given buffer to indicate we could not get - any info. and return. */ - bzero(data, LNX_EEPROM_SIZE); - goto RET; - } - - /* Read bytes from EEPROM. */ - for (n = 0; n < LNX_EEPROM_SIZE; n++) { - - /* Read a byte and store it into the buffer. */ - val = 0x00; - for (bit = 0x80; bit != 0x00; bit >>= 1) { - if (fe_eeprom_receive_lnx(reg20)) val |= bit; + break; + case FE_FMV0_MEDIUM_2: + switch ( revision ) { + case 8: + sc->typestr = "FMV-184 (CSR = 2)"; + break; } - *data++ = val; - - /* Acknowledge if we have to read more. */ - if (n < LNX_EEPROM_SIZE - 1) { - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_LO); + break; + case FE_FMV0_MEDIUM_5: + switch ( revision ) { + case 8: + sc->typestr = "FMV-184 (CSR = 1)"; + break; } - } - - /* Issue a STOP condition, de-activating the clock line. - It will be safer to keep the clock line low than to leave - it high. */ - fe_eeprom_cycle_lnx(reg20, LNX_CYCLE_STOP); - - RET: - outb(sc->ioaddr[0x14], save20); - -#if 1 - /* Report what we got. */ - data -= LNX_EEPROM_SIZE; - if (bootverbose) { - for (i = 0; i < JLI_EEPROM_SIZE; i += 16) { - printf("fe%d: EEPROM(LNX):%3x: %16D\n", - sc->sc_unit, i, data + i, " "); + 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 ] ) ); } -#endif -} - -static void -fe_init_lnx ( struct fe_softc * sc ) -{ - /* Reset the 86960. Do we need this? FIXME. */ - outb(sc->ioaddr[0x12], 0x06); - DELAY(100); - outb(sc->ioaddr[0x12], 0x07); - DELAY(100); - - /* Setup IRQ control register on the ASIC. */ - outb(sc->ioaddr[0x14], sc->priv_info); -} - -/* - * Ungermann-Bass boards support routine. - */ -static void -fe_init_ubn ( struct fe_softc * sc ) -{ - /* Do we need this? FIXME. */ - outb(sc->ioaddr[FE_DLCR7], - sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP); - outb(sc->ioaddr[0x18], 0x00); - DELAY( 200 ); - - /* Setup IRQ control register on the ASIC. */ - outb(sc->ioaddr[0x14], sc->priv_info); -} - -/* - * Machine dependent probe routines. - */ - -#ifdef PC98 -static int -fe_probe_fmv ( struct isa_device * dev, struct fe_softc * sc ) -{ - /* PC-98 has no board of this architechture. */ - return 0; -} - -/* ioaddr for RE1000/1000Plus - Very dirty! */ -static u_short ioaddr_re1000[MAXREGISTERS] = { - 0x0000, 0x0001, 0x0200, 0x0201, 0x0400, 0x0401, 0x0600, 0x0601, - 0x0800, 0x0801, 0x0a00, 0x0a01, 0x0c00, 0x0c01, 0x0e00, 0x0e01, - 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00, - 0x1001, 0x1201, 0x1401, 0x1601, 0x1801, 0x1a01, 0x1c01, 0x1e01, -}; - -/* - * Probe and initialization for Allied-Telesis RE1000 series. - */ -static void -fe_init_re1000 ( struct fe_softc * sc ) -{ - /* Setup IRQ control register on the ASIC. */ - outb(sc->ioaddr[FE_RE1000_IRQCONF], sc->priv_info); -} - -static int -fe_probe_re1000 ( struct isa_device * dev, struct fe_softc * sc ) -{ - int i, n; - u_char sum; - - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for RE1000. */ - /* [01]D[02468ACE] are allowed. */ - if ((sc->iobase & ~0x10E) != 0xD0) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - /* Re-map ioaddr for RE1000. */ - for (i = 0; i < MAXREGISTERS; i++) - sc->ioaddr[i] = sc->iobase + ioaddr_re1000[i]; + /* + * 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 ); + } - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; + /* + * Initialize constants in the per-line structure. + */ /* Get our station address from EEPROM. */ - inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); + inblk( sc, FE_FMV4, sc->sc_enaddr, ETHER_ADDR_LEN ); - /* Make sure it is Allied-Telesis's. */ - if (!valid_Ether_p(sc->sc_enaddr, 0x0000F4)) return 0; -#if 1 - /* Calculate checksum. */ - sum = inb(sc->ioaddr[0x1e]); - for (i = 0; i < ETHER_ADDR_LEN; i++) { - sum ^= sc->sc_enaddr[i]; - } - if (sum != 0) return 0; -#endif - /* Setup the board type. */ - sc->typestr = "RE1000"; - - /* This looks like an RE1000 board. It requires an - explicit IRQ setting in config. Make sure we have one, - determining an appropriate value for the IRQ control - register. */ - switch (dev->id_irq) { - case IRQ3: n = 0x10; break; - case IRQ5: n = 0x20; break; - case IRQ6: n = 0x40; break; - case IRQ12: n = 0x80; break; - default: - fe_irq_failure(sc->typestr, - sc->sc_unit, dev->id_irq, "3/5/6/12"); - return 0; - } - sc->priv_info = inb(sc->ioaddr[FE_RE1000_IRQCONF]) & 0x0f | n; + /* 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; - /* Setup hooks. We need a special initialization procedure. */ - sc->init = fe_init_re1000; + /* + * 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; - /* The I/O address range is fragmented in the RE1000. - It occupies 2*16 I/O addresses, by the way. */ - return 2; -} + /* + * Minimum initialization of the hardware. + * We write into registers; hope I/O ports have no + * overlap with other boards. + */ -/* JLI sub-probe for Allied-Telesis RE1000Plus/ME1500 series. */ -static u_short const * -fe_probe_jli_re1000p (struct fe_softc * sc, u_char const * eeprom) -{ - int i; - static u_short const irqmaps_re1000p [4] = { IRQ3, IRQ5, IRQ6, IRQ12 }; + /* Initialize ASIC. */ + outb( sc->ioaddr[ FE_FMV3 ], 0 ); + outb( sc->ioaddr[ FE_FMV10 ], 0 ); - /* Make sure the EEPROM contains Allied-Telesis bit pattern. */ - if (eeprom[1] != 0xFF) return NULL; - for (i = 2; i < 8; i++) if (eeprom[i] != 0xFF) return NULL; - for (i = 14; i < 24; i++) if (eeprom[i] != 0xFF) return NULL; + /* Initialize 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); - /* Get our station address from EEPROM, and make sure the - EEPROM contains Allied-Telesis's address. */ - bcopy(eeprom+8, sc->sc_enaddr, ETHER_ADDR_LEN); - if (!valid_Ether_p(sc->sc_enaddr, 0x0000F4)) return NULL; + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); - /* I don't know any sub-model identification. */ - sc->typestr = "RE1000Plus/ME1500"; + /* "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 ); - /* Returns the IRQ table for the RE1000Plus. */ - return irqmaps_re1000p; + /* + * That's all. FMV-180 occupies 32 I/O addresses, by the way. + */ + return 32; } /* - * Probe for Allied-Telesis RE1000Plus/ME1500 series. + * Probe and initialization for Allied-Telesis AT1700/RE2000 series. */ static int -fe_probe_jli (struct isa_device * dev, struct fe_softc * sc) +fe_probe_ati ( DEVICE * dev, struct fe_softc * sc ) { int i, n; - int irq; - u_char eeprom [JLI_EEPROM_SIZE]; - u_short const * irqmap; + u_char eeprom [ FE_EEPROM_SIZE ]; + u_char save16, save17; - static u_short const baseaddr [8] = - { 0x1D6, 0x1D8, 0x1DA, 0x1D4, 0x0D4, 0x0D2, 0x0D8, 0x0D0 }; + 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_DLCR1, 0x20, 0x00 }, Doesn't work. */ - { FE_DLCR2, 0x50, 0x00 }, + { FE_DLCR2, 0x70, 0x00 }, { FE_DLCR4, 0x08, 0x00 }, - /* { FE_DLCR5, 0x80, 0x00 }, Doesn't work. */ + { FE_DLCR5, 0x80, 0x00 }, #if 0 { FE_BMPR16, 0x1B, 0x00 }, { FE_BMPR17, 0x7F, 0x00 }, @@ -1229,20 +903,28 @@ fe_probe_jli (struct isa_device * dev, struct fe_softc * sc) { 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; + for ( i = 0; i < 8; i++ ) { + if ( baseaddr[ i ] == sc->iobase ) break; } - if (i == 8) return 0; + if ( i == 8 ) goto NOTFOUND; - /* Fill the softc struct with reasonable default. */ - fe_softc_defaults(sc); - - /* Re-map ioaddr for RE1000Plus. */ - for (i = 0; i < MAXREGISTERS; i++) - sc->ioaddr[i] = sc->iobase + ioaddr_re1000[i]; + /* 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. @@ -1252,637 +934,35 @@ fe_probe_jli (struct isa_device * dev, struct fe_softc * sc) * described in the Fujitsu document. On warm boot, however, * we can predict almost nothing about register values. */ - if (!fe_simple_probe(sc, probe_table)) return 0; + 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) return 0; + 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 MB86965 at the given - * address. So, read EEPROM through it. We have to write + * 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. */ - fe_read_eeprom_jli(sc, eeprom); - - /* Make sure that config info in EEPROM and 86965 agree. */ - if (eeprom[FE_EEPROM_CONF] != inb(sc->ioaddr[FE_BMPR19])) { - return 0; - } - - /* Use 86965 media selection scheme, unless othewise - specified. It is "AUTO always" and "select with BMPR13". - This behaviour covers most of the 86965 based board (as - minimum requirements.) It is backward compatible with - previous versions, also. */ - sc->mbitmap = MB_HA; - sc->defmedia = MB_HA; - sc->msel = fe_msel_965; - - /* Perform board-specific probe. */ - if ((irqmap = fe_probe_jli_re1000p(sc, eeprom)) == NULL) return 0; - - /* Find the IRQ read from EEPROM. */ - n = (inb(sc->ioaddr[FE_BMPR19]) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT; - irq = irqmap[n]; - - /* Try to determine IRQ setting. */ - if (dev->id_irq == NO_IRQ && irq == NO_IRQ) { - /* The device must be configured with an explicit IRQ. */ - printf("fe%d: IRQ auto-detection does not work\n", - sc->sc_unit); - return 0; - } else if (dev->id_irq == NO_IRQ && irq != NO_IRQ) { - /* Just use the probed IRQ value. */ - dev->id_irq = irq; - } else if (dev->id_irq != NO_IRQ && irq == NO_IRQ) { - /* No problem. Go ahead. */ - } else if (dev->id_irq == irq) { - /* Good. Go ahead. */ - } else { - /* User must be warned in this case. */ - sc->stability |= UNSTABLE_IRQ; - } - - /* Setup a hook, which resets te 86965 when the driver is being - initialized. This may solve a nasty bug. FIXME. */ - sc->init = fe_init_jli; - - /* The I/O address range is fragmented in the RE1000Plus. - It 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? */ - -static void -fe_init_cnet9ne ( struct fe_softc * sc ) -{ - /* Enable interrupt? FIXME. */ - outb(sc->ioaddr[FE_CNET9NE_INTR], 0x10); -} - -static int -fe_probe_cnet9ne ( struct isa_device * dev, struct fe_softc * sc ) -{ - int i; - - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - static u_short ioaddr[MAXREGISTERS - 16] = { - /* 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, */ - /* 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, */ - 0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e, - 0x401, 0x403, 0x405, 0x407, 0x409, 0x40b, 0x40d, 0x40f, - }; - - /* See if the specified I/O address is possible for C-NET(9N)E. */ - if (sc->iobase != 0x73D0) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - - /* Re-map ioaddr for C-NET(9N)E. */ - for (i = 16; i < MAXREGISTERS; i++) - sc->ioaddr[i] = sc->iobase + ioaddr[i - 16]; - - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* Get our station address from EEPROM. */ - inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Make sure it is Contec's. */ - if (!valid_Ether_p(sc->sc_enaddr, 0x00804C)) return 0; - - /* Setup the board type. */ - sc->typestr = "C-NET(9N)E"; - - /* C-NET(9N)E seems to work only IRQ5. FIXME. */ - if (dev->id_irq != IRQ5) { - fe_irq_failure(sc->typestr, sc->sc_unit, dev->id_irq, "5"); - return 0; - } - - /* We need an init hook to initialize ASIC before we start. */ - sc->init = fe_init_cnet9ne; - - /* C-NET(9N)E has 64KB SRAM. */ - sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB - | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM; - - /* The I/O address range is fragmented in the C-NET(9N)E. - This is the number of regs at iobase. */ - return 16; -} - -/* - * Probe for Contec C-NET(98)P2 series. - * (Logitec LAN-98TP/LAN-98T25P - parhaps) - */ -static int -fe_probe_ssi (struct isa_device *dev, struct fe_softc *sc) -{ - u_char eeprom [SSI_EEPROM_SIZE]; - - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x08, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - 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 INT41 INT5 INT6 */ - }; - - /* See if the specified I/O address is possible for 78Q8377A. */ - /* [0-D]3D0 are allowed. */ - if ((sc->iobase & 0xFFF) != 0x3D0) return 0; /* XXX */ - - /* Fill the softc struct with default values. */ - fe_softc_defaults(sc); - - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* We now have to read the config EEPROM. We should be very - careful, since doing so destroys a register. (Remember, we - are not yet sure we have a C-NET(98)P2 board here.) Don't - remember to select BMPRs bofore reading EEPROM, since other - register bank may be selected before the probe() is called. */ - fe_read_eeprom_ssi(sc, eeprom); - - /* Make sure the Ethernet (MAC) station address is of Contec's. */ - if (!valid_Ether_p(eeprom+FE_SSI_EEP_ADDR, 0x00804C)) return 0; - bcopy(eeprom+FE_SSI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Setup the board type. */ - sc->typestr = "C-NET(98)P2"; - - /* Get IRQ configuration from EEPROM. */ - dev->id_irq = irqmap[eeprom[FE_SSI_EEP_IRQ]]; - if (dev->id_irq == NO_IRQ) { - fe_irq_failure(sc->typestr, - sc->sc_unit, dev->id_irq, "3/5/6/9/10/12/13"); - return 0; - } - - /* Get Duplex-mode configuration from EEPROM. */ - sc->proto_dlcr4 |= (eeprom[FE_SSI_EEP_DUPLEX] & FE_D4_DSC); - - /* Fill softc struct accordingly. */ - sc->mbitmap = MB_HT; - sc->defmedia = MB_HT; - - /* We have 16 registers. */ - return 16; -} - -/* - * Probe for TDK LAC-98012/013/025/9N011 - parhaps. - */ -static int -fe_probe_lnx (struct isa_device *dev, struct fe_softc *sc) -{ -#ifndef FE_8BIT_SUPPORT - printf("fe%d: skip LAC-98012/013(only 16-bit cards are supported)\n", - sc->sc_unit); - return 0; -#else - int i; - u_char eeprom [LNX_EEPROM_SIZE]; - - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for TDK/LANX boards. */ - /* 0D0, 4D0, 8D0, and CD0 are allowed. */ - if ((sc->iobase & ~0xC00) != 0xD0) return 0; - - /* Fill the softc struct with default values. */ - fe_softc_defaults(sc); - - /* Re-map ioaddr for LAC-98. - * 0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e, - * 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e, - * 0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, 0x20c, 0x20e, - * 0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e, - */ - for (i = 0; i < MAXREGISTERS; i++) - sc->ioaddr[i] = sc->iobase + ((i & 7) << 1) + ((i & 0x18) << 5); - - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* We now have to read the config EEPROM. We should be very - careful, since doing so destroys a register. (Remember, we - are not yet sure we have a LAC-98012/98013 board here.) */ - fe_read_eeprom_lnx(sc, eeprom); - - /* Make sure the Ethernet (MAC) station address is of TDK/LANX's. */ - if (!valid_Ether_p(eeprom, 0x008098)) return 0; - bcopy(eeprom, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Setup the board type. */ - sc->typestr = "LAC-98012/98013"; - - /* This looks like a TDK/LANX board. It requires an - explicit IRQ setting in config. Make sure we have one, - determining an appropriate value for the IRQ control - register. */ - switch (dev->id_irq) { - case IRQ3 : sc->priv_info = 0x10 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ5 : sc->priv_info = 0x20 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ6 : sc->priv_info = 0x40 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ12: sc->priv_info = 0x80 | LNX_CLK_LO | LNX_SDA_HI; break; - default: - fe_irq_failure(sc->typestr, - sc->sc_unit, dev->id_irq, "3/5/6/12"); - return 0; - } - - /* LAC-98's system bus width is 8-bit. */ - sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x2KB - | FE_D6_BBW_BYTE | FE_D6_SBW_BYTE | FE_D6_SRAM_150ns; - - /* Setup hooks. We need a special initialization procedure. */ - sc->init = fe_init_lnx; - - /* The I/O address range is fragmented in the LAC-98. - It occupies 16*4 I/O addresses, by the way. */ - return 16; -#endif /* FE_8BIT_SUPPORT */ -} - -/* - * Probe for Gateway Communications' old cards. - * (both as Generic MB86960 probe routine) - */ -static int -fe_probe_gwy ( struct isa_device * dev, struct fe_softc * sc ) -{ - static struct fe_simple_probe_struct probe_table [] = { - /* { FE_DLCR2, 0x70, 0x00 }, */ - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* I'm not sure which address is possible, so accepts any. FIXME. */ - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - - /* Does we need to re-map ioaddr? FIXME. */ - - /* See if the card is on its address. */ - if ( !fe_simple_probe( sc, probe_table ) ) return 0; - - /* Get our station address from EEPROM. */ - inblk( sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN ); - if (!valid_Ether_p(sc->sc_enaddr, 0x000000)) return 0; - - /* Determine the card type. */ - sc->typestr = "Generic MB86960 Ethernet"; - if (valid_Ether_p(sc->sc_enaddr, 0x000061)) - sc->typestr = "Gateway Ethernet (Fujitsu chipset)"; - - /* Gateway's board requires an explicit IRQ to work, since it - is not possible to probe the setting of jumpers. */ - if (dev->id_irq == NO_IRQ) { - fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL); - return 0; - } - - /* We should change return value when re-mapping ioaddr. FIXME. */ - return 32; -} - -/* - * Probe for Ungermann-Bass Access/PC N98C+(Model 85152). - */ -static int -fe_probe_ubn (struct isa_device * dev, struct fe_softc * sc) -{ - u_char sum; - int i; - static struct fe_simple_probe_struct const probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for Access/PC. */ - /* [01][048C]D0 are allowed. */ - if ((sc->iobase & ~0x1C00) != 0xD0) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - - /* Re-map ioaddr for Access/PC N98C+. - * 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, - * 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, - * 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, - * 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f, - */ - for (i = 16; i < MAXREGISTERS; i++) - sc->ioaddr[i] = sc->iobase + 0x200 - 16 + i; - - /* Simple probe. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* Get our station address form ID ROM and make sure it is UBN's. */ - inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); - if (!valid_Ether_p(sc->sc_enaddr, 0x00DD01)) return 0; -#if 1 - /* Calculate checksum. */ - sum = inb(sc->ioaddr[0x1e]); - for (i = 0; i < ETHER_ADDR_LEN; i++) { - sum ^= sc->sc_enaddr[i]; - } - if (sum != 0) return 0; -#endif - /* Setup the board type. */ - sc->typestr = "Access/PC"; - - /* This looks like an AccessPC/N98C+ board. It requires an - explicit IRQ setting in config. Make sure we have one, - determining an appropriate value for the IRQ control - register. */ - switch (dev->id_irq) { - case IRQ3: sc->priv_info = 0x01; break; - case IRQ5: sc->priv_info = 0x02; break; - case IRQ6: sc->priv_info = 0x04; break; - case IRQ12: sc->priv_info = 0x08; break; - default: - fe_irq_failure(sc->typestr, - sc->sc_unit, dev->id_irq, "3/5/6/12"); - return 0; - } - - /* Setup hooks. We need a special initialization procedure. */ - sc->init = fe_init_ubn; - - /* The I/O address range is fragmented in the Access/PC N98C+. - This is the number of regs at iobase. */ - return 16; -} - -#else /* !PC98 */ -/* - * Probe and initialization for Fujitsu FMV-180 series boards - */ + save16 = inb( sc->ioaddr[ FE_BMPR16 ] ); + save17 = inb( sc->ioaddr[ FE_BMPR17 ] ); + fe_read_eeprom( sc, eeprom ); -static void -fe_init_fmv (struct fe_softc *sc) -{ - /* Initialize ASIC. */ - outb( sc->ioaddr[ FE_FMV3 ], 0 ); - outb( sc->ioaddr[ FE_FMV10 ], 0 ); + /* Make sure the EEPROM is turned off. */ + outb( sc->ioaddr[ FE_BMPR16 ], 0 ); + outb( sc->ioaddr[ FE_BMPR17 ], 0 ); -#if 0 - /* "Refresh" hardware configuration. FIXME. */ - outb( sc->ioaddr[ FE_FMV2 ], inb( sc->ioaddr[ FE_FMV2 ] ) ); -#endif - - /* Turn the "master interrupt control" flag of ASIC on. */ - outb( sc->ioaddr[ FE_FMV3 ], FE_FMV3_IRQENB ); -} - -static void -fe_msel_fmv184 (struct fe_softc *sc) -{ - u_char port; - - /* FMV-184 has a special "register" to switch between AUI/BNC. - Determine the value to write into the register, based on the - user-specified media selection. */ - port = (IFM_SUBTYPE(sc->media.ifm_media) == IFM_10_2) ? 0x00 : 0x01; - - /* The register is #5 on exntesion register bank... - (Details of the register layout is not yet discovered.) */ - outb(sc->ioaddr[0x1B], 0x46); /* ??? */ - outb(sc->ioaddr[0x1E], 0x04); /* select ex-reg #4. */ - outb(sc->ioaddr[0x1F], 0xC8); /* ??? */ - outb(sc->ioaddr[0x1E], 0x05); /* select ex-reg #5. */ - outb(sc->ioaddr[0x1F], port); /* Switch the media. */ - outb(sc->ioaddr[0x1E], 0x04); /* select ex-reg #4. */ - outb(sc->ioaddr[0x1F], 0x00); /* ??? */ - outb(sc->ioaddr[0x1B], 0x00); /* ??? */ - - /* Make sure to select "external tranceiver" on MB86964. */ - outb(sc->ioaddr[FE_BMPR13], sc->proto_bmpr13 | FE_B13_PORT_AUI); -} - -static int -fe_probe_fmv ( struct isa_device * dev, struct fe_softc * sc ) -{ - int n; - - static u_short const irqmap [ 4 ] = - { IRQ3, IRQ7, IRQ10, IRQ15 }; - - static struct fe_simple_probe_struct const probe_table [] = { - { FE_DLCR2, 0x71, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - - { FE_FMV0, 0x78, 0x50 }, /* ERRDY+PRRDY */ - { FE_FMV1, 0xB0, 0x00 }, /* FMV-183/4 has 0x48 bits. */ - { FE_FMV3, 0x7F, 0x00 }, - - { 0 } - }; - - /* Board subtypes; it lists known FMV-180 variants. */ - struct subtype { - u_short mcode; - u_short mbitmap; - u_short defmedia; - char const * str; - }; - static struct subtype const typelist [] = { - { 0x0005, MB_HA|MB_HT|MB_H5, MB_HA, "FMV-181" }, - { 0x0105, MB_HA|MB_HT|MB_H5, MB_HA, "FMV-181A" }, - { 0x0003, MB_HM, MB_HM, "FMV-182" }, - { 0x0103, MB_HM, MB_HM, "FMV-182A" }, - { 0x0804, MB_HT, MB_HT, "FMV-183" }, - { 0x0C04, MB_HT, MB_HT, "FMV-183 (on-board)" }, - { 0x0803, MB_H2|MB_H5, MB_H2, "FMV-184" }, - { 0, MB_HA, MB_HA, "unknown FMV-180 (?)" }, - }; - struct subtype const * type; - - /* Media indicator and "Hardware revision ID" */ - u_short mcode; - - /* See if the specified address is possible for FMV-180 - series. 220, 240, 260, 280, 2A0, 2C0, 300, and 340 are - allowed for all boards, and 200, 2E0, 320, 360, 380, 3A0, - 3C0, and 3E0 for PnP boards. */ - if ((sc->iobase & ~0x1E0) != 0x200) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - - /* Simple probe. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* Get our station address from EEPROM, and make sure it is - Fujitsu's. */ - inblk(sc, FE_FMV4, sc->sc_enaddr, ETHER_ADDR_LEN); - if (!valid_Ether_p(sc->sc_enaddr, 0x00000E)) return 0; - - /* Find the supported media and "hardware revision" to know - the model identification. */ - mcode = (inb(sc->ioaddr[FE_FMV0]) & FE_FMV0_MEDIA) - | ((inb(sc->ioaddr[FE_FMV1]) & FE_FMV1_REV) << 8); - - /* Determine the card type. */ - for (type = typelist; type->mcode != 0; type++) { - if (type->mcode == mcode) break; - } - if (type->mcode == 0) { - /* Unknown card type... Hope the driver works. */ - sc->stability |= UNSTABLE_TYPE; - if (bootverbose) { - printf("fe%d: unknown config: %x-%x-%x-%x\n", - sc->sc_unit, - inb(sc->ioaddr[FE_FMV0]), - inb(sc->ioaddr[FE_FMV1]), - inb(sc->ioaddr[FE_FMV2]), - inb(sc->ioaddr[FE_FMV3])); - } - } - - /* Setup the board type and media information. */ - sc->typestr = type->str; - sc->mbitmap = type->mbitmap; - sc->defmedia = type->defmedia; - sc->msel = fe_msel_965; - - if (type->mbitmap == (MB_H2 | MB_H5)) { - /* FMV184 requires a special media selection procedure. */ - sc->msel = fe_msel_fmv184; - } - - /* - * An FMV-180 has been probed. - * 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. */ - sc->stability |= UNSTABLE_IRQ; + /* Make sure that config info in EEPROM and 86965 agree. */ + if ( eeprom[ FE_EEPROM_CONF ] != inb( sc->ioaddr[ FE_BMPR19 ] ) ) { + goto NOTFOUND; } - /* We need an init hook to initialize ASIC before we start. */ - sc->init = fe_init_fmv; - - /* - * That's all. FMV-180 occupies 32 I/O addresses, by the way. - */ - return 32; -} - -/* - * Fujitsu MB86965 JLI mode probe routines. - * - * 86965 has a special operating mode called JLI (mode 0), under which - * the chip interfaces with ISA bus with a software-programmable - * configuration. (The Fujitsu document calls the feature "Plug and - * play," but it is not compatible with the ISA-PnP spec. designed by - * Intel and Microsoft.) Ethernet cards designed to use JLI are - * almost same, but there are two things which require board-specific - * probe routines: EEPROM layout and IRQ pin connection. - * - * JLI provides a handy way to access EEPROM which should contains the - * chip configuration information (such as I/O port address) as well - * as Ethernet station (MAC) address. The chip configuration info. is - * stored on a fixed location. However, the station address can be - * located anywhere in the EEPROM; it is up to the board designer to - * determine the location. (The manual just says "somewhere in the - * EEPROM.") The fe driver must somehow find out the correct - * location. - * - * Another problem resides in the IRQ pin connection. JLI provides a - * user to choose an IRQ from up to four predefined IRQs. The 86965 - * chip has a register to select one out of the four possibilities. - * However, the selection is against the four IRQ pins on the chip. - * (So-called IRQ-A, -B, -C and -D.) It is (again) up to the board - * designer to determine which pin to connect which IRQ line on the - * ISA bus. We need a vendor (or model, for some vendor) specific IRQ - * mapping table. - * - * The routine fe_probe_jli() provides all probe and initialization - * processes which are common to all JLI implementation, and sub-probe - * routines supply board-specific actions. - * - * JLI sub-probe routine has the following template: - * - * u_short const * func (struct fe_softc * sc, u_char const * eeprom); - * - * where eeprom is a pointer to an array of 32 byte data read from the - * config EEPROM on the board. It retuns an IRQ mapping table for the - * board, when the corresponding implementation is detected. It - * returns a NULL otherwise. - * - * Primary purpose of the functin is to analize the config EEPROM, - * determine if it matches with the pattern of that of supported card, - * and extract necessary information from it. One of the information - * expected to be extracted from EEPROM is the Ethernet station (MAC) - * address, which must be set to the softc table of the interface by - * the board-specific routine. - */ - -/* JLI sub-probe for Allied-Telesyn/Allied-Telesis AT1700/RE2000 series. */ -static u_short const * -fe_probe_jli_ati (struct fe_softc * sc, u_char const * eeprom) -{ - int i; - static u_short const irqmaps_ati [4][4] = - { - { IRQ3, IRQ4, IRQ5, IRQ9 }, - { IRQ10, IRQ11, IRQ12, IRQ15 }, - { IRQ3, IRQ11, IRQ5, IRQ15 }, - { IRQ10, IRQ11, IRQ14, IRQ15 }, - }; - - /* Make sure the EEPROM contains Allied-Telesis/Allied-Telesyn - bit pattern. */ - if (eeprom[1] != 0x00) return NULL; - for (i = 2; i < 8; i++) if (eeprom[i] != 0xFF) return NULL; - for (i = 14; i < 24; i++) if (eeprom[i] != 0xFF) return NULL; - - /* Get our station address from EEPROM, and make sure the - EEPROM contains ATI's address. */ - bcopy(eeprom+8, sc->sc_enaddr, ETHER_ADDR_LEN); - if (!valid_Ether_p(sc->sc_enaddr, 0x0000F4)) return NULL; - /* - * The following model identification codes are stolen + * The following model identification codes are stolen from * from the NetBSD port of the fe driver. My reviewers * suggested minor revision. */ @@ -1891,604 +971,222 @@ fe_probe_jli_ati (struct fe_softc * sc, u_char const * eeprom) switch (eeprom[FE_ATI_EEP_MODEL]) { case FE_ATI_MODEL_AT1700T: sc->typestr = "AT-1700T/RE2001"; - sc->mbitmap = MB_HT; - sc->defmedia = MB_HT; break; case FE_ATI_MODEL_AT1700BT: sc->typestr = "AT-1700BT/RE2003"; - sc->mbitmap = MB_HA | MB_HT | MB_H2; break; case FE_ATI_MODEL_AT1700FT: sc->typestr = "AT-1700FT/RE2009"; - sc->mbitmap = MB_HA | MB_HT | MB_HF; break; case FE_ATI_MODEL_AT1700AT: sc->typestr = "AT-1700AT/RE2005"; - sc->mbitmap = MB_HA | MB_HT | MB_H5; break; default: - sc->typestr = "unknown AT-1700/RE2000"; - sc->stability |= UNSTABLE_TYPE | UNSTABLE_IRQ; + sc->typestr = "unknown AT-1700/RE2000 ?"; break; } -#if 0 - /* Should we extract default media from eeprom? Linux driver - for AT1700 does it, although previous releases of FreeBSD - don't. FIXME. */ - /* Determine the default media selection from the config - EEPROM. The byte at offset EEP_MEDIA is believed to - contain BMPR13 value to be set. We just ignore STP bit or - squelch bit, since we don't support those. (It is - intentional.) */ - switch (eeprom[FE_ATI_EEP_MEDIA] & FE_B13_PORT) { - case FE_B13_AUTO: - sc->defmedia = MB_HA; - break; - case FE_B13_TP: - sc->defmedia = MB_HT; - break; - case FE_B13_AUI: - sc->defmedia = sc->mbitmap & (MB_H2|MB_H5|MB_H5); /*XXX*/ - break; - default: - sc->defmedia = MB_HA; - break; - } - - /* Make sure the default media is compatible with the supported - ones. */ - if ((sc->defmedia & sc->mbitmap) == 0) { - if (sc->defmedia == MB_HA) { - sc->defmedia = MB_HT; - } else { - sc->defmedia = MB_HA; - } - } -#endif - /* * Try to determine IRQ settings. * Different models use different ranges of IRQs. */ - switch ((eeprom[FE_ATI_EEP_REVISION] & 0xf0) - |(eeprom[FE_ATI_EEP_MAGIC] & 0x04)) { - case 0x30: case 0x34: return irqmaps_ati[3]; - case 0x10: case 0x14: - case 0x50: case 0x54: return irqmaps_ati[2]; - case 0x44: case 0x64: return irqmaps_ati[1]; - default: return irqmaps_ati[0]; - } -} - -/* JLI sub-probe and msel hook for ICL Ethernet. */ - -static void -fe_msel_icl (struct fe_softc *sc) -{ - u_char d4; - - /* Switch between UTP and "external tranceiver" as always. */ - fe_msel_965(sc); - - /* The board needs one more bit (on DLCR4) be set appropriately. */ - if (IFM_SUBTYPE(sc->media.ifm_media) == IFM_10_5) { - d4 = sc->proto_dlcr4 | FE_D4_CNTRL; - } else { - d4 = sc->proto_dlcr4 & ~FE_D4_CNTRL; - } - outb(sc->ioaddr[FE_DLCR4], d4); -} - -static u_short const * -fe_probe_jli_icl (struct fe_softc * sc, u_char const * eeprom) -{ - int i; - u_short defmedia; - u_char d6; - static u_short const irqmap_icl [4] = { IRQ9, IRQ10, IRQ5, IRQ15 }; - - /* Make sure the EEPROM contains ICL bit pattern. */ - for (i = 24; i < 39; i++) { - if (eeprom[i] != 0x20 && (eeprom[i] & 0xF0) != 0x30) return NULL; - } - for (i = 112; i < 122; i++) { - if (eeprom[i] != 0x20 && (eeprom[i] & 0xF0) != 0x30) return NULL; - } - - /* Make sure the EEPROM contains ICL's permanent station - address. If it isn't, probably this board is not an - ICL's. */ - if (!valid_Ether_p(eeprom+122, 0x00004B)) return NULL; - - /* Check if the "configured" Ethernet address in the EEPROM is - valid. Use it if it is, or use the "permanent" address instead. */ - if (valid_Ether_p(eeprom+4, 0x020000)) { - /* The configured address is valid. Use it. */ - bcopy(eeprom+4, sc->sc_enaddr, ETHER_ADDR_LEN); - } else { - /* The configured address is invalid. Use permanent. */ - bcopy(eeprom+122, sc->sc_enaddr, ETHER_ADDR_LEN); - } - - /* Determine model and supported media. */ - switch (eeprom[0x5E]) { - case 0: - sc->typestr = "EtherTeam16i/COMBO"; - sc->mbitmap = MB_HA | MB_HT | MB_H5 | MB_H2; - break; - case 1: - sc->typestr = "EtherTeam16i/TP"; - sc->mbitmap = MB_HT; - break; - case 2: - sc->typestr = "EtherTeam16i/ErgoPro"; - sc->mbitmap = MB_HA | MB_HT | MB_H5; - break; - case 4: - sc->typestr = "EtherTeam16i/DUO"; - sc->mbitmap = MB_HA | MB_HT | MB_H2; - break; - default: - sc->typestr = "EtherTeam16i"; - sc->stability |= UNSTABLE_TYPE; - if (bootverbose) { - printf("fe%d: unknown model code %02x for EtherTeam16i\n", - sc->sc_unit, eeprom[0x5E]); - } - break; - } - - /* I'm not sure the following msel hook is required by all - models or COMBO only... FIXME. */ - sc->msel = fe_msel_icl; - - /* Make the configured media selection the default media. */ - switch (eeprom[0x28]) { - case 0: defmedia = MB_HA; break; - case 1: defmedia = MB_H5; break; - case 2: defmedia = MB_HT; break; - case 3: defmedia = MB_H2; break; - default: - if (bootverbose) { - printf("fe%d: unknown default media: %02x\n", - sc->sc_unit, eeprom[0x28]); - } - defmedia = MB_HA; - break; - } - - /* Make sure the default media is compatible with the - supported media. */ - if ((defmedia & sc->mbitmap) == 0) { - if (bootverbose) { - printf("fe%d: default media adjusted\n", sc->sc_unit); - } - defmedia = sc->mbitmap; - } - - /* Keep the determined default media. */ - sc->defmedia = defmedia; - - /* ICL has "fat" models. We have to program 86965 to properly - reflect the hardware. */ - d6 = sc->proto_dlcr6 & ~(FE_D6_BUFSIZ | FE_D6_BBW); - switch ((eeprom[0x61] << 8) | eeprom[0x60]) { - case 0x2008: d6 |= FE_D6_BUFSIZ_32KB | FE_D6_BBW_BYTE; break; - case 0x4010: d6 |= FE_D6_BUFSIZ_64KB | FE_D6_BBW_WORD; break; - default: - /* We can't support it, since we don't know which bits - to set in DLCR6. */ - printf("fe%d: unknown SRAM config for ICL\n", sc->sc_unit); - return NULL; - } - sc->proto_dlcr6 = d6; - - /* Returns the IRQ table for the ICL board. */ - return irqmap_icl; -} - -/* JLI sub-probe for RATOC REX-5586/5587. */ -static u_short const * -fe_probe_jli_rex (struct fe_softc * sc, u_char const * eeprom) -{ - int i; - static u_short const irqmap_rex [4] = { IRQ3, IRQ4, IRQ5, NO_IRQ }; - - /* Make sure the EEPROM contains RATOC's config pattern. */ - if (eeprom[1] != eeprom[0]) return NULL; - for (i = 8; i < 32; i++) if (eeprom[i] != 0xFF) return NULL; - - /* Get our station address from EEPROM. Note that RATOC - stores it "byte-swapped" in each word. (I don't know why.) - So, we just can't use bcopy().*/ - sc->sc_enaddr[0] = eeprom[3]; - sc->sc_enaddr[1] = eeprom[2]; - sc->sc_enaddr[2] = eeprom[5]; - sc->sc_enaddr[3] = eeprom[4]; - sc->sc_enaddr[4] = eeprom[7]; - sc->sc_enaddr[5] = eeprom[6]; - - /* Make sure the EEPROM contains RATOC's station address. */ - if (!valid_Ether_p(sc->sc_enaddr, 0x00C0D0)) return NULL; - - /* I don't know any sub-model identification. */ - sc->typestr = "REX-5586/5587"; - - /* Returns the IRQ for the RATOC board. */ - return irqmap_rex; -} - -/* JLI sub-probe for Unknown board. */ -static u_short const * -fe_probe_jli_unk (struct fe_softc * sc, u_char const * eeprom) -{ - int i, n, romsize; - static u_short const irqmap [4] = { NO_IRQ, NO_IRQ, NO_IRQ, NO_IRQ }; - - /* The generic JLI probe considered this board has an 86965 - in JLI mode, but any other board-specific routines could - not find the matching implementation. So, we "guess" the - location by looking for a bit pattern which looks like a - MAC address. */ - - /* Determine how large the EEPROM is. */ - for (romsize = JLI_EEPROM_SIZE/2; romsize > 16; romsize >>= 1) { - for (i = 0; i < romsize; i++) { - if (eeprom[i] != eeprom[i+romsize]) break; + 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; } - if (i < romsize) break; } - romsize <<= 1; - - /* Look for a bit pattern which looks like a MAC address. */ - for (n = 2; n <= romsize - ETHER_ADDR_LEN; n += 2) { - if (!valid_Ether_p(eeprom + n, 0x000000)) continue; - } - - /* If no reasonable address was found, we can't go further. */ - if (n > romsize - ETHER_ADDR_LEN) return NULL; - /* Extract our (guessed) station address. */ - bcopy(eeprom+n, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* We are not sure what type of board it is... */ - sc->typestr = "(unknown JLI)"; - sc->stability |= UNSTABLE_TYPE | UNSTABLE_MAC; - - /* Returns the totally unknown IRQ mapping table. */ - return irqmap; -} - -/* - * Probe and initialization for all JLI implementations. - */ - -static int -fe_probe_jli (struct isa_device * dev, struct fe_softc * sc) -{ - int i, n; - int irq; - u_char eeprom [JLI_EEPROM_SIZE]; - u_short const * irqmap; - - static u_short const baseaddr [8] = - { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300 }; - static struct fe_simple_probe_struct const probe_table [] = { - { FE_DLCR1, 0x20, 0x00 }, - { FE_DLCR2, 0x50, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { FE_DLCR5, 0x80, 0x00 }, -#if 0 - { FE_BMPR16, 0x1B, 0x00 }, - { FE_BMPR17, 0x7F, 0x00 }, -#endif - { 0 } - }; /* - * See if the specified address is possible for MB86965A JLI mode. + * Initialize constants in the per-line structure. */ - for (i = 0; i < 8; i++) { - if (baseaddr[i] == sc->iobase) break; - } - if (i == 8) return 0; - /* Fill the softc struct with reasonable default. */ - fe_softc_defaults(sc); + /* Get our station address from EEPROM. */ + bcopy( eeprom + FE_ATI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN ); +#if 1 /* - * 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. + * This test doesn't work well for AT1700 look-alike by + * other vendors. */ - if (!fe_simple_probe(sc, probe_table)) return 0; + /* 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; - /* 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) 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 /* - * We are now almost sure we have an MB86965 at the given - * address. So, read EEPROM through it. 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. + * Program the 86960 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. */ - fe_read_eeprom_jli(sc, eeprom); + 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 - /* Make sure that config info in EEPROM and 86965 agree. */ - if (eeprom[FE_EEPROM_CONF] != inb(sc->ioaddr[FE_BMPR19])) { - return 0; - } +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "ATI found" ); +#endif - /* Use 86965 media selection scheme, unless othewise - specified. It is "AUTO always" and "select with BMPR13." - This behaviour covers most of the 86965 based board (as - minimum requirements.) It is backward compatible with - previous versions, also. */ - sc->mbitmap = MB_HA; - sc->defmedia = MB_HA; - sc->msel = fe_msel_965; - - /* Perform board-specific probe, one by one. Note that the - order of probe is important and should not be changed - arbitrarily. */ - if ((irqmap = fe_probe_jli_ati(sc, eeprom)) == NULL - && (irqmap = fe_probe_jli_rex(sc, eeprom)) == NULL - && (irqmap = fe_probe_jli_icl(sc, eeprom)) == NULL - && (irqmap = fe_probe_jli_unk(sc, eeprom)) == NULL) return 0; - - /* Find the IRQ read from EEPROM. */ - n = (inb(sc->ioaddr[FE_BMPR19]) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT; - irq = irqmap[n]; - - /* Try to determine IRQ setting. */ - if (dev->id_irq == NO_IRQ && irq == NO_IRQ) { - /* The device must be configured with an explicit IRQ. */ - printf("fe%d: IRQ auto-detection does not work\n", - sc->sc_unit); - return 0; - } else if (dev->id_irq == NO_IRQ && irq != NO_IRQ) { - /* Just use the probed IRQ value. */ - dev->id_irq = irq; - } else if (dev->id_irq != NO_IRQ && irq == NO_IRQ) { - /* No problem. Go ahead. */ - } else if (dev->id_irq == irq) { - /* Good. Go ahead. */ - } else { - /* User must be warned in this case. */ - sc->stability |= UNSTABLE_IRQ; - } + /* Setup hooks. This may solves a nasty bug. FIXME. */ + sc->init = fe_init_ati; - /* Setup a hook, which resets te 86965 when the driver is being - initialized. This may solve a nasty bug. FIXME. */ - sc->init = fe_init_jli; + /* 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. 86965 JLI occupies 32 I/O addresses, by the way. + * That's all. AT1700 occupies 32 I/O addresses, by the way. */ return 32; -} - -/* Probe for TDK LAK-AX031, which is an SSi 78Q8377A based board. */ - -static int -fe_probe_ssi (struct isa_device *dev, struct fe_softc *sc) -{ - u_char eeprom [SSI_EEPROM_SIZE]; - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x08, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for 78Q8377A. */ - if ((sc->iobase & ~0x3F0) != 0x000) return 0; - - /* Fill the softc struct with default values. */ - fe_softc_defaults(sc); - - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* We now have to read the config EEPROM. We should be very - careful, since doing so destroys a register. (Remember, we - are not yet sure we have a LAK-AX031 board here.) Don't - remember to select BMPRs bofore reading EEPROM, since other - register bank may be selected before the probe() is called. */ - fe_read_eeprom_ssi(sc, eeprom); - - /* Make sure the Ethernet (MAC) station address is of TDK's. */ - if (!valid_Ether_p(eeprom+FE_SSI_EEP_ADDR, 0x008098)) return 0; - bcopy(eeprom+FE_SSI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* This looks like a TDK-AX031 board. It requires an explicit - IRQ setting in config, since we currently don't know how we - can find the IRQ value assigned by ISA PnP manager. */ - if (dev->id_irq == NO_IRQ) { - fe_irq_failure("LAK-AX031", sc->sc_unit, dev->id_irq, NULL); - return 0; + 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 ); } - - /* Fill softc struct accordingly. */ - sc->typestr = "LAK-AX031"; - sc->mbitmap = MB_HT; - sc->defmedia = MB_HT; - - /* We have 16 registers. */ - return 16; + return ( 0 ); } -/* - * Probe and initialization for TDK/LANX LAC-AX012/013 boards. - */ -static int -fe_probe_lnx (struct isa_device *dev, struct fe_softc *sc) +/* ATI specific initialization routine. */ +static void +fe_init_ati ( struct fe_softc * sc ) { - u_char eeprom [LNX_EEPROM_SIZE]; - - static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for TDK/LANX boards. */ - /* 300, 320, 340, and 360 are allowed. */ - if ((sc->iobase & ~0x060) != 0x300) return 0; - - /* Fill the softc struct with default values. */ - fe_softc_defaults(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. + */ - /* See if the card is on its address. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* We now have to read the config EEPROM. We should be very - careful, since doing so destroys a register. (Remember, we - are not yet sure we have a LAC-AX012/AX013 board here.) */ - fe_read_eeprom_lnx(sc, eeprom); - - /* Make sure the Ethernet (MAC) station address is of TDK/LANX's. */ - if (!valid_Ether_p(eeprom, 0x008098)) return 0; - bcopy(eeprom, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* This looks like a TDK/LANX board. It requires an - explicit IRQ setting in config. Make sure we have one, - determining an appropriate value for the IRQ control - register. */ - switch (dev->id_irq) { - case IRQ3: sc->priv_info = 0x40 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ4: sc->priv_info = 0x20 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ5: sc->priv_info = 0x10 | LNX_CLK_LO | LNX_SDA_HI; break; - case IRQ9: sc->priv_info = 0x80 | LNX_CLK_LO | LNX_SDA_HI; break; - default: - fe_irq_failure("LAC-AX012/AX013", - sc->sc_unit, dev->id_irq, "3/4/5/9"); - return 0; - } + /* Minimal initialization of 86965. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); - /* Fill softc struct accordingly. */ - sc->typestr = "LAC-AX012/AX013"; - sc->init = fe_init_lnx; + /* "Reset" by wrting into an undocument register location. */ + outb( sc->ioaddr[ 0x1F ], 0 ); - /* We have 32 registers. */ - return 32; + /* How long do we have to wait after the reset? FIXME. */ + DELAY( 300 ); } /* * Probe and initialization for Gateway Communications' old cards. */ static int -fe_probe_gwy ( struct isa_device * dev, struct fe_softc * sc ) +fe_probe_gwy ( DEVICE * dev, struct fe_softc * sc ) { + int i; + static struct fe_simple_probe_struct probe_table [] = { - /* { FE_DLCR2, 0x70, 0x00 }, */ - { FE_DLCR2, 0x58, 0x00 }, + { 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 } }; - /* See if the specified I/O address is possible for Gateway boards. */ - if ((sc->iobase & ~0x1E0) != 0x200) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - - /* See if the card is on its address. */ - if ( !fe_simple_probe( sc, probe_table ) ) return 0; - - /* Get our station address from EEPROM. */ - inblk( sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN ); - - /* Make sure it is Gateway Communication's. */ - if (!valid_Ether_p(sc->sc_enaddr, 0x000061)) return 0; - - /* Gateway's board requires an explicit IRQ to work, since it - is not possible to probe the setting of jumpers. */ - if (dev->id_irq == NO_IRQ) { - fe_irq_failure("Gateway Ethernet", sc->sc_unit, NO_IRQ, NULL); - return 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 ); } - /* Fill softc struct accordingly. */ - sc->typestr = "Gateway Ethernet (Fujitsu chipset)"; - - /* That's all. The card occupies 32 I/O addresses, as always. */ - return 32; -} - -/* Probe and initialization for Ungermann-Bass Network - K.K. "Access/PC" boards. */ -static int -fe_probe_ubn (struct isa_device * dev, struct fe_softc * sc) -{ -#if 0 - u_char sum; +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "top of probe" ); #endif - static struct fe_simple_probe_struct const probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { 0 } - }; - - /* See if the specified I/O address is possible for AccessPC/ISA. */ - if ((sc->iobase & ~0x0E0) != 0x300) return 0; - - /* Setup an I/O address mapping table and some others. */ - fe_softc_defaults(sc); - /* Simple probe. */ - if (!fe_simple_probe(sc, probe_table)) return 0; - - /* Get our station address form ID ROM and make sure it is UBN's. */ - inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); - if (!valid_Ether_p(sc->sc_enaddr, 0x00DD01)) return 0; -#if 0 - /* Calculate checksum. */ - sum = inb(sc->ioaddr[0x1e]); - for (i = 0; i < ETHER_ADDR_LEN; i++) { - sum ^= sc->sc_enaddr[i]; + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; } - if (sum != 0) return 0; -#endif - /* This looks like an AccessPC/ISA board. It requires an - explicit IRQ setting in config. Make sure we have one, - determining an appropriate value for the IRQ control - register. */ - switch (dev->id_irq) { - case IRQ3: sc->priv_info = 0x02; break; - case IRQ4: sc->priv_info = 0x04; break; - case IRQ5: sc->priv_info = 0x08; break; - case IRQ10: sc->priv_info = 0x10; break; - default: - fe_irq_failure("Access/PC", - sc->sc_unit, dev->id_irq, "3/4/5/10"); + + /* See if the card is on its address. */ + if ( !fe_simple_probe( sc, probe_table ) ) { return 0; } - /* Fill softc struct accordingly. */ - sc->typestr = "Access/PC"; - sc->init = fe_init_ubn; + /* Determine the card type. */ + sc->typestr = "Gateway Ethernet w/ Fujitsu chipset"; - /* We have 32 registers. */ - return 32; -} -#endif /* PC98 */ + /* Get our station address from EEPROM. */ + inblk( sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN ); -#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(). - */ + /* + * 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; -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 ); @@ -2498,63 +1196,142 @@ fe_init_mbh ( struct fe_softc * sc ) 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 ); + /* 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 ( struct isa_device * dev, struct fe_softc * sc ) +fe_probe_mbh ( DEVICE * dev, struct fe_softc * sc ) { + int i,type; + static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x58, 0x00 }, + { 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 } }; -#ifdef DIAGNOSTIC - /* We need an explicit IRQ. */ - if (dev->id_irq == NO_IRQ) return 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 - /* Ethernet MAC address should *NOT* have been given by pccardd, - if this is a true MBH10302; i.e., Ethernet address must be - "all-zero" upon entry. */ - if (sc->sc_enaddr[0] || sc->sc_enaddr[1] || sc->sc_enaddr[2] || - sc->sc_enaddr[3] || sc->sc_enaddr[4] || sc->sc_enaddr[5]) { - return 0; + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; } - /* Fill the softc struct with default values. */ - fe_softc_defaults(sc); - /* * 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 (!valid_Ether_p(sc->sc_enaddr, 0)) return 0; + if ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) return 0; - /* Determine the card type. */ - sc->typestr = "MBH10302 (PCMCIA)"; - - /* We seems to need our own IDENT bits... FIXME. */ + /* + * 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> @@ -2562,24 +1339,41 @@ fe_probe_mbh ( struct isa_device * dev, struct fe_softc * sc ) * (Contec uses TDK Ethenet chip -- hosokawa) * * This version of fe_probe_tdk has been rewrote to handle - * *generic* PC card implementation of Fujitsu MB8696x family. The - * name _tdk is just for a historical reason. :-) + * *generic* PC card implementation of Fujitsu MB8696x and compatibles. + * The name _tdk is just for a historical reason. <seki> :-) */ static int -fe_probe_tdk ( struct isa_device * dev, struct fe_softc * sc ) +fe_probe_tdk ( DEVICE * dev, struct fe_softc * sc ) { + int i; + static struct fe_simple_probe_struct probe_table [] = { - { FE_DLCR2, 0x50, 0x00 }, + { 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 ); } - fe_softc_defaults(sc); + /* 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. @@ -2588,19 +1382,56 @@ fe_probe_tdk ( struct isa_device * dev, struct fe_softc * sc ) if ( !fe_simple_probe( sc, probe_table ) ) return 0; /* Determine the card type. */ - sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)"; + sc->typestr = "Generic MB8696x Ethernet (PCMCIA)"; /* * Initialize constants in the per-line structure. */ - /* Make sure we got a valid station address. */ - if (!valid_Ether_p(sc->sc_enaddr, 0)) return 0; + /* 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; /* - * That's all. C-NET(PC)C occupies 16 I/O addresses. - * XXX: Are there any card with 32 I/O addresses? FIXME. + * 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 */ @@ -2609,15 +1440,12 @@ fe_probe_tdk ( struct isa_device * dev, struct fe_softc * sc ) * Install interface into kernel networking data structures */ static int -fe_attach ( struct isa_device * dev ) +fe_attach ( DEVICE * dev ) { #if NCARD > 0 static int already_ifattach[NFE]; #endif struct fe_softc *sc = &fe_softc[dev->id_unit]; - int b; - - dev->id_ointr = feintr; /* * Initialize ifnet structure @@ -2629,20 +1457,12 @@ fe_attach ( struct isa_device * dev ) sc->sc_if.if_start = fe_start; sc->sc_if.if_ioctl = fe_ioctl; sc->sc_if.if_watchdog = fe_watchdog; - sc->sc_if.if_init = fe_init; - sc->sc_if.if_linkmib = &sc->mibdata; - sc->sc_if.if_linkmiblen = sizeof (sc->mibdata); - -#if 0 /* I'm not sure... */ - sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS; -#endif /* - * Set fixed interface flags. + * Set default interface flags. */ sc->sc_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; -#if 1 /* * Set maximum size of output queue, if it has not been set. * It is done here as this driver may be started after the @@ -2656,6 +1476,9 @@ fe_attach ( struct isa_device * dev ) 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 @@ -2676,33 +1499,16 @@ fe_attach ( struct isa_device * dev ) case FE_D6_TXBSIZ_2x8KB: sc->txb_size = 8192; break; default: /* Oops, we can't work with single buffer configuration. */ - if (bootverbose) { - printf("fe%d: strange TXBSIZ config; fixing\n", - sc->sc_unit); - } +#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; } - /* Initialize the if_media interface. */ - ifmedia_init(&sc->media, 0, fe_medchange, fe_medstat ); - for (b = 0; bit2media[b] != 0; b++) { - if (sc->mbitmap & (1 << b)) { - ifmedia_add(&sc->media, bit2media[b], 0, NULL); - } - } - for (b = 0; bit2media[b] != 0; b++) { - if (sc->defmedia & (1 << b)) { - ifmedia_set(&sc->media, bit2media[b]); - break; - } - } -#if 0 /* Turned off; this is called later, when the interface UPs. */ - fe_medchange(sc); -#endif - /* Attach and stop the interface. */ #if NCARD > 0 if (already_ifattach[dev->id_unit] != 1) { @@ -2712,14 +1518,14 @@ fe_attach ( struct isa_device * dev ) #else if_attach(&sc->sc_if); #endif - fe_stop(sc); + 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%s\n", sc->sc_unit, - sc->sc_enaddr, ":" , sc->typestr, - (sc->proto_dlcr4 & FE_D4_DSC) ? ", full duplex" : ""); - if (bootverbose) { + 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; @@ -2746,42 +1552,29 @@ fe_attach ( struct isa_device * dev ) 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); - } - if (sc->stability & UNSTABLE_IRQ) { - printf("fe%d: warning: IRQ number may be incorrect\n", - sc->sc_unit); - } - if (sc->stability & UNSTABLE_MAC) { - printf("fe%d: warning: above MAC address may be incorrect\n", - sc->sc_unit); - } - if (sc->stability & UNSTABLE_TYPE) { - printf("fe%d: warning: hardware type was not validated\n", - sc->sc_unit); + 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)); + bpfattach( &sc->sc_if, DLT_EN10MB, sizeof(struct ether_header)); #endif return 1; } /* - * Reset interface, after some (hardware) trouble is deteced. + * Reset interface. */ static void -fe_reset (struct fe_softc *sc) +fe_reset ( int unit ) { - /* Record how many packets are lost by this accident. */ - sc->sc_if.if_oerrors += sc->txb_sched + sc->txb_count; - sc->mibdata.dot3StatsInternalMacTransmitErrors++; - - /* Put the interface into known initial state. */ - fe_stop(sc); - if (sc->sc_if.if_flags & IFF_UP) fe_init(sc); + /* + * Stop interface and re-initialize. + */ + fe_stop(unit); + fe_init(unit); } /* @@ -2791,12 +1584,17 @@ fe_reset (struct fe_softc *sc) * if any, will be lost by stopping the interface. */ static void -fe_stop (struct fe_softc *sc) +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 ); @@ -2825,9 +1623,15 @@ fe_stop (struct fe_softc *sc) /* MAR loading can be delayed. */ sc->filter_change = 0; - /* Call a device-specific hook. */ + /* 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); } @@ -2840,39 +1644,80 @@ fe_watchdog ( struct ifnet *ifp ) { struct fe_softc *sc = (struct fe_softc *)ifp; +#if FE_DEBUG >= 1 /* A "debug" message. */ - printf("fe%d: transmission timeout (%d+%d)%s\n", - ifp->if_unit, sc->txb_sched, sc->txb_count, - (ifp->if_flags & IFF_UP) ? "" : " when down"); + 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 ) { - printf("fe%d: wrong IRQ setting in config?\n", ifp->if_unit); + 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 ); } - fe_reset( sc ); } /* * Initialize device. */ static void -fe_init (void * xsc) +fe_init ( int unit ) { - struct fe_softc *sc = xsc; + 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 */ -#ifdef DIAGNOSTIC - printf("fe%d: init() without any address\n", sc->sc_unit); +#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 before we start initializing the chip. */ + /* 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 @@ -2914,19 +1759,23 @@ fe_init (void * xsc) 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 ); - /* Select requested media, just before enabling DLC. */ - if (sc->msel) sc->msel(sc); - /* Enable transmitter and receiver. */ DELAY( 200 ); outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_ENABLE ); DELAY( 200 ); -#ifdef DIAGNOSTIC +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "just after enabling DLC" ); +#endif + /* * Make sure to empty the receive buffer. * @@ -2945,16 +1794,24 @@ fe_init (void * xsc) * The following message helps discovering the fact. FIXME. */ if ( !( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) ) { - printf("fe%d: receive buffer has some data after reset\n", - sc->sc_unit); + 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. */ -#endif +#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; @@ -2967,13 +1824,15 @@ fe_init (void * xsc) */ fe_setmode( sc ); -#if 0 +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "after setmode" ); +#endif + /* ...and attempt to start output queued packets. */ - /* TURNED OFF, because the semi-auto media prober wants to UP - the interface keeping it idle. The upper layer will soon - start the interface anyway, and there are no significant - delay. */ fe_start( &sc->sc_if ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "init() done" ); #endif (void) splx(s); @@ -3017,7 +1876,7 @@ fe_start ( struct ifnet *ifp ) struct fe_softc *sc = ifp->if_softc; struct mbuf *m; -#ifdef DIAGNOSTIC +#if FE_DEBUG >= 1 /* Just a sanity check. */ if ( ( sc->txb_count == 0 ) != ( sc->txb_free == sc->txb_size ) ) { /* @@ -3028,8 +1887,8 @@ fe_start ( struct ifnet *ifp ) * txb_count is zero if and only if txb_free is same * as txb_size (which represents whole buffer.) */ - printf("fe%d: inconsistent txb variables (%d, %d)\n", - sc->sc_unit, sc->txb_count, sc->txb_free); + 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? * @@ -3049,15 +1908,18 @@ fe_start ( struct ifnet *ifp ) } #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 ) ) { - printf("fe%d: transmitter idle with %d buffered packets\n", - sc->sc_unit, sc->txb_count); + 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 @@ -3179,41 +2041,17 @@ fe_droppacket ( struct fe_softc * sc, int len ) */ if ( len > 12 ) { /* Read 4 more bytes, and skip the rest of the packet. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - } - else -#endif - { - ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); - ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); - } - outb( sc->ioaddr[ FE_BMPR14 ], FE_B14_SKIP ); + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + outb( sc->ioaddr[ FE_BMPR14 ], FE_B14_SKIP ); } else { /* We should not come here unless receiving RUNTs. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - for ( i = 0; i < len; i++ ) { - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - } - } - else -#endif - { - for ( i = 0; i < len; i += 2 ) { - ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); - } + for ( i = 0; i < len; i += 2 ) { + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); } } } -#ifdef DIAGNOSTIC /* * Empty receiving buffer. */ @@ -3223,10 +2061,9 @@ fe_emptybuffer ( struct fe_softc * sc ) int i; u_char saved_dlcr5; -#ifdef FE_DEBUG - printf("fe%d: emptying receive buffer\n", sc->sc_unit); +#if FE_DEBUG >= 2 + log( LOG_WARNING, "fe%d: emptying receive buffer\n", sc->sc_unit ); #endif - /* * Stop receiving packets, temporarily. */ @@ -3235,32 +2072,21 @@ fe_emptybuffer ( struct fe_softc * sc ) DELAY(1300); /* - * When we come here, the receive buffer management may + * When we come here, the receive buffer management should * have been broken. So, we cannot use skip operation. * Just discard everything in the buffer. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - for ( i = 0; i < 65536; i++ ) { - if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) break; - ( void )inb( sc->ioaddr[ FE_BMPR8 ] ); - } - } - else -#endif - { - for ( i = 0; i < 65536; i += 2 ) { - if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) break; - ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); - } + 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 ) { - printf("fe%d: could not empty receive buffer\n", sc->sc_unit); + log( LOG_ERR, "fe%d: could not empty receive buffer\n", + sc->sc_unit ); /* Hmm. What should I do if this happens? FIXME. */ } @@ -3269,7 +2095,6 @@ fe_emptybuffer ( struct fe_softc * sc ) */ outb( sc->ioaddr[ FE_DLCR5 ], saved_dlcr5 ); } -#endif /* * Transmission interrupt handler @@ -3291,8 +2116,14 @@ fe_tint ( struct fe_softc * sc, u_char tstat ) * are left unsent in transmission buffer. */ left = inb( sc->ioaddr[ FE_BMPR10 ] ); - printf("fe%d: excessive collision (%d/%d)\n", - sc->sc_unit, left, sc->txb_sched); + +#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 @@ -3366,24 +2197,19 @@ fe_tint ( struct fe_softc * sc, u_char tstat ) col = 1; } sc->sc_if.if_collisions += col; - if ( col == 1 ) { - sc->mibdata.dot3StatsSingleCollisionFrames++; - } else { - sc->mibdata.dot3StatsMultipleCollisionFrames++; - } - sc->mibdata.dot3StatsCollFrequencies[col-1]++; +#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. */ - col = sc->tx_excolls; - sc->sc_if.if_opackets += sc->txb_sched - col; - sc->sc_if.if_oerrors += col; - sc->sc_if.if_collisions += col * 16; - sc->mibdata.dot3StatsExcessiveCollisions += col; - sc->mibdata.dot3StatsCollFrequencies[15] += col; + 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; /* @@ -3415,28 +2241,18 @@ fe_rint ( struct fe_softc * sc, u_char rstat ) /* * Update statistics if this interrupt is caused by an error. - * Note that, when the system was not sufficiently fast, the - * receive interrupt might not be acknowledged immediately. If - * one or more errornous frames were received before this routine - * was scheduled, they are ignored, and the following error stats - * give less than real values. */ if ( rstat & ( FE_D1_OVRFLO | FE_D1_CRCERR | FE_D1_ALGERR | FE_D1_SRTPKT ) ) { - if ( rstat & FE_D1_OVRFLO ) - sc->mibdata.dot3StatsInternalMacReceiveErrors++; - if ( rstat & FE_D1_CRCERR ) - sc->mibdata.dot3StatsFCSErrors++; - if ( rstat & FE_D1_ALGERR ) - sc->mibdata.dot3StatsAlignmentErrors++; -#if 0 - /* The reference MAC receiver defined in 802.3 - silently ignores short frames (RUNTs) without - notifying upper layer. RFC 1650 (dot3 MIB) is - based on the 802.3, and it has no stats entry for - RUNTs... */ - if ( rstat & FE_D1_SRTPKT ) - sc->mibdata.dot3StatsFrameTooShorts++; /* :-) */ +#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++; } @@ -3449,109 +2265,147 @@ fe_rint ( struct fe_softc * sc, u_char rstat ) * 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++ ) { + 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 ) return; + if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) break; /* - * Extract a receive status byte. + * 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. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - status = inb( sc->ioaddr[ FE_BMPR8 ] ); - ( void ) inb( sc->ioaddr[ FE_BMPR8 ] ); - } - else + 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 - { - status = ( u_char )inw( sc->ioaddr[ FE_BMPR8 ] ); - } /* * Extract the packet length. * It is a sum of a header (14 bytes) and a payload. * CRC has been stripped off by the 86960. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - len = inb( sc->ioaddr[ FE_BMPR8 ] ); - len |= ( inb( sc->ioaddr[ FE_BMPR8 ] ) << 8 ); + 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; } - else #endif - { - len = inw( sc->ioaddr[ FE_BMPR8 ] ); - } +#if FE_DEBUG >= 1 /* - * AS our 86960 is programed to ignore errored frame, - * we must not see any error indication in the - * receive buffer. So, any error condition is a - * serious error, e.g., out-of-sync of the receive - * buffer pointers. + * 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 ( ( status & 0xF0 ) != 0x20 - || len > ETHER_MAX_LEN - ETHER_CRC_LEN - || len < ETHER_MIN_LEN - ETHER_CRC_LEN ) { - printf("fe%d: RX buffer out-of-sync\n", sc->sc_unit); + 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++; - sc->mibdata.dot3StatsInternalMacReceiveErrors++; - fe_reset(sc); - return; + fe_emptybuffer( sc ); + break; } +#endif /* * Go get a packet. */ if ( fe_get_packet( sc, len ) < 0 ) { - /* - * Negative return from fe_get_packet() - * indicates no available mbuf. We stop - * receiving packets, even if there are more - * in the buffer. We hope we can get more - * mbuf next time. - */ + +#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++; - sc->mibdata.dot3StatsMissedFrames++; fe_droppacket( sc, len ); - return; + + /* + * 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++; } - - /* Maximum number of frames has been received. Something - strange is happening here... */ - printf("fe%d: unusual receive flood\n", sc->sc_unit); - sc->mibdata.dot3StatsInternalMacReceiveErrors++; - fe_reset(sc); } /* * Ethernet interface interrupt processor */ -static void +void feintr ( int unit ) { struct fe_softc *sc = &fe_softc[unit]; u_char tstat, rstat; - int loop_count = FE_MAX_LOOP; - /* Loop until there are no more new interrupt conditions. */ - while (loop_count-- > 0) { + /* + * 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 ( tstat == 0 && rstat == 0 ) return; + +#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. @@ -3560,7 +2414,8 @@ feintr ( int unit ) outb( sc->ioaddr[ FE_DLCR1 ], rstat ); /* - * Handle transmitter interrupts. + * Handle transmitter interrupts. Handle these first because + * the receiver will reset the board under some conditions. */ if ( tstat ) { fe_tint( sc, tstat ); @@ -3605,9 +2460,6 @@ feintr ( int unit ) } } - - printf("fe%d: too many loops\n", sc->sc_unit); - return; } /* @@ -3618,32 +2470,148 @@ static int fe_ioctl ( struct ifnet * ifp, u_long command, caddr_t data ) { struct fe_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; 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: - case SIOCSIFMTU: - /* Just an ordinary action. */ - error = ether_ioctl(ifp, command, data); + { + 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); + fe_init( sc->sc_unit ); } } else { if ( ( sc->sc_if.if_flags & IFF_RUNNING ) != 0 ) { - fe_stop(sc); + fe_stop( sc->sc_unit ); } } @@ -3653,28 +2621,47 @@ fe_ioctl ( struct ifnet * ifp, u_long command, caddr_t data ) */ fe_setmode( sc ); - /* Done. */ +#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: + { /* - * Multicast list has changed; set the hardware filter - * accordingly. + * Set the interface MTU. */ - fe_setmode( sc ); - break; + struct ifreq * ifr = ( struct ifreq * )data; - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - /* Let if_media to handle these commands and to call - us back. */ - error = ifmedia_ioctl(ifp, ifr, &sc->media, command); + if ( ifr->ifr_mtu > ETHERMTU ) { + error = EINVAL; + } else { + sc->sc_if.if_mtu = ifr->ifr_mtu; + } break; + } +#endif default: error = EINVAL; - break; } (void) splx(s); @@ -3746,20 +2733,11 @@ fe_get_packet ( struct fe_softc * sc, u_short len ) /* The following silliness is to make NFS happy */ m->m_data += NFS_MAGIC_OFFSET; - /* Get (actually just point to) the header part. */ - eh = mtod(m, struct ether_header *); - /* Get a packet. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - insb( sc->ioaddr[ FE_BMPR8 ], eh, len ); - } - else -#endif - { - insw( sc->ioaddr[ FE_BMPR8 ], eh, ( len + 1 ) >> 1 ); - } + 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) @@ -3773,26 +2751,6 @@ fe_get_packet ( struct fe_softc * sc, u_short len ) } #endif -#ifdef BRIDGE - if (do_bridge) { - struct ifnet *ifp; - - ifp = bridge_in(m); - if (ifp == BDG_DROP) { - m_freem(m); - return 0; - } - if (ifp != BDG_LOCAL) - bdg_forward(&m, ifp); /* not local, need forwarding */ - if (ifp == BDG_LOCAL || ifp == BDG_BCAST || ifp == BDG_MCAST) - goto getit; - /* not local and not multicast, just drop it */ - if (m) - m_freem(m); - return 0; - } -#endif - /* * Make sure this packet is (or may be) directed to us. * That is, the packet is either unicasted to our address, @@ -3815,9 +2773,22 @@ fe_get_packet ( struct fe_softc * sc, u_short len ) return 0; } -#ifdef BRIDGE -getit: +#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 ); @@ -3849,23 +2820,26 @@ fe_write_mbufs ( struct fe_softc *sc, struct mbuf *m ) static u_char padding [ ETHER_MIN_LEN - ETHER_CRC_LEN - ETHER_HDR_LEN ]; -#ifdef DIAGNOSTIC +#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; } - /* Check if this matches the one in the packet header. */ - if ( length != m->m_pkthdr.len ) { - printf("fe%d: packet length mismatch? (%d/%d)\n", sc->sc_unit, - length, m->m_pkthdr.len); - } #else /* Just use the length value in the packet header. */ length = m->m_pkthdr.len; #endif -#ifdef DIAGNOSTIC +#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. @@ -3873,10 +2847,10 @@ fe_write_mbufs ( struct fe_softc *sc, struct mbuf *m ) */ if ( length < ETHER_HDR_LEN || length > ETHER_MAX_LEN - ETHER_CRC_LEN ) { - printf("fe%d: got an out-of-spec packet (%u bytes) to send\n", - sc->sc_unit, length); + 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++; - sc->mibdata.dot3StatsInternalMacTransmitErrors++; return; } #endif @@ -3889,29 +2863,13 @@ fe_write_mbufs ( struct fe_softc *sc, struct mbuf *m ) * packet in the transmission buffer, we can skip the * padding process. It may gain performance slightly. FIXME. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - len = max( length, ETHER_MIN_LEN - ETHER_CRC_LEN ); - outb( addr_bmpr8, len & 0x00ff ); - outb( addr_bmpr8, ( len & 0xff00 ) >> 8 ); - } - else -#endif - { - outw( addr_bmpr8, max( length, ETHER_MIN_LEN - ETHER_CRC_LEN ) ); - } + 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(). */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_WORD) -#endif - { - length = ( length + 1 ) & ~1; - } + length = ( length + 1 ) & ~1; sc->txb_free -= FE_DATA_LEN_LEN + max( length, ETHER_MIN_LEN - ETHER_CRC_LEN); sc->txb_count++; @@ -3921,69 +2879,45 @@ fe_write_mbufs ( struct fe_softc *sc, struct mbuf *m ) * only words. So that we require some extra code to patch * over odd-length mbufs. */ -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - /* 8-bit cards are easy. */ - for ( mp = m; mp != 0; mp = mp->m_next ) { - if ( mp->m_len ) { - outsb( addr_bmpr8, mtod(mp, caddr_t), mp->m_len ); - } - } - } - else -#endif - { - /* 16-bit cards are a pain. */ - 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; - } + savebyte = NO_PENDING_BYTE; + for ( mp = m; mp != 0; mp = mp->m_next ) { - /* output contiguous words */ - if (len > 1) { - outsw( addr_bmpr8, data, len >> 1); - data += len & ~1; - len &= 1; - } + /* Ignore empty mbuf. */ + len = mp->m_len; + if ( len == 0 ) continue; - /* Save a remaining byte, if there is one. */ - if ( len > 0 ) { - savebyte = *data; - } - } + /* Find the actual data to send. */ + data = mtod(mp, caddr_t); - /* Spit the last byte, if the length is odd. */ + /* Finish the last byte. */ if ( savebyte != NO_PENDING_BYTE ) { - outw( addr_bmpr8, savebyte ); + 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 ) { -#ifdef FE_8BIT_SUPPORT - if ((sc->proto_dlcr6 & FE_D6_BBW) == FE_D6_BBW_BYTE) - { - outsb( addr_bmpr8, padding, ETHER_MIN_LEN - ETHER_CRC_LEN - length ); - } - else -#endif - { - outsw( addr_bmpr8, padding, ( ETHER_MIN_LEN - ETHER_CRC_LEN - length ) >> 1); - } + outsw( addr_bmpr8, padding, ( ETHER_MIN_LEN - ETHER_CRC_LEN - length ) >> 1); } } @@ -4029,9 +2963,9 @@ fe_mcaf ( struct fe_softc *sc ) if (ifma->ifma_addr->sa_family != AF_LINK) continue; index = fe_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); -#ifdef FE_DEBUG - printf("fe%d: hash(%6D) == %d\n", - sc->sc_unit, enm->enm_addrlo , ":", index); +#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); @@ -4078,6 +3012,10 @@ fe_setmode ( struct fe_softc *sc ) 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; } @@ -4088,14 +3026,23 @@ fe_setmode ( struct fe_softc *sc ) /* * 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 { + } 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. * @@ -4104,6 +3051,9 @@ fe_setmode ( struct fe_softc *sc ) * 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. */ @@ -4120,6 +3070,9 @@ fe_setmode ( struct fe_softc *sc ) * 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 } } @@ -4157,45 +3110,36 @@ fe_loadmar ( struct fe_softc * sc ) /* We have just updated the filter. */ sc->filter_change = 0; -} - -/* Change the media selection. */ -static int -fe_medchange (struct ifnet *ifp) -{ - struct fe_softc *sc = (struct fe_softc *)ifp->if_softc; -#ifdef DIAGNOSTIC - /* If_media should not pass any request for a media which this - interface doesn't support. */ - int b; - - for (b = 0; bit2media[b] != 0; b++) { - if (bit2media[b] == sc->media.ifm_media) break; - } - if (((1 << b) & sc->mbitmap) == 0) { - printf("fe%d: got an unsupported media request (0x%x)\n", - sc->sc_unit, sc->media.ifm_media); - return EINVAL; - } +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: address filter changed\n", sc->sc_unit ); #endif - - /* We don't actually change media when the interface is down. - fe_init() will do the job, instead. Should we also wait - until the transmission buffer being empty? Changing the - media when we are sending a frame will cause two garbages - on wires, one on old media and another on new. FIXME */ - if (sc->sc_if.if_flags & IFF_UP) { - if (sc->msel) sc->msel(sc); - } - - return 0; } -/* I don't know how I can support media status callback... FIXME. */ +#if FE_DEBUG >= 1 static void -fe_medstat (struct ifnet *ifp, struct ifmediareq *ifmr) -{ - (void)ifp; - (void)ifmr; +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/i386/isa/if_fereg.h b/sys/i386/isa/if_fereg.h index d9b943c5febff..2a26cbea10f1c 100644 --- a/sys/i386/isa/if_fereg.h +++ b/sys/i386/isa/if_fereg.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. */ -/* $Id: if_fereg.h,v 1.5 1997/02/22 09:36:28 peter Exp $ */ +/* $Id$ */ /* * Registers on FMV-180 series' ISA bus interface ASIC. @@ -116,3 +116,17 @@ /* IRQ configuration. */ #define FE_RE1000_IRQCONF 0x10 +#define FE_RE1000_IRQCONF_IRQ 0xf0 +#define FE_RE1000_IRQCONF_IRQSHIFT 4 + +/* MAC (station) address. */ +#define FE_RE1000_MAC0 0x11 +#define FE_RE1000_MAC1 0x13 +#define FE_RE1000_MAC2 0x15 +#define FE_RE1000_MAC3 0x17 +#define FE_RE1000_MAC4 0x19 +#define FE_RE1000_MAC5 0x1B + +/* "Check sum" -- an xor of MAC0 through MAC5 */ +#define FE_RE1000_MACCHK 0x1D + diff --git a/sys/i386/isa/if_ie.c b/sys/i386/isa/if_ie.c index 4b22ae52bc6cc..f894dc5407547 100644 --- a/sys/i386/isa/if_ie.c +++ b/sys/i386/isa/if_ie.c @@ -47,7 +47,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ie.c,v 1.57 1998/10/22 05:58:39 bde Exp $ + * $Id: if_ie.c,v 1.55 1998/08/10 14:27:32 bde Exp $ */ /* @@ -176,7 +176,6 @@ static struct mbuf *last_not_for_us; static int ieprobe(struct isa_device * dvp); static int ieattach(struct isa_device * dvp); -static ointhand2_t ieintr; static int sl_probe(struct isa_device * dvp); static int el_probe(struct isa_device * dvp); static int ni_probe(struct isa_device * dvp); @@ -790,8 +789,6 @@ ieattach(struct isa_device *dvp) struct ifnet *ifp = &ie->arpcom.ac_if; size_t allocsize; - dvp->id_ointr = ieintr; - /* * based on the amount of memory we have, allocate our tx and rx * resources. @@ -854,7 +851,7 @@ ieattach(struct isa_device *dvp) /* * What to do upon receipt of an interrupt. */ -static void +void ieintr(int unit) { register struct ie_softc *ie = &ie_softc[unit]; @@ -2261,9 +2258,7 @@ static int ieioctl(struct ifnet *ifp, u_long command, caddr_t data) { struct ifaddr *ifa = (struct ifaddr *) data; -#if defined(IPX) || defined(NS) struct ie_softc *ie = ifp->if_softc; -#endif struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; diff --git a/sys/i386/isa/if_le.c b/sys/i386/isa/if_le.c index fb9492f384290..f6b89edf411f5 100644 --- a/sys/i386/isa/if_le.c +++ b/sys/i386/isa/if_le.c @@ -21,7 +21,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: if_le.c,v 1.48 1998/10/22 05:58:39 bde Exp $ + * $Id: if_le.c,v 1.46 1998/07/15 09:38:09 bde Exp $ */ /* @@ -236,7 +236,6 @@ struct le_softc { static int le_probe(struct isa_device *dvp); static int le_attach(struct isa_device *dvp); -static ointhand2_t le_intr; static int le_ioctl(struct ifnet *ifp, u_long command, caddr_t data); static void le_input(le_softc_t *sc, caddr_t seg1, size_t total_len, size_t len2, caddr_t seg2); @@ -355,7 +354,6 @@ le_attach( le_softc_t *sc = &le_softc[dvp->id_unit]; struct ifnet *ifp = &sc->le_if; - dvp->id_ointr = le_intr; ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; printf("%s%d: %s ethernet address %6D\n", @@ -380,7 +378,7 @@ le_attach( return 1; } -static void +void le_intr( int unit) { @@ -1126,7 +1124,7 @@ lemac_start( /* * The first four bytes of each transmit buffer are for * control information. The first byte is the control - * byte, then the length (why not word aligned?), then + * byte, then the length (why not word aligned??), then * the off to the buffer. */ diff --git a/sys/i386/isa/if_lnc.c b/sys/i386/isa/if_lnc.c index 0e74247596c18..e31c600c823f5 100644 --- a/sys/i386/isa/if_lnc.c +++ b/sys/i386/isa/if_lnc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1994-1998 + * Copyright (c) 1995, 1996 * Paul Richards. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_lnc.c,v 1.50 1998/11/26 00:57:32 paul Exp $ + * $Id: if_lnc.c,v 1.45 1998/08/24 02:28:15 bde Exp $ */ /* @@ -177,15 +177,14 @@ static int pcnet_probe __P((struct lnc_softc *sc)); static int lnc_attach_sc __P((struct lnc_softc *sc, int unit)); static int lnc_attach __P((struct isa_device *isa_dev)); static void lnc_init __P((struct lnc_softc *sc)); -static ointhand2_t lncintr; static __inline int mbuf_to_buffer __P((struct mbuf *m, char *buffer)); static __inline struct mbuf *chain_to_cluster __P((struct mbuf *m)); static void lnc_start __P((struct ifnet *ifp)); static int lnc_ioctl __P((struct ifnet *ifp, u_long command, caddr_t data)); static void lnc_watchdog __P((struct ifnet *ifp)); #ifdef DEBUG -void lnc_dump_state __P((struct lnc_softc *sc)); -void mbuf_dump_chain __P((struct mbuf *m)); +static void lnc_dump_state __P((struct lnc_softc *sc)); +static void mbuf_dump_chain __P((struct mbuf *m)); #endif #if NPCI > 0 @@ -560,14 +559,13 @@ lnc_rint(struct lnc_softc *sc) log(LOG_ERR, "lnc%d: Receive overflow error \n", unit); } } else if (flags & ENP) { - if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC)==0) { /* * FRAM and CRC are valid only if ENP * is set and OFLO is not. */ if (flags & FRAM) { LNCSTATS(fram) - log(LOG_ERR, "lnc%d: Framing error\n", unit); + log(LOG_ERR, "lnc%d: Framming error\n", unit); /* * FRAM is only set if there's a CRC * error so avoid multiple messages @@ -576,7 +574,6 @@ lnc_rint(struct lnc_softc *sc) LNCSTATS(crc) log(LOG_ERR, "lnc%d: Receive CRC error\n", unit); } - } } /* Drop packet */ @@ -1276,10 +1273,8 @@ lnc_attach(struct isa_device * isa_dev) { int unit = isa_dev->id_unit; struct lnc_softc *sc = &lnc_softc[unit]; - int result; - isa_dev->id_ointr = lncintr; - result = lnc_attach_sc (sc, unit); + int result = lnc_attach_sc (sc, unit); if (result == 0) return (0); @@ -1311,7 +1306,7 @@ lnc_attach_ne2100_pci(int unit, unsigned iobase) sc->bdp = iobase + PCNET_BDP; sc->nic.ic = pcnet_probe(sc); - if (sc->nic.ic >= PCnet_32) { + if (sc->nic.ic >= PCnet_PCI) { sc->nic.ident = NE2100; sc->nic.mem_mode = DMA_FIXED; @@ -1597,7 +1592,7 @@ lncintr_sc(struct lnc_softc *sc) } } -static void +void lncintr(int unit) { struct lnc_softc *sc = &lnc_softc[unit]; @@ -1896,7 +1891,7 @@ lnc_watchdog(struct ifnet *ifp) } #ifdef DEBUG -void +static void lnc_dump_state(struct lnc_softc *sc) { int i; @@ -1951,7 +1946,7 @@ lnc_dump_state(struct lnc_softc *sc) outw(sc->rap, CSR0); } -void +static void mbuf_dump_chain(struct mbuf * m) { diff --git a/sys/i386/isa/if_lnc.h b/sys/i386/isa/if_lnc.h index f281eaf13ab4e..8d9ffabdbdba6 100644 --- a/sys/i386/isa/if_lnc.h +++ b/sys/i386/isa/if_lnc.h @@ -1,36 +1,11 @@ -/*- - * Copyright (c) 1994-1998 - * Paul Richards. 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, - * verbatim and that no modifications are made prior to this - * point in the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Paul Richards. - * 4. The name Paul Richards may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * Copyright (c) 1994, Paul Richards. 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. * - * $Id: $ */ #include <i386/isa/ic/Am7990.h> diff --git a/sys/i386/isa/if_rdp.c b/sys/i386/isa/if_rdp.c deleted file mode 100644 index 0d29b0aba602a..0000000000000 --- a/sys/i386/isa/if_rdp.c +++ /dev/null @@ -1,1456 +0,0 @@ -/* - * Copyright 1998, Joerg Wunsch - * 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 unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: if_rdp.c,v 1.2 1998/12/21 18:11:10 joerg Exp $ - */ - -/* - * Device driver for RealTek RTL 8002 (`REDP') based pocket-ethernet - * adapters, hooked up to a printer port. `rdp' is a shorthand for - * REDP since some tools like netstat work best if the interface name - * has no more than three letters. - * - * Driver configuration flags so far: - * flags 0x1 -- assume 74S288 EEPROM (default 94C46) - * flags 0x2 -- use `slow' mode (mode 3 of the packet driver, default 0) - * - * Maybe this driver will some day also work with the successor, RTL - * 8012 (`AREDP'), which is unfortunately not fully register- - * compatible with the 8002. The 8012 offers support for faster - * transfer modi like bidirectional SPP and EPP, 64 K x 4 buffer - * memory as opposed to 16 K x 4 for the 8002, a multicast filter, and - * a builtin multiplexer that allows chaining a printer behind the - * ethernet adapter. - * - * About the only documentation i've been able to find about the RTL - * 8002 was the packet driver source code at ftp.realtek.com.tw, so - * this driver is somewhat based on the way the packet driver handles - * the chip. The exact author of the packet driver is unknown, the - * only name that i could find in the source was someone called Chiu, - * supposedly an employee of RealTek. So credits to them for that - * piece of code which has proven valuable to me. - * - * Later on, Leo kuo <leo@realtek.com.tw> has been very helpful to me - * by sending me a readable (PDF) file documenting the RTL 8012, which - * helped me to also understand the 8002, as well as by providing me - * with the source code of the 8012 packet driver that i haven't been - * able to find on the FTP site. A big Thanks! goes here to RealTek - * for this kind of service. - */ - -#include "rdp.h" -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/sockio.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/syslog.h> - -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_mib.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_ether.h> -#endif - -#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 <machine/md_var.h> - -#include <i386/isa/isa_device.h> -#include <i386/isa/icu.h> -#include <i386/isa/if_rdpreg.h> -#include <i386/isa/intr_machdep.h> - -#define IOCTL_CMD_T u_long - -/* - * Debug levels (ORed together): - * != 0 - general (bad packets etc.) - * 2 - debug EEPROM IO - * 4 - debug interrupt status - */ -#undef DEBUG -#define DEBUG 0 - -/* - * rdp_softc: per interface info and status - */ -struct rdp_softc { - struct arpcom arpcom; /* - * Ethernet common, always goes first so - * a rdp_softc * can be cast into an - * arpcom * or into an ifnet *. - */ - - /* - * local stuff, somewhat sorted by memory alignment class - */ - u_short baseaddr; /* IO port address */ - u_short txsize; /* tx size for next (buffered) packet, - * there's only one additional packet - * we can buffer, thus a single variable - * ought to be enough */ - int txbusy; /* tx is transmitting */ - int txbuffered; /* # of packets in tx buffer */ - int slow; /* use lpt_control to send data */ - u_char irqenbit; /* mirror of current Ctrl_IRQEN */ - /* - * type of parameter EEPROM; device flags 0x1 selects 74S288 - */ - enum { - EEPROM_93C46, EEPROM_74S288 /* or 82S123 */ - } eeprom; -}; - -static struct rdp_softc rdp_softc[NRDP]; - -/* - * Since there's no fixed location in the EEPROM about where to find - * the ethernet hardware address, we drop a table of valid OUIs here, - * and search through the EEPROM until we find a possible valid - * Ethernet address. Only the first 16 bits of all possible OUIs are - * recorded in the table (as obtained from - * http://standards.ieee.org/regauth/oui/oui.txt). - */ - -static u_short allowed_ouis[] = { - 0x0000, 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0010, 0x001C, 0x0020, 0x0040, 0x0050, 0x0060, - 0x0070, 0x0080, 0x0090, 0x009D, 0x00A0, 0x00AA, 0x00BB, - 0x00C0, 0x00CF, 0x00DD, 0x00E0, 0x00E6, 0x0207, 0x021C, - 0x0260, 0x0270, 0x029D, 0x02AA, 0x02BB, 0x02C0, 0x02CF, - 0x02E6, 0x040A, 0x04E0, 0x0800, 0x08BB, 0x1000, 0x1100, - 0x8000, 0xAA00 -}; - -/* - * ISA bus support. - */ -static int rdp_probe __P((struct isa_device *)); -static int rdp_attach __P((struct isa_device *)); - -/* - * Required entry points. - */ -static void rdp_init(void *); -static int rdp_ioctl(struct ifnet *, IOCTL_CMD_T, caddr_t); -static void rdp_start(struct ifnet *); -static void rdp_reset(struct ifnet *); -static void rdp_watchdog(struct ifnet *); -static void rdpintr(int); - -/* - * REDP private functions. - */ - -static void rdp_stop(struct rdp_softc *); -static void rdp_rint(struct rdp_softc *); -static void rdp_get_packet(struct rdp_softc *, unsigned); -static u_short rdp_write_mbufs(struct rdp_softc *, struct mbuf *); -static int rdp_gethwaddr_93c46(struct rdp_softc *, u_char *); -static void rdp_gethwaddr_74s288(struct rdp_softc *, u_char *); -static void rdp_93c46_cmd(struct rdp_softc *, u_short, unsigned); -static u_short rdp_93c46_read(struct rdp_softc *); - -struct isa_driver rdpdriver = { - rdp_probe, - rdp_attach, - "rdp", - 1 /* we wanna get a chance before lptN */ -}; - -/* - * REDP-specific functions. - * - * They are inlined, thus go first in this file. Together with gcc's - * usual optimization, these functions probably come close to the - * packet driver's hand-optimized code. ;-) - * - * Comments are partially obtained from the packet driver as well. - * Some of the function names contain register names which don't make - * much sense for us, but i've kept them for easier reference in - * comparision to the packet driver. - * - * Some of the functions are currently not used by the driver; it's - * not quite clear whether we ever need them at all. They are - * supposedly even slower than what is currently implemented as `slow' - * mode. Right now, `fast' (default) mode is what the packet driver - * calls mode 0, slow mode is mode 3 (writing through lpt_control, - * reading twice). - * - * We should autoprobe the modi, as opposed to making them dependent - * on a kernel configuration flag. - */ - -/* - * read a nibble from rreg; end-of-data cmd is not issued; - * used for general register read. - * - * Unlike the packet driver's version, i'm shifting the result - * by 3 here (as opposed to within the caller's code) for clarity. - * -- Joerg - */ -static __inline u_char -RdNib(struct rdp_softc *sc, u_char rreg) -{ - - outb(sc->baseaddr + lpt_data, EOC + rreg); - outb(sc->baseaddr + lpt_data, RdAddr + rreg); /* write addr */ - (void)inb(sc->baseaddr + lpt_status); - return (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f; -} - -#if 0 -/* - * read a byte from MAR register through lpt_data; the low nibble is - * read prior to the high one; end-of-read command is not issued; used - * for remote DMA in mode 4 + 5 - */ -static __inline u_char -RdByte(struct rdp_softc *sc) -{ - u_char hinib, lonib; - - outb(sc->baseaddr + lpt_data, RdAddr + MAR); /* cmd for low nibble */ - lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f; - outb(sc->baseaddr + lpt_data, RdAddr + MAR + HNib); - hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0; - return hinib + lonib; -} - - -/* - * read a byte from MAR register through lpt_data; the low nibble is - * read prior to the high one; end-of-read command is not issued; used - * for remote DMA in mode 6 + 7 - */ -static __inline u_char -RdByte1(struct rdp_softc *sc) -{ - u_char hinib, lonib; - - outb(sc->baseaddr + lpt_data, RdAddr + MAR); /* cmd for low nibble */ - (void)inb(sc->baseaddr + lpt_status); - lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f; - outb(sc->baseaddr + lpt_data, RdAddr + MAR + HNib); - (void)inb(sc->baseaddr + lpt_status); - hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0; - return hinib + lonib; -} -#endif - - -/* - * read a byte from MAR register through lpt_control; the low nibble is - * read prior to the high one; end-of-read command is not issued; used - * for remote DMA in mode 0 + 1 - */ -static __inline u_char -RdByteA1(struct rdp_softc *sc) -{ - u_char hinib, lonib; - - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead); - lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f; - outb(sc->baseaddr + lpt_control, Ctrl_HNibRead); - hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0; - return hinib + lonib; -} - - -/* - * read a byte from MAR register through lpt_control; the low nibble is - * read prior to the high one; end-of-read command is not issued; used - * for remote DMA in mode 2 + 3 - */ -static __inline u_char -RdByteA2(struct rdp_softc *sc) -{ - u_char hinib, lonib; - - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead); - (void)inb(sc->baseaddr + lpt_status); - lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f; - outb(sc->baseaddr + lpt_control, Ctrl_HNibRead); - (void)inb(sc->baseaddr + lpt_status); - hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0; - return hinib + lonib; -} - -/* - * End-of-read cmd - */ -static __inline void -RdEnd(struct rdp_softc *sc, u_char rreg) -{ - - outb(sc->baseaddr + lpt_data, EOC + rreg); -} - -/* - * Write a nibble to a register; end-of-write is issued. - * Used for general register write. - */ -static __inline void -WrNib(struct rdp_softc *sc, u_char wreg, u_char wdata) -{ - - /* prepare and write address */ - outb(sc->baseaddr + lpt_data, EOC + wreg); - outb(sc->baseaddr + lpt_data, WrAddr + wreg); - outb(sc->baseaddr + lpt_data, WrAddr + wreg); - /* prepare and write data */ - outb(sc->baseaddr + lpt_data, WrAddr + wdata); - outb(sc->baseaddr + lpt_data, wdata); - outb(sc->baseaddr + lpt_data, wdata); - /* end-of-write */ - outb(sc->baseaddr + lpt_data, EOC + wdata); -} - -/* - * Write a byte to a register; end-of-write is issued. - * Used for general register write. - */ -static __inline void -WrByte(struct rdp_softc *sc, u_char wreg, u_char wdata) -{ - - /* prepare and write address */ - outb(sc->baseaddr + lpt_data, EOC + wreg); - outb(sc->baseaddr + lpt_data, WrAddr + wreg); - outb(sc->baseaddr + lpt_data, WrAddr + wreg); - /* prepare and write low nibble */ - outb(sc->baseaddr + lpt_data, WrAddr + (wdata & 0x0F)); - outb(sc->baseaddr + lpt_data, (wdata & 0x0F)); - outb(sc->baseaddr + lpt_data, (wdata & 0x0F)); - /* prepare and write high nibble */ - wdata >>= 4; - outb(sc->baseaddr + lpt_data, wdata); - outb(sc->baseaddr + lpt_data, wdata + HNib); - outb(sc->baseaddr + lpt_data, wdata + HNib); - /* end-of-write */ - outb(sc->baseaddr + lpt_data, EOC + wdata + HNib); -} - -/* - * Write the byte to DRAM via lpt_data; - * used for remote DMA write in mode 0 / 2 / 4 - */ -static __inline void -WrByteALToDRAM(struct rdp_softc *sc, u_char val) -{ - - outb(sc->baseaddr + lpt_data, val & 0x0F); - outb(sc->baseaddr + lpt_data, MkHi(val)); -} - -/* - * Write the byte to DRAM via lpt_control; - * used for remote DMA write in mode 1 / 3 / 5 - */ -static __inline void -WrByteALToDRAMA(struct rdp_softc *sc, u_char val) -{ - - outb(sc->baseaddr + lpt_data, val & 0x0F); - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit); - outb(sc->baseaddr + lpt_data, val >> 4); - outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit); -} - -#if 0 /* they could be used for the RAM test */ -/* - * Write the u_short to DRAM via lpt_data; - * used for remote DMA write in mode 0 / 2 / 4 - */ -static __inline void -WrWordbxToDRAM(struct rdp_softc *sc, u_short val) -{ - - outb(sc->baseaddr + lpt_data, val & 0x0F); - val >>= 4; - outb(sc->baseaddr + lpt_data, (val & 0x0F) + HNib); - val >>= 4; - outb(sc->baseaddr + lpt_data, val & 0x0F); - val >>= 4; - outb(sc->baseaddr + lpt_data, val + HNib); -} - - -/* - * Write the u_short to DRAM via lpt_control; - * used for remote DMA write in mode 1 / 3 / 5 - */ -static __inline void -WrWordbxToDRAMA(struct rdp_softc *sc, u_short val) -{ - - outb(sc->baseaddr + lpt_data, val & 0x0F); - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit); - val >>= 4; - outb(sc->baseaddr + lpt_data, (val & 0x0F) + HNib); - outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit); - val >>= 4; - outb(sc->baseaddr + lpt_data, val & 0x0F); - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit); - val >>= 4; - outb(sc->baseaddr + lpt_data, val + HNib); - outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit); -} -#endif - - -/* - * Determine if the device is present - * - * on entry: - * a pointer to an isa_device struct - * on exit: - * 0 if device not found - * or # of i/o addresses used (if found) - */ -static int -rdp_probe(struct isa_device *isa_dev) -{ - int unit = isa_dev->id_unit; - struct rdp_softc *sc = &rdp_softc[unit]; - u_char b1, b2; - intrmask_t irqmap[3]; - u_char sval[3]; - - if (unit < 0 || unit >= NRDP) - return 0; - - sc->baseaddr = isa_dev->id_iobase; - if (isa_dev->id_flags & 1) - sc->eeprom = EEPROM_74S288; - /* else defaults to 93C46 */ - if (isa_dev->id_flags & 2) - sc->slow = 1; - - /* let R/WB = A/DB = CSB = high to be ready for next r/w cycle */ - outb(sc->baseaddr + lpt_data, 0xFF); - /* DIR = 0 for write mode, IRQEN=0, SLCT=INIT=AUTOFEED=STB=high */ - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - /* software reset */ - WrNib(sc, CMR1 + HNib, MkHi(CMR1_RST)); - DELAY(2000); - /* is EPLC alive? */ - b1 = RdNib(sc, CMR1); - RdEnd(sc, CMR1); - b2 = RdNib(sc, CMR2) & 0x0f; - b2 |= RdNib(sc, CMR2 + HNib) << 4; - RdEnd(sc, CMR2 + HNib); - /* - * After the reset, we expect CMR1 & 7 to be 1 (rx buffer empty), - * and CMR2 & 0xf7 to be 0x20 (receive mode set to physical and - * broadcasts). - */ - if (bootverbose) - printf("rdp%d: CMR1 = %#x, CMR2 = %#x\n", unit, b1, b2); - - if ((b1 & (CMR1_BUFE | CMR1_IRQ | CMR1_TRA)) != CMR1_BUFE - || (b2 & ~CMR2_IRQINV) != CMR2_AM_PB) - return 0; - - /* - * We have found something that could be a RTL 80[01]2, now - * see whether we can generate an interrupt. - */ - disable_intr(); - - /* - * Test whether our configured IRQ is working. - * - * Set to no acception mode + IRQout, then enable RxE + TxE, - * then cause RBER (by advancing the read pointer although - * the read buffer is empty) to generate an interrupt. - */ - WrByte(sc, CMR2, CMR2_IRQOUT); - WrNib(sc, CMR1 + HNib, MkHi(CMR1_TE | CMR1_RE)); - WrNib(sc, CMR1, CMR1_RDPAC); - DELAY(1000); - - irqmap[0] = isa_irq_pending(); - sval[0] = inb(sc->baseaddr + lpt_status); - - /* allow IRQs to pass the parallel interface */ - outb(sc->baseaddr + lpt_control, Ctrl_IRQEN + Ctrl_SelData); - DELAY(1000); - /* generate interrupt */ - WrNib(sc, IMR + HNib, MkHi(ISR_RBER)); - DELAY(1000); - - irqmap[1] = isa_irq_pending(); - sval[1] = inb(sc->baseaddr + lpt_status); - - /* de-assert and disable IRQ */ - WrNib(sc, IMR + HNib, MkHi(0)); - (void)inb(sc->baseaddr + lpt_status); /* might be necessary to - clear IRQ */ - DELAY(1000); - irqmap[2] = isa_irq_pending(); - sval[2] = inb(sc->baseaddr + lpt_status); - - WrNib(sc, CMR1 + HNib, MkHi(0)); - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - WrNib(sc, CMR2, CMR2_IRQINV); - - enable_intr(); - - if (bootverbose) - printf("rdp%d: irq maps / lpt status " - "%#x/%#x - %#x/%#x - %#x/%#x (id_irq %#x)\n", - unit, irqmap[0], sval[0], irqmap[1], sval[1], - irqmap[2], sval[2], isa_dev->id_irq); - - if ((irqmap[1] & isa_dev->id_irq) == 0) { - printf("rdp%d: configured IRQ (%d) cannot be asserted " - "by device", - unit, ffs(isa_dev->id_irq) - 1); - if (irqmap[1]) - printf(" (probable IRQ: %d)", ffs(irqmap[1]) - 1); - printf("\n"); - return 0; - } - - /* - * XXX should do RAMtest here - */ - - switch (sc->eeprom) { - case EEPROM_93C46: - if (rdp_gethwaddr_93c46(sc, sc->arpcom.ac_enaddr) == 0) { - printf("rdp%d: failed to find a valid hardware " - "address in EEPROM\n", - unit); - return 0; - } - break; - - case EEPROM_74S288: - rdp_gethwaddr_74s288(sc, sc->arpcom.ac_enaddr); - break; - } - - return lpt_control + 1; -} - -/* - * Install interface into kernel networking data structures - */ -static int -rdp_attach(struct isa_device *isa_dev) -{ - int unit = isa_dev->id_unit; - struct rdp_softc *sc = &rdp_softc[unit]; - struct ifnet *ifp = &sc->arpcom.ac_if; - - isa_dev->id_ointr = rdpintr; - - /* - * Reset interface - */ - rdp_stop(sc); - - if (!ifp->if_name) { - /* - * Initialize ifnet structure - */ - ifp->if_softc = sc; - ifp->if_unit = unit; - ifp->if_name = "rdp"; - ifp->if_output = ether_output; - ifp->if_start = rdp_start; - ifp->if_ioctl = rdp_ioctl; - ifp->if_watchdog = rdp_watchdog; - ifp->if_init = rdp_init; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - - /* - * Attach the interface - */ - if_attach(ifp); - ether_ifattach(ifp); - } - - /* - * Print additional info when attached - */ - printf("%s%d: RealTek RTL%s pocket ethernet, EEPROM %s, %s mode\n", - ifp->if_name, ifp->if_unit, - "8002", /* hook for 8012 */ - sc->eeprom == EEPROM_93C46? "93C46": "74S288", - sc->slow? "slow": "fast"); - printf("%s%d: address %6D\n", ifp->if_name, ifp->if_unit, - sc->arpcom.ac_enaddr, ":"); - - /* - * If BPF is in the kernel, call the attach for it - */ -#if NBPFILTER > 0 - bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif - return 1; -} - -/* - * Reset interface. - */ -static void -rdp_reset(struct ifnet *ifp) -{ - struct rdp_softc *sc = ifp->if_softc; - int s; - - s = splimp(); - - /* - * Stop interface and re-initialize. - */ - rdp_stop(sc); - rdp_init(sc); - - (void) splx(s); -} - -/* - * Take interface offline. - */ -static void -rdp_stop(struct rdp_softc *sc) -{ - - sc->txbusy = sc->txbusy = 0; - - /* disable printer interface interrupts */ - sc->irqenbit = 0; - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - outb(sc->baseaddr + lpt_data, 0xff); - - /* reset the RTL 8002 */ - WrNib(sc, CMR1 + HNib, MkHi(CMR1_RST)); - DELAY(100); -} - -/* - * Device timeout/watchdog routine. Entered if the device neglects to - * generate an interrupt after a transmit has been started on it. - */ -static void -rdp_watchdog(struct ifnet *ifp) -{ - - log(LOG_ERR, "rdp%d: device timeout\n", ifp->if_unit); - ifp->if_oerrors++; - - rdp_reset(ifp); -} - -/* - * Initialize device. - */ -static void -rdp_init(void *xsc) -{ - struct rdp_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - int i, s; - u_char reg; - - /* address not known */ - if (TAILQ_EMPTY(&ifp->if_addrhead)) - return; - - s = splimp(); - - ifp->if_timer = 0; - - /* program ethernet ID into the chip */ - for (i = 0, reg = IDR0; i < 6; i++, reg++) - WrByte(sc, reg, sc->arpcom.ac_enaddr[i]); - - /* set accept mode */ - WrNib(sc, CMR2 + HNib, - MkHi((ifp->if_flags & IFF_PROMISC)? CMR2_AM_ALL: CMR2_AM_PB)); - - /* enable tx and rx */ - WrNib(sc, CMR1 + HNib, MkHi(CMR1_TE | CMR1_RE)); - - /* allow interrupts to happen */ - WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV); - WrNib(sc, IMR, ISR_TOK | ISR_TER | ISR_ROK | ISR_RER); - WrNib(sc, IMR + HNib, MkHi(ISR_RBER)); - - /* allow IRQs to pass the parallel interface */ - sc->irqenbit = Ctrl_IRQEN; - outb(sc->baseaddr + lpt_control, sc->irqenbit + Ctrl_SelData); - - /* clear all flags */ - sc->txbusy = sc->txbuffered = 0; - - /* - * Set 'running' flag, and clear output active flag. - */ - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - /* - * ...and attempt to start output - */ - rdp_start(ifp); - - (void) splx(s); -} - -/* - * 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) - */ -static void -rdp_start(struct ifnet *ifp) -{ - struct rdp_softc *sc = ifp->if_softc; - struct mbuf *m; - int len; - -outloop: - - /* - * See if there is room to put another packet in the buffer. - */ - if (sc->txbuffered) { - /* - * No room. Indicate this to the outside world and exit. - */ - ifp->if_flags |= IFF_OACTIVE; - return; - } - IF_DEQUEUE(&ifp->if_snd, m); - if (m == 0) { - /* - * 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. - */ - ifp->if_flags &= ~IFF_OACTIVE; - return; - } - - /* - * Copy the mbuf chain into the transmit buffer - */ - - len = rdp_write_mbufs(sc, m); - if (len == 0) - goto outloop; - - /* ensure minimal valid ethernet length */ - len = max(len, (ETHER_MIN_LEN-ETHER_CRC_LEN)); - - /* - * Actually start the transceiver. Set a timeout in case the - * Tx interrupt never arrives. - */ - if (!sc->txbusy) { - WrNib(sc, TBCR1, len >> 8); - WrByte(sc, TBCR0, len & 0xff); - WrNib(sc, CMR1, CMR1_TRA); - sc->txbusy = 1; - ifp->if_timer = 2; - } else { - sc->txbuffered = 1; - sc->txsize = len; - } - - /* - * Tap off here if there is a bpf listener. - */ -#if NBPFILTER > 0 - if (ifp->if_bpf) { - bpf_mtap(ifp, m); - } -#endif - - m_freem(m); - - /* - * Loop back to the top to possibly buffer more packets - */ - goto outloop; -} - -/* - * Process an ioctl request. - */ -static int -rdp_ioctl(struct ifnet *ifp, IOCTL_CMD_T command, caddr_t data) -{ - struct rdp_softc *sc = ifp->if_softc; - int s, error = 0; - - s = splimp(); - - switch (command) { - - case SIOCSIFADDR: - case SIOCGIFADDR: - case SIOCSIFMTU: - error = ether_ioctl(ifp, command, data); - break; - - case SIOCSIFFLAGS: - /* - * If the interface is marked up and stopped, then start it. - * If it is marked down and running, then stop it. - */ - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) - rdp_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) { - rdp_stop(sc); - ifp->if_flags &= ~IFF_RUNNING; - } - } - -#if NBPFILTER > 0 - /* - * Promiscuous flag may have changed, propagage this - * to the NIC. - */ - if (ifp->if_flags & IFF_UP) - WrNib(sc, CMR2 + HNib, - MkHi((ifp->if_flags & IFF_PROMISC)? - CMR2_AM_ALL: CMR2_AM_PB)); - -#endif - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - /* - * Multicast list has changed; we don't support it. - */ - error = ENOTTY; - break; - - default: - error = EINVAL; - } - (void) splx(s); - return (error); -} - -/* - * External interrupt service routine. - */ -void -rdpintr(int unit) -{ - struct rdp_softc *sc = rdp_softc + unit; - struct ifnet *ifp = (struct ifnet *)sc; - u_char isr, tsr, rsr, colls; - - /* disable interrupts, so SD3 can be routed to the pin */ - sc->irqenbit = 0; - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - WrNib(sc, CMR2, CMR2_IRQINV); - /* - * loop until there are no more new interrupts - */ - for (;;) { - isr = RdNib(sc, ISR); - isr |= RdNib(sc, ISR + HNib) << 4; - RdEnd(sc, ISR + HNib); - - if (isr == 0) - break; -#if DEBUG & 4 - printf("rdp%d: ISR = %#x\n", unit, isr); -#endif - - /* - * Clear the pending interrupt bits. - */ - WrNib(sc, ISR, isr & 0x0f); - if (isr & 0xf0) - WrNib(sc, ISR + HNib, MkHi(isr)); - - /* - * Handle transmitter interrupts. - */ - if (isr & (ISR_TOK | ISR_TER)) { - tsr = RdNib(sc, TSR); - RdEnd(sc, TSR); -#if DEBUG & 4 - if (isr & ISR_TER) - printf("rdp%d: tsr %#x\n", unit, tsr); -#endif - if (tsr & TSR_TABT) - ifp->if_oerrors++; - else - /* - * Update total number of successfully - * transmitted packets. - */ - ifp->if_opackets++; - - if (tsr & TSR_COL) { - colls = RdNib(sc, COLR); - RdEnd(sc, COLR); - ifp->if_collisions += colls; - } - - /* - * reset tx busy and output active flags - */ - sc->txbusy = 0; - ifp->if_flags &= ~IFF_OACTIVE; - - /* - * If we had already queued up another packet, - * start sending it now. - */ - if (sc->txbuffered) { - WrNib(sc, TBCR1, sc->txsize >> 8); - WrByte(sc, TBCR0, sc->txsize & 0xff); - WrNib(sc, CMR1, CMR1_TRA); - sc->txbusy = 1; - sc->txbuffered = 0; - ifp->if_timer = 2; - } else { - /* - * clear watchdog timer - */ - ifp->if_timer = 0; - } - - } - - /* - * Handle receiver interrupts - */ - if (isr & (ISR_ROK | ISR_RER | ISR_RBER)) { - rsr = RdNib(sc, RSR); - rsr |= RdNib(sc, RSR + HNib) << 4; - RdEnd(sc, RSR + HNib); -#if DEBUG & 4 - if (isr & (ISR_RER | ISR_RBER)) - printf("rdp%d: rsr %#x\n", unit, rsr); -#endif - - if (rsr & (RSR_PUN | RSR_POV)) { - printf("rdp%d: rsr %#x, resetting\n", - unit, rsr); - rdp_reset(ifp); - break; - } - - if (rsr & RSR_BUFO) - /* - * CRC and FA errors are recorded in - * rdp_rint() on a per-packet basis - */ - ifp->if_ierrors++; - if (isr & (ISR_ROK | ISR_RER)) - rdp_rint(sc); - } - - /* - * If it looks like the transmitter can take more data, - * attempt to start output on the interface. This is done - * after handling the receiver to give the receiver priority. - */ - if ((ifp->if_flags & IFF_OACTIVE) == 0) - rdp_start(ifp); - - } - /* re-enable interrupts */ - WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV); - sc->irqenbit = Ctrl_IRQEN; - outb(sc->baseaddr + lpt_control, Ctrl_SelData + sc->irqenbit); -} - -/* - * Ethernet interface receiver interrupt. - */ -static void -rdp_rint(struct rdp_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct rdphdr rh; - u_short len; - size_t i; - u_char *packet_ptr, b, status; - int excessive_bad_pkts = 0; - - /* - * Fetch the packets from the NIC's buffer. - */ - for (;;) { - b = RdNib(sc, CMR1); - RdEnd(sc, CMR1); - - if (b & CMR1_BUFE) - /* no more packets */ - break; - - /* first, obtain the buffer header */ - - outb(sc->baseaddr + lpt_data, MAR + EOC); /* prepare addr */ - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead); - outb(sc->baseaddr + lpt_data, MAR + RdAddr + HNib); - - packet_ptr = (u_char *)&rh; - if (sc->slow) - for (i = 0; i < sizeof rh; i++, packet_ptr++) - *packet_ptr = RdByteA2(sc); - else - for (i = 0; i < sizeof rh; i++, packet_ptr++) - *packet_ptr = RdByteA1(sc); - - RdEnd(sc, MAR + HNib); - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - - len = rh.pktlen - ETHER_CRC_LEN; - status = rh.status; - - if ((status & (RSR_ROK | RSR_CRC | RSR_FA)) != RSR_ROK || - len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || - len < (ETHER_MIN_LEN - ETHER_CRC_LEN) || - len > MCLBYTES) { -#if DEBUG - printf("rdp%d: bad packet in buffer, " - "len %d, status %#x\n", - ifp->if_unit, (int)len, (int)status); -#endif - ifp->if_ierrors++; - /* rx jump packet */ - WrNib(sc, CMR1, CMR1_RDPAC); - if (++excessive_bad_pkts > 5) { - /* - * the chip seems to be stuck, we are - * probably seeing the same bad packet - * over and over again - */ -#if DEBUG - printf("rdp%d: resetting due to an " - "excessive number of bad packets\n", - ifp->if_unit); -#endif - rdp_reset(ifp); - return; - } - continue; - } - - /* - * Go get packet. - */ - excessive_bad_pkts = 0; - rdp_get_packet(sc, len); - ifp->if_ipackets++; - } -} - -/* - * Retreive packet from NIC memory and send to the next level up via - * ether_input(). If there is a BPF listener, give a copy to BPF, - * too. - */ -static void -rdp_get_packet(struct rdp_softc *sc, unsigned len) -{ - struct ether_header *eh; - struct mbuf *m; - u_char *packet_ptr; - size_t s; - - /* Allocate a header mbuf */ - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - return; - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - m->m_pkthdr.len = m->m_len = len; - - /* - * We always put the received packet in a single buffer - - * either with just an mbuf header or in a cluster attached - * to the header. The +2 is to compensate for the alignment - * fixup below. - */ - if ((len + 2) > MHLEN) { - /* Attach an mbuf cluster */ - MCLGET(m, M_DONTWAIT); - - /* Insist on getting a cluster */ - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - return; - } - } - - /* - * The +2 is to longword align the start of the real packet. - * This is important for NFS. - */ - m->m_data += 2; - eh = mtod(m, struct ether_header *); - - /* - * Get packet, including link layer address, from interface. - */ - outb(sc->baseaddr + lpt_control, Ctrl_LNibRead); - outb(sc->baseaddr + lpt_data, RdAddr + MAR); - - packet_ptr = (u_char *)eh; - if (sc->slow) - for (s = 0; s < len; s++, packet_ptr++) - *packet_ptr = RdByteA2(sc); - else - for (s = 0; s < len; s++, packet_ptr++) - *packet_ptr = RdByteA1(sc); - - RdEnd(sc, MAR + HNib); - outb(sc->baseaddr + lpt_control, Ctrl_SelData); - WrNib(sc, CMR1, CMR1_RDPAC); - -#if NBPFILTER > 0 - - /* - * Check if there's a BPF listener on this interface. If so, hand off - * the raw packet to bpf. - */ - if (sc->arpcom.ac_if.if_bpf) { - bpf_mtap(&sc->arpcom.ac_if, m); - - /* - * Note that the interface cannot be in promiscuous mode if - * there are no BPF listeners. And if we are in promiscuous - * mode, we have to check if this packet is really ours. - */ - if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) && - bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, - sizeof(eh->ether_dhost)) != 0) { - m_freem(m); - return; - } - } -#endif - - /* - * Remove link layer address. - */ - m->m_pkthdr.len = m->m_len = len - sizeof(struct ether_header); - m->m_data += sizeof(struct ether_header); - - ether_input(&sc->arpcom.ac_if, eh, m); - return; -} - -/* - * Write an mbuf chain to the NIC's tx buffer. - */ -static u_short -rdp_write_mbufs(struct rdp_softc *sc, struct mbuf *m) -{ - u_short total_len; - struct mbuf *mp; - u_char *dp, b; - int i; - - /* First, count up the total number of bytes to copy */ - for (total_len = 0, mp = m; mp; mp = mp->m_next) - total_len += mp->m_len; - - if (total_len == 0) - return 0; - - outb(sc->baseaddr + lpt_data, MAR | EOC); - - /* - * Transfer the mbuf chain to the NIC memory. - */ - if (sc->slow) { - /* writing the first byte is complicated */ - outb(sc->baseaddr + lpt_control, - Ctrl_LNibRead | sc->irqenbit); - outb(sc->baseaddr + lpt_data, MAR | WrAddr); - b = *(u_char *)m->m_data; - outb(sc->baseaddr + lpt_data, (b & 0x0f) | 0x40); - outb(sc->baseaddr + lpt_data, b & 0x0f); - outb(sc->baseaddr + lpt_data, b >> 4); - outb(sc->baseaddr + lpt_control, - Ctrl_HNibRead | sc->irqenbit); - /* advance the mbuf pointer */ - mp = m; - m->m_len--; - m->m_data++; - /* write the remaining bytes */ - while (m) { - for (i = 0, dp = (u_char *)m->m_data; - i < m->m_len; - i++, dp++) - WrByteALToDRAMA(sc, *dp); - m = m->m_next; - } - /* - * restore old mbuf in case we have to hand it off to - * BPF again - */ - m = mp; - m->m_len++; - m->m_data--; - - /* the RTL 8002 requires an even byte-count remote DMA */ - if (total_len & 1) - WrByteALToDRAMA(sc, 0); - } else { - outb(sc->baseaddr + lpt_data, MAR | WrAddr); - while (m) { - for (i = 0, dp = (u_char *)m->m_data; - i < m->m_len; - i++, dp++) - WrByteALToDRAM(sc, *dp); - m = m->m_next; - } - - /* the RTL 8002 requires an even byte-count remote DMA */ - if (total_len & 1) - WrByteALToDRAM(sc, 0); - } - - outb(sc->baseaddr + lpt_data, 0xff); - outb(sc->baseaddr + lpt_control, - Ctrl_HNibRead | Ctrl_SelData | sc->irqenbit); - - return total_len; -} - -/* - * Read the designated ethernet hardware address out of a 93C46 - * (serial) EEPROM. - * Note that the 93C46 uses 16-bit words in big-endian notation. - */ -static int -rdp_gethwaddr_93c46(struct rdp_softc *sc, u_char *etheraddr) -{ - int i, magic; - size_t j = 0; - u_short w; - - WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */ - - /* - * The original RealTek packet driver had the ethernet address - * starting at EEPROM address 0. Other vendors seem to have - * gone `creative' here -- while they didn't do anything else - * than changing a few strings in the entire driver, compared - * to the RealTek version, they also moved out the ethernet - * address to a different location in the EEPROM, so the - * original RealTek driver won't work correctly with them, and - * vice versa. Sounds pretty cool, eh? $@%&! - * - * Anyway, we walk through the EEPROM, until we find some - * allowable value based upon our table of IEEE OUI assignments. - */ - for (i = magic = 0; magic < 3 && i < 32; i++) { - /* read cmd (+ 6 bit address) */ - rdp_93c46_cmd(sc, 0x180 + i, 10); - w = rdp_93c46_read(sc); - switch (magic) { - case 0: - for (j = 0; - j < sizeof allowed_ouis / sizeof(u_short); - j++) - if (w == allowed_ouis[j]) { - etheraddr[0] = (w >> 8) & 0xff; - etheraddr[1] = w & 0xff; - magic++; - break; - } - break; - - case 1: - /* - * If the first two bytes have been 00:00, we - * discard the match iff the next two bytes - * are also 00:00, so we won't get fooled by - * an EEPROM that has been filled with zeros. - * This in theory would disallow 64 K of legal - * addresses assigned to Xerox, but it's - * almost certain that those addresses haven't - * been used for RTL80[01]2 chips anyway. - */ - if ((etheraddr[0] | etheraddr[1]) == 0 && w == 0) { - magic--; - break; - } - - etheraddr[2] = (w >> 8) & 0xff; - etheraddr[3] = w & 0xff; - magic++; - break; - - case 2: - etheraddr[4] = (w >> 8) & 0xff; - etheraddr[5] = w & 0xff; - magic++; - break; - } - } - - WrNib(sc, CMR2, CMR2_IRQINV); /* back to page 0 */ - - return magic == 3; -} - -/* - * Read the designated ethernet hardware address out of a 74S288 - * EEPROM. - * - * This is untested, since i haven't seen any adapter actually using - * a 74S288. In the RTL 8012, only the serial EEPROM (94C46) is - * supported anymore. - */ -static void -rdp_gethwaddr_74s288(struct rdp_softc *sc, u_char *etheraddr) -{ - int i; - u_char b; - - WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */ - - for (i = 0; i < 6; i++) { - WrNib(sc, PCMR, i & 0x0f); /* lower 4 bit of addr */ - WrNib(sc, PCMR + HNib, HNib + 4); /* upper 2 bit addr + /CS */ - WrNib(sc, PCMR + HNib, HNib); /* latch data now */ - b = RdNib(sc, PDR) & 0x0f; - b |= (RdNib(sc, PDR + HNib) & 0x0f) << 4; - etheraddr[i] = b; - } - - RdEnd(sc, PDR + HNib); - WrNib(sc, CMR2, CMR2_IRQINV); /* reselect page 0 */ -} - -/* - * Send nbits of data (starting with MSB) out to the 93c46 as a - * command. Assumes register page 1 has already been selected. - */ -static void -rdp_93c46_cmd(struct rdp_softc *sc, u_short data, unsigned nbits) -{ - u_short mask = 1 << (nbits - 1); - unsigned i; - u_char b; - -#if DEBUG & 2 - printf("rdp_93c46_cmd(): "); -#endif - for (i = 0; i < nbits; i++, mask >>= 1) { - b = HNib + PCMR_SK + PCMR_CS; - if (data & mask) - b += PCMR_DO; -#if DEBUG & 2 - printf("%d", b & 1); -#endif - WrNib(sc, PCMR + HNib, b); - DELAY(1); - WrNib(sc, PCMR + HNib, b & ~PCMR_SK); - DELAY(1); - } -#if DEBUG & 2 - printf("\n"); -#endif -} - -/* - * Read one word of data from the 93c46. Actually, we have to read - * 17 bits, and discard the very first bit. Assumes register page 1 - * to be selected as well. - */ -static u_short -rdp_93c46_read(struct rdp_softc *sc) -{ - u_short data = 0; - u_char b; - int i; - -#if DEBUG & 2 - printf("rdp_93c46_read(): "); -#endif - for (i = 0; i < 17; i++) { - WrNib(sc, PCMR + HNib, PCMR_SK + PCMR_CS + HNib); - DELAY(1); - WrNib(sc, PCMR + HNib, PCMR_CS + HNib); - DELAY(1); - b = RdNib(sc, PDR); - data <<= 1; - if (b & 1) - data |= 1; -#if DEBUG & 2 - printf("%d", b & 1); -#endif - RdEnd(sc, PDR); - DELAY(1); - } - -#if DEBUG & 2 - printf("\n"); -#endif - /* end of cycle */ - WrNib(sc, PCMR + HNib, PCMR_SK + HNib); - DELAY(1); - - return data; -} diff --git a/sys/i386/isa/if_rdpreg.h b/sys/i386/isa/if_rdpreg.h deleted file mode 100644 index cab679a4bd3eb..0000000000000 --- a/sys/i386/isa/if_rdpreg.h +++ /dev/null @@ -1,187 +0,0 @@ -#ifndef IF_RDPREG_H -#define IF_RDPREG_H 1 -/* - * Copyright (c) 1998 Joerg Wunsch - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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_rdpreg.h,v 1.1.1.1 1998/12/21 12:43:35 j Exp $ - */ - -/* - * Part of the definitions here has been copied over from the REDP - * packet driver's REDPPD.INC file. This provides us with the same - * set of acronyms as the packet driver is using. - * - * The packet driver had no copyright, and is believed to be in the - * public domain. The author seems to be someone who calls himself - * "Chiu", so that's the only acknowledgment i can give here. - * Supposedly the author was someone from RealTek. - */ - -/* - * We're hanging upon an LPT port, thus suck in the lpt defs as well. - */ -#include <i386/isa/lptreg.h> - -struct rdphdr { - /* RTL8002 header that is prepended to the actual packet */ - u_char unused2[2]; - u_short pktlen; - u_char status; /* copy of RSR for this packet */ - u_char unused3[3]; -}; - -/* - * - * 8 Data Modes are provided: - * - * +--------+---------------+-------------+ - * | Mode | Read | Write | - * +--------+---------------+-------------+ - * | 0 | LptCtrl | LptData | - * +--------+---------------+-------------+ - * | 1 | LptCtrl | LptCtrl | - * +--------+---------------+-------------+ - * | 2 | LptCtrl*2 | LptData | - * +--------+---------------+-------------+ - * | 3 | LptCtrl*2 | LptCtrl | - * +--------+---------------+-------------+ - * | 4 | LptData | LptData | - * +--------+---------------+-------------+ - * | 5 | LptData | LptCtrl | - * +--------+---------------+-------------+ - * | 6 | LptData*2 | LptData | - * +--------+---------------+-------------+ - * | 7 | LptData*2 | LptCtrl | - * +--------+---------------+-------------+ - * - * Right now, this driver only implements mode 0 (which ought to work - * on any standard parallel interface). - * - */ - -/* - * Page 0 of EPLC registers - */ -#define IDR0 0x00 /* Ethernet ID register (R/W) */ -#define IDR1 0x01 -#define IDR2 0x02 -#define IDR3 0x03 -#define IDR4 0x04 -#define IDR5 0x05 -#define TBCR0 0x06 /* transmit byte count (W), 11 bits valid */ -#define TBCR1 0x07 -#define TSR 0x08 /* transmit status (R), cleared upon next tx */ -# define TSR_TOK 1 /* transmit OK */ -# define TSR_TABT 2 /* transmit aborted (excessive collisions) */ -# define TSR_COL 4 /* collision detected */ -# define TSR_CDH 8 /* CD heartbeat detected */ -#define RSR 0x09 /* - * receiver status (R), cleared upon next - * received packet (but stored in rx buffer - * header anyway) - */ -# define RSR_ROK 1 /* receive OK */ -# define RSR_CRC 2 /* CRC error */ -# define RSR_FA 4 /* frame alignment error (not multiple of 8) */ -# define RSR_BUFO 0x10 /* rx buffer overflow, packet discarded */ -# define RSR_PUN 0x20 /* packet count underflow (jump command issued - * but rx buffer was empty) */ -# define RSR_POV 0x40 /* packet count overflow (more than 254 (?) - * packets still in buffer) */ -#define ISR 0x0A /* interrupt status register (R), writing - * clears the written bits */ -# define ISR_TOK 1 /* transmission OK (~ TSR_TOK) */ -# define ISR_TER 2 /* transmitter error (~ TSR_TABT) */ -# define ISR_ROK 4 /* receive OK (~ RSR_ROK) */ -# define ISR_RER 8 /* receiver error (~ RSR_CRC|RSR_FA) */ -# define ISR_RBER 0x10 /* rx buffer overflow (POV|PUN|BUFO) */ -#define IMR 0x0B /* interrupt mask register (R/W), bit as ISR */ -#define CMR1 0x0C /* command register 1 (R/W) */ -# define CMR1_BUFE 1 /* (R) rx buffer empty */ -# define CMR1_IRQ 2 /* (R) interrupt request */ -# define CMR1_TRA 4 /* (R) transmission in progress */ - /* (W) transmit start */ -# define CMR1_TE 0x10 /* (R/W) transmitter enable */ -# define CMR1_RE 0x20 /* (R/W) receiver enable */ -# define CMR1_RST 0x40 /* (R/W) reset; sticks until reset completed */ -# define CMR1_RDPAC 1 /* (W) `rx jump packet', prepare for reading - * next packet from ring buffer */ -# define CMR1_WRPAC 2 /* (W) `tx jump packet', packet in tx buffer - * is complete and can be sent */ -# define CMR1_RETX 8 /* (W) retransmit (must be accomp'ed by TRA) */ -# define CMR1_MUX 0x80 /* (W) RTL8012: tell the printer MUX to - * connect the output pins to the host */ -#define CMR2 0x0D /* command register 2 (R/W) */ -# define CMR2_IRQOUT 1 /* interrupt signal output enabled */ -# define CMR2_RAMTST 2 /* enable RAM test */ -# define CMR2_PAGE 4 /* select register page #1 */ -# define CMR2_IRQINV 8 /* make active IRQ `low' */ -# define CMR2_AMbits 0x30 /* address mode bits: */ -# define CMR2_AM_NONE 0x00 /* 0: accept nothing */ -# define CMR2_AM_PHYS 0x10 /* 1: only physical addr */ -# define CMR2_AM_PB 0x20 /* 2: phys + broadcast */ -# define CMR2_AM_ALL 0x30 /* 3: promiscuous */ -# define CMR2_LBK 0x40 /* enable loopback */ -# define CMR2_SER 0x80 /* save error packet */ -#define MAR 0x0E /* memory access register (?), used for - * remote DMA to the 8002's buffer */ -#define PNR TBCR0 /* received packet number (R) */ -#define COLR TBCR1 /* collision count (R) (4 bit valid) */ - -/* - * Page 1 of EPLC registers -- EEPROM control - */ -#define PCMR TBCR0 /* port command register */ -/* bits for 93C46 control -- add HNib */ -#define PCMR_SK 0x04 /* serial clock for EEPROM */ -#define PCMR_CS 0x02 /* chip select for EEPROM */ -#define PCMR_DO 0x01 /* DI to EEPROM */ - -/* EEPROM data, nibbles for 74S288, bits for 93C46 */ -#define PDR TBCR1 /* DO from EEPROM, only bit 0 valid for - * serial EEPROM */ - -/* - * The following definitionss define remote DMA command through LptCtrl - */ -#define ATFD 3 /* ATFD bit in Lpt's Control register */ - /* -> ATFD bit is added for Xircom's MUX */ -#define Ctrl_LNibRead (0x08+ATFD) /* specify low nibble */ -#define Ctrl_HNibRead (0+ATFD) /* specify high nibble */ -#define Ctrl_SelData (0x04+ATFD) /* not through LptCtrl but through */ - /* LptData */ -#define Ctrl_IRQEN 0x10 /* set IRQEN of lpt control register */ - -/* Here define constants to construct the required read/write commands */ -#define WrAddr 0x40 /* set address of EPLC write register */ -#define RdAddr 0x0C0 /* set address of EPLC read register */ -#define EOR 0x20 /* ORed to make 'end of read',set CSB=1 */ -#define EOW 0x0E0 /* end of write, R/WB=A/DB=CSB=1 */ -#define EOC 0x0E0 /* End Of r/w Command, R/WB=A/DB=CSB=1 */ -#define HNib 0x10 - -#define MkHi(value) (((value) >> 4) | HNib) - -#endif /* IF_RDPREG_H */ diff --git a/sys/i386/isa/if_sr.c b/sys/i386/isa/if_sr.c index b37e5633f387b..236bb42f0d1d4 100644 --- a/sys/i386/isa/if_sr.c +++ b/sys/i386/isa/if_sr.c @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_sr.c,v 1.20 1999/01/18 21:23:47 julian Exp $ + * $Id: if_sr.c,v 1.14 1998/06/17 13:54:56 bde Exp $ */ /* @@ -269,7 +269,6 @@ struct sr_hardc *srattach_pci(int unit, vm_offset_t plx_vaddr, vm_offset_t sca_vaddr); void srintr_hc(struct sr_hardc *hc); -static ointhand2_t srintr; static int srattach(struct sr_hardc *hc); static void sr_xmit(struct sr_softc *sc); static void srstart(struct ifnet *ifp); @@ -572,8 +571,6 @@ srattach_isa(struct isa_device *id) u_char mar; struct sr_hardc *hc = &sr_hardc[id->id_unit]; - id->id_ointr = srintr; - outb(hc->iobase + SR_PCR, inb(hc->iobase + SR_PCR) | SR_PCR_SCARUN); outb(hc->iobase + SR_PSR, inb(hc->iobase + SR_PSR) | SR_PSR_EN_SCA_DMA); outb(hc->iobase + SR_MCR, @@ -860,26 +857,24 @@ srattach(struct sr_hardc *hc) } /* - * N2 Interrupt Service Routine. - * Get the ISA interrupts. - * + * N2 Interrupt Service Routine + * * First figure out which SCA gave the interrupt. - * + * Process it. + * See if there is other interrupts pending. + * Repeat until there no interrupts remain. */ -static void +void srintr(int unit) -{ - struct sr_hardc *hc; +{ + struct sr_hardc *hc; hc = &sr_hardc[unit]; srintr_hc(hc); - return; + return; } -/* - * PCI interrupts come straight here - */ void srintr_hc(struct sr_hardc *hc) { @@ -1315,6 +1310,13 @@ srioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->ifsppp.pp_flags |= PP_KEEPALIVE; sppp_attach(&sc->ifsppp.pp_if); + /* + * Shortcut the sppp tls/tlf actions to + * up/down events since our lower layer is + * always ready. + */ + sc->ifsppp.pp_tls = sc->ifsppp.pp_up; + sc->ifsppp.pp_tlf = sc->ifsppp.pp_down; } sc->attached = sc->protocol; @@ -1499,6 +1501,13 @@ sr_up(struct sr_softc *sc) sc->ifsppp.pp_flags |= PP_KEEPALIVE; sppp_attach(&sc->ifsppp.pp_if); + /* + * Shortcut the sppp tls/tlf actions to + * up/down events since our lower layer is + * always ready. + */ + sc->ifsppp.pp_tls = sc->ifsppp.pp_up; + sc->ifsppp.pp_tlf = sc->ifsppp.pp_down; } sc->attached = sc->protocol; diff --git a/sys/i386/isa/if_wl.c b/sys/i386/isa/if_wl.c index 42fc0f91bf82b..66dbffd407867 100644 --- a/sys/i386/isa/if_wl.c +++ b/sys/i386/isa/if_wl.c @@ -1,4 +1,4 @@ -/* $Id: if_wl.c,v 1.19 1998/12/09 03:30:51 eivind Exp $ */ +/* $Id: if_wl.c,v 1.14 1998/08/20 05:49:59 msmith Exp $ */ /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -81,7 +81,7 @@ * * sample config: * - * device wl0 at isa? port 0x300 net irq ? + * device wl0 at isa? port 0x300 net irq ? vector wlintr * * Ifdefs: * 1. WLDEBUG. (off) - if turned on enables IFF_DEBUG set via ifconfig debug @@ -302,7 +302,6 @@ static void wlstart(struct ifnet *ifp); static void wlinit(void *xsc); static int wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data); static timeout_t wlwatchdog; -static ointhand2_t wlintr; static void wlxmt(int unt, struct mbuf *m); static int wldiag(int unt); static int wlconfig(int unit); @@ -311,6 +310,7 @@ static void wlmmcstat(int unit); static u_short wlbldru(int unit); static u_short wlmmcread(u_int base, u_short reg); static void wlinitmmc(int unit); +static void wlsetirq(int base, int irq); static int wlhwrst(int unit); static void wlrustrt(int unit); static void wlbldcu(int unit); @@ -331,7 +331,7 @@ static void wl_cache_store(int, int, struct ether_header *, struct mbuf *); static void wl_cache_zero(int unit); #endif #ifdef MULTICAST -# if defined(__FreeBSD__) && __FreeBSD_version < 300000 +# if __FreeBSD < 3 static int check_allmulti(int unit); # endif #endif @@ -364,6 +364,7 @@ wlprobe(struct isa_device *id) { struct wl_softc *sc = &wl_softc[id->id_unit]; register short base = id->id_iobase; + int unit = id->id_unit; char *str = "wl%d: board out of range [0..%d]\n"; u_char inbuf[100]; unsigned long oldpri; @@ -442,7 +443,6 @@ wlattach(struct isa_device *id) #ifdef WLDEBUG printf("wlattach: base %x, unit %d\n", base, unit); #endif - id->id_ointr = wlintr; sc->base = base; sc->unit = unit; sc->flags = 0; @@ -494,7 +494,7 @@ wlattach(struct isa_device *id) #endif #if MULTICAST ifp->if_flags |= IFF_MULTICAST; -#endif /* MULTICAST */ +#endif MULTICAST ifp->if_name = "wl"; ifp->if_unit = unit; ifp->if_init = wlinit; @@ -680,7 +680,7 @@ wlinit(void *xsc) if (sc->wl_if.if_flags & IFF_DEBUG) printf("wl%d: entered wlinit()\n",sc->unit); #endif -#if defined(__FreeBSD__) && __FreeBSD_version >= 300000 +#if __FreeBSD__ >= 3 if (ifp->if_addrhead.tqh_first == (struct ifaddr *)0) { #else if (ifp->if_addrlist == (struct ifaddr *)0) { @@ -721,6 +721,8 @@ static int wlhwrst(int unit) { register struct wl_softc *sc = WLSOFTC(unit); + int i; + short base = sc->base; #ifdef WLDEBUG if (sc->wl_if.if_flags & IFF_DEBUG) @@ -736,7 +738,7 @@ wlhwrst(int unit) #ifdef WLDEBUG if (sc->wl_if.if_flags & IFF_DEBUG) wlmmcstat(unit); /* Display MMC registers */ -#endif /* WLDEBUG */ +#endif WLDEBUG wlbldcu(unit); /* set up command unit structures */ if (wldiag(unit) == 0) @@ -1167,6 +1169,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) short base = sc->base; short mode = 0; int opri, error = 0; + u_short tmp; struct proc *p = curproc; /* XXX */ int irq, irqval, i, isroot, size; caddr_t up; @@ -1254,7 +1257,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCADDMULTI: case SIOCDELMULTI: -#if defined(__FreeBSD__) && __FreeBSD_version < 300000 +#if __FreeBSD__ < 3 if (cmd == SIOCADDMULTI) { error = ether_addmulti(ifr, &sc->wl_ac); } @@ -1284,7 +1287,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } #endif break; -#endif /* MULTICAST */ +#endif MULTICAST /* DEVICE SPECIFIC */ @@ -1469,13 +1472,16 @@ wlwatchdog(void *vsc) * output : either a packet is received, or a packet is transfered * */ -static void +void wlintr(unit) int unit; { register struct wl_softc *sc = &wl_softc[unit]; + scb_t scb; + ac_t cb; short base = sc->base; - int ac_status; + int next, x, opri; + int i, ac_status; u_short int_type, int_type1; #ifdef WLDEBUG @@ -1563,7 +1569,7 @@ int unit; if (ac_status & TC_CARRIER) { printf("wl%d: no carrier\n", unit); } -#endif /* notdef */ +#endif notdef if (ac_status & TC_CLS) { printf("wl%d: no CTS\n", unit); } @@ -1725,7 +1731,7 @@ wlrequeue(int unit, u_short fd_p) #ifdef WLDEBUG static int xmt_debug = 0; -#endif /* WLDEBUG */ +#endif WLDEBUG /* * wlxmt: @@ -1775,7 +1781,7 @@ wlxmt(int unit, struct mbuf *m) printf("ether type %x\n", eh_p->ether_type); } } -#endif /* WLDEBUG */ +#endif WLDEBUG outw(PIOR0(base), OFFSET_TBD); outw(PIOP0(base), 0); /* act_count */ outw(PIOR1(base), OFFSET_TBD + 4); @@ -1830,13 +1836,13 @@ wlxmt(int unit, struct mbuf *m) if (sc->wl_if.if_flags & IFF_DEBUG) if (xmt_debug) printf("mbuf+ L%d @%p ", count, (void *)mb_p); -#endif /* WLDEBUG */ +#endif WLDEBUG } #ifdef WLDEBUG if (sc->wl_if.if_flags & IFF_DEBUG) if (xmt_debug) printf("CLEN = %d\n", clen); -#endif /* WLDEBUG */ +#endif WLDEBUG outw(PIOR0(base), tbd_p); if (clen < ETHERMIN) { outw(PIOP0(base), inw(PIOP0(base)) + ETHERMIN - clen); @@ -1854,7 +1860,7 @@ wlxmt(int unit, struct mbuf *m) printf("\n"); } } -#endif /* WLDEBUG */ +#endif WLDEBUG outw(PIOR0(base), OFFSET_SCB + 2); /* address of scb_command */ /* @@ -2031,7 +2037,7 @@ wlconfig(int unit) short base = sc->base; #if MULTICAST -#if defined(__FreeBSD__) && __FreeBSD_version >= 300000 +#if __FreeBSD__ >= 3 struct ifmultiaddr *ifma; u_char *addrp; #else @@ -2039,7 +2045,7 @@ wlconfig(int unit) struct ether_multistep step; #endif int cnt = 0; -#endif /* MULTICAST */ +#endif MULTICAST #ifdef WLDEBUG if (sc->wl_if.if_flags & IFF_DEBUG) @@ -2100,7 +2106,7 @@ wlconfig(int unit) outw(PIOP1(base), 0); /* ac_status */ outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */ outw(PIOR1(base), OFFSET_CU + 8); -#if defined(__FreeBSD__) && __FreeBSD_version >= 300000 +#if __FreeBSD__ >= 3 for (ifma = sc->wl_if.if_multiaddrs.lh_first; ifma; ifma = ifma->ifma_link.le_next) { if (ifma->ifma_addr->sa_family != AF_LINK) @@ -2151,7 +2157,7 @@ printf("mcast_addr[%d,%d,%d] %x %x %x %x %x %x\n", lo, hi, cnt, outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE); if(wlcmd(unit, "config()-mcaddress") == 0) return 0; -#endif /* MULTICAST */ +#endif MULTICAST outw(PIOR1(base), OFFSET_CU); outw(PIOP1(base), 0); /* ac_status */ @@ -2320,6 +2326,7 @@ static void wlsftwsleaze(u_short *countp, u_char **mb_pp, struct mbuf **tm_pp, int unit) { struct mbuf *tm_p = *tm_pp; + u_char *mb_p = *mb_pp; u_short count = 0; u_char *cp = (u_char *) t_packet; int len; @@ -2378,6 +2385,10 @@ wlmmcread(u_int base, u_short reg) static void getsnr(int unit) { + register struct wl_softc *sc = WLSOFTC(unit); + short base = sc->base; + register int s; + MMC_WRITE(MMC_FREEZE,1); /* * SNR retrieval procedure : @@ -2549,7 +2560,7 @@ static void wl_cache_store (int unit, int base, struct ether_header *eh, struct mbuf *m) { - struct ip *ip = NULL; /* Avoid GCC warning */ + struct ip *ip; int i; int signal, silence; int w_insertcache; /* computed index for cache entry storage */ @@ -2671,7 +2682,7 @@ void wl_cache_store (int unit, int base, struct ether_header *eh, */ #ifdef MULTICAST -#if defined(__FreeBSD__) && __FreeBSD_version < 300000 /* not required */ +#if __FreeBSD__ < 3 /* not required */ static int check_allmulti(int unit) { diff --git a/sys/i386/isa/if_wl.h b/sys/i386/isa/if_wl.h index 70d5d30cdb661..90801c38f8ab9 100644 --- a/sys/i386/isa/if_wl.h +++ b/sys/i386/isa/if_wl.h @@ -116,5 +116,5 @@ typedef struct { outw(MMCR(WLSOFTC(unit)->base), \ (u_short)(((u_short)(val) << 8) | ((cmd) << 1) | 1)) -#endif /* _IF_WL_H */ +#endif _IF_WL_H diff --git a/sys/i386/isa/if_ze.c b/sys/i386/isa/if_ze.c index 3000e89eb8c95..2821470173de9 100644 --- a/sys/i386/isa/if_ze.c +++ b/sys/i386/isa/if_ze.c @@ -47,7 +47,7 @@ */ /* - * $Id: if_ze.c,v 1.55 1998/10/22 05:58:39 bde Exp $ + * $Id: if_ze.c,v 1.53 1998/06/07 17:10:39 dfr Exp $ */ /* XXX don't mix different PCCARD support code. */ @@ -168,7 +168,6 @@ static void ze_init __P((int unit)); static __inline void ze_xmit __P((struct ifnet *ifp)); static void ze_start __P((struct ifnet *ifp)); static __inline void ze_rint __P((int unit)); -static ointhand2_t zeintr; static int ze_ioctl __P((struct ifnet *ifp, u_long command, caddr_t data)); static void ze_get_packet __P((struct ze_softc *sc, char *buf, int len)); static __inline char *ze_ring_copy __P((struct ze_softc *sc, char *src, @@ -587,8 +586,6 @@ ze_attach(isa_dev) struct ifnet *ifp = &sc->arpcom.ac_if; int pl; - isa_dev->id_ointr = zeintr; - /* PCMCIA card can be offlined. Reconfiguration is required */ if (isa_dev->id_reconfig) { ze_reset(isa_dev->id_unit); @@ -726,9 +723,7 @@ ze_watchdog(ifp) #if 1 struct ze_softc *sc = (struct ze_softc *)ifp; u_char isr, imr; -#ifndef SMP u_int imask; -#endif if(!(ifp->if_flags & IFF_UP)) return; @@ -1150,7 +1145,7 @@ ze_rint(unit) /* * Ethernet interface interrupt processor */ -static void +void zeintr(unit) int unit; { diff --git a/sys/i386/isa/if_zp.c b/sys/i386/isa/if_zp.c index 11e562c8b6a92..b2e9ad8d4626b 100644 --- a/sys/i386/isa/if_zp.c +++ b/sys/i386/isa/if_zp.c @@ -34,7 +34,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * From: if_ep.c,v 1.9 1994/01/25 10:46:29 deraadt Exp $ - * $Id: if_zp.c,v 1.48 1998/06/07 17:10:40 dfr Exp $ + * $Id: if_zp.c,v 1.47 1998/05/26 02:28:18 jmb Exp $ */ /*- * TODO: @@ -198,7 +198,6 @@ static int zpioctl __P((struct ifnet * ifp, u_long, caddr_t)); static u_short read_eeprom_data __P((int, int)); static void zpinit __P((int)); -static ointhand2_t zpintr; static void zpmbuffill __P((void *)); static void zpmbufempty __P((struct zp_softc *)); static void zpread __P((struct zp_softc *)); @@ -485,8 +484,6 @@ zpattach(isa_dev) u_short i; int pl; - isa_dev->id_ointr = zpintr; - /* PCMCIA card can be offlined. Reconfiguration is required */ if (isa_dev->id_reconfig) { if (!isa_dev->id_alive && sc->last_alive) { @@ -777,7 +774,7 @@ readcheck: } goto startagain; } -static void +void zpintr(unit) int unit; { diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c index 0254195f5ddb1..3f891f2af315d 100644 --- a/sys/i386/isa/intr_machdep.c +++ b/sys/i386/isa/intr_machdep.c @@ -34,15 +34,12 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.15 1998/12/04 22:54:46 archie Exp $ + * $Id: intr_machdep.c,v 1.13 1998/06/18 16:08:46 bde Exp $ */ #include "opt_auto_eoi.h" #include <sys/param.h> -#ifndef SMP -#include <machine/lock.h> -#endif #include <sys/systm.h> #include <sys/syslog.h> #include <machine/ipl.h> @@ -328,7 +325,7 @@ find_device_id(int irq) char *cp; int free_id, id; - snprintf(buf, sizeof(buf), "pci irq%d", irq); + sprintf(buf, "pci irq%d", irq); cp = intrnames; /* default to 0, which corresponds to clk0 */ free_id = 0; diff --git a/sys/i386/isa/ipl_funcs.c b/sys/i386/isa/ipl_funcs.c index 38b1945f7ac01..cd4628cad2359 100644 --- a/sys/i386/isa/ipl_funcs.c +++ b/sys/i386/isa/ipl_funcs.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ipl_funcs.c,v 1.13 1998/02/01 22:04:58 bde Exp $ + * $Id: ipl_funcs.c,v 1.12 1998/01/15 07:34:01 gibbs Exp $ */ #include <sys/types.h> @@ -379,10 +379,9 @@ splx(unsigned ipl) intrmask_t splq(intrmask_t mask) { - intrmask_t tmp; -#ifdef INTR_SPL - intrmask_t tmp2; + intrmask_t tmp, tmp2; +#ifdef INTR_SPL for (;;) { IFCPL_LOCK(); tmp = tmp2 = cpl; diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c index 177024d17d6b1..eb280936bbfc6 100644 --- a/sys/i386/isa/isa.c +++ b/sys/i386/isa/isa.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.116 1998/10/22 05:58:39 bde Exp $ + * $Id: isa.c,v 1.114 1998/10/12 13:12:45 bde Exp $ */ /* @@ -513,7 +513,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 != @@ -557,10 +557,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 @@ -597,7 +594,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/i386/isa/isa.h b/sys/i386/isa/isa.h index ea25f20604ee3..6ec3ae276d411 100644 --- a/sys/i386/isa/isa.h +++ b/sys/i386/isa/isa.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.h 5.7 (Berkeley) 5/9/91 - * $Id: isa.h,v 1.21 1997/02/22 09:36:41 peter Exp $ + * $Id$ */ #ifdef PC98 @@ -147,7 +147,7 @@ #define IO_ISASIZES #define IO_ASCSIZE 5 /* AmiScan GI1904-based hand scanner */ -#define IO_CGASIZE 12 /* CGA controllers */ +#define IO_CGASIZE 16 /* CGA controllers */ #define IO_COMSIZE 8 /* 8250, 16x50 com controllers */ #define IO_DMASIZE 16 /* 8237 DMA controllers */ #define IO_DPGSIZE 32 /* 74LS612 DMA page registers */ @@ -158,10 +158,9 @@ #define IO_ICUSIZE 16 /* 8259A interrupt controllers */ #define IO_KBDSIZE 16 /* 8042 Keyboard controllers */ #define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */ -#define IO_MDASIZE 12 /* Monochrome display controllers */ +#define IO_MDASIZE 16 /* Monochrome display controllers */ #define IO_NPXSIZE 16 /* 80387/80487 NPX registers */ #define IO_PMPSIZE 2 /* 82347 power management peripheral */ -#define IO_PSMSIZE 5 /* 8042 Keyboard controllers */ #define IO_RTCSIZE 16 /* CMOS real time clock, NMI control */ #define IO_TMRSIZE 16 /* 8253 programmable timers */ #define IO_VGASIZE 16 /* VGA controllers */ diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h index d23f701914e62..17aad1dd263d5 100644 --- a/sys/i386/isa/isa_device.h +++ b/sys/i386/isa/isa_device.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91 - * $Id: isa_device.h,v 1.56 1998/10/22 05:58:39 bde Exp $ + * $Id: isa_device.h,v 1.54 1998/09/15 10:04:08 gibbs Exp $ */ #ifndef _I386_ISA_ISA_DEVICE_H_ @@ -41,8 +41,6 @@ * ISA Bus Autoconfiguration */ -typedef void ointhand2_t __P((int unit)); - /* * Per device structure. * @@ -59,12 +57,7 @@ struct isa_device { int id_drq; /* DMA request */ caddr_t id_maddr; /* physical i/o memory address on bus (if any)*/ int id_msize; /* size of i/o memory */ - union { - inthand2_t *id_i; - ointhand2_t *id_oi; - } id_iu; /* interrupt interface routine */ -#define id_intr id_iu.id_i -#define id_ointr id_iu.id_oi + inthand2_t *id_intr; /* interrupt interface routine */ int id_unit; /* unit number */ int id_flags; /* flags */ int id_scsiid; /* scsi id if needed */ @@ -130,6 +123,76 @@ int isa_dmastatus __P((int chan)); int isa_dmastop __P((int chan)); void reconfig_isadev __P((struct isa_device *isdp, u_int *mp)); +typedef void ointhand2_t __P((int unit)); + +/* + * The "old" interrupt handlers really have type ointhand2_t although they + * appear to be declared as having type inthand2_t. However, if this + * header is included by ioconf.c, pretend that the handlers really have + * type inthand_t. Assume that `C' is defined only by ioconf.c. + */ +#ifndef C +#define inthand2_t ointhand2_t +#endif + +inthand2_t adintr; +inthand2_t ahaintr; +inthand2_t aicintr; +inthand2_t alogintr; +inthand2_t arintr; +inthand2_t ascintr; +#ifdef PC98 +inthand2_t bsintr; +#endif +inthand2_t csintr; +inthand2_t cxintr; +inthand2_t cyintr; +inthand2_t edintr; +inthand2_t egintr; +inthand2_t elintr; +inthand2_t epintr; +inthand2_t exintr; +inthand2_t fdintr; +inthand2_t feintr; +inthand2_t gusintr; +inthand2_t ieintr; +inthand2_t labpcintr; +inthand2_t le_intr; +inthand2_t lncintr; +inthand2_t loranintr; +inthand2_t lptintr; +inthand2_t m6850intr; +inthand2_t mcdintr; +inthand2_t mseintr; +inthand2_t ncaintr; +inthand2_t npxintr; +inthand2_t pasintr; +inthand2_t pcmintr; +inthand2_t pcrint; +inthand2_t ppcintr; +inthand2_t pcfintr; +inthand2_t psmintr; +inthand2_t rcintr; +inthand2_t sbintr; +inthand2_t scintr; +inthand2_t seaintr; +inthand2_t siointr; +inthand2_t sndintr; +inthand2_t spigintr; +inthand2_t srintr; +inthand2_t sscapeintr; +inthand2_t stlintr; +inthand2_t twintr; +inthand2_t uhaintr; +inthand2_t wdintr; +inthand2_t wdsintr; +inthand2_t wlintr; +inthand2_t wtintr; +inthand2_t zeintr; +inthand2_t zpintr; + +#undef inthand2_t + #endif /* KERNEL */ #endif /* !_I386_ISA_ISA_DEVICE_H_ */ diff --git a/sys/i386/isa/istallion.c b/sys/i386/isa/istallion.c index 51db908f9780c..d0d172d669863 100644 --- a/sys/i386/isa/istallion.c +++ b/sys/i386/isa/istallion.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: istallion.c,v 1.22 1998/08/23 09:57:09 bde Exp $ + * $Id: istallion.c,v 1.21 1998/08/23 08:26:40 bde Exp $ */ /*****************************************************************************/ @@ -540,6 +540,7 @@ struct tty *stlidevtotty(dev_t dev); * Internal function prototypes. */ static stliport_t *stli_dev2port(dev_t dev); +static int stli_chksharemem(void); static int stli_isaprobe(struct isa_device *idp); static int stli_eisaprobe(struct isa_device *idp); static int stli_mcaprobe(struct isa_device *idp); @@ -3547,7 +3548,6 @@ static int stli_brdattach(stlibrd_t *brdp) * FIX: need to start this optimization somewhere... */ -#ifdef notdef static int stli_chksharemem() { stlibrd_t *brdp, *nxtbrdp; @@ -3597,7 +3597,6 @@ static int stli_chksharemem() return(0); } -#endif /* notdef */ /*****************************************************************************/ diff --git a/sys/i386/isa/kbdio.c b/sys/i386/isa/kbdio.c new file mode 100644 index 0000000000000..71cde28278e16 --- /dev/null +++ b/sys/i386/isa/kbdio.c @@ -0,0 +1,1037 @@ +/*- + * Copyright (c) 1996 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: kbdio.c,v 1.12 1998/02/13 07:09:38 bde Exp $ + */ + +#include "sc.h" +#include "vt.h" +#include "psm.h" +#include "opt_kbdio.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/syslog.h> +#include <machine/clock.h> +#include <i386/isa/kbdio.h> + +/* + * driver specific options: the following options may be set by + * `options' statements in the kernel configuration file. + */ + +/* 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 */ +#ifdef PC98 +#define KBDC_DELAYTIME 37 +#define KBDD_DELAYTIME 37 +#else +#define KBDC_DELAYTIME 20 +#define KBDD_DELAYTIME 7 +#endif + +/* debug option */ +#ifndef KBDIO_DEBUG +#define KBDIO_DEBUG 0 +#endif + +/* end of driver specific options */ + +/* constants */ + +#define NKBDC MAX(MAX(NSC, NVT), NPSM) +#define KBDQ_BUFSIZE 32 + +/* macros */ + +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +#define kbdcp(p) ((struct kbdc_softc *)(p)) +#define nextq(i) (((i) + 1) % KBDQ_BUFSIZE) +#define availq(q) ((q)->head != (q)->tail) +#if KBDIO_DEBUG >= 2 +#define emptyq(q) ((q)->tail = (q)->head = (q)->qcount = 0) +#else +#define emptyq(q) ((q)->tail = (q)->head = 0) +#endif + +/* local variables */ + +typedef struct _kqueue { + int head; + int tail; + unsigned char q[KBDQ_BUFSIZE]; +#if KBDIO_DEBUG >= 2 + int call_count; + int qcount; + int max_qcount; +#endif +} kqueue; + +struct kbdc_softc { + int port; /* base port address */ + int command_byte; /* current command byte value */ + int command_mask; /* command byte mask bits for kbd/aux devices */ + int lock; /* FIXME: XXX not quite a semaphore... */ + kqueue kbd; /* keyboard data queue */ + kqueue aux; /* auxiliary data queue */ +}; + +static struct kbdc_softc kbdc_softc[NKBDC] = { { 0 }, }; + +static int verbose = KBDIO_DEBUG; + +/* function prototypes */ + +#ifndef PC98 +static int addq(kqueue *q, int c); +static int removeq(kqueue *q); +static int wait_while_controller_busy(struct kbdc_softc *kbdc); +static int wait_for_data(struct kbdc_softc *kbdc); +#endif +static int wait_for_kbd_data(struct kbdc_softc *kbdc); +#ifndef PC98 +static int wait_for_kbd_ack(struct kbdc_softc *kbdc); +static int wait_for_aux_data(struct kbdc_softc *kbdc); +static int wait_for_aux_ack(struct kbdc_softc *kbdc); +#endif + +/* associate a port number with a KBDC */ + +KBDC +kbdc_open(int port) +{ +#ifdef PC98 + if (NKBDC) { + /* 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 */ +#else + int s; + int i; + + s = spltty(); + for (i = 0; i < NKBDC; ++i) { + if (kbdc_softc[i].port == port) { + splx(s); + return (KBDC) &kbdc_softc[i]; + } + if (kbdc_softc[i].port <= 0) { + kbdc_softc[i].port = port; + kbdc_softc[i].command_byte = -1; + kbdc_softc[i].command_mask = 0; + kbdc_softc[i].lock = FALSE; + kbdc_softc[i].kbd.head = kbdc_softc[i].kbd.tail = 0; + kbdc_softc[i].aux.head = kbdc_softc[i].aux.tail = 0; +#if KBDIO_DEBUG >= 2 + kbdc_softc[i].kbd.call_count = 0; + kbdc_softc[i].kbd.qcount = kbdc_softc[i].kbd.max_qcount = 0; + kbdc_softc[i].aux.call_count = 0; + kbdc_softc[i].aux.qcount = kbdc_softc[i].aux.max_qcount = 0; +#endif + splx(s); + return (KBDC) &kbdc_softc[i]; + } + } + splx(s); + return NULL; +#endif +} + +/* + * I/O access arbitration in `kbdio' + * + * The `kbdio' module uses a simplistic convention to arbitrate + * I/O access to the controller/keyboard/mouse. The convention requires + * close cooperation of the calling device driver. + * + * The device driver which utilizes the `kbdio' module are assumed to + * have the following set of routines. + * a. An interrupt handler (the bottom half of the driver). + * b. Timeout routines which may briefly polls the keyboard controller. + * c. Routines outside interrupt context (the top half of the driver). + * They should follow the rules below: + * 1. The interrupt handler may assume that it always has full access + * to the controller/keyboard/mouse. + * 2. The other routines must issue `spltty()' if they wish to + * prevent the interrupt handler from accessing + * the controller/keyboard/mouse. + * 3. The timeout routines and the top half routines of the device driver + * arbitrate I/O access by observing the lock flag in `kbdio'. + * The flag is manipulated via `kbdc_lock()'; when one wants to + * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if + * the call returns with TRUE. Otherwise the caller must back off. + * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion + * is finished. This mechanism does not prevent the interrupt + * handler from being invoked at any time and carrying out I/O. + * Therefore, `spltty()' must be strategically placed in the device + * driver code. Also note that the timeout routine may interrupt + * `kbdc_lock()' called by the top half of the driver, but this + * interruption is OK so long as the timeout routine observes the + * the rule 4 below. + * 4. The interrupt and timeout routines should not extend I/O operation + * across more than one interrupt or timeout; they must complete + * necessary I/O operation within one invokation of the routine. + * This measns that if the timeout routine acquires the lock flag, + * it must reset the flag to FALSE before it returns. + */ + +/* set/reset polling lock */ +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 */ +int +kbdc_data_ready(KBDC p) +{ +#ifdef PC98 + return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL); +#else + return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux) + || (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)); +#endif +} + +#ifndef PC98 +/* queuing functions */ + +static int +addq(kqueue *q, int c) +{ + if (nextq(q->tail) != q->head) { + q->q[q->tail] = c; + q->tail = nextq(q->tail); +#if KBDIO_DEBUG >= 2 + ++q->call_count; + ++q->qcount; + if (q->qcount > q->max_qcount) + q->max_qcount = q->qcount; +#endif + return TRUE; + } + return FALSE; +} + +static int +removeq(kqueue *q) +{ + int c; + + if (q->tail != q->head) { + c = q->q[q->head]; + q->head = nextq(q->head); +#if KBDIO_DEBUG >= 2 + --q->qcount; +#endif + return c; + } + return -1; +} + +/* + * device I/O routines + */ +static int +wait_while_controller_busy(struct kbdc_softc *kbdc) +{ + /* CPU will stay inside the loop for 100msec at most */ + int retry = 5000; + int port = kbdc->port; + int f; + + while ((f = inb(port + KBD_STATUS_PORT)) & KBDS_INPUT_BUFFER_FULL) { + if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdc->kbd, inb(port + KBD_DATA_PORT)); + } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdc->aux, inb(port + KBD_DATA_PORT)); + } + DELAY(KBDC_DELAYTIME); + if (--retry < 0) + return FALSE; + } + return TRUE; +} + +/* + * wait for any data; whether it's from the controller, + * the keyboard, or the aux device. + */ +static int +wait_for_data(struct kbdc_softc *kbdc) +{ + /* CPU will stay inside the loop for 200msec at most */ + int retry = 10000; + int port = kbdc->port; + int f; + + while ((f = inb(port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) == 0) { + DELAY(KBDC_DELAYTIME); + if (--retry < 0) + return 0; + } + DELAY(KBDD_DELAYTIME); + return f; +} +#endif /* !PC98 */ + +/* 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; + int f; + + while ((f = inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) + != KBDS_KBD_BUFFER_FULL) { +#ifdef PC98 + DELAY(KBDD_DELAYTIME); +#else + if (f == KBDS_AUX_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdc->aux, inb(port + KBD_DATA_PORT)); + } +#endif + DELAY(KBDC_DELAYTIME); + if (--retry < 0) + return 0; + } + DELAY(KBDD_DELAYTIME); + return f; +} + +#ifndef PC98 +/* + * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard. + * queue anything else. + */ +static int +wait_for_kbd_ack(struct kbdc_softc *kbdc) +{ + /* CPU will stay inside the loop for 200msec at most */ + int retry = 10000; + int port = kbdc->port; + int f; + int b; + + while (retry-- > 0) { + if ((f = inb(port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + b = inb(port + KBD_DATA_PORT); + if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { + if ((b == KBD_ACK) || (b == KBD_RESEND) + || (b == KBD_RESET_FAIL)) + return b; + addq(&kbdc->kbd, b); + } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { + addq(&kbdc->aux, b); + } + } + DELAY(KBDC_DELAYTIME); + } + return -1; +} + +/* wait for data from the aux device */ +static int +wait_for_aux_data(struct kbdc_softc *kbdc) +{ + /* CPU will stay inside the loop for 200msec at most */ + int retry = 10000; + int port = kbdc->port; + int f; + + while ((f = inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) + != KBDS_AUX_BUFFER_FULL) { + if (f == KBDS_KBD_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdc->kbd, inb(port + KBD_DATA_PORT)); + } + DELAY(KBDC_DELAYTIME); + if (--retry < 0) + return 0; + } + DELAY(KBDD_DELAYTIME); + return f; +} + +/* + * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device. + * queue anything else. + */ +static int +wait_for_aux_ack(struct kbdc_softc *kbdc) +{ + /* CPU will stay inside the loop for 200msec at most */ + int retry = 10000; + int port = kbdc->port; + int f; + int b; + + while (retry-- > 0) { + if ((f = inb(port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + b = inb(port + KBD_DATA_PORT); + if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { + if ((b == PSM_ACK) || (b == PSM_RESEND) + || (b == PSM_RESET_FAIL)) + return b; + addq(&kbdc->aux, b); + } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { + addq(&kbdc->kbd, b); + } + } + DELAY(KBDC_DELAYTIME); + } + return -1; +} + +/* write a one byte command to the controller */ +int +write_controller_command(KBDC p, int c) +{ + if (!wait_while_controller_busy(kbdcp(p))) + return FALSE; + outb(kbdcp(p)->port + KBD_COMMAND_PORT, c); + return TRUE; +} + +/* write a one byte data to the controller */ +int +write_controller_data(KBDC p, int c) +{ + if (!wait_while_controller_busy(kbdcp(p))) + return FALSE; + outb(kbdcp(p)->port + KBD_DATA_PORT, c); + return TRUE; +} + +/* write a one byte keyboard command */ +int +write_kbd_command(KBDC p, int c) +{ + if (!wait_while_controller_busy(kbdcp(p))) + return FALSE; + outb(kbdcp(p)->port + KBD_DATA_PORT, c); + return TRUE; +} + +/* write a one byte auxiliary device command */ +int +write_aux_command(KBDC p, int c) +{ + if (!write_controller_command(p, KBDC_WRITE_TO_AUX)) + return FALSE; + return write_controller_data(p, c); +} + +/* send a command to the keyboard and wait for ACK */ +int +send_kbd_command(KBDC p, int c) +{ + int retry = KBD_MAXRETRY; + int res = -1; + + while (retry-- > 0) { + if (!write_kbd_command(p, c)) + continue; + res = wait_for_kbd_ack(kbdcp(p)); + if (res == KBD_ACK) + break; + } + return res; +} + +/* send a command to the auxiliary device and wait for ACK */ +int +send_aux_command(KBDC p, int c) +{ + int retry = KBD_MAXRETRY; + int res = -1; + + while (retry-- > 0) { + if (!write_aux_command(p, c)) + continue; + /* + * FIXME: XXX + * The aux device may have already sent one or two bytes of + * status data, when a command is received. It will immediately + * stop data transmission, thus, leaving an incomplete data + * packet in our buffer. We have to discard any unprocessed + * data in order to remove such packets. Well, we may remove + * unprocessed, but necessary data byte as well... + */ + emptyq(&kbdcp(p)->aux); + res = wait_for_aux_ack(kbdcp(p)); + if (res == PSM_ACK) + break; + } + return res; +} + +/* send a command and a data to the keyboard, wait for ACKs */ +int +send_kbd_command_and_data(KBDC p, int c, int d) +{ + int retry; + int res = -1; + + for (retry = KBD_MAXRETRY; retry > 0; --retry) { + if (!write_kbd_command(p, c)) + continue; + res = wait_for_kbd_ack(kbdcp(p)); + if (res == KBD_ACK) + break; + else if (res != KBD_RESEND) + return res; + } + if (retry <= 0) + return res; + + for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { + if (!write_kbd_command(p, d)) + continue; + res = wait_for_kbd_ack(kbdcp(p)); + if (res != KBD_RESEND) + break; + } + return res; +} + +/* send a command and a data to the auxiliary device, wait for ACKs */ +int +send_aux_command_and_data(KBDC p, int c, int d) +{ + int retry; + int res = -1; + + for (retry = KBD_MAXRETRY; retry > 0; --retry) { + if (!write_aux_command(p, c)) + continue; + emptyq(&kbdcp(p)->aux); + res = wait_for_aux_ack(kbdcp(p)); + if (res == PSM_ACK) + break; + else if (res != PSM_RESEND) + return res; + } + if (retry <= 0) + return res; + + for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) { + if (!write_aux_command(p, d)) + continue; + res = wait_for_aux_ack(kbdcp(p)); + if (res != PSM_RESEND) + break; + } + return res; +} + +/* + * read one byte from any source; whether from the controller, + * the keyboard, or the aux device + */ +int +read_controller_data(KBDC p) +{ + if (availq(&kbdcp(p)->kbd)) + return removeq(&kbdcp(p)->kbd); + if (availq(&kbdcp(p)->aux)) + return removeq(&kbdcp(p)->aux); + if (!wait_for_data(kbdcp(p))) + return -1; /* timeout */ + return inb(kbdcp(p)->port + KBD_DATA_PORT); +} +#endif /* !PC98 */ + +#if KBDIO_DEBUG >= 2 +static int call = 0; +#endif + +/* read one byte from the keyboard */ +int +read_kbd_data(KBDC p) +{ +#ifndef PC98 +#if KBDIO_DEBUG >= 2 + if (++call > 2000) { + call = 0; + log(LOG_DEBUG, "KBDIO: kbd q: %d calls, max %d chars, " + "aux q: %d calls, max %d chars\n", + kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, + kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); + } +#endif + + if (availq(&kbdcp(p)->kbd)) + return removeq(&kbdcp(p)->kbd); +#endif /* !PC98 */ + if (!wait_for_kbd_data(kbdcp(p))) + return -1; /* timeout */ +#ifdef PC98 + DELAY(KBDC_DELAYTIME); +#endif + return inb(kbdcp(p)->port + KBD_DATA_PORT); +} + +/* read one byte from the keyboard, but return immediately if + * no data is waiting + */ +int +read_kbd_data_no_wait(KBDC p) +{ + int f; + +#ifdef PC98 + f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL; +#else +#if KBDIO_DEBUG >= 2 + if (++call > 2000) { + call = 0; + log(LOG_DEBUG, "KBDIO: kbd q: %d calls, max %d chars, " + "aux q: %d calls, max %d chars\n", + kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount, + kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount); + } +#endif + + if (availq(&kbdcp(p)->kbd)) + return removeq(&kbdcp(p)->kbd); + f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL; + if (f == KBDS_AUX_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdcp(p)->aux, inb(kbdcp(p)->port + KBD_DATA_PORT)); + f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL; + } +#endif /* PC98 */ + if (f == KBDS_KBD_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + return inb(kbdcp(p)->port + KBD_DATA_PORT); + } + return -1; /* no data */ +} + +#ifndef PC98 +/* read one byte from the aux device */ +int +read_aux_data(KBDC p) +{ + if (availq(&kbdcp(p)->aux)) + return removeq(&kbdcp(p)->aux); + if (!wait_for_aux_data(kbdcp(p))) + return -1; /* timeout */ + return inb(kbdcp(p)->port + KBD_DATA_PORT); +} + +/* read one byte from the aux device, but return immediately if + * no data is waiting + */ +int +read_aux_data_no_wait(KBDC p) +{ + int f; + + if (availq(&kbdcp(p)->aux)) + return removeq(&kbdcp(p)->aux); + f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL; + if (f == KBDS_KBD_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + addq(&kbdcp(p)->kbd, inb(kbdcp(p)->port + KBD_DATA_PORT)); + f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL; + } + if (f == KBDS_AUX_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + return inb(kbdcp(p)->port + KBD_DATA_PORT); + } + return -1; /* no data */ +} + +/* discard data from the keyboard */ +void +empty_kbd_buffer(KBDC p, int wait) +{ + int t; + int b; + int f; +#if KBDIO_DEBUG >= 2 + int c1 = 0; + int c2 = 0; +#endif + int delta = 2; + + for (t = wait; t > 0; ) { + if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + b = inb(kbdcp(p)->port + KBD_DATA_PORT); + if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) { + addq(&kbdcp(p)->aux, b); +#if KBDIO_DEBUG >= 2 + ++c2; + } else { + ++c1; +#endif + } + t = wait; + } else { + t -= delta; + } + DELAY(delta*1000); + } +#if KBDIO_DEBUG >= 2 + if ((c1 > 0) || (c2 > 0)) + log(LOG_DEBUG, "kbdio: %d:%d char read (empty_kbd_buffer)\n", c1, c2); +#endif + + emptyq(&kbdcp(p)->kbd); +} + +/* discard data from the aux device */ +void +empty_aux_buffer(KBDC p, int wait) +{ + int t; + int b; + int f; +#if KBDIO_DEBUG >= 2 + int c1 = 0; + int c2 = 0; +#endif + int delta = 2; + + for (t = wait; t > 0; ) { + if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + b = inb(kbdcp(p)->port + KBD_DATA_PORT); + if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { + addq(&kbdcp(p)->kbd, b); +#if KBDIO_DEBUG >= 2 + ++c1; + } else { + ++c2; +#endif + } + t = wait; + } else { + t -= delta; + } + DELAY(delta*1000); + } +#if KBDIO_DEBUG >= 2 + if ((c1 > 0) || (c2 > 0)) + log(LOG_DEBUG, "kbdio: %d:%d char read (empty_aux_buffer)\n", c1, c2); +#endif + + emptyq(&kbdcp(p)->aux); +} + +/* discard any data from the keyboard or the aux device */ +void +empty_both_buffers(KBDC p, int wait) +{ + int t; + int f; +#if KBDIO_DEBUG >= 2 + int c1 = 0; + int c2 = 0; +#endif + int delta = 2; + + for (t = wait; t > 0; ) { + if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) { + DELAY(KBDD_DELAYTIME); + (void)inb(kbdcp(p)->port + KBD_DATA_PORT); +#if KBDIO_DEBUG >= 2 + if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) + ++c1; + else + ++c2; +#endif + t = wait; + } else { + t -= delta; + } + DELAY(delta*1000); + } +#if KBDIO_DEBUG >= 2 + if ((c1 > 0) || (c2 > 0)) + log(LOG_DEBUG, "kbdio: %d:%d char read (empty_both_buffers)\n", c1, c2); +#endif + + emptyq(&kbdcp(p)->kbd); + emptyq(&kbdcp(p)->aux); +} + +/* keyboard and mouse device control */ + +/* NOTE: enable the keyboard port but disable the keyboard + * interrupt before calling "reset_kbd()". + */ +int +reset_kbd(KBDC p) +{ + int retry = KBD_MAXRETRY; + int again = KBD_MAXWAIT; + int c = KBD_RESEND; /* keep the compiler happy */ + + while (retry-- > 0) { + empty_both_buffers(p, 10); + if (!write_kbd_command(p, KBDC_RESET_KBD)) + continue; + emptyq(&kbdcp(p)->kbd); + c = read_controller_data(p); + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: RESET_KBD return code:%04x\n", c); + if (c == KBD_ACK) /* keyboard has agreed to reset itself... */ + break; + } + if (retry < 0) + return FALSE; + + while (again-- > 0) { + /* wait awhile, well, in fact we must wait quite loooooooooooong */ + DELAY(KBD_RESETDELAY*1000); + c = read_controller_data(p); /* RESET_DONE/RESET_FAIL */ + if (c != -1) /* wait again if the controller is not ready */ + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: RESET_KBD status:%04x\n", c); + if (c != KBD_RESET_DONE) + return FALSE; + return TRUE; +} + +/* NOTE: enable the aux port but disable the aux interrupt + * before calling `reset_aux_dev()'. + */ +int +reset_aux_dev(KBDC p) +{ + int retry = KBD_MAXRETRY; + int again = KBD_MAXWAIT; + int c = PSM_RESEND; /* keep the compiler happy */ + + while (retry-- > 0) { + empty_both_buffers(p, 10); + if (!write_aux_command(p, PSMC_RESET_DEV)) + continue; + emptyq(&kbdcp(p)->aux); + /* NOTE: Compaq Armada laptops require extra delay here. XXX */ + for (again = KBD_MAXWAIT; again > 0; --again) { + DELAY(KBD_RESETDELAY*1000); + c = read_aux_data_no_wait(p); + if (c != -1) + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: RESET_AUX return code:%04x\n", c); + if (c == PSM_ACK) /* aux dev is about to reset... */ + break; + } + if (retry < 0) + return FALSE; + + for (again = KBD_MAXWAIT; again > 0; --again) { + /* wait awhile, well, quite looooooooooooong */ + DELAY(KBD_RESETDELAY*1000); + c = read_aux_data_no_wait(p); /* RESET_DONE/RESET_FAIL */ + if (c != -1) /* wait again if the controller is not ready */ + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: RESET_AUX status:%04x\n", c); + if (c != PSM_RESET_DONE) /* reset status */ + return FALSE; + + c = read_aux_data(p); /* device ID */ + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: RESET_AUX ID:%04x\n", c); + /* NOTE: we could check the device ID now, but leave it later... */ + return TRUE; +} + +/* controller diagnostics and setup */ + +int +test_controller(KBDC p) +{ + int retry = KBD_MAXRETRY; + int again = KBD_MAXWAIT; + int c = KBD_DIAG_FAIL; + + while (retry-- > 0) { + empty_both_buffers(p, 10); + if (write_controller_command(p, KBDC_DIAGNOSE)) + break; + } + if (retry < 0) + return FALSE; + + emptyq(&kbdcp(p)->kbd); + while (again-- > 0) { + /* wait awhile */ + DELAY(KBD_RESETDELAY*1000); + c = read_controller_data(p); /* DIAG_DONE/DIAG_FAIL */ + if (c != -1) /* wait again if the controller is not ready */ + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: DIAGNOSE status:%04x\n", c); + return (c == KBD_DIAG_DONE); +} + +int +test_kbd_port(KBDC p) +{ + int retry = KBD_MAXRETRY; + int again = KBD_MAXWAIT; + int c = -1; + + while (retry-- > 0) { + empty_both_buffers(p, 10); + if (write_controller_command(p, KBDC_TEST_KBD_PORT)) + break; + } + if (retry < 0) + return FALSE; + + emptyq(&kbdcp(p)->kbd); + while (again-- > 0) { + c = read_controller_data(p); + if (c != -1) /* try again if the controller is not ready */ + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: TEST_KBD_PORT status:%04x\n", c); + return c; +} + +int +test_aux_port(KBDC p) +{ + int retry = KBD_MAXRETRY; + int again = KBD_MAXWAIT; + int c = -1; + + while (retry-- > 0) { + empty_both_buffers(p, 10); + if (write_controller_command(p, KBDC_TEST_AUX_PORT)) + break; + } + if (retry < 0) + return FALSE; + + emptyq(&kbdcp(p)->kbd); + while (again-- > 0) { + c = read_controller_data(p); + if (c != -1) /* try again if the controller is not ready */ + break; + } + if (verbose || bootverbose) + log(LOG_DEBUG, "kbdio: TEST_AUX_PORT status:%04x\n", c); + return c; +} + +int +kbdc_get_device_mask(KBDC p) +{ + return kbdcp(p)->command_mask; +} + +void +kbdc_set_device_mask(KBDC p, int mask) +{ + kbdcp(p)->command_mask = + mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS); +} + +int +get_controller_command_byte(KBDC p) +{ + if (kbdcp(p)->command_byte != -1) + return kbdcp(p)->command_byte; + if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE)) + return -1; + emptyq(&kbdcp(p)->kbd); + kbdcp(p)->command_byte = read_controller_data(p); + return kbdcp(p)->command_byte; +} + +int +set_controller_command_byte(KBDC p, int mask, int command) +{ + if (get_controller_command_byte(p) == -1) + return FALSE; + + command = (kbdcp(p)->command_byte & ~mask) | (command & mask); + if (command & KBD_DISABLE_KBD_PORT) { + if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT)) + return FALSE; + } + if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE)) + return FALSE; + if (!write_controller_data(p, command)) + return FALSE; + kbdcp(p)->command_byte = command; + + if (verbose) + log(LOG_DEBUG, "kbdio: new command byte:%04x (set_controller...)\n", + command); + + return TRUE; +} +#endif /* !PC98 */ diff --git a/sys/i386/isa/kbdio.h b/sys/i386/isa/kbdio.h new file mode 100644 index 0000000000000..b544681f5d571 --- /dev/null +++ b/sys/i386/isa/kbdio.h @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 1996 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: kbdio.h,v 1.7 1997/12/07 08:09:15 yokota Exp $ + */ + +#ifndef _I386_ISA_KBDIO_H_ +#define _I386_ISA_KBDIO_H_ + +/* constants */ + +/* I/O ports */ +#ifdef PC98 +#define KBD_STATUS_PORT 2 /* status port, read */ +#define KBD_COMMAND_PORT 2 /* controller command port, write */ +#define KBD_DATA_PORT 0 /* data port, read/write + * also used as keyboard command + * and mouse command port + */ +#else +#define KBD_STATUS_PORT 4 /* status port, read */ +#define KBD_COMMAND_PORT 4 /* controller command port, write */ +#define KBD_DATA_PORT 0 /* data port, read/write + * also used as keyboard command + * and mouse command port + */ +#endif /* PC98 */ + +/* FIXME: `IO_PSMSIZE' should really be in `isa.h'. */ +#define IO_PSMSIZE (KBD_COMMAND_PORT - KBD_DATA_PORT + 1) /* 5 */ + +/* controller commands (sent to KBD_COMMAND_PORT) */ +#define KBDC_SET_COMMAND_BYTE 0x0060 +#define KBDC_GET_COMMAND_BYTE 0x0020 +#define KBDC_WRITE_TO_AUX 0x00d4 +#define KBDC_DISABLE_AUX_PORT 0x00a7 +#define KBDC_ENABLE_AUX_PORT 0x00a8 +#define KBDC_TEST_AUX_PORT 0x00a9 +#define KBDC_DIAGNOSE 0x00aa +#define KBDC_TEST_KBD_PORT 0x00ab +#define KBDC_DISABLE_KBD_PORT 0x00ad +#define KBDC_ENABLE_KBD_PORT 0x00ae + +/* controller command byte (set by KBDC_SET_COMMAND_BYTE) */ +#define KBD_TRANSLATION 0x0040 +#define KBD_RESERVED_BITS 0x0004 +#define KBD_OVERRIDE_KBD_LOCK 0x0008 +#define KBD_ENABLE_KBD_PORT 0x0000 +#define KBD_DISABLE_KBD_PORT 0x0010 +#define KBD_ENABLE_AUX_PORT 0x0000 +#define KBD_DISABLE_AUX_PORT 0x0020 +#define KBD_ENABLE_AUX_INT 0x0002 +#define KBD_DISABLE_AUX_INT 0x0000 +#define KBD_ENABLE_KBD_INT 0x0001 +#define KBD_DISABLE_KBD_INT 0x0000 +#define KBD_KBD_CONTROL_BITS (KBD_DISABLE_KBD_PORT | KBD_ENABLE_KBD_INT) +#define KBD_AUX_CONTROL_BITS (KBD_DISABLE_AUX_PORT | KBD_ENABLE_AUX_INT) + +/* keyboard device commands (sent to KBD_DATA_PORT) */ +#define KBDC_RESET_KBD 0x00ff +#define KBDC_ENABLE_KBD 0x00f4 +#define KBDC_DISABLE_KBD 0x00f5 +#define KBDC_SET_DEFAULTS 0x00f6 +#define KBDC_SEND_DEV_ID 0x00f2 +#define KBDC_SET_LEDS 0x00ed +#define KBDC_ECHO 0x00ee +#define KBDC_SET_SCANCODE_SET 0x00f0 +#define KBDC_SET_TYPEMATIC 0x00f3 + +/* aux device commands (sent to KBD_DATA_PORT) */ +#define PSMC_RESET_DEV 0x00ff +#define PSMC_ENABLE_DEV 0x00f4 +#define PSMC_DISABLE_DEV 0x00f5 +#define PSMC_SET_DEFAULTS 0x00f6 +#define PSMC_SEND_DEV_ID 0x00f2 +#define PSMC_SEND_DEV_STATUS 0x00e9 +#define PSMC_SEND_DEV_DATA 0x00eb +#define PSMC_SET_SCALING11 0x00e6 +#define PSMC_SET_SCALING21 0x00e7 +#define PSMC_SET_RESOLUTION 0x00e8 +#define PSMC_SET_STREAM_MODE 0x00ea +#define PSMC_SET_REMOTE_MODE 0x00f0 +#define PSMC_SET_SAMPLING_RATE 0x00f3 + +/* PSMC_SET_RESOLUTION argument */ +#define PSMD_RES_LOW 0 /* typically 25ppi */ +#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */ +#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */ +#define PSMD_RES_HIGH 3 /* typically 200ppi */ +#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH + +/* PSMC_SET_SAMPLING_RATE */ +#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */ + +/* status bits (KBD_STATUS_PORT) */ +#ifdef PC98 +#define KBDS_BUFFER_FULL 0x0002 +#define KBDS_ANY_BUFFER_FULL 0x0002 +#define KBDS_KBD_BUFFER_FULL 0x0002 +#define KBDS_AUX_BUFFER_FULL 0x0002 +#else +#define KBDS_BUFFER_FULL 0x0021 +#define KBDS_ANY_BUFFER_FULL 0x0001 +#define KBDS_KBD_BUFFER_FULL 0x0001 +#define KBDS_AUX_BUFFER_FULL 0x0021 +#endif +#define KBDS_INPUT_BUFFER_FULL 0x0002 + +/* return code */ +#define KBD_ACK 0x00fa +#define KBD_RESEND 0x00fe +#define KBD_RESET_DONE 0x00aa +#define KBD_RESET_FAIL 0x00fc +#define KBD_DIAG_DONE 0x0055 +#define KBD_DIAG_FAIL 0x00fd +#define KBD_ECHO 0x00ee + +#define PSM_ACK 0x00fa +#define PSM_RESEND 0x00fe +#define PSM_RESET_DONE 0x00aa +#define PSM_RESET_FAIL 0x00fc + +/* aux device ID */ +#define PSM_MOUSE_ID 0 +#define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 + +#ifdef KERNEL + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* types/structures */ + +typedef caddr_t KBDC; + +/* function prototypes */ + +KBDC kbdc_open __P((int port)); + +int kbdc_lock __P((KBDC kbdc, int lock)); + +int kbdc_data_ready __P((KBDC kbdc)); + +int write_controller_command __P((KBDC kbdc,int c)); +int write_controller_data __P((KBDC kbdc,int c)); + +int write_kbd_command __P((KBDC kbdc,int c)); +int write_aux_command __P((KBDC kbdc,int c)); +int send_kbd_command __P((KBDC kbdc,int c)); +int send_aux_command __P((KBDC kbdc,int c)); +int send_kbd_command_and_data __P((KBDC kbdc,int c,int d)); +int send_aux_command_and_data __P((KBDC kbdc,int c,int d)); + +int read_controller_data __P((KBDC kbdc)); +int read_kbd_data __P((KBDC kbdc)); +int read_kbd_data_no_wait __P((KBDC kbdc)); +int read_aux_data __P((KBDC kbdc)); +int read_aux_data_no_wait __P((KBDC kbdc)); + +void empty_kbd_buffer __P((KBDC kbdc, int t)); +void empty_aux_buffer __P((KBDC kbdc, int t)); +void empty_both_buffers __P((KBDC kbdc, int t)); + +int reset_kbd __P((KBDC kbdc)); +int reset_aux_dev __P((KBDC kbdc)); + +int test_controller __P((KBDC kbdc)); +int test_kbd_port __P((KBDC kbdc)); +int test_aux_port __P((KBDC kbdc)); + +int kbdc_get_device_mask __P((KBDC kbdc)); +void kbdc_set_device_mask __P((KBDC kbdc, int mask)); + +int get_controller_command_byte __P((KBDC kbdc)); +int set_controller_command_byte __P((KBDC kbdc, int command, int flag)); + +#endif /* KERNEL */ + +#endif /* !_I386_ISA_KBDIO_H_ */ diff --git a/sys/i386/isa/kbdtables.h b/sys/i386/isa/kbdtables.h index c0d4663a6eacd..61376f48b919f 100644 --- a/sys/i386/isa/kbdtables.h +++ b/sys/i386/isa/kbdtables.h @@ -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: kbdtables.h,v 1.41 1998/09/15 18:16:37 sos Exp $ + * $Id$ */ #define SET8 0x80 /* set eight bit on */ @@ -93,8 +93,8 @@ static keymap_t key_map = { 0x80, /* PC98 keymap */ /* sc=33 */ NOP, '_', 0x1F, 0x1F, '\\', '|', 0x1C, 0x1C, 0x80, 0x00, /* sc=34 */ ' ', ' ', 0x00, 0x00, ' ', ' ', 0x00, 0x00, 0x00, 0x00, /* sc=35 */ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, -/* sc=36 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, -/* sc=37 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, +/* sc=36 */ F(51), F(51), F(51), F(51), F(51), F(51), F(51), F(51), 0xFF, 0x00, +/* sc=37 */ F(59), F(59), F(59), F(59), F(59), F(59), F(59), F(59), 0xFF, 0x00, /* sc=38 */ F(60), F(60), F(60), F(60), F(60), F(60), F(60), F(60), 0xFF, 0x00, /* sc=39 */ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, RBT, RBT, 0x03, 0x02, /* sc=3a */ F(50), F(50), F(50), F(50), F(50), F(50), F(50), F(50), 0xFF, 0x00, diff --git a/sys/i386/isa/labpc.c b/sys/i386/isa/labpc.c index e893a21fbd40a..4e19b64b5658f 100644 --- a/sys/i386/isa/labpc.c +++ b/sys/i386/isa/labpc.c @@ -57,9 +57,7 @@ #include <sys/devfsext.h> #endif /*DEVFS*/ -#ifdef LOUTB #include <machine/clock.h> -#endif #include <i386/isa/isa_device.h> @@ -298,7 +296,6 @@ static struct cdevsw labpc_cdevsw = labpcioctl, nostop, nullreset, nodevtotty, seltrue, nommap, labpcstrategy, "labpc", NULL, -1 }; -static ointhand2_t labpcintr; static void start(struct ctlr *ctlr); static void @@ -399,7 +396,7 @@ labpcinit(void) labpcs = malloc(NLABPC * sizeof(struct ctlr *), M_DEVBUF, M_NOWAIT); if (labpcs) { - bzero(labpcs, NLABPC * sizeof(struct ctlr *)); + bzero(labpcs, NLABPC * sizeof(struct cltr *)); return 1; } return 0; @@ -408,7 +405,7 @@ labpcinit(void) static int labpcprobe(struct isa_device *dev) { - static int unit; + static unit; struct ctlr scratch, *ctlr; u_char status; @@ -476,7 +473,6 @@ labpcattach(struct isa_device *dev) { struct ctlr *ctlr = labpcs[dev->id_unit]; - dev->id_ointr = labpcintr; callout_handle_init(&ctlr->ch); ctlr->sample_us = (1000000.0 / (double)LABPC_DEFAULT_HERZ) + .50; reset(ctlr); @@ -696,7 +692,7 @@ static void ad_intr(struct ctlr *ctlr) } } -static void labpcintr(int unit) +void labpcintr(int unit) { struct ctlr *ctlr = labpcs[unit]; (*ctlr->intr)(ctlr); @@ -1098,7 +1094,7 @@ labpcioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc *p) } -static int labpc_devsw_installed = 0; +static labpc_devsw_installed = 0; static void labpc_drvinit(void *unused) { diff --git a/sys/i386/isa/loran.c b/sys/i386/isa/loran.c index d4dca4d24ed41..e92d793c4fb98 100644 --- a/sys/i386/isa/loran.c +++ b/sys/i386/isa/loran.c @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: loran.c,v 1.13 1998/12/07 21:58:22 archie Exp $ + * $Id: loran.c,v 1.7 1998/08/17 18:47:36 bde Exp $ * * This device-driver helps the userland controlprogram for a LORAN-C * receiver avoid monopolizing the CPU. @@ -32,13 +32,13 @@ #include <i386/isa/isa_device.h> #endif /* KERNEL */ -typedef TAILQ_HEAD(, datapoint) dphead_t; - struct datapoint { - /* Fields used by kernel */ + void *ident; + int index; u_int64_t scheduled; + u_int delay; u_int code; - u_int fri; + u_int gri; u_int agc; u_int phase; u_int width; @@ -47,24 +47,16 @@ struct datapoint { u_int qsig; u_int ssig; u_int64_t epoch; + struct timespec actual; TAILQ_ENTRY(datapoint) list; - u_char status; - int vco; - int bounce; - pid_t pid; - struct timespec when; - - int priority; - dphead_t *home; - - /* Fields used only in userland */ - void *ident; - int index; double ival; double qval; double sval; double mval; - + u_char status; + u_int vco; + int count; + int remain; }; /* @@ -85,21 +77,14 @@ struct datapoint { #define EN5 0x40 /* enable counter 5 bit */ #define ENG 0x80 /* enable gri bit */ -#define VCO_SHIFT 8 /* bits of fraction on VCO value */ -#define VCO (2048 << VCO_SHIFT) /* initial vco dac (0 V)*/ - - -#define PGUARD 990 /* program guard time (cycle) (990!) */ - +#define VCO 2048 /* initial vco dac (0 V)*/ #ifdef KERNEL -#define NLORAN 10 /* Allow ten minor devices */ - -#define NDUMMY 4 /* How many idlers we want */ #define PORT 0x0300 /* controller port address */ +#define PGUARD 990 /* program guard time (cycle) (990!) */ #define GRI 800 /* pulse-group gate (cycle) */ @@ -198,24 +183,25 @@ struct datapoint { /**********************************************************************/ -dphead_t minors[NLORAN], working, holding; +static TAILQ_HEAD(qhead, datapoint) qdone, qready; -static struct datapoint dummy[NDUMMY]; +static struct datapoint dummy; static u_int64_t ticker; static u_char par; +static struct datapoint *this, *next; + static MALLOC_DEFINE(M_LORAN, "Loran", "Loran datapoints"); static int loranerror; static char lorantext[80]; -static u_int vco_is; -static u_int vco_should; -static u_int vco_want; -static u_int64_t vco_when; -static int64_t vco_error; +static u_int vco_is; +static u_int vco_should; + +static int lorantc_magic; /**********************************************************************/ @@ -227,8 +213,7 @@ static d_open_t loranopen; static d_close_t loranclose; static d_read_t loranread; static d_write_t loranwrite; -static ointhand2_t loranintr; -extern struct timecounter loran_timecounter; +extern struct timecounter loran_timecounter[]; /**********************************************************************/ @@ -243,10 +228,10 @@ loranprobe(struct isa_device *dvp) } u_short tg_init[] = { /* stc initialization vector */ - 0x0562, 12, 13, /* counter 1 (p0) Mode J */ - 0x0262, PGUARD, GRI, /* counter 2 (gri) Mode J */ + 0x0562, 12, 13, /* counter 1 (p0) */ + 0x0262, PGUARD, GRI, /* counter 2 (gri) */ 0x8562, PCX, 5000 - PCX, /* counter 3 (pcx) */ - 0xc562, 0, STROBE, /* counter 4 (stb) Mode L */ + 0xc562, 0, STROBE, /* counter 4 (stb) */ 0x052a, 0, 0 /* counter 5 (out) */ }; @@ -272,37 +257,31 @@ loranattach(struct isa_device *isdp) { int i; - isdp->id_ointr = loranintr; - /* We need to be a "fast-intr" */ isdp->id_ri_flags |= RI_FAST; printf("loran0: LORAN-C Receiver\n"); - vco_should = VCO; - vco_is = vco_should >> VCO_SHIFT; - LOAD_DAC(DACA, vco_is); + vco_is = VCO; + LOAD_DAC(DACA, VCO); init_tgc(); - init_timecounter(&loran_timecounter); + init_timecounter(loran_timecounter); - TAILQ_INIT(&working); - TAILQ_INIT(&holding); - for (i = 0; i < NLORAN; i++) { - TAILQ_INIT(&minors[i]); - - } + TAILQ_INIT(&qdone); + TAILQ_INIT(&qready); - for (i = 0; i < NDUMMY; i++) { - dummy[i].agc = 4095; - dummy[i].code = 0xac; - dummy[i].fri = PGUARD; - dummy[i].phase = 50; - dummy[i].width = 50; - dummy[i].priority = 9999; - TAILQ_INSERT_TAIL(&working, &dummy[i], list); - } + dummy.agc = 4095; + dummy.code = 0xac; + dummy.delay = PGUARD - GRI; + dummy.gri = PGUARD; + dummy.phase = 50; + dummy.width = 50; + + TAILQ_INSERT_HEAD(&qready, &dummy, list); + this = &dummy; + next = &dummy; inb(ADC); /* Flush any old result */ outb(ADC, ADC_S); @@ -316,18 +295,28 @@ loranattach(struct isa_device *isdp) static int loranopen (dev_t dev, int flags, int fmt, struct proc *p) { - int idx; - - idx = minor(dev); - if (idx >= NLORAN) - return (ENODEV); + u_long ef; + struct datapoint *this; + while (!TAILQ_EMPTY(&qdone)) { + ef = read_eflags(); + disable_intr(); + this = TAILQ_FIRST(&qdone); + TAILQ_REMOVE(&qdone, this, list); + write_eflags(ef); + FREE(this, M_LORAN); + } + init_tgc(); + loranerror = 0; return(0); } static int loranclose(dev_t dev, int flags, int fmt, struct proc *p) { + /* + * Lower ENG + */ return(0); } @@ -337,22 +326,19 @@ loranread(dev_t dev, struct uio * uio, int ioflag) u_long ef; struct datapoint *this; int err, c; - int idx; - - idx = minor(dev); if (loranerror) { printf("Loran0: %s", lorantext); return(EIO); } - if (TAILQ_EMPTY(&minors[idx])) - tsleep ((caddr_t)&minors[idx], PZERO + 8 |PCATCH, "loranrd", hz*2); - if (TAILQ_EMPTY(&minors[idx])) + if (TAILQ_EMPTY(&qdone)) + tsleep ((caddr_t)&qdone, PZERO + 8 |PCATCH, "loranrd", hz*2); + if (TAILQ_EMPTY(&qdone)) return(0); - this = TAILQ_FIRST(&minors[idx]); + this = TAILQ_FIRST(&qdone); ef = read_eflags(); disable_intr(); - TAILQ_REMOVE(&minors[idx], this, list); + TAILQ_REMOVE(&qdone, this, list); write_eflags(ef); c = imin(uio->uio_resid, (int)sizeof *this); @@ -362,146 +348,92 @@ loranread(dev_t dev, struct uio * uio, int ioflag) } static void -loranenqueue(struct datapoint *dp) +loranenqueue(struct datapoint *this) { - struct datapoint *dpp, *dpn; - - while(dp) { - /* - * The first two elements on "working" are sacred, - * they're already partly setup in hardware, so the - * earliest slot we can use is #3 - */ - dpp = TAILQ_FIRST(&working); - dpp = TAILQ_NEXT(dpp, list); - dpn = TAILQ_NEXT(dpp, list); - while (1) { - /* - * We cannot bump "dpp", so if "dp" overlaps it - * skip a beat. - * XXX: should use better algorithm ? - */ - if (dpp->scheduled + PGUARD > dp->scheduled) { - dp->scheduled += dp->fri; - continue; - } - - /* - * If "dpn" will be done before "dp" wants to go, - * we must look further down the list. - */ - if (dpn && dpn->scheduled + PGUARD < dp->scheduled) { - dpp = dpn; - dpn = TAILQ_NEXT(dpp, list); - continue; - } - - /* - * If at end of list, put "dp" there - */ - if (!dpn) { - TAILQ_INSERT_AFTER(&working, dpp, dp, list); - break; - } - - /* - * If "dp" fits before "dpn", insert it there - */ - if (dpn->scheduled > dp->scheduled + PGUARD) { - TAILQ_INSERT_AFTER(&working, dpp, dp, list); - break; - } - - /* - * If "dpn" is less important, bump it. - */ - if (dp->priority < dpn->priority) { - TAILQ_REMOVE(&working, dpn, list); - TAILQ_INSERT_TAIL(&holding, dpn, list); - dpn = TAILQ_NEXT(dpp, list); - continue; - } - - /* - * "dpn" was more or equally important, "dp" must - * take yet turn. - */ - dp->scheduled += dp->fri; - } + struct datapoint *p, *q; + u_long ef; + u_int64_t x; + + if (this->scheduled < ticker) { + x = (ticker - this->scheduled) / (2 * this->gri); + this->scheduled += x * 2 * this->gri; + } + + ef = read_eflags(); + disable_intr(); - do { - /* - * If anything was bumped, put it back as best we can - */ - if (TAILQ_EMPTY(&holding)) { - dp = 0; - break; - } - dp = TAILQ_FIRST(&holding); - TAILQ_REMOVE(&holding, dp, list); - if (dp->home) { - if (!--dp->bounce) { - TAILQ_INSERT_TAIL(dp->home, dp, list); - wakeup((caddr_t)dp->home); - dp = 0; - } - } - } while (!dp); + p = TAILQ_FIRST(&qready); + while (1) { + while (this->scheduled < p->scheduled + PGUARD) + this->scheduled += 2 * this->gri; + q = TAILQ_NEXT(p, list); + if (!q) { + this->delay = this->scheduled - p->scheduled - GRI; + TAILQ_INSERT_TAIL(&qready, this, list); + break; + } + if (this->scheduled + PGUARD < q->scheduled) { + this->delay = this->scheduled - p->scheduled - GRI; + TAILQ_INSERT_BEFORE(q, this, list); + q->delay = q->scheduled - this->scheduled - GRI; + break; + } + p = q; } + write_eflags(ef); } static int loranwrite(dev_t dev, struct uio * uio, int ioflag) { - u_long ef; int err = 0, c; struct datapoint *this; - int idx; - u_int64_t dt; - - idx = minor(dev); MALLOC(this, struct datapoint *, sizeof *this, M_LORAN, M_WAITOK); c = imin(uio->uio_resid, (int)sizeof *this); err = uiomove((caddr_t)this, c, uio); - if (!err && this->fri == 0) + if (!err && this->gri == 0) err = EINVAL; - /* XXX more checks */ - this->home = &minors[idx]; - this->priority = idx; - if (ticker > this->scheduled) { - dt = ticker - this->scheduled; - dt -= dt % this->fri; - this->scheduled += dt; - } if (!err) { - ef = read_eflags(); - disable_intr(); loranenqueue(this); - write_eflags(ef); - if (this->vco >= 0) - vco_want = this->vco; + vco_should = this->vco; } else { FREE(this, M_LORAN); } return(err); } -static void +void loranintr(int unit) { u_long ef; int status = 0, count = 0, i; - struct datapoint *this, *next; - int delay; ef = read_eflags(); disable_intr(); - this = TAILQ_FIRST(&working); - TAILQ_REMOVE(&working, this, list); + if (this != &dummy) { + outb(TGC, DSABDPS); + outb(TGC, TG_LOADDP + 0x12); /* hold counter #2 */ + this->remain = -1; + i = 2; + for (i = 0; i < 2; i++) { + count = this->remain; + do { + outb(TGC, TG_SAVE + 0x12); + this->remain = inb(TGD) & 0xff; + this->remain |= inb(TGD) << 8; + } while (count == this->remain); + } + lorantc_magic = 1; + nanotime(&this->actual); + lorantc_magic = 0; + outb(TGC, TG_LOADDP + 0x0a); + this->count = inb(TGD); + this->count |= inb(TGD) << 8; + LOAD_9513(0x12, GRI) + } - nanotime(&this->when); this->ssig = inb(ADC); par &= ~(ENG | IEN); @@ -522,20 +454,30 @@ loranintr(int unit) outb(ADC, ADC_S); this->epoch = ticker; - this->vco = vco_is; - if (this->home) { - TAILQ_INSERT_TAIL(this->home, this, list); - wakeup((caddr_t)this->home); - } else { - loranenqueue(this); + if (this != &dummy) { + TAILQ_INSERT_TAIL(&qdone, this, list); + wakeup((caddr_t)&qdone); } - this = TAILQ_FIRST(&working); - next = TAILQ_NEXT(this, list); - - delay = next->scheduled - this->scheduled; - delay -= GRI; + if (next != &dummy || TAILQ_NEXT(next, list)) + TAILQ_REMOVE(&qready, next, list); + + this = next; + ticker += GRI; + ticker += this->delay; + + next = TAILQ_FIRST(&qready); + if (!next) { + next = &dummy; + TAILQ_INSERT_HEAD(&qready, next, list); + } else if (next->delay + GRI > PGUARD * 2) { + next->delay -= PGUARD; + next = &dummy; + TAILQ_INSERT_HEAD(&qready, next, list); + } + if (next == &dummy) + next->scheduled = ticker + GRI + next->delay; /* load this->params */ par &= ~(INTEG|GATE); @@ -545,7 +487,7 @@ loranintr(int unit) outb(CODE, this->code); - LOAD_9513(0x0a, delay); + LOAD_9513(0x0a, next->delay); /* * We need to load this from the opposite register * due to some @@ -557,17 +499,10 @@ loranintr(int unit) outb(TGC, TG_LOADARM + 0x08); LOAD_9513(0x14, this->width); - vco_error += ((vco_is << VCO_SHIFT) - vco_should) * (ticker - vco_when); - vco_should = vco_want; - i = vco_should >> VCO_SHIFT; - if (vco_error < 0) - i++; - - if (vco_is != i) { - LOAD_DAC(DACA, i); - vco_is = i; + if (vco_is != vco_should) { + LOAD_DAC(DACA, vco_should); + vco_is = vco_should; } - vco_when = ticker; this->status = inb(TGC); #if 1 @@ -587,13 +522,15 @@ loranintr(int unit) outb(PAR, par); if (status) { - snprintf(lorantext, sizeof(lorantext), - "Missed: %02x %d %d this:%p next:%p (dummy=%p)\n", - status, count, delay, this, next, &dummy); + sprintf(lorantext, "Missed: %02x %d %d this:%p next:%p (dummy=%p)\n", + status, count, next->delay, this, next, &dummy); + loranerror = 1; + } + if (next->delay < PGUARD - GRI) { + sprintf(lorantext, "Bogus: %02x %d %d\n", + status, count, next->delay); loranerror = 1; } - - ticker = this->scheduled; write_eflags(ef); } @@ -605,11 +542,13 @@ loran_get_timecount(struct timecounter *tc) { unsigned count; u_long ef; + u_int high, low; ef = read_eflags(); disable_intr(); - outb(TGC, TG_SAVE + 0x10); /* save counter #5 */ + if (!lorantc_magic) + outb(TGC, TG_SAVE + 0x10); /* save counter #5 */ outb(TGC, TG_LOADDP +0x15); /* hold counter #5 */ count = inb(TGD); count |= inb(TGD) << 8; @@ -618,7 +557,7 @@ loran_get_timecount(struct timecounter *tc) return (count); } -static struct timecounter loran_timecounter = { +static struct timecounter loran_timecounter[3] = { loran_get_timecount, /* get_timecount */ 0, /* no pps_poll */ 0xffff, /* counter_mask */ @@ -627,7 +566,7 @@ static struct timecounter loran_timecounter = { }; SYSCTL_OPAQUE(_debug, OID_AUTO, loran_timecounter, CTLFLAG_RD, - &loran_timecounter, sizeof(loran_timecounter), "S,timecounter", ""); + loran_timecounter, sizeof(loran_timecounter), "S,timecounter", ""); /**********************************************************************/ diff --git a/sys/i386/isa/lpt.c b/sys/i386/isa/lpt.c index 2b5615817eafd..d9e1592c9ade2 100644 --- a/sys/i386/isa/lpt.c +++ b/sys/i386/isa/lpt.c @@ -46,7 +46,7 @@ * SUCH DAMAGE. * * from: unknown origin, 386BSD 0.1 - * $Id: lpt.c,v 1.71 1998/10/22 05:58:39 bde Exp $ + * $Id: lpt.c,v 1.69 1998/06/07 17:10:44 dfr Exp $ */ /* @@ -189,12 +189,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 @@ -262,7 +259,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 @@ -318,8 +314,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); } @@ -426,7 +422,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; @@ -434,7 +429,7 @@ lptattach(struct isa_device *isdp) outb(sc->sc_port+lpt_control, LPC_NINIT); /* 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); @@ -443,9 +438,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? */ @@ -483,7 +478,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; @@ -497,7 +492,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 */ @@ -524,7 +519,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); } @@ -556,14 +551,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); } @@ -573,7 +568,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) @@ -630,7 +625,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); } @@ -649,7 +644,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 */ @@ -720,16 +715,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))) { @@ -739,7 +734,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); } @@ -754,7 +749,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; @@ -784,7 +779,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) */ @@ -801,7 +796,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) && @@ -809,7 +804,7 @@ lptintr(int unit) sc->sc_state |= ERROR; /* lptout() will jump in and try to restart. */ } - lprintf(("sts %x ", sts)); + lprintf("sts %x ", sts); } static int @@ -992,7 +987,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; @@ -1089,7 +1084,7 @@ lpintr (int unit) sc->sc_iferrs = 0; if (IF_QFULL(&ipintrq)) { - lprintf(("DROP")); + lprintf("DROP"); IF_DROP(&ipintrq); goto done; } @@ -1138,7 +1133,7 @@ lpintr (int unit) sc->sc_iferrs = 0; if (IF_QFULL(&ipintrq)) { - lprintf(("DROP")); + lprintf("DROP"); IF_DROP(&ipintrq); goto done; } @@ -1160,7 +1155,7 @@ lpintr (int unit) err: outb(lpt_data_port, 0); - lprintf(("R")); + lprintf("R"); sc->sc_if.if_ierrors++; sc->sc_iferrs++; @@ -1224,7 +1219,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); } @@ -1284,7 +1279,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; @@ -1293,7 +1288,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); @@ -1301,7 +1296,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, } if (inb(lpt_stat_port) & LPIP_SHAKE) { - lprintf(("&")); + lprintf("&"); lptintr(ifp->if_unit); } @@ -1326,7 +1321,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; @@ -1354,7 +1349,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/i386/isa/matcd/audio.c b/sys/i386/isa/matcd/audio.c index b395fb410645b..a7891cb123624 100644 --- a/sys/i386/isa/matcd/audio.c +++ b/sys/i386/isa/matcd/audio.c @@ -213,7 +213,7 @@ static int matcd_pause(int ldrive, int cdrive, int controller, int action) } /*<14>*/ unlockbus(controller, ldrive); /*<16>Release bus*/ - if ((z & MATCD_ST_AUDIOBSY) == 0 && /*<14>If drive is idle*/ + if (z & MATCD_ST_AUDIOBSY==0 && /*<14>If drive is idle*/ cd->status==CD_AS_PLAY_IN_PROGRESS) { /*<14>but was playing*/ cd->status=CD_AS_PLAY_COMPLETED; /*<14>then its done*/ return(0); diff --git a/sys/i386/isa/matcd/matcd.c b/sys/i386/isa/matcd/matcd.c index 4f1943a589f96..adc8f8f1b73ca 100644 --- a/sys/i386/isa/matcd/matcd.c +++ b/sys/i386/isa/matcd/matcd.c @@ -337,7 +337,7 @@ static char MATCDVERSION[]="Version 1(26) 18-Oct-95"; static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV"; /* The proceeding strings may not be changed*/ -/* $Id: matcd.c,v 1.36 1998/07/15 10:11:21 bde Exp $ */ +/* $Id: matcd.c,v 1.35 1998/07/04 22:30:20 julian Exp $ */ /*--------------------------------------------------------------------------- Include declarations @@ -437,7 +437,7 @@ static struct matcd_data { void *rlc_devfs_token; void *la_devfs_token; void *lc_devfs_token; -#endif /* DEVFS */ +#endif DEVFS } matcd_data[TOTALDRIVES]; @@ -2445,7 +2445,7 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller, struct cd_toc_entry *to; int len,trk,i,z,port; unsigned char cmd[MAXCMDSIZ]; - unsigned char data[8]; + unsigned char data[5]; cd=&matcd_data[ldrive]; port=cd->iobase; diff --git a/sys/i386/isa/mcd.c b/sys/i386/isa/mcd.c index a24a79fca7aa3..0e3bd17eaae9d 100644 --- a/sys/i386/isa/mcd.c +++ b/sys/i386/isa/mcd.c @@ -40,7 +40,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mcd.c,v 1.100 1998/07/13 09:53:01 bde Exp $ + * $Id: mcd.c,v 1.99 1998/07/04 22:30:17 julian Exp $ */ static const char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; @@ -178,7 +178,6 @@ static int mcd_send(int unit, int cmd,int nretrys); static void hsg2msf(int hsg, bcd_t *msf); static int msf2hsg(bcd_t *msf, int relative); static int mcd_volinfo(int unit); -static ointhand2_t mcdintr; static int mcd_waitrdy(int port,int dly); static timeout_t mcd_timeout; static void mcd_doread(int state, struct mcd_mbx *mbxin); @@ -250,7 +249,6 @@ int mcd_attach(struct isa_device *dev) int unit = dev->id_unit; struct mcd_data *cd = mcd_data + unit; - dev->id_ointr = mcdintr; cd->iobase = dev->id_iobase; cd->flags |= MCDINIT; mcd_soft_reset(unit); @@ -979,7 +977,7 @@ mcd_volinfo(int unit) return EINVAL; } -static void +void mcdintr(unit) int unit; { diff --git a/sys/i386/isa/mse.c b/sys/i386/isa/mse.c index 6579de2d6a2a2..d907e4c0ac8e9 100644 --- a/sys/i386/isa/mse.c +++ b/sys/i386/isa/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.38 1998/06/07 17:10:47 dfr Exp $ + * $Id: mse.c,v 1.37 1998/01/24 02:54:22 eivind Exp $ */ /* * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and @@ -87,7 +87,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(), @@ -258,7 +257,6 @@ mseattach(idp) int unit = idp->id_unit; struct mse_softc *sc = &mse_sc[unit]; - idp->id_ointr = mseintr; sc->sc_port = idp->id_iobase; sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; #ifdef DEVFS @@ -548,7 +546,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/i386/isa/ncr5380.c b/sys/i386/isa/ncr5380.c new file mode 100644 index 0000000000000..e8978372bd01c --- /dev/null +++ b/sys/i386/isa/ncr5380.c @@ -0,0 +1,1536 @@ +/* + * FreeBSD generic NCR-5380/NCR-53C400 SCSI driver + * + * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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. + */ + +/* + * Tested on the following hardware: + * Adapter: Trantor T130 + * Streamer: Archive Viper 150, + * CD-ROM: NEC CDR-25 + */ +#undef DEBUG + +#include "nca.h" +#if NNCA > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <machine/clock.h> + +#include <i386/isa/isa_device.h> +#include <i386/isa/ic/ncr5380.h> +#include <i386/isa/ic/ncr53400.h> + +#include <scsi/scsiconf.h> + +#ifdef DEBUG +# define PRINT(s) printf s +#else +# define PRINT(s) /*void*/ +#endif + +#define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */ +#define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */ +#define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */ + +/* + * Defice config flags + */ +#define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */ + +/* + * ProAudioSpectrum registers + */ +#define PAS16_DATA 8 /* Data Register */ +#define PAS16_STAT 9 /* Status Register */ +#define PAS16_STAT_DREQ 0x80 /* Pseudo-DMA ready bit */ +#define PAS16_REG(r) (((r) & 0xc) << 11 | ((r) & 3)) + +static u_char pas16_irq_magic[] = + { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; + +/* + * SCSI bus phases + */ +#define PHASE_MASK (CSBR_MSG | CSBR_CD | CSBR_IO) +#define PHASE_DATAOUT 0 +#define PHASE_DATAIN CSBR_IO +#define PHASE_CMDOUT CSBR_CD +#define PHASE_STATIN (CSBR_CD | CSBR_IO) +#define PHASE_MSGOUT (CSBR_MSG | CSBR_CD) +#define PHASE_MSGIN (CSBR_MSG | CSBR_CD | CSBR_IO) +#define PHASE_NAME(ph) phase_name[(ph)>>2] +#define PHASE_TO_TCR(ph) ((ph) >> 2) + +static char *phase_name[] = { + "DATAOUT", "DATAIN", "CMDOUT", "STATIN", + "Phase4?", "Phase5?", "MSGOUT", "MSGIN", +}; + +/* + * SCSI message codes + */ +#define MSG_COMMAND_COMPLETE 0x00 +#define MSG_SAVE_POINTERS 0x02 +#define MSG_RESTORE_POINTERS 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_ABORT 0x06 +#define MSG_MESSAGE_REJECT 0x07 +#define MSG_NOP 0x08 +#define MSG_BUS_DEV_RESET 0x0c +#define MSG_IDENTIFY(lun) (0xc0 | ((lun) & 0x7)) +#define MSG_ISIDENT(m) ((m) & 0x80) + +/* + * SCSI control block used to keep info about a scsi command + */ +typedef struct scb { + int flags; /* status of the instruction */ +#define SCB_FREE 0x00 +#define SCB_ACTIVE 0x01 +#define SCB_ABORTED 0x02 +#define SCB_TIMEOUT 0x04 +#define SCB_ERROR 0x08 +#define SCB_TIMECHK 0x10 /* we have set a timeout on this one */ +#define SCB_SENSE 0x20 /* sensed data available */ +#define SCB_TBUSY 0x40 /* target busy */ + struct scb *next; /* in free list */ + struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */ + u_char *data; /* position in data buffer so far */ + int32_t datalen; /* bytes remaining to transfer */ +} scb_t; + +typedef enum { + CTLR_NONE, + CTLR_NCR_5380, + CTLR_NCR_53C400, + CTLR_PAS_16 +} ctlr_t; + +/* + * Data structure describing the target state. + */ +typedef struct { + u_char busy; /* mask of busy luns at device target */ + u_long perrcnt; /* counter of target parity errors */ +} target_t; + +/* + * Data structure describing current status of the scsi bus. One for each + * controller card. + */ +typedef struct { + ctlr_t type; /* Seagate or Future Domain */ + char *name; /* adapter name */ + + /* NCR-5380 controller registers */ + u_short ODR; /* (wo-0) Output Data Register */ + u_short CSDR; /* (ro-0) Current SCSI Data Register */ + u_short ICR; /* (rw-1) Initiator Command Register */ + u_short MR; /* (rw-2) Mode Register */ + u_short TCR; /* (rw-3) Target Command Register */ + u_short SER; /* (wo-4) Select Enable Register */ + u_short CSBR; /* (ro-4) Current SCSI Bus Status Register */ + u_short BSR; /* (ro-5) Bus and Status Register */ + u_short SDSR; /* (wo-5) Start DMA Send Register */ + u_short SDIR; /* (wo-7) Start DMA Initiator Receive Register */ + u_short RPIR; /* (ro-7) Reset Parity/Interrupt Register */ + + /* NCR-53C400 controller registers */ + u_short CSR; /* (rw-0) Control and Status Register */ + u_short CCR; /* (rw-1) Clock Counter Register */ + u_short HBR; /* (rw-4) Host Buffer Register */ + + /* ProAudioSpectrum controller registers */ + u_short PDATA; /* (rw) Pseudo-DMA Data Register */ + u_short PSTAT; /* (rw) Pseudo-DMA Status Register */ + + u_char scsi_addr; /* our scsi address, 0..7 */ + u_char scsi_id; /* our scsi id mask */ + u_char parity; /* parity flag: CMD_EN_PARITY or 0 */ + u_char irq; /* IRQ number used or 0 if no IRQ */ + u_int timeout_active : 1; /* timeout() active (requested) */ + + struct scsi_link sc_link; /* struct connecting different data */ + scb_t *queue; /* waiting to be issued */ + scb_t *disconnected_queue; /* waiting to reconnect */ + + int numscb; /* number of scsi control blocks */ + scb_t *free_scb; /* free scb list */ + scb_t scbs[SCB_TABLE_SIZE]; + + target_t target[8]; /* target state data */ +} adapter_t; + +static adapter_t ncadata[NNCA]; + +#define IS_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &\ + (1 << (b)->xfer->sc_link->lun)) +#define SET_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy |=\ + (1 << (b)->xfer->sc_link->lun)) +#define CLEAR_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &=\ + ~(1 << (b)->xfer->sc_link->lun)) + +/* + * Wait for condition, given as an boolean expression. + * Print the message on timeout. + */ +#define WAITFOR(condition,count,message) {\ + register u_long cnt = count; char *_msg = message;\ + while (cnt-- && ! (condition)) continue;\ + if (cnt == -1 && _msg)\ + printf ("nca: %s timeout\n", _msg); } + +static int nca_probe (struct isa_device *dev); +static int nca_attach (struct isa_device *dev); +static int32_t nca_scsi_cmd (struct scsi_xfer *xs); +static u_int32_t nca_adapter_info (int unit); +static void nca_timeout (void *scb); +static void ncaminphys (struct buf *bp); +static void nca_done (adapter_t *z, scb_t *scb); +static void nca_start (adapter_t *z); +static void nca_information_transfer (adapter_t *z, scb_t *scb); +static int nca_poll (adapter_t *z, scb_t *scb); +static int nca_init (adapter_t *z); +static int nca_reselect (adapter_t *z); +static int nca_select (adapter_t *z, scb_t *scb); +static int nca_abort (adapter_t *z, scb_t *scb); +static void nca_send_abort (adapter_t *z); +static u_char nca_msg_input (adapter_t *z); +static void nca_tick (void *arg); +static int nca_sense (adapter_t *z, scb_t *scb); +static void nca_data_output (adapter_t *z, u_char **pdata, u_long *plen); +static void nca_data_input (adapter_t *z, u_char **pdata, u_long *plen); +static void nca_cmd_output (adapter_t *z, u_char *cmd, int cmdlen); +static void nca_53400_dma_xfer (adapter_t *z, int r, u_char **dat, u_long *len); +static void nca_pas_dma_xfer (adapter_t *z, int r, u_char **dat, u_long *len); + +static struct scsi_adapter nca_switch = { + nca_scsi_cmd, ncaminphys, 0, 0, nca_adapter_info, "nca", {0}, +}; +static struct scsi_device nca_dev = { NULL, NULL, NULL, NULL, "nca", 0, {0} }; +struct isa_driver ncadriver = { nca_probe, nca_attach, "nca" }; + +/* + * Check if the device can be found at the port given and if so, + * detect the type of board. Set it up ready for further work. + * Takes the isa_dev structure from autoconf as an argument. + * Returns 1 if card recognized, 0 if errors. + */ +int nca_probe (struct isa_device *dev) +{ + adapter_t *z = &ncadata[dev->id_unit]; + int i; + + /* Init fields used by our routines */ + z->parity = (dev->id_flags & FLAG_NOPARITY) ? 0 : + MR_ENABLE_PARITY_CHECKING; + z->scsi_addr = HOST_SCSI_ADDR; + z->scsi_id = 1 << z->scsi_addr; + z->irq = dev->id_irq ? ffs (dev->id_irq) - 1 : 0; + z->queue = 0; + z->disconnected_queue = 0; + for (i=0; i<8; i++) + z->target[i].busy = 0; + + /* Link up the free list of scbs */ + z->numscb = SCB_TABLE_SIZE; + z->free_scb = z->scbs; + for (i=1; i<SCB_TABLE_SIZE; i++) + z->scbs[i-1].next = z->scbs + i; + z->scbs[SCB_TABLE_SIZE-1].next = 0; + + /* Try NCR 5380. */ + z->type = CTLR_NCR_5380; + z->name = "NCR-5380"; + z->ODR = dev->id_iobase + C80_ODR; + z->CSDR = dev->id_iobase + C80_CSDR; + z->ICR = dev->id_iobase + C80_ICR; + z->MR = dev->id_iobase + C80_MR; + z->TCR = dev->id_iobase + C80_TCR; + z->SER = dev->id_iobase + C80_SER; + z->CSBR = dev->id_iobase + C80_CSBR; + z->BSR = dev->id_iobase + C80_BSR; + z->SDSR = dev->id_iobase + C80_SDSR; + z->SDIR = dev->id_iobase + C80_SDIR; + z->RPIR = dev->id_iobase + C80_RPIR; + z->CSR = 0; + z->CCR = 0; + z->HBR = 0; + z->PDATA = 0; + z->PSTAT = 0; + if (nca_init (z) == 0) + return (8); + + /* Try NCR 53C400. */ + z->type = CTLR_NCR_53C400; + z->name = "NCR-53C400"; + z->ODR = dev->id_iobase + C400_5380_REG_OFFSET + C80_ODR; + z->CSDR = dev->id_iobase + C400_5380_REG_OFFSET + C80_CSDR; + z->ICR = dev->id_iobase + C400_5380_REG_OFFSET + C80_ICR; + z->MR = dev->id_iobase + C400_5380_REG_OFFSET + C80_MR; + z->TCR = dev->id_iobase + C400_5380_REG_OFFSET + C80_TCR; + z->SER = dev->id_iobase + C400_5380_REG_OFFSET + C80_SER; + z->CSBR = dev->id_iobase + C400_5380_REG_OFFSET + C80_CSBR; + z->BSR = dev->id_iobase + C400_5380_REG_OFFSET + C80_BSR; + z->SDSR = dev->id_iobase + C400_5380_REG_OFFSET + C80_SDSR; + z->SDIR = dev->id_iobase + C400_5380_REG_OFFSET + C80_SDIR; + z->RPIR = dev->id_iobase + C400_5380_REG_OFFSET + C80_RPIR; + z->CSR = dev->id_iobase + C400_CSR; + z->CCR = dev->id_iobase + C400_CCR; + z->HBR = dev->id_iobase + C400_HBR; + z->PDATA = 0; + z->PSTAT = 0; + if (nca_init (z) == 0) + return (16); + + /* Try ProAudioSpectrum-16. */ + z->type = CTLR_PAS_16; + z->name = "ProAudioSpectrum"; /* changed later */ + z->ODR = dev->id_iobase ^ PAS16_REG (C80_ODR); + z->CSDR = dev->id_iobase ^ PAS16_REG (C80_CSDR); + z->ICR = dev->id_iobase ^ PAS16_REG (C80_ICR); + z->MR = dev->id_iobase ^ PAS16_REG (C80_MR); + z->TCR = dev->id_iobase ^ PAS16_REG (C80_TCR); + z->SER = dev->id_iobase ^ PAS16_REG (C80_SER); + z->CSBR = dev->id_iobase ^ PAS16_REG (C80_CSBR); + z->BSR = dev->id_iobase ^ PAS16_REG (C80_BSR); + z->SDSR = dev->id_iobase ^ PAS16_REG (C80_SDSR); + z->SDIR = dev->id_iobase ^ PAS16_REG (C80_SDIR); + z->RPIR = dev->id_iobase ^ PAS16_REG (C80_RPIR); + z->CSR = 0; + z->CCR = 0; + z->HBR = 0; + z->PDATA = dev->id_iobase ^ PAS16_REG (PAS16_DATA); + z->PSTAT = dev->id_iobase ^ PAS16_REG (PAS16_STAT); + if (nca_init (z) == 0) + return (4); + + bzero (z, sizeof (*z)); + return (0); +} + +/* + * Probe the adapter, and if found, reset the board and the scsi bus. + * Return 0 if the adapter found. + */ +int nca_init (adapter_t *z) +{ + int i, c; + + if (z->type == CTLR_NCR_53C400) { + if (inb (z->CSR) == 0xFF) + return (100); + + /* Reset 53C400. */ + outb (z->CSR, CSR_5380_ENABLE); + + /* Enable interrupts. */ + outb (z->CSR, z->irq ? CSR_5380_INTR : 0); + } + + if (z->type == CTLR_PAS_16) { + u_short base = z->PDATA & 0x3FF; + + outb (0x9a01, 0xbc + (z-ncadata)); /* unit number */ + outb (0x9a01, base >> 2); + + if (inb (base^0x803) == 0xFF) + return (200); + + if (inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF && + inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF && + inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF && + inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF) + return (201); + + i = inb (base^0x803); + outb (base^0x803, i ^ 0xE0); + c = inb (base^0x803); + outb (base^0x803, 1); + if (i != c) + return (202); + + /* Various magic. */ + outb (base^0x4000, 0x30); /* Timeout counter */ + outb (base^0x4001, 0x01); /* Reset TC */ + outb (base^0xbc00, 0x01); /* 1 Wait state */ + outb (base^0x8003, 0x4d); /* sysconfig_4 */ + i = pas16_irq_magic[z->irq]; + if (!i) { + z->irq = 0; + } else { + outb (base^0xf002, i << 4); + outb (base^0x8003, 0x6d); /* sysconfig_4 */ + } + + switch (inb (base^0xEC03) & 0xF) { + case 6: z->name = "ProAudioSpectrum-Plus"; break; + case 12: z->name = "ProAudioSpectrum-16D"; break; + case 14: z->name = "ProAudioSpectrum-CDPC"; break; + case 15: z->name = "ProAudioSpectrum-16"; break; + default: return (203); + } + } + + /* Read RPI port, resetting parity/interrupt state. */ + inb (z->RPIR); + + /* Test BSR: parity error, interrupt request and busy loss state + * should be cleared. */ + if (inb (z->BSR) & (BSR_PARITY_ERROR | + BSR_INTERRUPT_REQUEST_ACTIVE | BSR_BUSY_ERROR)) { + PRINT (("nca: invalid bsr[0x%x]=%b\n", z->BSR, + inb (z->BSR), BSR_BITS)); + return (1); + } + + /* Reset the SCSI bus. */ + outb (z->ICR, ICR_ASSERT_RST); + outb (z->ODR, 0); + /* Hold reset for at least 25 microseconds. */ + DELAY (25); + /* Check that status cleared. */ + if (inb (z->CSBR) != CSBR_RST) { + PRINT (("nca: invalid csbr[0x%x]=%b\n", z->CSBR, + inb (z->CSBR), CSBR_BITS)); + outb (z->ICR, 0); + return (2); + } + /* Clear reset. */ + outb (z->ICR, 0); + /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */ + DELAY (2); + + /* Enable data drivers. */ + outb (z->ICR, ICR_ASSERT_DATA_BUS); + + /* Check that data register is writable. */ + for (i=0; i<256; ++i) { + outb (z->ODR, i); + DELAY (1); + if (inb (z->CSDR) != i) { + PRINT (("nca: ODR[0x%x] not writable: 0x%x should be 0x%x\n", + z->ODR, inb (z->CSDR), i)); + outb (z->ICR, 0); + return (3); + } + } + + /* Disable data drivers. */ + outb (z->ICR, 0); + + /* Check that data register is NOT writable. */ + c = inb (z->CSDR); + for (i=0; i<256; ++i) { + outb (z->ODR, i); + DELAY (1); + if (inb (z->CSDR) != c) { + PRINT (("nca: ODR[0x%x] writable: 0x%x should be 0x%x\n", + z->ODR, inb (z->CSDR), c)); + return (4); + } + } + + /* Initialize the controller. */ + outb (z->MR, z->parity); + outb (z->TCR, 0); + outb (z->SER, z->scsi_id); + return (0); +} + +/* + * Attach all sub-devices we can find. + */ +int nca_attach (struct isa_device *dev) +{ + int unit = dev->id_unit; + adapter_t *z = &ncadata[unit]; + struct scsibus_data *scbus; + + printf ("nca%d: type %s%s\n", unit, z->name, + (dev->id_flags & FLAG_NOPARITY) ? ", no parity" : ""); + + /* fill in the prototype scsi_link */ + z->sc_link.adapter_unit = unit; + z->sc_link.adapter_targ = z->scsi_addr; + z->sc_link.adapter_softc = z; + z->sc_link.adapter = &nca_switch; + z->sc_link.device = &nca_dev; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if(!scbus) + return 0; + scbus->adapter_link = &z->sc_link; + + /* ask the adapter what subunits are present */ + scsi_attachdevs (scbus); + + return (1); +} + +/* + * Return some information to the caller about + * the adapter and its capabilities. + */ +u_int32_t nca_adapter_info (int unit) +{ + return (1); +} + +void ncaminphys (struct buf *bp) +{ +} + +/* + * Catch an interrupt from the adaptor. + */ +void ncaintr (int unit) +{ + adapter_t *z = &ncadata[unit]; + + PRINT (("nca%d: interrupt bsr=%b csbr=%b\n", unit, + inb (z->BSR), BSR_BITS, inb (z->CSBR), CSBR_BITS)); + nca_start (z); + /* Reset interrupt state. */ + inb (z->RPIR); +} + +/* + * This routine is used in the case when we have no IRQ line (z->irq == 0). + * It is called every timer tick and polls for reconnect from target. + */ +void nca_tick (void *arg) +{ + adapter_t *z = arg; + int x = splbio (); + + z->timeout_active = 0; + nca_start (z); + /* Reset interrupt state. */ + inb (z->RPIR); + if (z->disconnected_queue && ! z->timeout_active) { + timeout (nca_tick, z, 1); + z->timeout_active = 1; + } + splx (x); +} + +/* + * Start a scsi operation given the command and the data address. + * Also needs the unit, target and lu. Get a free scb and set it up. + * Call send_scb. Either start timer or wait until done. + */ +int32_t nca_scsi_cmd (struct scsi_xfer *xs) +{ + int unit = xs->sc_link->adapter_unit, flags = xs->flags, x = 0; + adapter_t *z = (adapter_t *)xs->sc_link->adapter_softc; + scb_t *scb; + + /* PRINT (("nca%d/%d/%d command 0x%x\n", unit, xs->sc_link->target, + xs->sc_link->lun, xs->cmd->opcode)); */ + if (xs->bp) + flags |= SCSI_NOSLEEP; + if (flags & ITSDONE) { + printf ("nca%d: already done?", unit); + xs->flags &= ~ITSDONE; + } + if (! (flags & INUSE)) { + printf ("nca%d: not in use?", unit); + xs->flags |= INUSE; + } + if (flags & SCSI_RESET) + printf ("nca%d: SCSI_RESET not implemented\n", unit); + + if (! (flags & SCSI_NOMASK)) + x = splbio (); + + /* Get a free scb. + * If we can and have to, sleep waiting for one to come free. */ + while (! (scb = z->free_scb)) { + if (flags & SCSI_NOSLEEP) { + xs->error = XS_DRIVER_STUFFUP; + if (! (flags & SCSI_NOMASK)) + splx (x); + return (TRY_AGAIN_LATER); + } + tsleep ((caddr_t)&z->free_scb, PRIBIO, "ncascb", 0); + } + /* Get scb from free list. */ + z->free_scb = scb->next; + scb->next = 0; + scb->flags = SCB_ACTIVE; + + /* Put all the arguments for the xfer in the scb */ + scb->xfer = xs; + scb->datalen = xs->datalen; + scb->data = xs->data; + + /* Setup the scb to contain necessary values. + * The interesting values can be read from the xs that is saved. + * I therefore think that the structure can be kept very small. + * The driver doesn't use DMA so the scatter/gather is not needed? */ + if (! z->queue) { + scb->next = z->queue; + z->queue = scb; + } else { + scb_t *q; + + for (q=z->queue; q->next; q=q->next) + continue; + q->next = scb; + scb->next = 0; /* placed at the end of the queue */ + } + + /* Try to send this command to the board. */ + nca_start (z); + + /* Usually return SUCCESSFULLY QUEUED. */ + if (! (flags & SCSI_NOMASK)) { + splx (x); + if (xs->flags & ITSDONE) + /* Timeout timer not started, already finished. + * Tried to return COMPLETE but the machine hanged + * with this. */ + return (SUCCESSFULLY_QUEUED); + xs->timeout_ch = timeout (nca_timeout, (caddr_t) scb, + (xs->timeout * hz) / 1000); + scb->flags |= SCB_TIMECHK; + PRINT (("nca%d/%d/%d command queued\n", unit, + xs->sc_link->target, xs->sc_link->lun)); + return (SUCCESSFULLY_QUEUED); + } + + /* If we can't use interrupts, poll on completion. */ + if (! nca_poll (z, scb)) { + /* We timed out, so call the timeout handler manually, + * accounting for the fact that the clock is not running yet + * by taking out the clock queue entry it makes. */ + nca_timeout ((void*) scb); + + /* Because we are polling, take out the timeout entry + * nca_timeout made. */ + untimeout (nca_timeout, (void*) scb, scb->xfer->timeout_ch); + + if (! nca_poll (z, scb)) + /* We timed out again... This is bad. Notice that + * this time there is no clock queue entry to remove. */ + nca_timeout ((void*) scb); + } + /* PRINT (("nca%d/%d/%d command %s\n", unit, + xs->sc_link->target, xs->sc_link->lun, + xs->error ? "failed" : "done")); */ + return (xs->error ? HAD_ERROR : COMPLETE); +} + +/* + * Coroutine that runs as long as more work can be done. + * Both scsi_cmd() and intr() will try to start it in + * case it is not running. + * Always called with interrupts disabled. + */ +void nca_start (adapter_t *z) +{ + scb_t *q, *prev; +again: + /* First check that if any device has tried + * a reconnect while we have done other things + * with interrupts disabled. */ + if (nca_reselect (z)) + goto again; + + /* Search through the queue for a command + * destined for a target that's not busy. */ + for (q=z->queue, prev=0; q; prev=q, q=q->next) { + /* Attempt to establish an I_T_L nexus here. */ + if (IS_BUSY (z, q) || ! nca_select (z, q)) + continue; + + /* Remove the command from the issue queue. */ + if (prev) + prev->next = q->next; + else + z->queue = q->next; + q->next = 0; + + /* We are connected. Do the task. */ + nca_information_transfer (z, q); + goto again; + } +} + +void nca_timeout (void *arg) +{ + scb_t *scb = (scb_t*) arg; + int unit = scb->xfer->sc_link->adapter_unit; + adapter_t *z = (adapter_t *)scb->xfer->sc_link->adapter_softc; + int x = splbio (); + + if (! (scb->xfer->flags & SCSI_NOMASK)) + printf ("nca%d/%d/%d (%s%d) timed out\n", unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + scb->xfer->sc_link->device->name, + scb->xfer->sc_link->dev_unit); + + /* If it has been through before, then a previous abort has failed, + * don't try abort again. */ + if (! (scb->flags & SCB_ABORTED)) { + nca_abort (z, scb); + /* 2 seconds for the abort */ + scb->xfer->timeout_ch = timeout (nca_timeout, (caddr_t)scb, + 2*hz); + scb->flags |= (SCB_ABORTED | SCB_TIMECHK); + } else { + /* abort timed out */ + scb->flags |= SCB_ABORTED; + scb->xfer->retries = 0; + nca_done (z, scb); + } + splx (x); +} + +static __inline void nca_sendbyte (adapter_t *z, u_char data) +{ + outb (z->ODR, data); + outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_ACK); + WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 10000, "sendbyte"); + outb (z->ICR, ICR_ASSERT_DATA_BUS); +} + +static __inline u_char nca_recvbyte (adapter_t *z) +{ + u_char data; + + data = inb (z->CSDR); + outb (z->ICR, ICR_ASSERT_ACK); + WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 10000, "recvbyte"); + outb (z->ICR, 0); + return (data); +} + +/* + * Establish I_T_L or I_T_L_Q nexus for new or existing command + * including ARBITRATION, SELECTION, and initial message out + * for IDENTIFY and queue messages. + * Return 1 if selection succeded. + */ +int nca_select (adapter_t *z, scb_t *scb) +{ + /* Set the phase bits to 0, otherwise the NCR5380 won't drive the + * data bus during SELECTION. */ + outb (z->TCR, 0); + + /* Start arbitration. */ + outb (z->ODR, z->scsi_id); + outb (z->MR, MR_ARBITRATE); + + /* Wait for arbitration logic to complete (20 usec) */ + WAITFOR (inb (z->ICR) & ICR_ARBITRATION_IN_PROGRESS, 200, 0); + if (! (inb (z->ICR) & ICR_ARBITRATION_IN_PROGRESS)) { + PRINT (("nca%d/%d/%d no arbitration progress, bsr=%b csbr=%b\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, inb (z->BSR), BSR_BITS, + inb (z->CSBR), CSBR_BITS)); + outb (z->MR, z->parity); + return (0); + } + DELAY (3); + + /* Check for lost arbitration. */ + if ((inb (z->ICR) & ICR_LOST_ARBITRATION) || + (inb (z->CSDR) >> 1 >> z->scsi_addr) || + (inb (z->ICR) & ICR_LOST_ARBITRATION)) { + PRINT (("nca%d/%d/%d arbitration lost\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + outb (z->MR, z->parity); + return (0); + } + + outb (z->ICR, ICR_ASSERT_SEL); + if (inb (z->ICR) & ICR_LOST_ARBITRATION) { + PRINT (("nca%d/%d/%d arbitration lost after SEL\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + outb (z->ICR, 0); + outb (z->MR, z->parity); + return (0); + } + DELAY (2); + + /* Start selection, asserting the host and target ID's on the bus. */ + outb (z->SER, 0); + outb (z->ODR, z->scsi_id | (1 << scb->xfer->sc_link->target)); + outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_BSY | + ICR_ASSERT_SEL); + + /* Finish arbitration, drop BSY. */ + outb (z->MR, 0); + outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_SEL | + ICR_ASSERT_ATN); + DELAY (1); + + /* The SCSI specification calls for a 250 ms timeout for the actual + * selection. */ + WAITFOR (inb (z->CSBR) & CSBR_BSY, 100000, 0); + if (! (inb (z->CSBR) & CSBR_BSY)) { + /* The target does not respond. Not an error, though. */ + PRINT (("nca%d/%d/%d target does not respond\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + outb (z->ICR, 0); + outb (z->SER, z->scsi_id); + outb (z->MR, z->parity); + scb->flags |= SCB_TIMEOUT; + return (0); + } + + /* Clear SEL and SCSI id. + * Wait for start of REQ/ACK handshake. */ + outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_ATN); + WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, 0); + if (! (inb (z->CSBR) & CSBR_REQ)) { + PRINT (("nca%d/%d/%d timeout waiting for REQ\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + outb (z->ICR, 0); + outb (z->SER, z->scsi_id); + outb (z->MR, z->parity); + scb->flags |= SCB_ERROR; + return (0); + } + + /* Check for phase mismatch. */ + if ((inb (z->CSBR) & PHASE_MASK) != PHASE_MSGOUT) { + /* This should not be taken as an error, but more like + * an unsupported feature! + * Should set a flag indicating that the target don't support + * messages, and continue without failure. + * (THIS IS NOT AN ERROR!) */ + PRINT (("nca%d/%d/%d waiting for MSGOUT: invalid phase %s\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + PHASE_NAME (inb (z->CSBR) & PHASE_MASK))); + outb (z->ICR, 0); + outb (z->SER, z->scsi_id); + outb (z->MR, z->parity); + scb->flags |= SCB_ERROR; + return (0); + } + + /* Allow disconnects. */ + outb (z->TCR, PHASE_TO_TCR (PHASE_MSGOUT)); + outb (z->ICR, ICR_ASSERT_DATA_BUS); + nca_sendbyte (z, MSG_IDENTIFY (scb->xfer->sc_link->lun)); + outb (z->ICR, 0); + outb (z->SER, z->scsi_id); + outb (z->MR, z->parity); + + SET_BUSY (z, scb); + return (1); +} + +int nca_reselect (adapter_t *z) +{ + scb_t *q = 0, *prev = 0; + u_char msg, target_mask, lun; +again: + /* Wait for a device to win the reselection phase. */ + /* Signals this by asserting the I/O signal. */ + if ((inb (z->CSBR) & (CSBR_SEL | CSBR_IO | CSBR_BSY)) != + (CSBR_SEL | CSBR_IO)) + return (0); + + /* The data bus contains original initiator id ORed with target id. */ + /* See that we really are the initiator. */ + target_mask = inb (z->CSDR); + if (! (target_mask & z->scsi_id)) { + PRINT (("nca%d reselect not for me: mask=0x%x, csbr=%b\n", + z->sc_link.adapter_unit, target_mask, + inb (z->CSBR), CSBR_BITS)); + goto again; + } + + /* Find target who won. */ + /* Host responds by asserting the BSY signal. */ + /* Target should respond by deasserting the SEL signal. */ + target_mask &= ~z->scsi_id; + outb (z->ICR, ICR_ASSERT_BSY); + WAITFOR (! (inb (z->CSBR) & CSBR_SEL), 10000, "SEL deassert"); + + /* Remove the busy status. */ + /* Target should set the MSGIN phase. */ + outb (z->ICR, 0); + WAITFOR (inb (z->CSBR) & CSBR_REQ, 10000, "MSGIN"); + + /* Hope we get an IDENTIFY message. */ + msg = nca_msg_input (z); + if (MSG_ISIDENT (msg)) { + /* Find the command corresponding to the I_T_L or I_T_L_Q + * nexus we just restablished, and remove it from + * the disconnected queue. */ + lun = (msg & 7); + for (q=z->disconnected_queue; q; prev=q, q=q->next) { + if (target_mask != (1 << q->xfer->sc_link->target)) + continue; + if (lun != q->xfer->sc_link->lun) + continue; + if (prev) + prev->next = q->next; + else + z->disconnected_queue = q->next; + q->next = 0; + PRINT (("nca%d/%d/%d reselect done\n", + z->sc_link.adapter_unit, + ffs (target_mask) - 1, lun)); + nca_information_transfer (z, q); + WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "reselect !busy"); + return (1); + } + } else + printf ("nca%d reselect: expecting IDENTIFY, got 0x%x\n", + z->sc_link.adapter_unit, msg); + + /* Since we have an established nexus that we can't + * do anything with, we must abort it. */ + nca_send_abort (z); + PRINT (("nca%d reselect aborted\n", z->sc_link.adapter_unit)); + WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "reselect abort !busy"); + goto again; +} + +/* + * Send an abort to the target. + * Return 1 success, 0 on failure. + * Called on splbio level. + */ +int nca_abort (adapter_t *z, scb_t *scb) +{ + scb_t *q, **prev; + + /* If the command hasn't been issued yet, we simply remove it + * from the issue queue. */ + prev = &z->queue; + for (q=z->queue; q; q=q->next) { + if (scb == q) { + (*prev) = q->next; + q->next = 0; + return (1); + } + prev = &q->next; + } + + /* If the command is currently disconnected from the bus, + * we reconnect the I_T_L or I_T_L_Q nexus associated with it, + * go into message out, and send an abort message. */ + for (q=z->disconnected_queue; q; q=q->next) { + if (scb != q) + continue; + + if (! nca_select (z, scb)) + return (0); + nca_send_abort (z); + + prev = &z->disconnected_queue; + for (q=z->disconnected_queue; q; q=q->next) { + if (scb == q) { + *prev = q->next; + q->next = 0; + /* Set some type of error result + * for the operation. */ + return (1); + } + prev = &q->next; + } + } + + /* Command not found in any queue. */ + return (0); +} + +/* + * The task accomplished, mark the i/o control block as done. + * Always called with interrupts disabled. + */ +void nca_done (adapter_t *z, scb_t *scb) +{ + struct scsi_xfer *xs = scb->xfer; + + if (scb->flags & SCB_TIMECHK) + untimeout (nca_timeout, (caddr_t) scb, xs->timeout_ch); + + /* How much of the buffer was not touched. */ + xs->resid = scb->datalen; + + if (scb->flags != SCB_ACTIVE && ! (xs->flags & SCSI_ERR_OK)) + if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED)) + xs->error = XS_TIMEOUT; + else if (scb->flags & SCB_ERROR) + xs->error = XS_DRIVER_STUFFUP; + else if (scb->flags & SCB_TBUSY) + xs->error = XS_BUSY; + else if (scb->flags & SCB_SENSE) + xs->error = XS_SENSE; + + xs->flags |= ITSDONE; + + /* Free the control block. */ + scb->next = z->free_scb; + z->free_scb = scb; + scb->flags = SCB_FREE; + + /* If there were none, wake anybody waiting for one to come free, + * starting with queued entries. */ + if (! scb->next) + wakeup ((caddr_t) &z->free_scb); + + scsi_done (xs); +} + +/* + * Wait for completion of command in polled mode. + * Always called with interrupts masked out. + */ +int nca_poll (adapter_t *z, scb_t *scb) +{ + int count; + + for (count=0; count<30; ++count) { + DELAY (1000); /* delay for a while */ + nca_start (z); /* retry operation */ + if (scb->xfer->flags & ITSDONE) + return (1); /* all is done */ + if (scb->flags & SCB_TIMEOUT) + return (0); /* no target present */ + } + return (0); +} + +/* + * Perform NCR-53C400 pseudo-dma data transfer. + */ +void nca_53400_dma_xfer (adapter_t *z, int read, u_char **pdata, u_long *plen) +{ + /* Set dma direction. */ + outb (z->CSR, read ? CSR_TRANSFER_DIRECTION : 0); + + /* Enable dma mode. */ + outb (z->MR, MR_DMA_MODE | (read ? z->parity : 0)); + + /* Start dma transfer. */ + outb (read ? z->SDIR : z->SDSR, 0); + + /* Set up clock counter. */ + outb (z->CCR, *plen/128); + + for (; *plen>=128; *plen-=128, *pdata+=128) { + /* Wait for 53C400 host buffer ready. */ + WAITFOR (! (inb (z->CSR) & CSR_HOST_BUF_NOT_READY), 100000, 0); + if (inb (z->CSR) & CSR_HOST_BUF_NOT_READY) + break; + + /* Transfer 128 bytes of data. */ + if (read) + insw (z->HBR, *pdata, 64); + else + outsw (z->HBR, *pdata, 64); + } + + /* Wait for 5380 registers ready. */ + WAITFOR (inb (z->CSR) & CSR_5380_ENABLE, 10000, 0); + if (! (inb (z->CSR) & CSR_5380_ENABLE)) { + /* Reset 53C400. */ + PRINT (("nca%d: reset: pseudo-dma incomplete, csr=%b\n", + z->sc_link.adapter_unit, inb (z->CSR), CSR_BITS)); + outb (z->CSR, CSR_5380_ENABLE); + outb (z->CSR, 0); + } + + /* Wait for FIFO flush on write. */ + if (! read) + WAITFOR (inb (z->TCR) & TCR_LAST_BYTE_SENT, 10000, "last byte"); + + /* Clear dma mode. */ + outb (z->MR, z->parity); + + /* Re-enable interrupts. */ + outb (z->CSR, z->irq ? CSR_5380_INTR : 0); +} + +/* + * Perform PAS-16 pseudo-dma data transfer. + */ +void nca_pas_dma_xfer (adapter_t *z, int read, u_char **pdata, u_long *plen) +{ + /* Enable dma mode. */ + outb (z->MR, MR_DMA_MODE | (read ? z->parity : 0)); + + /* Start dma transfer. */ + outb (read ? z->SDIR : z->SDSR, 0); + + for (; *plen>=512; *plen-=512, *pdata+=512) { + /* Wait for pseudo-DMA request. */ + WAITFOR (inb (z->PSTAT) & PAS16_STAT_DREQ, 10000, "pseudo-dma"); + if (! (inb (z->PSTAT) & PAS16_STAT_DREQ)) + break; + + /* Transfer 512 bytes of data. */ + if (read) + insb (z->PDATA, *pdata, 512); + else + outsb (z->PDATA, *pdata, 512); + } + + /* Clear dma mode. */ + outb (z->MR, z->parity); +} + +/* + * Send data to the target. + */ +void nca_data_output (adapter_t *z, u_char **pdata, u_long *plen) +{ + u_char *data = *pdata; + u_long len = *plen; + + outb (z->ICR, ICR_ASSERT_DATA_BUS); + if (z->type == CTLR_NCR_53C400 && len%128 == 0) + /* Use NCR-53C400 pseudo-dma for data transfer. */ + nca_53400_dma_xfer (z, 0, &data, &len); + else if (z->type == CTLR_PAS_16 && len%512 == 0) + /* Use PAS-16 pseudo-dma for data transfer. */ + nca_pas_dma_xfer (z, 0, &data, &len); + else + for (;;) { + /* Check SCSI bus phase. */ + u_char s = inb (z->CSBR) ^ (CSBR_BSY | PHASE_DATAOUT); + if (s & (CSBR_BSY | PHASE_MASK)) + break; + + /* Wait for REQ. */ + if (! (s & CSBR_REQ)) + continue; + + /* Output data. */ + outb (z->ODR, *data++); + + /* Assert ACK and wait for REQ deassert, + * with irqs disabled. */ + disable_intr (); + outb (z->ICR, ICR_ASSERT_ACK | ICR_ASSERT_DATA_BUS); + WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 1000, 0); + enable_intr (); + + /* Deassert ACK. */ + outb (z->ICR, ICR_ASSERT_DATA_BUS); + --len; + } + outb (z->ICR, 0); + PRINT (("nca (DATAOUT) send %ld bytes\n", *plen - len)); + *plen = len; + *pdata = data; +} + +/* + * Receive data from the target. + */ +void nca_data_input (adapter_t *z, u_char **pdata, u_long *plen) +{ + u_char *data = *pdata; + u_long len = *plen; + + if (z->type == CTLR_NCR_53C400 && len%128 == 0) + /* Use NCR-53C400 pseudo-dma for data transfer. */ + nca_53400_dma_xfer (z, 1, &data, &len); + else if (z->type == CTLR_PAS_16 && len%512 == 0) + /* Use PAS-16 pseudo-dma for data transfer. */ + nca_pas_dma_xfer (z, 1, &data, &len); + else + for (;;) { + /* Check SCSI bus phase. */ + u_char s = inb (z->CSBR) ^ (CSBR_BSY | PHASE_DATAIN); + if (s & (CSBR_BSY | PHASE_MASK)) + break; + + /* Wait for REQ. */ + if (! (s & CSBR_REQ)) + continue; + + /* Input data. */ + *data++ = inb (z->CSDR); + + /* Assert ACK and wait for REQ deassert, + * with irqs disabled. */ + disable_intr (); + outb (z->ICR, ICR_ASSERT_ACK); + WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 1000, 0); + enable_intr (); + + /* Deassert ACK. */ + outb (z->ICR, 0); + --len; + } + PRINT (("nca (DATAIN) got %ld bytes\n", *plen - len)); + *plen = len; + *pdata = data; +} + +/* + * Send the command to the target. + */ +void nca_cmd_output (adapter_t *z, u_char *cmd, int cmdlen) +{ + PRINT (("nca%d send command (%d bytes) ", z->sc_link.adapter_unit, + cmdlen)); + + outb (z->ICR, ICR_ASSERT_DATA_BUS); + while (cmdlen) { + /* Check for target disconnect. */ + u_char sts = inb (z->CSBR); + if (! (sts & CSBR_BSY)) + break; + + /* Check for phase mismatch. */ + if ((sts & PHASE_MASK) != PHASE_CMDOUT) { + printf ("nca: sending command: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + break; + } + + /* Wait for REQ. */ + if (! (sts & CSBR_REQ)) + continue; + + PRINT (("-%x", *cmd)); + nca_sendbyte (z, *cmd++); + --cmdlen; + } + outb (z->ICR, 0); + PRINT (("\n")); +} + +/* + * Send the message to the target. + */ +void nca_send_abort (adapter_t *z) +{ + u_char sts; + + outb (z->ICR, ICR_ASSERT_ATN); + + /* Wait for REQ, after which the phase bits will be valid. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 1000000, "abort message"); + sts = inb (z->CSBR); + if (! (sts & CSBR_REQ)) + goto ret; + + /* Check for phase mismatch. */ + if ((sts & PHASE_MASK) != PHASE_MSGOUT) { + printf ("nca: sending MSG_ABORT: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + goto ret; + } + + outb (z->ICR, ICR_ASSERT_DATA_BUS); + outb (z->TCR, PHASE_TO_TCR (PHASE_MSGOUT)); + nca_sendbyte (z, MSG_ABORT); + + PRINT (("nca%d send MSG_ABORT\n", z->sc_link.adapter_unit)); +ret: outb (z->ICR, 0); +} + +/* + * Get the message from the target. + * Return the length of the received message. + */ +u_char nca_msg_input (adapter_t *z) +{ + u_char sts, msg; + + /* Wait for REQ, after which the phase bits will be valid. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 1000000, "message input"); + sts = inb (z->CSBR); + if (! (sts & CSBR_REQ)) + return (MSG_ABORT); + + /* Check for phase mismatch. + * Reached if the target decides that it has finished the transfer. */ + if ((sts & PHASE_MASK) != PHASE_MSGIN) { + printf ("nca: sending message: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + return (MSG_ABORT); + } + + /* Do actual transfer from SCSI bus to memory. */ + outb (z->TCR, PHASE_TO_TCR (PHASE_MSGIN)); + msg = nca_recvbyte (z); + PRINT (("nca%d (MSG_INPUT) got 0x%x\n", z->sc_link.adapter_unit, msg)); + return (msg); +} + +/* + * Send request-sense op to the target. + * Return 1 success, 0 on failure. + * Called on splbio level. + */ +int nca_sense (adapter_t *z, scb_t *scb) +{ + u_char cmd[6], status, msg, *data; + u_long len; + + /* Wait for target to disconnect. */ + WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "sense bus free"); + if (inb (z->CSBR) & CSBR_BSY) + return (0); + + /* Select the target again. */ + if (! nca_select (z, scb)) + return (0); + + /* Wait for CMDOUT phase. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense CMDOUT"); + if (! (inb (z->CSBR) & CSBR_REQ) || + (inb (z->CSBR) & PHASE_MASK) != PHASE_CMDOUT) + return (0); + outb (z->TCR, PHASE_TO_TCR (PHASE_CMDOUT)); + + /* Send command. */ + len = sizeof (scb->xfer->sense); + cmd[0] = REQUEST_SENSE; + cmd[1] = scb->xfer->sc_link->lun << 5; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = len; + cmd[5] = 0; + nca_cmd_output (z, cmd, sizeof (cmd)); + + /* Wait for DATAIN phase. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense DATAIN"); + if (! (inb (z->CSBR) & CSBR_REQ) || + (inb (z->CSBR) & PHASE_MASK) != PHASE_DATAIN) + return (0); + outb (z->TCR, PHASE_TO_TCR (PHASE_DATAIN)); + + data = (u_char*) &scb->xfer->sense; + nca_data_input (z, &data, &len); + PRINT (("nca%d sense %x-%x-%x-%x-%x-%x-%x-%x\n", + z->sc_link.adapter_unit, scb->xfer->sense.error_code, + scb->xfer->sense.ext.extended.segment, + scb->xfer->sense.ext.extended.flags, + scb->xfer->sense.ext.extended.info[0], + scb->xfer->sense.ext.extended.info[1], + scb->xfer->sense.ext.extended.info[2], + scb->xfer->sense.ext.extended.info[3], + scb->xfer->sense.ext.extended.extra_len)); + + /* Wait for STATIN phase. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense STATIN"); + if (! (inb (z->CSBR) & CSBR_REQ) || + (inb (z->CSBR) & PHASE_MASK) != PHASE_STATIN) + return (0); + outb (z->TCR, PHASE_TO_TCR (PHASE_STATIN)); + + status = nca_recvbyte (z); + + /* Wait for MSGIN phase. */ + WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense MSGIN"); + if (! (inb (z->CSBR) & CSBR_REQ) || + (inb (z->CSBR) & PHASE_MASK) != PHASE_MSGIN) + return (0); + outb (z->TCR, PHASE_TO_TCR (PHASE_MSGIN)); + + msg = nca_recvbyte (z); + + if (status != 0 || msg != 0) + printf ("nca%d: bad sense status=0x%x, msg=0x%x\n", + z->sc_link.adapter_unit, status, msg); + return (1); +} + +/* + * Do the transfer. We know we are connected. Update the flags, + * call nca_done when task accomplished. Dialog controlled by the target. + * Always called with interrupts disabled. + */ +void nca_information_transfer (adapter_t *z, scb_t *scb) +{ + u_char *data = scb->data; /* current data buffer */ + u_long datalen = scb->datalen; /* current data transfer size */ + register u_char sts; + u_char msg; + + while ((sts = inb (z->CSBR)) & CSBR_BSY) { + /* We only have a valid SCSI phase when REQ is asserted. */ + if (! (sts & CSBR_REQ)) + continue; + if (inb (z->BSR) & BSR_PARITY_ERROR) { + int target = scb->xfer->sc_link->target; + if (++z->target[target].perrcnt <= 8) + printf ("nca%d/%d/%d parity error\n", + z->sc_link.adapter_unit, target, + scb->xfer->sc_link->lun); + if (z->target[target].perrcnt == 8) + printf ("nca%d/%d/%d too many parity errors, not logging any more\n", + z->sc_link.adapter_unit, target, + scb->xfer->sc_link->lun); + /* Clear parity error. */ + inb (z->RPIR); + } + outb (z->TCR, PHASE_TO_TCR (sts & PHASE_MASK)); + switch (sts & PHASE_MASK) { + case PHASE_DATAOUT: + if (datalen <= 0) { + printf ("nca%d/%d/%d data length underflow\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun); + /* send zero byte */ + outb (z->ICR, ICR_ASSERT_DATA_BUS); + nca_sendbyte (z, 0); + outb (z->ICR, 0); + break; + } + nca_data_output (z, &data, &datalen); + break; + case PHASE_DATAIN: + if (datalen <= 0) { + /* Get extra data. Some devices (e.g. CDROMs) + * use fixed-length blocks (e.g. 2k), + * even if we need less. */ + PRINT (("@")); + nca_recvbyte (z); + break; + } + nca_data_input (z, &data, &datalen); + break; + case PHASE_CMDOUT: + nca_cmd_output (z, (u_char*) scb->xfer->cmd, + scb->xfer->cmdlen); + break; + case PHASE_STATIN: + scb->xfer->status = nca_recvbyte (z); + PRINT (("nca%d/%d/%d (STATIN) got 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + (u_char) scb->xfer->status)); + break; + case PHASE_MSGOUT: + /* Send no-op message. */ + outb (z->ICR, ICR_ASSERT_DATA_BUS); + nca_sendbyte (z, MSG_NOP); + outb (z->ICR, 0); + PRINT (("nca%d/%d/%d (MSGOUT) send NOP\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + break; + case PHASE_MSGIN: + /* Don't handle multi-byte messages here, because they + * should not be present here. */ + msg = nca_recvbyte (z); + PRINT (("nca%d/%d/%d (MSGIN) got 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, msg)); + switch (msg) { + case MSG_COMMAND_COMPLETE: + scb->data = data; + scb->datalen = datalen; + /* In the case of check-condition status, + * perform the request-sense op. */ + switch (scb->xfer->status & 0x1e) { + case SCSI_CHECK: + if (nca_sense (z, scb)) + scb->flags = SCB_SENSE; + break; + case SCSI_BUSY: + scb->flags = SCB_TBUSY; + break; + } + goto done; + case MSG_ABORT: + printf ("nca: command aborted by target\n"); + scb->flags = SCB_ABORTED; + goto done; + case MSG_MESSAGE_REJECT: + printf ("nca: message rejected\n"); + scb->flags = SCB_ABORTED; + goto done; + case MSG_DISCONNECT: + scb->next = z->disconnected_queue; + z->disconnected_queue = scb; + if (! z->irq && ! z->timeout_active) { + timeout (nca_tick, z, 1); + z->timeout_active = 1; + } + PRINT (("nca%d/%d/%d disconnected\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + goto ret; + case MSG_SAVE_POINTERS: + scb->data = data; + scb->datalen = datalen; + break; + case MSG_RESTORE_POINTERS: + data = scb->data; + datalen = scb->datalen; + break; + default: + printf ("nca%d/%d/%d unknown message: 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, msg); + break; + } + break; + default: + printf ("nca: unknown phase: %b\n", sts, CSBR_BITS); + break; + } + } + printf ("nca%d/%d/%d unexpected target disconnect\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun); + scb->flags = SCB_ERROR; +done: + CLEAR_BUSY (z, scb); + nca_done (z, scb); +ret: + outb (z->ICR, 0); + outb (z->TCR, 0); + outb (z->SER, z->scsi_id); + WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "xfer bus free"); +} +#endif /* NNCA */ diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 6bb4e0fa4d175..869111f5a708a 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.64 1998/12/14 19:16:17 bde Exp $ + * $Id: npx.c,v 1.60 1998/04/19 15:39:26 bde Exp $ */ #include "npx.h" @@ -58,7 +58,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 @@ -84,7 +86,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__ @@ -135,17 +145,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 /* @@ -240,10 +248,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 @@ -378,8 +384,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/i386/isa/pcaudio.c b/sys/i386/isa/pcaudio.c index 4f840619bf91b..e2b0c6557835e 100644 --- a/sys/i386/isa/pcaudio.c +++ b/sys/i386/isa/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.44 1998/12/13 23:32:44 eivind Exp $ + * $Id$ */ #include "pca.h" @@ -48,6 +48,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 */ @@ -80,44 +85,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; @@ -194,7 +161,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; @@ -563,4 +530,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/i386/isa/pcf.c b/sys/i386/isa/pcf.c index b3e11d8093e44..7b498d7e0afbc 100644 --- a/sys/i386/isa/pcf.c +++ b/sys/i386/isa/pcf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pcf.c,v 1.5 1998/11/04 22:09:17 nsouch Exp $ + * $Id: pcf.c,v 1.1.1.17 1998/08/29 17:04:23 son Exp $ * */ #include <sys/param.h> @@ -41,7 +41,7 @@ #include <dev/iicbus/iiconf.h> #include "iicbus_if.h" -#define TIMEOUT 9999 /* XXX */ +#define TIMEOUT 99999 /* XXX */ /* Status bits of S1 register (read only) */ #define nBB 0x01 /* busy when low set/reset by STOP/START*/ @@ -67,15 +67,13 @@ #define SLAVE_TRANSMITTER 0x1 #define SLAVE_RECEIVER 0x2 -#define PCF_DEFAULT_ADDR 0xaa - struct pcf_softc { int pcf_base; /* isa port */ - u_char pcf_addr; /* interface I2C address */ + int pcf_count; + int pcf_own_address; /* own address */ int pcf_slave_mode; /* receiver or transmitter */ - int pcf_started; /* 1 if start condition sent */ device_t iicbus; /* the corresponding iicbus */ }; @@ -105,13 +103,12 @@ static int pcf_probe(device_t); static int pcf_attach(device_t); static void pcf_print_child(device_t, device_t); -static int pcf_repeated_start(device_t, u_char, int); -static int pcf_start(device_t, u_char, int); +static int pcf_repeated_start(device_t, u_char); +static int pcf_start(device_t, u_char); static int pcf_stop(device_t); -static int pcf_write(device_t, char *, int, int *, int); -static int pcf_read(device_t, char *, int, int *, int, int); -static ointhand2_t pcfintr; -static int pcf_rst_card(device_t, u_char, u_char, u_char *); +static int pcf_write(device_t, char *, int, int *); +static int pcf_read(device_t, char *, int, int *); +static int pcf_rst_card(device_t, u_char); static device_method_t pcf_methods[] = { /* device interface */ @@ -122,7 +119,6 @@ static device_method_t pcf_methods[] = { DEVMETHOD(bus_print_child, pcf_print_child), /* iicbus interface */ - DEVMETHOD(iicbus_callback, iicbus_null_callback), DEVMETHOD(iicbus_repeated_start, pcf_repeated_start), DEVMETHOD(iicbus_start, pcf_start), DEVMETHOD(iicbus_stop, pcf_stop), @@ -149,6 +145,7 @@ pcfprobe_isa(struct isa_device *dvp) { device_t pcfdev; struct pcf_isa_softc *pcf; + int error; if (npcf >= MAXPCF) return (0); @@ -171,6 +168,7 @@ pcfprobe_isa(struct isa_device *dvp) if (!pcfdev) goto error; +end_probe: return (1); error: @@ -181,7 +179,6 @@ error: static int pcfattach_isa(struct isa_device *isdp) { - isdp->id_ointr = pcfintr; return (1); /* ok */ } @@ -189,21 +186,16 @@ static int pcf_probe(device_t pcfdev) { struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev); - int unit = device_get_unit(pcfdev); - - /* retrieve base address from isa initialization - * - * XXX should use ivars with isabus - */ - pcf->pcf_base = pcfdata[unit]->pcf_base; - - /* reset the chip */ - pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); /* XXX try do detect chipset */ device_set_desc(pcfdev, "PCF8584 I2C bus controller"); + pcf->iicbus = iicbus_alloc_bus(pcfdev); + + if (!pcf->iicbus) + return (EINVAL); + return (0); } @@ -211,8 +203,13 @@ static int pcf_attach(device_t pcfdev) { struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev); + int unit = device_get_unit(pcfdev); - pcf->iicbus = iicbus_alloc_bus(pcfdev); + /* retrieve base address from isa initialization + * + * XXX should use ivars with isabus + */ + pcf->pcf_base = pcfdata[unit]->pcf_base; /* probe and attach the iicbus */ device_probe_and_attach(pcf->iicbus); @@ -223,10 +220,8 @@ pcf_attach(device_t pcfdev) static void pcf_print_child(device_t bus, device_t dev) { - struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(bus); - printf(" on %s%d addr 0x%x", device_get_name(bus), - device_get_unit(bus), (int)pcf->pcf_addr); + device_get_unit(bus), iicbus_get_own_address(dev)); return; } @@ -296,39 +291,13 @@ static int pcf_stop(device_t pcfdev) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); - /* - * Send STOP condition iff the START condition was previously sent. - * STOP is sent only once even if a iicbus_stop() is called after - * an iicbus_read()... see pcf_read(): the pcf needs to send the stop - * before the last char is read. - */ - if (pcf->pcf_started) { - /* set stop condition and enable IT */ - PCF_SET_S1(pcf, PIN|ES0|ENI|STO|ACK); - - pcf->pcf_started = 0; - } + /* set stop condition and enable IT */ + PCF_SET_S1(pcf, PIN|ES0|ENI|STO|ACK); return (0); } - -static int pcf_noack(struct pcf_softc *pcf, int timeout) -{ - int noack; - int k = timeout/10; - - do { - noack = PCF_GET_S1(pcf) & LRB; - if (!noack) - break; - DELAY(10); /* XXX wait 10 us */ - } while (k--); - - return (noack); -} - -static int pcf_repeated_start(device_t pcfdev, u_char slave, int timeout) +static int pcf_repeated_start(device_t pcfdev, u_char slave) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); int error = 0; @@ -344,8 +313,8 @@ static int pcf_repeated_start(device_t pcfdev, u_char slave, int timeout) if ((error = pcf_wait_byte(pcf))) goto error; - /* check for ack */ - if (pcf_noack(pcf, timeout)) { + /* check ACK */ + if (PCF_GET_S1(pcf) & LRB) { error = IIC_ENOACK; goto error; } @@ -357,7 +326,7 @@ error: return (error); } -static int pcf_start(device_t pcfdev, u_char slave, int timeout) +static int pcf_start(device_t pcfdev, u_char slave) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); int error = 0; @@ -372,14 +341,12 @@ static int pcf_start(device_t pcfdev, u_char slave, int timeout) /* START only */ PCF_SET_S1(pcf, PIN|ES0|STA|ACK); - pcf->pcf_started = 1; - /* wait for address sent, polling */ if ((error = pcf_wait_byte(pcf))) goto error; - /* check for ACK */ - if (pcf_noack(pcf, timeout)) { + /* check ACK */ + if (PCF_GET_S1(pcf) & LRB) { error = IIC_ENOACK; goto error; } @@ -391,7 +358,7 @@ error: return (error); } -static void +void pcfintr(unit) { struct pcf_softc *pcf = @@ -499,23 +466,19 @@ error: return; } -static int pcf_rst_card(device_t pcfdev, u_char speed, u_char addr, u_char *oldaddr) +static int pcf_rst_card(device_t pcfdev, u_char speed) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); - - if (oldaddr) - *oldaddr = pcf->pcf_addr; + u_char ownaddr; /* retrieve own address from bus level */ - if (!addr) - pcf->pcf_addr = PCF_DEFAULT_ADDR; - else - pcf->pcf_addr = addr; + if ((ownaddr = iicbus_get_own_address(pcf->iicbus)) == 0) + ownaddr = 0xaa; PCF_SET_S1(pcf, PIN); /* initialize S1 */ /* own address S'O<>0 */ - PCF_SET_S0(pcf, pcf->pcf_addr >> 1); + PCF_SET_S0(pcf, ownaddr >> 1); /* select clock register */ PCF_SET_S1(pcf, PIN|ES1); @@ -546,7 +509,7 @@ static int pcf_rst_card(device_t pcfdev, u_char speed, u_char addr, u_char *olda } static int -pcf_write(device_t pcfdev, char *buf, int len, int *sent, int timeout /* us */) +pcf_write(device_t pcfdev, char *buf, int len, int *sent) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); int bytes, error = 0; @@ -560,12 +523,10 @@ pcf_write(device_t pcfdev, char *buf, int len, int *sent, int timeout /* us */) PCF_SET_S0(pcf, *buf++); - /* wait for the byte to be send */ if ((error = pcf_wait_byte(pcf))) goto error; - /* check if ack received */ - if (pcf_noack(pcf, timeout)) { + if (PCF_GET_S1(pcf) & LRB) { error = IIC_ENOACK; goto error; } @@ -586,8 +547,7 @@ error: } static int -pcf_read(device_t pcfdev, char *buf, int len, int *read, int last, - int delay /* us */) +pcf_read(device_t pcfdev, char *buf, int len, int *read) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); int bytes, error = 0; @@ -598,7 +558,7 @@ pcf_read(device_t pcfdev, char *buf, int len, int *read, int last, /* trig the bus to get the first data byte in S0 */ if (len) { - if (len == 1 && last) + if (len == 1) /* just one byte to read */ PCF_SET_S1(pcf, ES0); /* no ack */ @@ -608,25 +568,26 @@ pcf_read(device_t pcfdev, char *buf, int len, int *read, int last, bytes = 0; while (len) { - /* XXX delay needed here */ - - /* wait for trigged byte */ if ((error = pcf_wait_byte(pcf))) { pcf_stop(pcfdev); goto error; } - if (len == 1 && last) - /* ok, last data byte already in S0, no I2C activity - * on next PCF_GET_S0() */ + if (len == 1) { + + /* ok, last data byte already in S0 */ pcf_stop(pcfdev); - else if (len == 2 && last) - /* next trigged byte with no ack */ - PCF_SET_S1(pcf, ES0); + *buf = PCF_GET_S0(pcf); - /* receive byte, trig next byte */ - *buf++ = PCF_GET_S0(pcf); + } else { + if (len == 2) + /* next trigged byte with no ack */ + PCF_SET_S1(pcf, ES0); + + /* read last data byte, trig for next data byte */ + *buf++ = PCF_GET_S0(pcf); + } len --; bytes ++; diff --git a/sys/i386/isa/pcvt/pcvt_drv.c b/sys/i386/isa/pcvt/pcvt_drv.c index cb557e10a468e..90758b2cf9459 100644 --- a/sys/i386/isa/pcvt/pcvt_drv.c +++ b/sys/i386/isa/pcvt/pcvt_drv.c @@ -114,19 +114,6 @@ static void vgapelinit(void); /* read initial VGA DAC palette */ static int pcvt_xmode_set(int on, struct proc *p); /* initialize for X mode */ #endif /* XSERVER && !PCVT_USL_VT_COMPAT */ -#ifdef _DEV_KBD_KBDREG_H_ -static void detect_kbd(void *arg); -static kbd_callback_func_t pcevent; -#endif - -static cn_probe_t pccnprobe; -static cn_init_t pccninit; -static cn_getc_t pccngetc; -static cn_checkc_t pccncheckc; -static cn_putc_t pccnputc; - -CONS_DRIVER(pc, pccnprobe, pccninit, pccngetc, pccncheckc, pccnputc); - static d_open_t pcopen; static d_close_t pcclose; static d_read_t pcread; @@ -166,18 +153,17 @@ pcprobe(struct isa_device *dev) #endif /* PCVT_NETBSD > 9 */ #endif /* PCVT_NETBSD > 100 */ { -#ifdef _DEV_KBD_KBDREG_H_ - int i; +#ifdef _I386_ISA_KBDIO_H_ + kbdc = kbdc_open(IO_KBD); - if (kbd == NULL) { + if(kbdc == NULL) + { reset_keyboard = 0; - kbd_configure(KB_CONF_PROBE_ONLY); - i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)dev->id_unit); - if ((i < 0) || ((kbd = kbd_get_keyboard(i)) == NULL)) - return (-1); + return 1; } + reset_keyboard = 1; /* it's now safe to do kbd reset */ -#endif /* _DEV_KBD_KBDREG_H_ */ +#endif /* _I386_ISA_KBDIO_H_ */ kbd_code_init(); @@ -185,9 +171,7 @@ pcprobe(struct isa_device *dev) ((struct isa_attach_args *)aux)->ia_iosize = 16; return 1; #else -#ifdef _DEV_KBD_KBDREG_H_ - return (-1); -#elif PCVT_NETBSD || PCVT_FREEBSD +#if PCVT_NETBSD || PCVT_FREEBSD return (16); #else return 1; @@ -215,11 +199,6 @@ pcattach(struct isa_device *dev) vt_coldmalloc(); /* allocate memory for screens */ -#ifdef _DEV_KBD_KBDREG_H_ - if (kbd == NULL) - timeout(detect_kbd, (void *)dev->id_unit, hz*2); -#endif /* _DEV_KBD_KBDREG_H_ */ - #if PCVT_NETBSD || PCVT_FREEBSD #if PCVT_NETBSD > 9 @@ -405,8 +384,6 @@ pcattach(struct isa_device *dev) #else /* PCVT_NETBSD > 9 */ - dev->id_ointr = pcrint; - return 1; #endif /* PCVT_NETBSD > 9 */ @@ -791,7 +768,7 @@ do_standard: } int -pcmmap(Dev_t dev, vm_offset_t offset, int nprot) +pcmmap(Dev_t dev, int offset, int nprot) { if (offset > 0x20000 - PAGE_SIZE) return -1; @@ -862,51 +839,6 @@ pcvt_timeout(void *arg) } #endif -#ifdef _DEV_KBD_KBDREG_H_ -static void -detect_kbd(void *arg) -{ - int unit = (int)arg; - int i; - - if (kbd != NULL) - return; - i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit); - if (i >= 0) - kbd = kbd_get_keyboard(i); - if (kbd != NULL) - { - reset_keyboard = 1; /* ok to reset the keyboard */ - kbd_code_init(); - return; - } - reset_keyboard = 0; - timeout(detect_kbd, (void *)unit, hz*2); -} - -int -pcevent(keyboard_t *thiskbd, int event, void *arg) -{ - int unit = (int)arg; - - if (thiskbd != kbd) - return EINVAL; /* shouldn't happen */ - - switch (event) { - case KBDIO_KEYINPUT: - pcrint(unit); - return 0; - case KBDIO_UNLOADING: - reset_keyboard = 0; - kbd = NULL; - kbd_release(thiskbd, (void *)&kbd); - timeout(detect_kbd, (void *)unit, hz*4); - return 0; - default: - return EINVAL; - } -} -#endif /* _DEV_KBD_KBDREG_H_ */ void pcrint(int unit) @@ -920,7 +852,7 @@ pcrint(int unit) int s; # endif -# ifdef _DEV_KBD_KBDREG_H_ +# ifdef _I386_ISA_KBDIO_H_ int c; # endif @@ -928,6 +860,25 @@ pcrint(int unit) u_char *cp; #endif /* PCVT_KBD_FIFO */ + /* + * in case the keyboard was not plugged in while booting, kbdc + * was set to NULL at that time. When a keyboard IRQ occurs and + * kbdc is NULL, the keyboard was probably reconnected to the + * keyboard controller and we have to initialize the keyboard. + */ + + if(kbdc == NULL) + { + kbdc = kbdc_open(IO_KBD); + if(kbdc == NULL) + { + reset_keyboard = 0; + return; + } + reset_keyboard = 1; + kbd_code_init(); + } + #if PCVT_SCREENSAVER pcvt_scrnsv_reset(); #endif /* PCVT_SCREENSAVER */ @@ -939,7 +890,7 @@ pcrint(int unit) return; } -# ifndef _DEV_KBD_KBDREG_H_ +# ifndef _I386_ISA_KBDIO_H_ while (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) /* check 8042 buffer */ { ret = 1; /* got something */ @@ -948,11 +899,11 @@ pcrint(int unit) dt = inb(CONTROLLER_DATA); /* get it 8042 data */ # else - while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) != -1) + while ((c = read_kbd_data_no_wait(kbdc)) != -1) { ret = 1; /* got something */ dt = c; -# endif /* _DEV_KBD_KBDREG_H_ */ +# endif /* _I386_ISA_KBDIO_H_ */ if (pcvt_kbd_count >= PCVT_KBD_FIFO_SZ) /* fifo overflow ? */ { @@ -1163,47 +1114,39 @@ consinit() /* init for kernel messages during boot */ #endif /* PCVT_NETBSD */ #if PCVT_FREEBSD > 205 -static void +void #else int #endif pccnprobe(struct consdev *cp) { struct isa_device *dvp; - int i; - /* - * Take control if we are the highest priority enabled display device. - */ - dvp = find_display(); - if (dvp == NULL || dvp->id_driver != &vtdriver) { - cp->cn_pri = CN_DEAD; - return; - } - -#ifdef _DEV_KBD_KBDREG_H_ +#ifdef _I386_ISA_KBDIO_H_ + kbdc = kbdc_open(IO_KBD); /* * Don't reset the keyboard via `kbdio' just yet. * The system clock has not been calibrated... */ reset_keyboard = 0; - if (kbd == NULL) { - kbd_configure(KB_CONF_PROBE_ONLY); - i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)dvp->id_unit); - if (i >= 0) - kbd = kbd_get_keyboard(i); - } - #if PCVT_SCANSET == 2 /* * Turn off scancode translation early so that UserConfig * and DDB can read the keyboard. */ - empty_both_buffers(*(KBDC *)kbd->kb_data, 10); - set_controller_command_byte(*(KBDC *)kbd->kb_data, KBD_TRANSLATION, 0); + empty_both_buffers(kbdc, 10); + set_controller_command_byte(kbdc, KBD_TRANSLATION, 0); #endif /* PCVT_SCANSET == 2 */ +#endif /* _I386_ISA_KBDIO_H_ */ -#endif /* _DEV_KBD_KBDREG_H_ */ + /* + * Take control if we are the highest priority enabled display device. + */ + dvp = find_display(); + if (dvp == NULL || dvp->id_driver != &vtdriver) { + cp->cn_pri = CN_DEAD; + return; + } /* initialize required fields */ @@ -1226,7 +1169,7 @@ pccnprobe(struct consdev *cp) } #if PCVT_FREEBSD > 205 -static void +void #else int #endif @@ -1239,7 +1182,7 @@ pccninit(struct consdev *cp) } #if PCVT_FREEBSD > 205 -static void +void #else int #endif @@ -1273,7 +1216,7 @@ pccnputc(Dev_t dev, U_char c) #endif } -static int +int pccngetc(Dev_t dev) { register int s; @@ -1301,13 +1244,7 @@ pccngetc(Dev_t dev) s = spltty(); /* block pcrint while we poll */ kbd_polling = 1; -#ifdef _DEV_KBD_KBDREG_H_ - (*kbdsw[kbd->kb_index]->enable)(kbd); -#endif cp = sgetc(0); -#ifdef _DEV_KBD_KBDREG_H_ - (*kbdsw[kbd->kb_index]->disable)(kbd); -#endif kbd_polling = 0; splx(s); c = *cp++; @@ -1328,19 +1265,13 @@ pccngetc(Dev_t dev) } #if PCVT_FREEBSD >= 200 -static int +int pccncheckc(Dev_t dev) { char *cp; int x = spltty(); kbd_polling = 1; -#ifdef _DEV_KBD_KBDREG_H_ - (*kbdsw[kbd->kb_index]->enable)(kbd); -#endif cp = sgetc(1); -#ifdef _DEV_KBD_KBDREG_H_ - (*kbdsw[kbd->kb_index]->disable)(kbd); -#endif kbd_polling = 0; splx(x); return (cp == NULL ? -1 : *cp); @@ -1579,7 +1510,7 @@ pcvt_xmode_set(int on, struct proc *p) vsp->Crtat = vsp->Memory; /* operate in memory now */ -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ #if PCVT_SCANSET == 2 /* put keyboard to return ancient PC scan codes */ @@ -1593,15 +1524,15 @@ pcvt_xmode_set(int on, struct proc *p) #endif /* PCVT_USEKBDSEC */ #endif /* PCVT_SCANSET == 2 */ -#else /* _DEV_KBD_KBDREG_H_ */ +#else /* _I386_ISA_KBDIO_H_ */ #if PCVT_SCANSET == 2 /* put keyboard to return ancient PC scan codes */ - set_controller_command_byte(*(KBDC *)kbd->kb_data, + set_controller_command_byte(kbdc, KBD_TRANSLATION, KBD_TRANSLATION); #endif /* PCVT_SCANSET == 2 */ -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_NETBSD > 9 fp->tf_eflags |= PSL_IOPL; @@ -1638,7 +1569,7 @@ pcvt_xmode_set(int on, struct proc *p) pcvt_set_scrnsv_tmo(saved_scrnsv_tmo); #endif /* PCVT_SCREENSAVER */ -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ #if PCVT_SCANSET == 2 kbc_8042cmd(CONTR_WRITE); @@ -1651,14 +1582,13 @@ pcvt_xmode_set(int on, struct proc *p) #endif /* PCVT_USEKBDSEC */ #endif /* PCVT_SCANSET == 2 */ -#else /* _DEV_KBD_KBDREG_H_ */ +#else /* _I386_ISA_KBDIO_H_ */ #if PCVT_SCANSET == 2 - set_controller_command_byte(*(KBDC *)kbd->kb_data, - KBD_TRANSLATION, 0); + set_controller_command_byte(kbdc, KBD_TRANSLATION, 0); #endif /* PCVT_SCANSET == 2 */ -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ if(adaptor_type == MDA_ADAPTOR) { diff --git a/sys/i386/isa/pcvt/pcvt_hdr.h b/sys/i386/isa/pcvt/pcvt_hdr.h index 2c9aac8a29c53..70c28919f4385 100644 --- a/sys/i386/isa/pcvt/pcvt_hdr.h +++ b/sys/i386/isa/pcvt/pcvt_hdr.h @@ -107,9 +107,7 @@ #endif /* PCVT_FREEBSD >= 200 */ #include <i386/isa/pcvt/pcvt_conf.h> - -#include <dev/kbd/kbdreg.h> -#include <dev/kbd/atkbdcreg.h> +#include <i386/isa/kbdio.h> #if PCVT_NETBSD > 9 #include "device.h" @@ -170,14 +168,6 @@ #include <machine/clock.h> #include <machine/md_var.h> #endif -/* - * The following values are defined in machine/console.h, but the header - * file is not included here due to conflicts with pcvt_ioctl.h. - */ -#define KDGKBTYPE _IOR('K', 64, int) -#define KB_84 1 -#define KB_101 2 -#define KB_OTHER 3 #else /* PCVT_FREEBSD >= 200 */ #include "machine/pc/display.h" #endif /* PCVT_FREEBSD >= 200 */ @@ -270,7 +260,7 @@ in the config file" * Keyboard and Keyboard Controller *---------------------------------------------------------------------------*/ -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ #define CONTROLLER_CTRL 0x64 /* W - command, R - status */ #define CONTROLLER_DATA 0x60 /* R/W - data */ @@ -318,7 +308,7 @@ in the config file" #define KEYB_C_ECHO 0xee /* diagnostic, echo 0xee */ #define KEYB_C_LEDS 0xed /* set/reset numlock,capslock & scroll lock */ -#endif /* _DEV_KBD_KBDREG_H_ */ +#endif /* _I386_ISA_KBDIO_H_ */ /* responses from the KEYBOARD (via the 8042 controller on mainboard..) */ @@ -1010,10 +1000,10 @@ u_char chargen_access = 0; /* synchronize access */ u_char keyboard_type = KB_UNKNOWN; /* type of keyboard */ u_char keyboard_is_initialized = 0; /* for ddb sanity */ u_char kbd_polling = 0; /* keyboard is being polled */ -#ifdef _DEV_KBD_KBDREG_H_ +#ifdef _I386_ISA_KBDIO_H_ u_char reset_keyboard = 0; /* OK to reset keyboard */ -keyboard_t *kbd = NULL; -#endif /* _DEV_KBD_KBDREG_H_ */ +KBDC kbdc = NULL; /* keyboard controller */ +#endif /* _I386_ISA_KBDIO_H_ */ #if PCVT_SHOWKEYS u_char keyboard_show = 0; /* normal display */ @@ -1151,10 +1141,10 @@ extern u_char can_do_132col; extern u_char vga_family; extern u_char keyboard_is_initialized; extern u_char kbd_polling; -#ifdef _DEV_KBD_KBDREG_H_ +#ifdef _I386_ISA_KBDIO_H_ extern u_char reset_keyboard; -extern keyboard_t *kbd; -#endif /* _DEV_KBD_KBDREG_H_ */ +extern KBDC kbdc; +#endif /* _I386_ISA_KBDIO_H_ */ #if PCVT_SHOWKEYS extern u_char keyboard_show; @@ -1233,7 +1223,6 @@ int pccncheckc ( Dev_t dev ); int pccnputc ( Dev_t dev, U_char c ); #endif -ointhand2_t pcrint; void pcstart ( struct tty *tp ); void pcstop ( struct tty *tp, int flag ); @@ -1278,10 +1267,10 @@ void fkl_on ( struct video_state *svsp ); struct tty *get_pccons ( Dev_t dev ); void init_sfkl ( struct video_state *svsp ); void init_ufkl ( struct video_state *svsp ); -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ int kbd_cmd ( int val ); int kbd_response ( void ); -#endif /* _DEV_KBD_KBDREG_H_ */ +#endif /* _I386_ISA_KBDIO_H_ */ void kbd_code_init ( void ); void kbd_code_init1 ( void ); diff --git a/sys/i386/isa/pcvt/pcvt_kbd.c b/sys/i386/isa/pcvt/pcvt_kbd.c index 50457dc16b5d7..579c1a23abb5b 100644 --- a/sys/i386/isa/pcvt/pcvt_kbd.c +++ b/sys/i386/isa/pcvt/pcvt_kbd.c @@ -91,9 +91,11 @@ static void doreset ( void ); static void ovlinit ( int force ); static void settpmrate ( int rate ); static void setlockkeys ( int snc ); -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ static int kbc_8042cmd ( int val ); -#endif /* !_DEV_KBD_KBDREG_H_ */ +#else +static int set_keyboard_param( int command, int data ); +#endif /* !_I386_ISA_KBDIO_H_ */ static int getokeydef ( unsigned key, struct kbd_ovlkey *thisdef ); static int getckeydef ( unsigned key, struct kbd_ovlkey *thisdef ); static int rmkeydef ( int key ); @@ -168,7 +170,7 @@ do_vgapage(int page) #define PCVT_UPDLED_LOSES_INTR 0 /* disabled for now */ -#if PCVT_UPDLED_LOSES_INTR || defined(_DEV_KBD_KBDREG_H_) +#if PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_) /*---------------------------------------------------------------------------* * check for lost keyboard interrupts @@ -201,7 +203,7 @@ static struct callout_handle lost_intr_ch = static void check_for_lost_intr (void *arg) { -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ lost_intr_timeout_queued = 0; if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) { @@ -213,20 +215,19 @@ check_for_lost_intr (void *arg) int opri; lost_intr_timeout_queued = 0; - if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) { + if (kbdc_lock(kbdc, TRUE)) { opri = spltty (); - (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE); - if ((*kbdsw[kbd->kb_index]->check)(kbd)) + kbdc_lock(kbdc, FALSE); + if (kbdc_data_ready(kbdc)) pcrint (0); splx (opri); } - lost_intr_ch = timeout(check_for_lost_intr, (void *)NULL, hz); lost_intr_timeout_queued = 1; -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ } -#endif /* PCVT_UPDLED_LOSES_INTR || defined(_DEV_KBD_KBDREG_H_) */ +#endif /* PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_) */ /*---------------------------------------------------------------------------* * update keyboard led's @@ -238,23 +239,16 @@ update_led(void) /* Don't update LED's unless necessary. */ - int opri, new_ledstate; + int opri, new_ledstate, response1, response2; opri = spltty(); -#ifndef _DEV_KBD_KBDREG_H_ new_ledstate = (vsp->scroll_lock) | (vsp->num_lock * 2) | (vsp->caps_lock * 4); -#else - new_ledstate = ((vsp->scroll_lock) ? LED_SCR : 0) | - ((vsp->num_lock) ? LED_NUM : 0) | - ((vsp->caps_lock) ? LED_CAP : 0); -#endif /* _DEV_KBD_KBDREG_H_ */ if (new_ledstate != ledstate) { -#ifndef _DEV_KBD_KBDREG_H_ - int response1, response2; +#ifndef _I386_ISA_KBDIO_H_ ledstate = LEDSTATE_UPDATE_PENDING; @@ -301,20 +295,19 @@ update_led(void) printf( "Keyboard LED command not ACKed (responses %#x %#x)\n", response1, response2); -#else /* _DEV_KBD_KBDREG_H_ */ +#else /* _I386_ISA_KBDIO_H_ */ - if (kbd == NULL) { + if (kbdc == NULL) { ledstate = new_ledstate; splx(opri); } else { ledstate = LEDSTATE_UPDATE_PENDING; splx(opri); - if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED, - (caddr_t)&new_ledstate) == 0) + if (set_keyboard_param(KBDC_SET_LEDS, new_ledstate) == 0) ledstate = new_ledstate; } -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_UPDLED_LOSES_INTR if (lost_intr_timeout_queued) @@ -326,7 +319,7 @@ update_led(void) } -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ splx(opri); #endif @@ -339,22 +332,20 @@ update_led(void) static void settpmrate(int rate) { -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ tpmrate = rate & 0x7f; if(kbd_cmd(KEYB_C_TYPEM) != 0) printf("Keyboard TYPEMATIC command timeout\n"); else if(kbd_cmd(tpmrate) != 0) printf("Keyboard TYPEMATIC data timeout\n"); #else - if (kbd == NULL) - return; tpmrate = rate & 0x7f; - if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETRAD, (caddr_t)&tpmrate)) + if (set_keyboard_param(KBDC_SET_TYPEMATIC, tpmrate) != 0) printf("pcvt: failed to set keyboard TYPEMATIC.\n"); -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ } -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ /*---------------------------------------------------------------------------* * Pass command to keyboard controller (8042) *---------------------------------------------------------------------------*/ @@ -416,7 +407,62 @@ kbd_response(void) return ch; } -#endif /* _DEV_KBD_KBDREG_H_ */ +#else +static int +set_keyboard_param(int command, int data) +{ + int s; + int c; + + if (kbdc == NULL) + return 1; + + /* prevent the timeout routine from polling the keyboard */ + if (!kbdc_lock(kbdc, TRUE)) + return 1; + + /* disable the keyboard and mouse interrupt */ + s = spltty(); +#if 0 + c = get_controller_command_byte(kbdc); + if ((c == -1) + || !set_controller_command_byte(kbdc, + kbdc_get_device_mask(kbdc), + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { + /* CONTROLLER ERROR */ + kbdc_lock(kbdc, FALSE); + splx(s); + return 1; + } + /* + * 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 + + if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) + send_kbd_command(kbdc, KBDC_ENABLE_KBD); + +#if 0 + /* restore the interrupts */ + if (!set_controller_command_byte(kbdc, + kbdc_get_device_mask(kbdc), + c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { + /* CONTROLLER ERROR */ + } +#else + splx(s); +#endif + kbdc_lock(kbdc, FALSE); + + return 0; +} +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_SCANSET > 1 /*---------------------------------------------------------------------------* @@ -425,7 +471,7 @@ kbd_response(void) void kbd_emulate_pc(int do_emulation) { -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ int cmd, timeo = 10000; cmd = COMMAND_SYSFLG|COMMAND_IRQEN; /* common base cmd */ @@ -443,9 +489,9 @@ kbd_emulate_pc(int do_emulation) break; outb(CONTROLLER_DATA, cmd); #else - set_controller_command_byte(*(KBDC *)kbd->kb_data, KBD_TRANSLATION, + set_controller_command_byte(kbdc, KBD_TRANSLATION, (do_emulation) ? KBD_TRANSLATION : 0); -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ } #endif /* PCVT_SCANSET > 1 */ @@ -461,7 +507,7 @@ kbd_emulate_pc(int do_emulation) static void doreset(void) { -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ int again = 0; int once = 0; int response, opri; @@ -622,8 +668,10 @@ r_entry: #endif /* PCVT_KEYBDID */ -#else /* _DEV_KBD_KBDREG_H_ */ - int type; +#else /* _I386_ISA_KBDIO_H_ */ + int c; + int m; + int s; if (!reset_keyboard) /* no, we are not ready to reset */ return; @@ -633,11 +681,29 @@ r_entry: lost_intr_timeout_queued = 0; } - if (kbd == NULL) - return; /* shouldn't happen */ - (*kbdsw[kbd->kb_index]->init)(kbd); + if (kbdc == NULL) + kbdc = kbdc_open(IO_KBD); - ledstate = LEDSTATE_UPDATE_PENDING; + if (!kbdc_lock(kbdc, TRUE)) /* strange, somebody got there first */ + return; + + /* remove any noise */ + empty_both_buffers(kbdc, 10); + + s = spltty(); + + /* save the current controller command byte */ + m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS; + c = get_controller_command_byte(kbdc); + if (c == -1) { + /* CONTROLLER ERROR */ + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + splx(s); + printf("pcvt: unable to get the command byte.\n"); + return; + } #if PCVT_USEKBDSEC /* security enabled */ @@ -657,33 +723,105 @@ r_entry: #endif /* PCVT_USEKBDSEC */ - set_controller_command_byte(*(KBDC *)kbd->kb_data, - KBD_OVERRIDE_KBD_LOCK | KBD_TRANSLATION, KBDINITCMD); - - keyboard_type = KB_MFII; /* force it .. */ + /* disable the keyboard interrupt and the aux port and interrupt */ + if (!set_controller_command_byte(kbdc, + KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, + KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT | KBDINITCMD)) { + /* CONTROLLER ERROR: there is very little we can do... */ + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + splx(s); + printf("pcvt: unable to set the command byte.\n"); + return; + } + splx(s); + + /* reset keyboard hardware */ + ledstate = LEDSTATE_UPDATE_PENDING; + if (!reset_kbd(kbdc)) { + /* KEYBOARD ERROR */ + empty_both_buffers(kbdc, 10); + test_controller(kbdc); + test_kbd_port(kbdc); + /* + * We could disable the keyboard port and interrupt now... + * but, the keyboard may still exist. + */ + printf("pcvt: failed to reset the keyboard.\n"); + /* try to restore the original command byte */ + set_controller_command_byte(kbdc, 0xff, c); + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + return; + } + #if PCVT_KEYBDID - type = KB_101; - (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBTYPE, (caddr_t)&type); - switch (type) - { - case KB_84: - keyboard_type = KB_AT; - break; - case KB_101: - keyboard_type = KB_MFII; - break; - default: - keyboard_type = KB_UNKNOWN; - break; + + keyboard_type = KB_UNKNOWN; + if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) == KBD_ACK) { + DELAY(10000); /* 10msec delay */ + switch (read_kbd_data(kbdc)) { + case KEYB_R_MF2ID1: + switch (read_kbd_data(kbdc)) { + case KEYB_R_MF2ID2: + case KEYB_R_MF2ID2HP: + keyboard_type = KB_MFII; + break; + case -1: + default: + break; + } + break; + case -1: + keyboard_type = KB_AT; + /* fall through */ + default: + /* XXX: should we read the second byte? */ + empty_both_buffers(kbdc, 10); /* XXX */ + break; + } + } else { + /* + * The send ID command failed. This error is considered + * benign, but may need recovery. + */ + empty_both_buffers(kbdc, 10); + test_controller(kbdc); + test_kbd_port(kbdc); } + +#else /* PCVT_KEYBDID */ + + keyboard_type = KB_MFII; /* force it .. */ + #endif /* PCVT_KEYBDID */ + /* enable the keyboard port and intr. */ + if (!set_controller_command_byte(kbdc, + KBD_KBD_CONTROL_BITS, + KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { + /* CONTROLLER ERROR + * This is serious; we are left with the disabled + * keyboard intr. + */ + printf("pcvt: failed to enable the keyboard port and intr.\n"); + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + return; + } + + kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); + kbdc_lock(kbdc, FALSE); + update_led(); lost_intr_ch = timeout(check_for_lost_intr, (void *)NULL, hz); lost_intr_timeout_queued = 1; -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ } /*---------------------------------------------------------------------------* @@ -1105,15 +1243,15 @@ sgetc(int noblock) static char keybuf[2] = {0}; /* the second 0 is a delimiter! */ #endif /* XSERVER */ -#ifdef _DEV_KBD_KBDREG_H_ +#ifdef _I386_ISA_KBDIO_H_ int c; -#endif /* _DEV_KBD_KBDREG_H_ */ +#endif /* _I386_ISA_KBDIO_H_ */ loop: #ifdef XSERVER -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ #if PCVT_KBD_FIFO @@ -1148,7 +1286,7 @@ loop: #endif /* !PCVT_KBD_FIFO */ -#else /* _DEV_KBD_KBDREG_H_ */ +#else /* _I386_ISA_KBDIO_H_ */ #if PCVT_KBD_FIFO if (pcvt_kbd_count) { @@ -1161,18 +1299,18 @@ loop: } else #endif /* PCVT_KBD_FIFO */ if (!noblock) { - while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, TRUE)) == -1) + while ((c = read_kbd_data(kbdc)) == -1) ; dt = c; } else { - if ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) == -1) + if ((c = read_kbd_data_no_wait(kbdc)) == -1) return NULL; dt = c; } { -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ /* * If x mode is active, only care for locking keys, then @@ -1450,7 +1588,7 @@ no_mouse_event: #else /* !XSERVER */ -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ # if PCVT_KBD_FIFO @@ -1487,7 +1625,7 @@ no_mouse_event: #endif /* !PCVT_KBD_FIFO */ -#else /* _DEV_KBD_KBDREG_H_ */ +#else /* _I386_ISA_KBDIO_H_ */ #if PCVT_KBD_FIFO if (pcvt_kbd_count) { @@ -1500,20 +1638,20 @@ no_mouse_event: } else #endif /* PCVT_KBD_FIFO */ if (!noblock) { - while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, TRUE)) == -1) + while ((c = read_kbd_data(kbdc)) == -1) ; dt = c; } else { - if ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) == -1) + if ((c = read_kbd_data_no_wait(kbdc)) == -1) return NULL; dt = c; } -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ #endif /* !XSERVER */ -#ifndef _DEV_KBD_KBDREG_H_ +#ifndef _I386_ISA_KBDIO_H_ else { if(noblock) @@ -1521,7 +1659,7 @@ no_mouse_event: else goto loop; } -#endif /* !_DEV_KBD_KBDREG_H_ */ +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_SHOWKEYS showkey (' ', dt); diff --git a/sys/i386/isa/pcvt/pcvt_sup.c b/sys/i386/isa/pcvt/pcvt_sup.c index de7f938840e8a..3b0019103258d 100644 --- a/sys/i386/isa/pcvt/pcvt_sup.c +++ b/sys/i386/isa/pcvt/pcvt_sup.c @@ -261,7 +261,7 @@ vgaioctl(Dev_t dev, int cmd, caddr_t data, int flag) static void vgapcvtid(struct pcvtid *data) { - snprintf(data->name, sizeof(data->name), "%s", PCVTIDNAME); + strcpy(data->name, PCVTIDNAME); data->rmajor = PCVTIDMAJOR; data->rminor = PCVTIDMINOR; } diff --git a/sys/i386/isa/pnp.c b/sys/i386/isa/pnp.c index a3635cb2449d7..9b4bb55633742 100644 --- a/sys/i386/isa/pnp.c +++ b/sys/i386/isa/pnp.c @@ -23,12 +23,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pnp.c,v 1.8 1998/11/21 01:54:50 archie Exp $ + * $Id: pnp.c,v 1.5 1998/02/09 06:08:38 eivind Exp $ */ #include <sys/param.h> #include <sys/systm.h> -#include <sys/linker_set.h> +#include <sys/kernel.h> /* for DATA_SET */ #include <sys/malloc.h> #include <sys/interrupt.h> #include <machine/clock.h> @@ -373,9 +373,9 @@ config_pnp_device(pnp_id *p, int csn) /* these are for autoconfigure a-la pci */ struct pnp_device *dvp, **dvpp; - char *name = NULL; + char *name ; - printf("CSN %d Vendor ID: %c%c%c%02x%02x [0x%08lx] Serial 0x%08lx Comp ID: %c%c%c%02x%02x [0x%08lx]\n", + printf("CSN %d Vendor ID: %c%c%c%02x%02x [0x%08x] Serial 0x%08x Comp ID: %c%c%c%02x%02x [0x%08x]\n", csn, ((data[0] & 0x7c) >> 2) + '@', (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + '@', @@ -456,7 +456,7 @@ config_pnp_device(pnp_id *p, int csn) nod->dev.id_driver->name ? nod->dev.id_driver->name : "unknown", unit, dvp->pd_name, name, p->serial); if (nod->dev.id_alive) { - if (nod->dev.id_irq != 0 && nod->dev.id_intr != NULL) { + if (nod->dev.id_irq) { /* the board uses interrupts. Register it. */ if (dvp->imask) INTRMASK( *(dvp->imask), nod->dev.id_irq ); @@ -533,7 +533,7 @@ pnp_scan_resdata(pnp_id *p, int csn) bcopy(resinfo, &p->comp_id, 4); retval = TRUE; if (bootverbose) - printf("PnP: CSN %d COMP_DEVICE_ID = 0x%08lx\n", csn, p->comp_id); + printf("PnP: CSN %d COMP_DEVICE_ID = 0x%08x\n", csn, p->comp_id); } /* * We found what we were looking for, or got an error from diff --git a/sys/i386/isa/ppc.c b/sys/i386/isa/ppc.c index bd6249b33a711..4dc6a44178d21 100644 --- a/sys/i386/isa/ppc.c +++ b/sys/i386/isa/ppc.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppc.c,v 1.14 1999/01/10 12:04:53 nsouch Exp $ + * $Id: ppc.c,v 1.8 1998/09/13 20:57:06 nsouch Exp $ * */ #include "ppc.h" @@ -49,11 +49,6 @@ #include <i386/isa/ppcreg.h> -#include "opt_ppc.h" - -#define LOG_PPC(function, ppc, string) \ - if (bootverbose) printf("%s: %s\n", function, string) - static int ppcprobe(struct isa_device *); static int ppcattach(struct isa_device *); @@ -66,7 +61,7 @@ static int nppc = 0; static char *ppc_types[] = { "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306", - "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0 + "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0 }; /* list of available modes */ @@ -113,12 +108,12 @@ static void ppc_insw_epp(int unit, char *addr, int cnt) { static void ppc_insl_epp(int unit, char *addr, int cnt) { insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } -static u_char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); } -static u_char ppc_rstr(int unit) { return r_str(ppcdata[unit]); } -static u_char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); } -static u_char ppc_repp(int unit) { return r_epp(ppcdata[unit]); } -static u_char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); } -static u_char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); } +static char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); } +static char ppc_rstr(int unit) { return r_str(ppcdata[unit]); } +static char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); } +static char ppc_repp(int unit) { return r_epp(ppcdata[unit]); } +static char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); } +static char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); } static void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); } static void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); } @@ -129,15 +124,11 @@ static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); } static void ppc_reset_epp_timeout(int); static void ppc_ecp_sync(int); -static ointhand2_t ppcintr; static int ppc_exec_microseq(int, struct ppb_microseq **); static int ppc_generic_setmode(int, int); static int ppc_smclike_setmode(int, int); -static int ppc_read(int, char *, int, int); -static int ppc_write(int, char *, int, int); - static struct ppb_adapter ppc_smclike_adapter = { 0, /* no intr handler, filled by chipset dependent code */ @@ -146,7 +137,7 @@ static struct ppb_adapter ppc_smclike_adapter = { ppc_exec_microseq, - ppc_smclike_setmode, ppc_read, ppc_write, + ppc_smclike_setmode, ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp, ppc_insb_epp, ppc_insw_epp, ppc_insl_epp, @@ -163,7 +154,7 @@ static struct ppb_adapter ppc_generic_adapter = { ppc_exec_microseq, - ppc_generic_setmode, ppc_read, ppc_write, + ppc_generic_setmode, ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp, ppc_insb_epp, ppc_insw_epp, ppc_insl_epp, @@ -181,11 +172,8 @@ ppc_ecp_sync(int unit) { struct ppc_data *ppc = ppcdata[unit]; int i, r; - if (!(ppc->ppc_avm & PPB_ECP)) - return; - r = r_ecr(ppc); - if ((r & 0xe0) != PPC_ECR_EPP) + if ((r & 0xe0) != 0x80) return; for (i = 0; i < 100; i++) { @@ -201,115 +189,13 @@ ppc_ecp_sync(int unit) { return; } -/* - * ppc_detect_fifo() - * - * Detect parallel port FIFO - */ -static int -ppc_detect_fifo(struct ppc_data *ppc) +void +ppcintr(int unit) { - char ecr_sav; - char ctr_sav, ctr, cc; - short i; - - /* save registers */ - ecr_sav = r_ecr(ppc); - ctr_sav = r_ctr(ppc); - - /* enter ECP configuration mode, no interrupt, no DMA */ - w_ecr(ppc, 0xf4); - - /* read PWord size - transfers in FIFO mode must be PWord aligned */ - ppc->ppc_pword = (r_cnfgA(ppc) & PPC_PWORD_MASK); - - /* XXX 16 and 32 bits implementations not supported */ - if (ppc->ppc_pword != PPC_PWORD_8) { - LOG_PPC(__FUNCTION__, ppc, "PWord not supported"); - goto error; - } - - w_ecr(ppc, 0x34); /* byte mode, no interrupt, no DMA */ - ctr = r_ctr(ppc); - w_ctr(ppc, ctr | PCD); /* set direction to 1 */ - - /* enter ECP test mode, no interrupt, no DMA */ - w_ecr(ppc, 0xd4); - - /* flush the FIFO */ - for (i=0; i<1024; i++) { - if (r_ecr(ppc) & PPC_FIFO_EMPTY) - break; - cc = r_fifo(ppc); - } - - if (i >= 1024) { - LOG_PPC(__FUNCTION__, ppc, "can't flush FIFO"); - goto error; - } - - /* enable interrupts, no DMA */ - w_ecr(ppc, 0xd0); - - /* determine readIntrThreshold - * fill the FIFO until serviceIntr is set - */ - for (i=0; i<1024; i++) { - w_fifo(ppc, (char)i); - if (!ppc->ppc_rthr && (r_ecr(ppc) & PPC_SERVICE_INTR)) { - /* readThreshold reached */ - ppc->ppc_rthr = i+1; - } - if (r_ecr(ppc) & PPC_FIFO_FULL) { - ppc->ppc_fifo = i+1; - break; - } - } - - if (i >= 1024) { - LOG_PPC(__FUNCTION__, ppc, "can't fill FIFO"); - goto error; - } + /* call directly upper code */ + ppb_intr(&ppcdata[unit]->ppc_link); - w_ecr(ppc, 0xd4); /* test mode, no interrupt, no DMA */ - w_ctr(ppc, ctr & ~PCD); /* set direction to 0 */ - w_ecr(ppc, 0xd0); /* enable interrupts */ - - /* determine writeIntrThreshold - * empty the FIFO until serviceIntr is set - */ - for (i=ppc->ppc_fifo; i>0; i--) { - if (r_fifo(ppc) != (char)(ppc->ppc_fifo-i)) { - LOG_PPC(__FUNCTION__, ppc, "invalid data in FIFO"); - goto error; - } - if (r_ecr(ppc) & PPC_SERVICE_INTR) { - /* writeIntrThreshold reached */ - ppc->ppc_wthr = ppc->ppc_fifo - i+1; - } - /* if FIFO empty before the last byte, error */ - if (i>1 && (r_ecr(ppc) & PPC_FIFO_EMPTY)) { - LOG_PPC(__FUNCTION__, ppc, "data lost in FIFO"); - goto error; - } - } - - /* FIFO must be empty after the last byte */ - if (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) { - LOG_PPC(__FUNCTION__, ppc, "can't empty the FIFO"); - goto error; - } - - w_ctr(ppc, ctr_sav); - w_ecr(ppc, ecr_sav); - - return (0); - -error: - w_ctr(ppc, ctr_sav); - w_ecr(ppc, ecr_sav); - - return (EINVAL); + return; } static int @@ -318,7 +204,7 @@ ppc_detect_port(struct ppc_data *ppc) w_ctr(ppc, 0x0c); /* To avoid missing PS2 ports */ w_dtr(ppc, 0xaa); - if (r_dtr(ppc) != 0xaa) + if (r_dtr(ppc) != (char) 0xaa) return (0); return (1); @@ -334,44 +220,27 @@ ppc_detect_port(struct ppc_data *ppc) */ static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0}; static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0}; -static int pc873xx_irqtab[] = {5, 7, 5, 0}; - -static int pc873xx_regstab[] = { - PC873_FER, PC873_FAR, PC873_PTR, - PC873_FCR, PC873_PCR, PC873_PMC, - PC873_TUP, PC873_SID, PC873_PNP0, - PC873_PNP1, PC873_LPTBA, -1 -}; - -static char *pc873xx_rnametab[] = { - "FER", "FAR", "PTR", "FCR", "PCR", - "PMC", "TUP", "SID", "PNP0", "PNP1", - "LPTBA", NULL -}; static int ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */ { static int index = 0; - int idport, irq; - int ptr, pcr, val, i; + int base, idport; + int val; while ((idport = pc873xx_basetab[index++])) { /* XXX should check first to see if this location is already claimed */ /* - * Pull the 873xx through the power-on ID cycle (2.2,1.). - * We can't use this to locate the chip as it may already have - * been used by the BIOS. + * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this + * to locate the chip as it may already have been used by the BIOS. */ - (void)inb(idport); (void)inb(idport); - (void)inb(idport); (void)inb(idport); + (void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport); /* * Read the SID byte. Possible values are : * - * 01010xxx PC87334 * 0001xxxx PC87332 * 01110xxx PC87306 */ @@ -381,27 +250,14 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for ppc->ppc_type = NS_PC87332; } else if ((val & 0xf8) == 0x70) { ppc->ppc_type = NS_PC87306; - } else if ((val & 0xf8) == 0x50) { - ppc->ppc_type = NS_PC87334; } else { if (bootverbose && (val != 0xff)) printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val); continue ; /* not recognised */ } - - /* print registers */ - if (bootverbose) { - printf("PC873xx"); - for (i=0; pc873xx_regstab[i] != -1; i++) { - outb(idport, pc873xx_regstab[i]); - printf(" %s=0x%x", pc873xx_rnametab[i], - inb(idport + 1) & 0xff); - } - printf("\n"); - } /* - * We think we have one. Is it enabled and where we want it to be? + * We think we have one. Is it enabled and where we want it to be? */ outb(idport, PC873_FER); val = inb(idport + 1); @@ -419,168 +275,96 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for pc873xx_porttab[val], ppc->ppc_base); continue; } - - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - - /* get irq settings */ - if (ppc->ppc_base == 0x378) - irq = (ptr & PC873_LPTBIRQ7) ? 7 : 5; - else - irq = pc873xx_irqtab[val]; - - if (bootverbose) - printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base); - /* - * Check if irq settings are correct + /* + * This is the port we want. Can we dink with it to improve + * our chances? */ - if (irq != ppc->ppc_irq) { - /* - * If the chipset is not locked and base address is 0x378, - * we have another chance - */ - if (ppc->ppc_base == 0x378 && !(ptr & PC873_CFGLOCK)) { - if (ppc->ppc_irq == 7) { - outb(idport + 1, (ptr | PC873_LPTBIRQ7)); - outb(idport + 1, (ptr | PC873_LPTBIRQ7)); - } else { - outb(idport + 1, (ptr & ~PC873_LPTBIRQ7)); - outb(idport + 1, (ptr & ~PC873_LPTBIRQ7)); - } - if (bootverbose) - printf("PC873xx irq set to %d\n", ppc->ppc_irq); - } else { - if (bootverbose) - printf("PC873xx sorry, can't change irq setting\n"); + outb(idport, PC873_PTR); + val = inb(idport + 1); + if (val & PC873_CFGLOCK) { + if (bootverbose) + printf("PC873xx locked\n"); + + /* work out what mode we're in */ + ppc->ppc_avm |= PPB_NIBBLE; /* worst case */ + + outb(idport, PC873_PCR); + val = inb(idport + 1); + if ((val & PC873_EPPEN) && (val & PC873_EPP19)) { + outb(idport, PC873_PTR); + val = inb(idport + 1); + if (!(val & PC873_EPPRDIR)) { + ppc->ppc_avm |= PPB_EPP; /* As we would have done it anwyay */ } + } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) { + ppc->ppc_avm |= PPB_PS2; /* tolerable alternative */ + } } else { - if (bootverbose) - printf("PC873xx irq settings are correct\n"); - } - - outb(idport, PC873_PCR); - pcr = inb(idport + 1); - - if ((ptr & PC873_CFGLOCK) || !chipset_mode) { if (bootverbose) - printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked"); - - ppc->ppc_avm |= PPB_NIBBLE; - if (bootverbose) - printf(", NIBBLE"); - - if (pcr & PC873_EPPEN) { - ppc->ppc_avm |= PPB_EPP; - + printf("PC873xx unlocked, "); + +#if 0 /* broken */ + /* + * Frob the zero-wait-state option if possible; it causes + * unreliable operation. + */ + outb(idport, PC873_FCR); + val = inb(idport + 1); + if ((ppc->ppc_type == NS_PC87306) || /* we are a '306 */ + !(val & PC873_ZWSPWDN)) { /* or pin _is_ ZWS */ + val &= ~PC873_ZWS; + outb(idport + 1, val); /* must disable ZWS */ + outb(idport + 1, val); + if (bootverbose) - printf(", EPP"); - - if (pcr & PC873_EPP19) - ppc->ppc_epp = EPP_1_9; - else - ppc->ppc_epp = EPP_1_7; + printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled"); + } - if ((ppc->ppc_type == NS_PC87332) && bootverbose) { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - if (ptr & PC873_EPPRDIR) - printf(", Regular mode"); - else - printf(", Automatic mode"); - } - } else if (pcr & PC873_ECPEN) { - ppc->ppc_avm |= PPB_ECP; +#endif + if (bootverbose) + printf("reconfiguring for "); + + /* + * if the chip is at 0x3bc, we can't use EPP as there's no room + * for the extra registers. + * + * XXX should we use ECP mode always and use the EPP submode? + */ + if (ppc->ppc_base != 0x3bc) { if (bootverbose) - printf(", ECP"); + printf("EPP 1.9\n"); + + /* configure for EPP 1.9 operation XXX should be configurable */ + outb(idport, PC873_PCR); + val = inb(idport + 1); + val &= ~(PC873_ECPEN | PC873_ECPCLK); /* disable ECP */ + val |= (PC873_EPPEN | PC873_EPP19); /* enable EPP */ + outb(idport + 1, val); + outb(idport + 1, val); + + /* enable automatic direction turnover */ + outb(idport, PC873_PTR); + val = inb(idport + 1); + val &= ~PC873_EPPRDIR; /* disable "regular" direction change */ + outb(idport + 1, val); + outb(idport + 1, val); - if (pcr & PC873_ECPCLK) { /* XXX */ - ppc->ppc_avm |= PPB_PS2; - if (bootverbose) - printf(", PS/2"); - } + /* we are an EPP-32 port */ + ppc->ppc_avm |= PPB_EPP; } else { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - if (ptr & PC873_EXTENDED) { - ppc->ppc_avm |= PPB_SPP; - if (bootverbose) - printf(", SPP"); - } - } - } else { if (bootverbose) - printf("PC873xx unlocked"); - - if (chipset_mode & PPB_ECP) { - if ((chipset_mode & PPB_EPP) && bootverbose) - printf(", ECP+EPP not supported"); - - pcr &= ~PC873_EPPEN; - pcr |= (PC873_ECPEN | PC873_ECPCLK); /* XXX */ - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - if (bootverbose) - printf(", ECP"); - - } else if (chipset_mode & PPB_EPP) { - pcr &= ~(PC873_ECPEN | PC873_ECPCLK); - pcr |= (PC873_EPPEN | PC873_EPP19); - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - ppc->ppc_epp = EPP_1_9; /* XXX */ - - if (bootverbose) - printf(", EPP1.9"); - - /* enable automatic direction turnover */ - if (ppc->ppc_type == NS_PC87332) { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - ptr &= ~PC873_EPPRDIR; - outb(idport + 1, ptr); - outb(idport + 1, ptr); - - if (bootverbose) - printf(", Automatic mode"); - } - } else { - pcr &= ~(PC873_ECPEN | PC873_ECPCLK | PC873_EPPEN); - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - /* configure extended bit in PTR */ - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - - if (chipset_mode & PPB_PS2) { - ptr |= PC873_EXTENDED; - - if (bootverbose) - printf(", PS/2"); - - } else { - /* default to NIBBLE mode */ - ptr &= ~PC873_EXTENDED; - - if (bootverbose) - printf(", NIBBLE"); - } - outb(idport + 1, ptr); - outb(idport + 1, ptr); - } + printf("ECP\n"); + + /* configure as an ECP port to get bidirectional operation for now */ + outb(idport, PC873_PCR); + outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK); - ppc->ppc_avm = chipset_mode; + /* we look like a PS/2 port */ + ppc->ppc_avm |= PPB_PS2; + } } - if (bootverbose) - printf("\n"); - - ppc->ppc_link.adapter = &ppc_generic_adapter; - ppc_generic_setmode(ppc->ppc_unit, chipset_mode); - return(chipset_mode); } return(-1); @@ -767,13 +551,6 @@ config: ppc->ppc_avm = chipset_mode; } - /* set FIFO threshold to 16 */ - if (ppc->ppc_avm & PPB_ECP) { - /* select CRA */ - outb(csr, 0xa); - outb(cio, 16); - } - end_detect: if (bootverbose) @@ -821,7 +598,7 @@ static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRA static int ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode) { - int i, j, efer; + int i, j, efer, base; unsigned char r, hefere, hefras; for (i = 0; i < 4; i ++) { @@ -996,6 +773,8 @@ found: static int ppc_generic_detect(struct ppc_data *ppc, int chipset_mode) { + char save_control; + /* default to generic */ ppc->ppc_link.adapter = &ppc_generic_adapter; @@ -1004,14 +783,14 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode) if (!chipset_mode) { /* first, check for ECP */ - w_ecr(ppc, PPC_ECR_PS2); - if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) { + w_ecr(ppc, 0x20); + if ((r_ecr(ppc) & 0xe0) == 0x20) { ppc->ppc_avm |= PPB_ECP | PPB_SPP; if (bootverbose) printf(" ECP SPP"); /* search for SMC style ECP+EPP mode */ - w_ecr(ppc, PPC_ECR_EPP); + w_ecr(ppc, 0x80); } /* try to reset EPP timeout bit */ @@ -1031,7 +810,7 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode) } } else { /* restore to standard mode */ - w_ecr(ppc, PPC_ECR_STD); + w_ecr(ppc, 0x0); } /* XXX try to detect NIBBLE and PS2 modes */ @@ -1083,25 +862,13 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) { * * after detection, the port must support running in compatible mode */ - if (ppc->ppc_flags & 0x40) { - if (bootverbose) - printf("ppc: chipset forced to generic\n"); - - ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode); - - } else { - for (i=0; chipset_detect[i] != NULL; i++) { - if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) { - ppc->ppc_mode = mode; - break; - } + for (i=0; chipset_detect[i] != NULL; i++) { + if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) { + ppc->ppc_mode = mode; + break; } } - /* configure/detect ECP FIFO */ - if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80)) - ppc_detect_fifo(ppc); - return (0); } @@ -1128,7 +895,7 @@ ppc_exec_microseq(int unit, struct ppb_microseq **p_msq) struct ppb_microseq *stack = 0; /* microsequence registers are equivalent to PC-like port registers */ -#define r_reg(register,ppc) (inb((ppc)->ppc_base + register)) +#define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register)) #define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte) #define INCR_PC (mi ++) /* increment program counter */ @@ -1326,244 +1093,6 @@ ppc_exec_microseq(int unit, struct ppb_microseq **p_msq) /* unreached */ } -static void -ppcintr(int unit) -{ - struct ppc_data *ppc = ppcdata[unit]; - char ctr, ecr; - - ctr = r_ctr(ppc); - ecr = r_ecr(ppc); - -#ifdef PPC_DEBUG - printf("!"); -#endif - - /* don't use ecp mode with IRQENABLE set */ - if (ctr & IRQENABLE) { - /* call upper code */ - ppb_intr(&ppc->ppc_link); - return; - } - - if (ctr & nFAULT) { - if (ppc->ppc_irqstat & PPC_IRQ_nFAULT) { - - w_ecr(ppc, ecr | PPC_nFAULT_INTR); - ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT; - } else { - /* call upper code */ - ppb_intr(&ppc->ppc_link); - return; - } - } - - if (ppc->ppc_irqstat & PPC_IRQ_DMA) { - /* disable interrupts (should be done by hardware though) */ - w_ecr(ppc, ecr | PPC_SERVICE_INTR); - ppc->ppc_irqstat &= ~PPC_IRQ_DMA; - ecr = r_ecr(ppc); - - /* check if DMA completed */ - if ((ppc->ppc_avm & PPB_ECP) && (ecr & PPC_ENABLE_DMA)) { -#ifdef PPC_DEBUG - printf("a"); -#endif - /* stop DMA */ - w_ecr(ppc, ecr & ~PPC_ENABLE_DMA); - ecr = r_ecr(ppc); - - if (ppc->ppc_dmastat == PPC_DMA_STARTED) { -#ifdef PPC_DEBUG - printf("d"); -#endif - isa_dmadone( - ppc->ppc_dmaflags, - ppc->ppc_dmaddr, - ppc->ppc_dmacnt, - ppc->ppc_dmachan); - - ppc->ppc_dmastat = PPC_DMA_COMPLETE; - - /* wakeup the waiting process */ - wakeup((caddr_t)ppc); - } - } - } else if (ppc->ppc_irqstat & PPC_IRQ_FIFO) { - - /* classic interrupt I/O */ - ppc->ppc_irqstat &= ~PPC_IRQ_FIFO; - - } - - return; -} - -static int -ppc_read(int unit, char *buf, int len, int mode) -{ - return (EINVAL); -} - -/* - * Call this function if you want to send data in any advanced mode - * of your parallel port: FIFO, DMA - * - * If what you want is not possible (no ECP, no DMA...), - * EINVAL is returned - */ -static int -ppc_write(int unit, char *buf, int len, int how) -{ - struct ppc_data *ppc = ppcdata[unit]; - char ecr, ecr_sav, ctr, ctr_sav; - int s, error = 0; - int spin; - -#ifdef PPC_DEBUG - printf("w"); -#endif - - ecr_sav = r_ecr(ppc); - ctr_sav = r_ctr(ppc); - - /* - * Send buffer with DMA, FIFO and interrupts - */ - if (ppc->ppc_avm & PPB_ECP) { - - if (ppc->ppc_dmachan >= 0) { - - /* byte mode, no intr, no DMA, dir=0, flush fifo - */ - ecr = PPC_ECR_STD | PPC_DISABLE_INTR; - w_ecr(ppc, ecr); - - /* disable nAck interrupts */ - ctr = r_ctr(ppc); - ctr &= ~IRQENABLE; - w_ctr(ppc, ctr); - - ppc->ppc_dmaflags = 0; - ppc->ppc_dmaddr = (caddr_t)buf; - ppc->ppc_dmacnt = (u_int)len; - - switch (ppc->ppc_mode) { - case PPB_COMPATIBLE: - /* compatible mode with FIFO, no intr, DMA, dir=0 */ - ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA; - break; - case PPB_ECP: - ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA; - break; - default: - error = EINVAL; - goto error; - } - - w_ecr(ppc, ecr); - ecr = r_ecr(ppc); - - /* enter splhigh() not to be preempted - * by the dma interrupt, we may miss - * the wakeup otherwise - */ - s = splhigh(); - - ppc->ppc_dmastat = PPC_DMA_INIT; - - /* enable interrupts */ - ecr &= ~PPC_SERVICE_INTR; - ppc->ppc_irqstat = PPC_IRQ_DMA; - w_ecr(ppc, ecr); - - isa_dmastart( - ppc->ppc_dmaflags, - ppc->ppc_dmaddr, - ppc->ppc_dmacnt, - ppc->ppc_dmachan); -#ifdef PPC_DEBUG - printf("s%d", ppc->ppc_dmacnt); -#endif - ppc->ppc_dmastat = PPC_DMA_STARTED; - - /* Wait for the DMA completed interrupt. We hope we won't - * miss it, otherwise a signal will be necessary to unlock the - * process. - */ - do { - /* release CPU */ - error = tsleep((caddr_t)ppc, - PPBPRI | PCATCH, "ppcdma", 0); - - } while (error == EWOULDBLOCK); - - splx(s); - - if (error) { -#ifdef PPC_DEBUG - printf("i"); -#endif - /* stop DMA */ - isa_dmadone( - ppc->ppc_dmaflags, ppc->ppc_dmaddr, - ppc->ppc_dmacnt, ppc->ppc_dmachan); - - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; - goto error; - } - - /* wait for an empty fifo */ - while (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) { - - for (spin=100; spin; spin--) - if (r_ecr(ppc) & PPC_FIFO_EMPTY) - goto fifo_empty; -#ifdef PPC_DEBUG - printf("Z"); -#endif - error = tsleep((caddr_t)ppc, PPBPRI | PCATCH, "ppcfifo", hz/100); - if (error != EWOULDBLOCK) { -#ifdef PPC_DEBUG - printf("I"); -#endif - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; - error = EINTR; - goto error; - } - } - -fifo_empty: - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - } else - error = EINVAL; /* XXX we should FIFO and - * interrupts */ - } else - error = EINVAL; - -error: - - /* PDRQ must be kept unasserted until nPDACK is - * deasserted for a minimum of 350ns (SMC datasheet) - * - * Consequence may be a FIFO that never empty - */ - DELAY(1); - - w_ecr(ppc, ecr_sav); - w_ctr(ppc, ctr_sav); - - return (error); -} - /* * Configure current operating mode */ @@ -1571,34 +1100,32 @@ static int ppc_generic_setmode(int unit, int mode) { struct ppc_data *ppc = ppcdata[unit]; - u_char ecr = 0; + + /* back to compatible mode, XXX don't know yet what to do here */ + if (mode == 0) { + ppc->ppc_mode = PPB_COMPATIBLE; + return (0); + } /* check if mode is available */ - if (mode && !(ppc->ppc_avm & mode)) - return (EINVAL); + if (!(ppc->ppc_avm & mode)) + return (EOPNOTSUPP); /* if ECP mode, configure ecr register */ if (ppc->ppc_avm & PPB_ECP) { - /* return to byte mode (keeping direction bit), - * no interrupt, no DMA to be able to change to - * ECP - */ - w_ecr(ppc, PPC_ECR_RESET); - ecr = PPC_DISABLE_INTR; + /* XXX disable DMA, enable interrupts */ if (mode & PPB_EPP) - return (EINVAL); - else if (mode & PPB_ECP) - /* select ECP mode */ - ecr |= PPC_ECR_ECP; + return (EOPNOTSUPP); else if (mode & PPB_PS2) /* select PS2 mode with ECP */ - ecr |= PPC_ECR_PS2; + w_ecr(ppc, 0x20); + else if (mode & PPB_ECP) + /* select ECP mode */ + w_ecr(ppc, 0x60); else - /* select COMPATIBLE/NIBBLE mode */ - ecr |= PPC_ECR_STD; - - w_ecr(ppc, ecr); + /* select standard parallel port mode */ + w_ecr(ppc, 0x00); } ppc->ppc_mode = mode; @@ -1606,50 +1133,42 @@ ppc_generic_setmode(int unit, int mode) return (0); } -/* - * The ppc driver is free to choose options like FIFO or DMA - * if ECP mode is available. - * - * The 'RAW' option allows the upper drivers to force the ppc mode - * even with FIFO, DMA available. - */ int ppc_smclike_setmode(int unit, int mode) { struct ppc_data *ppc = ppcdata[unit]; - u_char ecr = 0; + + /* back to compatible mode, XXX don't know yet what to do here */ + if (mode == 0) { + ppc->ppc_mode = PPB_COMPATIBLE; + return (0); + } /* check if mode is available */ - if (mode && !(ppc->ppc_avm & mode)) - return (EINVAL); + if (!(ppc->ppc_avm & mode)) + return (EOPNOTSUPP); /* if ECP mode, configure ecr register */ if (ppc->ppc_avm & PPB_ECP) { - /* return to byte mode (keeping direction bit), - * no interrupt, no DMA to be able to change to - * ECP or EPP mode - */ - w_ecr(ppc, PPC_ECR_RESET); - ecr = PPC_DISABLE_INTR; + /* XXX disable DMA, enable interrupts */ if (mode & PPB_EPP) /* select EPP mode */ - ecr |= PPC_ECR_EPP; - else if (mode & PPB_ECP) - /* select ECP mode */ - ecr |= PPC_ECR_ECP; + w_ecr(ppc, 0x80); else if (mode & PPB_PS2) /* select PS2 mode with ECP */ - ecr |= PPC_ECR_PS2; + w_ecr(ppc, 0x20); + else if (mode & PPB_ECP) + /* select ECP mode */ + w_ecr(ppc, 0x60); else - /* select COMPATIBLE/NIBBLE mode */ - ecr |= PPC_ECR_STD; - - w_ecr(ppc, ecr); + /* select standard parallel port mode */ + w_ecr(ppc, 0x00); } ppc->ppc_mode = mode; + return (0); } @@ -1658,7 +1177,7 @@ ppc_smclike_setmode(int unit, int mode) * Semantics of clearing EPP timeout bit. * PC87332 - reading SPP_STR does it... * SMC - write 1 to EPP timeout bit XXX - * Others - (?) write 0 to EPP timeout bit + * Others - (???) write 0 to EPP timeout bit */ static void ppc_reset_epp_timeout(int unit) @@ -1678,6 +1197,7 @@ ppcprobe(struct isa_device *dvp) { static short next_bios_ppc = 0; struct ppc_data *ppc; + int error; /* * If port not specified, use bios list. @@ -1686,9 +1206,8 @@ ppcprobe(struct isa_device *dvp) if((next_bios_ppc < BIOS_MAX_PPC) && (*(BIOS_PORTS+next_bios_ppc) != 0) ) { dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++); - if (bootverbose) - printf("ppc: parallel port found at 0x%x\n", - dvp->id_iobase); + printf("ppc: parallel port found at 0x%x\n", + dvp->id_iobase); } else return (0); } @@ -1712,9 +1231,6 @@ ppcprobe(struct isa_device *dvp) ppc->ppc_unit = dvp->id_unit; ppc->ppc_type = GENERIC; - /* store boot flags */ - ppc->ppc_flags = dvp->id_flags; - ppc->ppc_mode = PPB_COMPATIBLE; ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4; @@ -1722,9 +1238,7 @@ ppcprobe(struct isa_device *dvp) * XXX Try and detect if interrupts are working */ if (!(dvp->id_flags & 0x20)) - ppc->ppc_irq = ffs(dvp->id_irq) - 1; - - ppc->ppc_dmachan = dvp->id_drq; + ppc->ppc_irq = (dvp->id_irq); ppcdata[ppc->ppc_unit] = ppc; nppc ++; @@ -1742,6 +1256,8 @@ ppcprobe(struct isa_device *dvp) if (ppc_detect(ppc, dvp->id_flags & 0xf)) goto error; +end_probe: + return (1); error: @@ -1753,19 +1269,13 @@ ppcattach(struct isa_device *isdp) { struct ppc_data *ppc = ppcdata[isdp->id_unit]; struct ppb_data *ppbus; + char * mode; printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit, ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm], ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ? ppc_epp_protocol[ppc->ppc_epp] : ""); - if (ppc->ppc_fifo) - printf("ppc%d: FIFO with %d/%d/%d bytes threshold\n", - ppc->ppc_unit, ppc->ppc_fifo, ppc->ppc_wthr, - ppc->ppc_rthr); - - isdp->id_ointr = ppcintr; - /* * Prepare ppbus data area for upper level code. */ @@ -1777,13 +1287,6 @@ ppcattach(struct isa_device *isdp) ppc->ppc_link.ppbus = ppbus; ppbus->ppb_link = &ppc->ppc_link; - if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) { - - /* acquire the DMA channel forever */ - isa_dma_acquire(ppc->ppc_dmachan); - isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */ - } - /* * Probe the ppbus and attach devices found. */ diff --git a/sys/i386/isa/ppcreg.h b/sys/i386/isa/ppcreg.h index c847e6ccd218e..fe7e72480fe5e 100644 --- a/sys/i386/isa/ppcreg.h +++ b/sys/i386/isa/ppcreg.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppcreg.h,v 1.6 1999/01/10 12:04:53 nsouch Exp $ + * $Id: ppcreg.h,v 1.3 1998/08/03 19:14:33 msmith Exp $ * */ #ifndef __PPCREG_H @@ -32,17 +32,16 @@ /* * Parallel Port Chipset type. */ -#define SMC_LIKE 0 -#define SMC_37C665GT 1 -#define SMC_37C666GT 2 -#define NS_PC87332 3 -#define NS_PC87306 4 -#define INTEL_820191AA 5 /* XXX not implemented */ -#define GENERIC 6 -#define WINB_W83877F 7 -#define WINB_W83877AF 8 -#define WINB_UNKNOWN 9 -#define NS_PC87334 10 +#define SMC_LIKE 0x0 +#define SMC_37C665GT 0x1 +#define SMC_37C666GT 0x2 +#define NS_PC87332 0x3 +#define NS_PC87306 0x4 +#define INTEL_820191AA 0x5 /* XXX not implemented */ +#define GENERIC 0x6 +#define WINB_W83877F 0x7 +#define WINB_W83877AF 0x8 +#define WINB_UNKNOWN 0x9 /* * Generic structure to hold parallel port chipset info. @@ -55,34 +54,6 @@ struct ppc_data { int ppc_mode; /* chipset current mode */ int ppc_avm; /* chipset available modes */ -#define PPC_IRQ_NONE 0x0 -#define PPC_IRQ_nACK 0x1 -#define PPC_IRQ_DMA 0x2 -#define PPC_IRQ_FIFO 0x4 -#define PPC_IRQ_nFAULT 0x8 - int ppc_irqstat; /* remind irq settings */ - -#define PPC_DMA_INIT 0x01 -#define PPC_DMA_STARTED 0x02 -#define PPC_DMA_COMPLETE 0x03 -#define PPC_DMA_INTERRUPTED 0x04 -#define PPC_DMA_ERROR 0x05 - int ppc_dmastat; /* dma state */ - int ppc_dmachan; /* dma channel */ - int ppc_dmaflags; /* dma transfer flags */ - caddr_t ppc_dmaddr; /* buffer address */ - u_int ppc_dmacnt; /* count of bytes sent with dma */ - -#define PPC_PWORD_MASK 0x30 -#define PPC_PWORD_16 0x00 -#define PPC_PWORD_8 0x10 -#define PPC_PWORD_32 0x20 - char ppc_pword; /* PWord size */ - short ppc_fifo; /* FIFO threshold */ - - short ppc_wthr; /* writeIntrThresold */ - short ppc_rthr; /* readIntrThresold */ - #define ppc_base ppc_link.base #define ppc_epp ppc_link.epp_protocol #define ppc_irq ppc_link.id_irq @@ -99,44 +70,25 @@ struct ppc_data { * Parallel Port Chipset registers. */ #define PPC_SPP_DTR 0 /* SPP data register */ -#define PPC_ECP_A_FIFO 0 /* ECP Address fifo register */ #define PPC_SPP_STR 1 /* SPP status register */ #define PPC_SPP_CTR 2 /* SPP control register */ #define PPC_EPP_DATA 4 /* EPP data register (8, 16 or 32 bit) */ -#define PPC_ECP_D_FIFO 0x400 /* ECP Data fifo register */ -#define PPC_ECP_CNFGA 0x400 /* Configuration register A */ -#define PPC_ECP_CNFGB 0x401 /* Configuration register B */ +#define PPC_ECP_FIFO 0x400 /* ECP fifo register */ #define PPC_ECP_ECR 0x402 /* ECP extended control register */ -#define PPC_FIFO_EMPTY 0x1 /* ecr register - bit 0 */ -#define PPC_FIFO_FULL 0x2 /* ecr register - bit 1 */ -#define PPC_SERVICE_INTR 0x4 /* ecr register - bit 2 */ -#define PPC_ENABLE_DMA 0x8 /* ecr register - bit 3 */ -#define PPC_nFAULT_INTR 0x10 /* ecr register - bit 4 */ -#define PPC_ECR_STD 0x0 -#define PPC_ECR_PS2 0x20 -#define PPC_ECR_FIFO 0x40 -#define PPC_ECR_ECP 0x60 -#define PPC_ECR_EPP 0x80 - -#define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR) -#define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR) - -#define r_dtr(ppc) (inb((ppc)->ppc_base + PPC_SPP_DTR)) -#define r_str(ppc) (inb((ppc)->ppc_base + PPC_SPP_STR)) -#define r_ctr(ppc) (inb((ppc)->ppc_base + PPC_SPP_CTR)) -#define r_epp(ppc) (inb((ppc)->ppc_base + PPC_EPP_DATA)) -#define r_cnfgA(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGA)) -#define r_cnfgB(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGB)) -#define r_ecr(ppc) (inb((ppc)->ppc_base + PPC_ECP_ECR)) -#define r_fifo(ppc) (inb((ppc)->ppc_base + PPC_ECP_D_FIFO)) +#define r_dtr(ppc) ((char)inb((ppc)->ppc_base + PPC_SPP_DTR)) +#define r_str(ppc) ((char)inb((ppc)->ppc_base + PPC_SPP_STR)) +#define r_ctr(ppc) ((char)inb((ppc)->ppc_base + PPC_SPP_CTR)) +#define r_epp(ppc) ((char)inb((ppc)->ppc_base + PPC_EPP_DATA)) +#define r_ecr(ppc) ((char)inb((ppc)->ppc_base + PPC_ECP_ECR)) +#define r_fifo(ppc) ((char)inb((ppc)->ppc_base + PPC_ECP_FIFO)) #define w_dtr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_DTR, byte) #define w_str(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_STR, byte) #define w_ctr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_CTR, byte) #define w_epp(ppc,byte) outb((ppc)->ppc_base + PPC_EPP_DATA, byte) #define w_ecr(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_ECR, byte) -#define w_fifo(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_D_FIFO, byte) +#define w_fifo(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_FIFO, byte) /* * Register defines for the PC873xx parts @@ -148,8 +100,6 @@ struct ppc_data { #define PC873_PTR 0x02 #define PC873_CFGLOCK (1<<6) #define PC873_EPPRDIR (1<<7) -#define PC873_EXTENDED (1<<7) -#define PC873_LPTBIRQ7 (1<<3) #define PC873_FCR 0x03 #define PC873_ZWS (1<<5) #define PC873_ZWSPWDN (1<<6) @@ -161,9 +111,6 @@ struct ppc_data { #define PC873_PMC 0x06 #define PC873_TUP 0x07 #define PC873_SID 0x08 -#define PC873_PNP0 0x1b -#define PC873_PNP1 0x1c -#define PC873_LPTBA 0x19 /* * Register defines for the SMC FDC37C66xGT parts diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/isa/prof_machdep.c index 60167ea8ae797..f2849ad1a9dda 100644 --- a/sys/i386/isa/prof_machdep.c +++ b/sys/i386/isa/prof_machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: prof_machdep.c,v 1.10 1998/04/19 15:41:06 bde Exp $ + * $Id: prof_machdep.c,v 1.9 1998/04/15 17:45:43 bde Exp $ */ #ifdef GUPROF @@ -171,8 +171,7 @@ cputime() { u_int count; int delta; -#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) && \ - defined(PERFMON) && defined(I586_PMC_GUPROF) +#ifdef I586_PMC_GUPROF u_quad_t event_count; #endif u_char high, low; @@ -230,11 +229,9 @@ static int sysctl_machdep_cputime_clock SYSCTL_HANDLER_ARGS { int clock; - int error; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) int event; + int error; struct pmc pmc; -#endif clock = cputime_clock; #if defined(PERFMON) && defined(I586_PMC_GUPROF) diff --git a/sys/i386/isa/psm.c b/sys/i386/isa/psm.c index ca85f57386d88..389b1b8828e27 100644 --- a/sys/i386/isa/psm.c +++ b/sys/i386/isa/psm.c @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: psm.c,v 1.59 1999/01/11 03:18:23 yokota Exp $ + * $Id: psm.c,v 1.54 1998/07/06 16:10:06 eivind Exp $ */ /* @@ -86,10 +86,8 @@ #include <machine/limits.h> #include <machine/mouse.h> -#include <dev/kbd/atkbdcreg.h> - -#include <i386/isa/isa.h> #include <i386/isa/isa_device.h> +#include <i386/isa/kbdio.h> /* * Driver specific options: the following options may be set by @@ -181,20 +179,20 @@ static struct psm_softc { /* Driver status information */ #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ #define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ #define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ -#define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */ -#define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */ -#define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */ -#define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */ #define PSM_CONFIG_FLAGS (PSM_CONFIG_RESOLUTION \ | PSM_CONFIG_ACCEL \ - | PSM_CONFIG_NOCHECKSYNC \ - | PSM_CONFIG_NOIDPROBE \ - | PSM_CONFIG_NORESET \ - | PSM_CONFIG_FORCETAP \ - | PSM_CONFIG_IGNPORTERROR) + | PSM_CONFIG_NOCHECKSYNC) /* other flags (flags) */ +/* + * Pass mouse data packet to the user land program `as is', even if + * the mouse has vendor-specific enhanced features and uses non-standard + * packet format. Otherwise manipulate the mouse data packet so that + * it can be recognized by the programs which can only understand + * the standard packet format. +*/ +#define PSM_FLAGS_NATIVEMODE 0x0200 /* for backward compatibility */ #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t) @@ -240,19 +238,14 @@ static int get_aux_id __P((KBDC)); static int set_mouse_sampling_rate __P((KBDC, int)); static int set_mouse_scaling __P((KBDC, int)); static int set_mouse_resolution __P((KBDC, int)); -#ifdef PSM_RESETAFTERSUSPEND static int set_mouse_mode __P((KBDC)); -#endif /* PSM_RESETAFTERSUSPEND */ static int get_mouse_buttons __P((KBDC)); static int is_a_mouse __P((int)); static void recover_from_error __P((KBDC)); static int restore_controller __P((KBDC, int)); -#ifdef PSM_RESETAFTERSUSPEND static int reinitialize __P((int, mousemode_t *)); -#endif static int doopen __P((int, int)); static char *model_name(int); -static ointhand2_t psmintr; /* vendor specific features */ typedef int probefunc_t __P((struct psm_softc *)); @@ -287,7 +280,6 @@ static struct { { MOUSE_MODEL_GENERIC, 0xc0, MOUSE_PS2_PACKETSIZE, NULL, }, }; -#define GENERIC_MOUSE_ENTRY 6 /* device driver declarateion */ struct isa_driver psmdriver = { psmprobe, psmattach, "psm", FALSE }; @@ -435,7 +427,6 @@ set_mouse_resolution(KBDC kbdc, int val) return ((res == PSM_ACK) ? val : -1); } -#ifdef PSM_RESETAFTERSUSPEND /* * NOTE: once `set_mouse_mode()' is called, the mouse device must be * re-enabled by calling `enable_aux_dev()' @@ -451,8 +442,6 @@ set_mouse_mode(KBDC kbdc) return (res == PSM_ACK); } -#endif /* PSM_RESETAFTERSUSPEND */ - static int get_mouse_buttons(KBDC kbdc) @@ -570,7 +559,6 @@ restore_controller(KBDC kbdc, int command_byte) } } -#ifdef PSM_RESETAFTERSUSPEND /* * Re-initialize the aux port and device. The aux port must be enabled * and its interrupt must be disabled before calling this routine. @@ -598,28 +586,19 @@ reinitialize(int unit, mousemode_t *mode) case -1: /* time out */ default: /* error */ recover_from_error(kbdc); - if (sc->config & PSM_CONFIG_IGNPORTERROR) - break; log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n", unit, i); return FALSE; } - if (sc->config & PSM_CONFIG_NORESET) { - /* - * Don't try to reset the pointing device. It may possibly be - * left in the unknown state, though... - */ - } else { - /* - * NOTE: some controllers appears to hang the `keyboard' when - * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. - */ - if (!reset_aux_dev(kbdc)) { - recover_from_error(kbdc); - log(LOG_ERR, "psm%d: failed to reset the aux device.\n", unit); - return FALSE; - } + /* + * NOTE: some controllers appears to hang the `keyboard' when + * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. + */ + if (!reset_aux_dev(kbdc)) { + recover_from_error(kbdc); + log(LOG_ERR, "psm%d: failed to reset the aux device.\n", unit); + return FALSE; } /* @@ -632,19 +611,15 @@ reinitialize(int unit, mousemode_t *mode) } empty_both_buffers(kbdc, 10); /* remove stray data if any */ - if (sc->config & PSM_CONFIG_NOIDPROBE) { - i = GENERIC_MOUSE_ENTRY; - } else { - /* FIXME: hardware ID, mouse buttons? */ - - /* other parameters */ - for (i = 0; vendortype[i].probefunc != NULL; ++i) { - if ((*vendortype[i].probefunc)(sc)) { - if (verbose >= 2) - log(LOG_ERR, "psm%d: found %s\n", - unit, model_name(vendortype[i].model)); - break; - } + /* FIXME: hardware ID, mouse buttons? */ + + /* other parameters */ + for (i = 0; vendortype[i].probefunc != NULL; ++i) { + if ((*vendortype[i].probefunc)(sc)) { + if (verbose >= 2) + log(LOG_ERR, "psm%d: found %s\n", + unit, model_name(vendortype[i].model)); + break; } } @@ -677,7 +652,6 @@ reinitialize(int unit, mousemode_t *mode) return TRUE; } -#endif /* PSM_RESETAFTERSUSPEND */ static int doopen(int unit, int command_byte) @@ -818,7 +792,6 @@ psmprobe(struct isa_device *dvp) printf("psm%d: unable to set the command byte.\n", unit); endprobe(0); } - write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT); /* * NOTE: `test_aux_port()' is designed to return with zero if the aux @@ -849,8 +822,6 @@ psmprobe(struct isa_device *dvp) case -1: /* time out */ default: /* error */ recover_from_error(sc->kbdc); - if (sc->config & PSM_CONFIG_IGNPORTERROR) - break; restore_controller(sc->kbdc, command_byte); if (verbose) printf("psm%d: the aux port is not functioning (%d).\n", @@ -858,25 +829,17 @@ psmprobe(struct isa_device *dvp) endprobe(0); } - if (sc->config & PSM_CONFIG_NORESET) { - /* - * Don't try to reset the pointing device. It may possibly be - * left in the unknown state, though... - */ - } else { - /* - * NOTE: some controllers appears to hang the `keyboard' when the aux - * port doesn't exist and `PSMC_RESET_DEV' is issued. - */ - if (!reset_aux_dev(sc->kbdc)) { - recover_from_error(sc->kbdc); - restore_controller(sc->kbdc, command_byte); - if (verbose) - printf("psm%d: failed to reset the aux device.\n", unit); - endprobe(0); - } + /* + * NOTE: some controllers appears to hang the `keyboard' when the aux + * port doesn't exist and `PSMC_RESET_DEV' is issued. + */ + if (!reset_aux_dev(sc->kbdc)) { + recover_from_error(sc->kbdc); + restore_controller(sc->kbdc, command_byte); + if (verbose) + printf("psm%d: failed to reset the aux device.\n", unit); + endprobe(0); } - /* * both the aux port and the aux device is functioning, see if the * device can be enabled. NOTE: when enabled, the device will start @@ -884,12 +847,11 @@ psmprobe(struct isa_device *dvp) * the device can be enabled. */ if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) { - /* MOUSE ERROR */ - recover_from_error(sc->kbdc); - restore_controller(sc->kbdc, command_byte); - if (verbose) - printf("psm%d: failed to enable the aux device.\n", unit); - endprobe(0); + /* MOUSE ERROR */ + restore_controller(sc->kbdc, command_byte); + if (verbose) + printf("psm%d: failed to enable the aux device.\n", unit); + endprobe(0); } /* save the default values after reset */ @@ -925,21 +887,16 @@ psmprobe(struct isa_device *dvp) break; } - if (sc->config & PSM_CONFIG_NOIDPROBE) { - sc->hw.buttons = 2; - i = GENERIC_MOUSE_ENTRY; - } else { - /* # of buttons */ - sc->hw.buttons = get_mouse_buttons(sc->kbdc); - - /* other parameters */ - for (i = 0; vendortype[i].probefunc != NULL; ++i) { - if ((*vendortype[i].probefunc)(sc)) { - if (verbose >= 2) - printf("psm%d: found %s\n", - unit, model_name(vendortype[i].model)); - break; - } + /* # of buttons */ + sc->hw.buttons = get_mouse_buttons(sc->kbdc); + + /* other parameters */ + for (i = 0; vendortype[i].probefunc != NULL; ++i) { + if ((*vendortype[i].probefunc)(sc)) { + if (verbose >= 2) + printf("psm%d: found %s\n", + unit, model_name(vendortype[i].model)); + break; } } @@ -952,8 +909,6 @@ psmprobe(struct isa_device *dvp) sc->dflt_mode.syncmask[0] = 0; else sc->dflt_mode.syncmask[0] = vendortype[i].syncmask; - if (sc->config & PSM_CONFIG_FORCETAP) - sc->mode.syncmask[0] &= ~MOUSE_PS2_TAP; sc->dflt_mode.syncmask[1] = 0; /* syncbits */ sc->mode = sc->dflt_mode; sc->mode.packetsize = vendortype[i].packetsize; @@ -1013,7 +968,7 @@ psmprobe(struct isa_device *dvp) psm_softc[unit] = sc; kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS); kbdc_lock(sc->kbdc, FALSE); - return ((dvp->id_iobase < 0) ? -1 : IO_PSMSIZE); + return (IO_PSMSIZE); } static int @@ -1022,8 +977,6 @@ psmattach(struct isa_device *dvp) int unit = dvp->id_unit; struct psm_softc *sc = psm_softc[unit]; - dvp->id_ointr = psmintr; - if (sc == NULL) /* shouldn't happen */ return (0); @@ -1709,7 +1662,7 @@ psmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) return error; } -static void +void psmintr(int unit) { /* @@ -1778,9 +1731,6 @@ psmintr(int unit) z = 0; ms.obutton = sc->button; /* previous button state */ ms.button = butmap[c & MOUSE_PS2_BUTTONS]; - /* `tapping' action */ - if (sc->config & PSM_CONFIG_FORCETAP) - ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN; switch (sc->hw.model) { diff --git a/sys/i386/isa/rc.c b/sys/i386/isa/rc.c index ae1108a8e1dae..e946c5876ef37 100644 --- a/sys/i386/isa/rc.c +++ b/sys/i386/isa/rc.c @@ -172,7 +172,6 @@ static int rc_rcsrt[16] = { }; /* Static prototypes */ -static ointhand2_t rcintr; static void rc_hwreset __P((int, int, unsigned int)); static int rc_test __P((int, int)); static void rc_discard_output __P((struct rc_chans *)); @@ -232,8 +231,6 @@ rcattach(dvp) static int rc_started = 0; struct tty *tp; - dvp->id_ointr = rcintr; - /* Thorooughly test the device */ if (rcb->rcb_probed != RC_PROBED) return 0; @@ -281,8 +278,7 @@ rcattach(dvp) } /* RC interrupt handling */ -static void -rcintr(unit) +void rcintr(unit) int unit; { register struct rc_softc *rcb = &rc_softc[unit]; diff --git a/sys/i386/isa/rp.c b/sys/i386/isa/rp.c index 28acaeec53bbb..847660e70c92d 100644 --- a/sys/i386/isa/rp.c +++ b/sys/i386/isa/rp.c @@ -768,7 +768,7 @@ void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) static int rpprobe __P((struct isa_device *)); static int rpattach __P((struct isa_device *)); -static const char* rp_pciprobe(pcici_t tag, pcidi_t type); +static char* rp_pciprobe(pcici_t tag, pcidi_t type); static void rp_pciattach(pcici_t tag, int unit); static u_long rp_pcicount; @@ -809,11 +809,10 @@ static struct cdevsw rp_cdevsw = { static int rp_controller_port = 0; static int rp_num_ports_open = 0; +static int rp_timeout; static int ndevs = 0; static int minor_to_unit[128]; -#if 0 static struct tty rp_tty[128]; -#endif static int rp_num_ports[4]; /* Number of ports on each controller */ @@ -859,7 +858,7 @@ static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp, { int spl; unsigned int CharNStat; - int ToRecv, ch; + int ToRecv, wRecv, ch; ToRecv = sGetRxCnt(cp); if(ToRecv == 0) @@ -925,7 +924,7 @@ static _INLINE_ void rp_handle_port(struct rp_port *rp) CHANNEL_t *cp; struct tty *tp; unsigned int IntMask, ChanStatus; - /* int oldcts; */ + int oldcts, ToRecv; if(!rp) return; @@ -1007,7 +1006,7 @@ static void rp_do_poll(void *not_used) timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); } -static const char* +static char* rp_pciprobe(pcici_t tag, pcidi_t type) { int vendor_id; @@ -1024,8 +1023,9 @@ int rpprobe(dev) struct isa_device *dev; { + struct isa_device *idev; int controller, unit; - int aiop, num_aiops; + int i, aiop, num_aiops; unsigned int aiopio[MAX_AIOPS_PER_BOARD]; CONTROLLER_t *ctlp; @@ -1070,7 +1070,7 @@ static void rp_pciattach(pcici_t tag, int unit) { dev_t rp_dev; - int success, oldspl; + int success, rpmajor, oldspl; u_short iobase; int num_ports, num_chan, num_aiops; int aiop, chan, port; @@ -1079,6 +1079,7 @@ rp_pciattach(pcici_t tag, int unit) struct rp_port *rp; struct tty *tty; CONTROLLER_t *ctlp; + char status; success = pci_map_port(tag, 0x10, &iobase); if(!success) @@ -1182,7 +1183,7 @@ struct isa_device *dev; { struct isa_device *idev; dev_t rp_dev; - int iobase, unit, /*rpmajor,*/ oldspl; + int iobase, unit, rpmajor, oldspl; int num_ports, num_chan, num_aiops; int aiop, chan, port; int ChanStatus, line, i, count; @@ -1190,6 +1191,7 @@ struct isa_device *dev; struct rp_port *rp; struct tty *tty; CONTROLLER_t *ctlp; + char status; iobase = dev->id_iobase; unit = dev->id_unit; @@ -1301,7 +1303,7 @@ rpopen(dev, flag, mode, p) struct proc *p; { struct rp_port *rp; - int unit, port, mynor, umynor, flags; /* SG */ + int unit, i, port, mynor, umynor, flags; /* SG */ struct tty *tp; int oldspl, error; unsigned int IntMask, ChanStatus; @@ -1448,7 +1450,7 @@ rpclose(dev, flag, mode, p) int flag, mode; struct proc *p; { - int oldspl, unit, mynor, umynor, port; /* SG */ + int oldspl, unit, mynor, umynor, port, status, i; /* SG */ struct rp_port *rp; struct tty *tp; CHANNEL_t *cp; @@ -1481,7 +1483,7 @@ rpclose(dev, flag, mode, p) static void rphardclose(struct rp_port *rp) { - int mynor; + int status, oldspl, mynor; struct tty *tp; CHANNEL_t *cp; @@ -1523,7 +1525,7 @@ rpread(dev, uio, flag) { struct rp_port *rp; struct tty *tp; - int unit, mynor, umynor, port, error = 0; /* SG */ + int unit, i, mynor, umynor, port, error = 0; /* SG */ umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ port = (minor(dev) & 0x1f); /* SG */ @@ -1547,7 +1549,7 @@ rpwrite(dev, uio, flag) { struct rp_port *rp; struct tty *tp; - int unit, mynor, port, umynor, error = 0; /* SG */ + int unit, i, mynor, port, umynor, error = 0; /* SG */ umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ port = (minor(dev) & 0x1f); /* SG */ @@ -1592,8 +1594,9 @@ rpioctl(dev, cmd, data, flag, p) CHANNEL_t *cp; struct tty *tp; int unit, mynor, port, umynor; /* SG */ - int oldspl; - int error = 0; + int oldspl, cflag, iflag, oflag, lflag; + int i, error = 0; + char status; int arg, flags, result, ChanStatus; int oldcmd; struct termios term, *t; @@ -1801,9 +1804,9 @@ rpparam(tp, t) { struct rp_port *rp; CHANNEL_t *cp; - int unit, mynor, port, umynor; /* SG */ + int unit, i, mynor, port, umynor; /* SG */ int oldspl, cflag, iflag, oflag, lflag; - int ospeed; + int ospeed, flags; umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ @@ -1939,10 +1942,10 @@ rpstart(tp) struct rp_port *rp; CHANNEL_t *cp; struct clist *qp; - int unit, mynor, port, umynor; /* SG */ - char ch, flags; + int unit, i, mynor, port, umynor; /* SG */ + char status, ch, flags; int spl, xmit_fifo_room; - int count; + int count, ToRecv; umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ @@ -1999,8 +2002,11 @@ rpstop(tp, flag) { struct rp_port *rp; CHANNEL_t *cp; + struct clist *qp; int unit, mynor, port, umynor; /* SG */ - int spl; + char status, ch; + int spl, xmit_fifo_room; + int i, count; umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ port = (minor(tp->t_dev) & 0x1f); /* SG */ @@ -2038,7 +2044,7 @@ struct tty * rpdevtotty(dev_t dev) { struct rp_port *rp; - int unit, port, mynor, umynor; /* SG */ + int unit, i, port, mynor, umynor; /* SG */ umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ port = (minor(dev) & 0x1f); /* SG */ diff --git a/sys/i386/isa/scd.c b/sys/i386/isa/scd.c index 7eeca7b004c2d..15ad25ed505c9 100644 --- a/sys/i386/isa/scd.c +++ b/sys/i386/isa/scd.c @@ -41,7 +41,7 @@ */ -/* $Id: scd.c,v 1.40 1998/07/13 09:53:02 bde Exp $ */ +/* $Id: scd.c,v 1.39 1998/07/04 22:30:17 julian Exp $ */ /* Please send any comments to micke@dynas.se */ @@ -201,8 +201,7 @@ static struct cdevsw scd_cdevsw = { D_DISK, 0, -1 }; -static int -scd_attach(struct isa_device *dev) +int scd_attach(struct isa_device *dev) { int unit = dev->id_unit; struct scd_data *cd = scd_data + unit; @@ -695,13 +694,7 @@ scd_subchan(int unit, struct ioc_read_subchannel *sc) return 0; } -static __inline void -write_control(unsigned port, unsigned data) -{ - outb(port + OREG_CONTROL, data); -} - -static int +int scd_probe(struct isa_device *dev) { struct sony_drive_configuration drive_config; @@ -1292,6 +1285,12 @@ read_toc(dev_t dev) return 0; } +static __inline void +write_control(unsigned port, unsigned data) +{ + outb(port + OREG_CONTROL, data); +} + static void init_drive(unsigned unit) { diff --git a/sys/i386/isa/scvesactl.c b/sys/i386/isa/scvesactl.c new file mode 100644 index 0000000000000..aabfe1901b566 --- /dev/null +++ b/sys/i386/isa/scvesactl.c @@ -0,0 +1,145 @@ +/*- + * 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: scvesactl.c,v 1.5 1998/09/26 03:38:40 yokota Exp $ + */ + +#include "sc.h" +#include "opt_vesa.h" +#include "opt_vm86.h" + +#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/tty.h> +#include <sys/kernel.h> + +#include <machine/apm_bios.h> +#include <machine/console.h> +#include <machine/pc/vesa.h> + +#include <i386/isa/videoio.h> +#include <i386/isa/syscons.h> + +static d_ioctl_t *prev_user_ioctl; + +static int +vesa_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + scr_stat *scp; + struct tty *tp; + video_info_t info; + video_adapter_t *adp; + int mode; + int error; + int s; + + tp = scdevtotty(dev); + if (!tp) + return ENXIO; + scp = sc_get_scr_stat(tp->t_dev); + + switch (cmd) { + + /* generic text modes */ + case SW_TEXT_132x25: case SW_TEXT_132x30: + case SW_TEXT_132x43: case SW_TEXT_132x50: + case SW_TEXT_132x60: + adp = get_adapter(scp); + if (!(adp->va_flags & V_ADP_MODECHANGE)) + return ENODEV; + return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); + + /* text modes */ + case SW_VESA_C80x60: + case SW_VESA_C132x25: + case SW_VESA_C132x43: + case SW_VESA_C132x50: + case SW_VESA_C132x60: + adp = get_adapter(scp); + if (!(adp->va_flags & V_ADP_MODECHANGE)) + return ENODEV; + mode = (cmd & 0xff) + M_VESA_BASE; +vesa_text: + return sc_set_text_mode(scp, tp, mode, 0, 0, 0); + + /* graphics modes */ + case SW_VESA_32K_320: case SW_VESA_64K_320: + case SW_VESA_FULL_320: + + case SW_VESA_CG640x400: + + case SW_VESA_CG640x480: + case SW_VESA_32K_640: case SW_VESA_64K_640: + case SW_VESA_FULL_640: + + case SW_VESA_800x600: case SW_VESA_CG800x600: + case SW_VESA_32K_800: case SW_VESA_64K_800: + case SW_VESA_FULL_800: + + case SW_VESA_1024x768: case SW_VESA_CG1024x768: + case SW_VESA_32K_1024: case SW_VESA_64K_1024: + case SW_VESA_FULL_1024: + + case SW_VESA_1280x1024: case SW_VESA_CG1280x1024: + case SW_VESA_32K_1280: case SW_VESA_64K_1280: + case SW_VESA_FULL_1280: + adp = get_adapter(scp); + if (!(adp->va_flags & V_ADP_MODECHANGE)) + return ENODEV; + mode = (cmd & 0xff) + M_VESA_BASE; +vesa_graphics: + return sc_set_graphics_mode(scp, tp, mode); + } + + if (prev_user_ioctl) + return (*prev_user_ioctl)(dev, cmd, data, flag, p); + else + return ENOIOCTL; +} + +int +vesa_load_ioctl(void) +{ + if (prev_user_ioctl) + return EBUSY; + prev_user_ioctl = sc_user_ioctl; + sc_user_ioctl = vesa_ioctl; + return 0; +} + +int +vesa_unload_ioctl(void) +{ + if (sc_user_ioctl != vesa_ioctl) + return EBUSY; + sc_user_ioctl = prev_user_ioctl; + prev_user_ioctl = NULL; + return 0; +} + +#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */ diff --git a/sys/i386/isa/scvidctl.c b/sys/i386/isa/scvidctl.c new file mode 100644 index 0000000000000..065dee28357a9 --- /dev/null +++ b/sys/i386/isa/scvidctl.c @@ -0,0 +1,496 @@ +/*- + * 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.4 1998/09/29 02:00:56 ache 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 <i386/isa/videoio.h> +#include <i386/isa/syscons.h> + +/* video ioctl */ + +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_adapter_t *adp; + video_info_t info; + int error; + int s; + int i; + + if ((*biosvidsw.get_info)(scp->adp, mode, &info)) + return ENODEV; + adp = get_adapter(scp); + + /* 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->xpixel = scp->xsize*8; + scp->ypixel = scp->ysize*fontsize; + + /* allocate buffers */ + sc_alloc_scr_buffer(scp, TRUE, TRUE); + if (ISMOUSEAVAIL(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_adapter_t *adp; + video_info_t info; + int error; + int s; + + if ((*biosvidsw.get_info)(scp->adp, mode, &info)) + return ENODEV; + adp = get_adapter(scp); + + /* 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->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_adapter_t *adp; + video_info_t info; + int error; + int s; + int i; + + if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) + return ENODEV; /* this shouldn't happen */ + adp = get_adapter(scp); + +#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", + 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(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; + video_adapter_t *adp; + int error; + int s; + + scp = sc_get_scr_stat(tp->t_dev); + + switch (cmd) { + + case CONS_CURRENT: /* get current adapter type */ + adp = get_adapter(scp); + *(int *)data = adp->va_type; + return 0; + + case CONS_CURRENTADP: /* get current adapter index */ + *(int *)data = scp->adp; + return 0; + + case CONS_ADPINFO: /* adapter information */ + adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index); + if (adp == NULL) + return ENODEV; + bcopy(adp, data, sizeof(*adp)); + return 0; + + case CONS_GET: /* get current video mode */ + *(int *)data = scp->mode; + return 0; + + case CONS_MODEINFO: /* get mode information */ + return ((*biosvidsw.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 ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data) + ? ENODEV : 0); + + case CONS_SETWINORG: + return ((*biosvidsw.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: + adp = get_adapter(scp); + if (!(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: + adp = get_adapter(scp); + if (!(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 + adp = get_adapter(scp); + if (ISFONTAVAIL(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, palette); + + /* move hardware cursor out of the way */ + (*biosvidsw.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; + } + 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; + 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, 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); + 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(cur_console, scp->border); + return 0; + } + + return ENOIOCTL; +} + +#endif /* NSC > 0 */ diff --git a/sys/i386/isa/seagate.c b/sys/i386/isa/seagate.c new file mode 100644 index 0000000000000..8b2be3ff63d57 --- /dev/null +++ b/sys/i386/isa/seagate.c @@ -0,0 +1,1506 @@ +/* + * (Free/Net/386)BSD ST01/02, Future Domain TMC-885, TMC-950 SCSI driver for + * Julians SCSI-code + * + * Copyright 1994, Kent Palmkvist (kentp@isy.liu.se) + * Copyright 1994, Robert Knier (rknier@qgraph.com) + * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu) + * Copyright 1994, Julian Elischer (julian@tfs.com) + * Copyright 1994-1995, Serge Vakulenko (vak@cronyx.ru) + * Copyright 1995 Stephen Hocking (sysseh@devetir.qld.gov.au) + * + * Others that has contributed by example code is + * Glen Overby (overby@cray.com) + * Tatu Yllnen + * Brian E Litzinger + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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. + */ + +/* + * kentp 940307 alpha version based on newscsi-03 version of Julians SCSI-code + * kentp 940314 Added possibility to not use messages + * rknier 940331 Added fast transfer code + * rknier 940407 Added assembler coded data transfers + * vak 941226 New probe algorithm, based on expected behaviour + * instead of BIOS signatures analysis, better timeout handling, + * new asm fragments for data input/output, target-dependent + * delays, device flags, polling mode, generic cleanup + * vak 950115 Added request-sense ops + * seh 950701 Fixed up Future Domain TMC-885 problems with disconnects, + * weird phases and the like. (we could probably investigate + * what the board's idea of the phases are, but that requires + * doco that I don't have). Note that it is slower than the + * 2.0R driver with both SEA_BLINDTRANSFER & SEA_ASSEMBLER + * defined by a factor of more than 2. I'll look at that later! + * seh 950712 The performance release 8^). Put in the blind transfer code + * from the 2.0R source. Don't use it by commenting out the + * SEA_BLINDTRANSFER below. Note that it only kicks in during + * DATAOUT or DATAIN and then only when the transfer is a + * multiple of BLOCK_SIZE bytes (512). Most devices fit into + * that category, with the possible exception of scanners and + * some of the older MO drives. + * + * $Id: seagate.c,v 1.30 1998/07/15 09:38:10 bde Exp $ + */ + +/* + * What should really be done: + * + * Restructure interrupt enable/disable code (runs too long with int disabled) + * Add code to handle Future Domain 840, 841, 880 and 881 + * Add code to use tagged commands in SCSI2 + * Add code to handle slow devices better (sleep if device not disconnecting) + * Fix unnecessary interrupts + */ + +/* Note to users trying to share a disk between DOS and unix: + * The ST01/02 is a translating host-adapter. It is not giving DOS + * the same number of heads/tracks/sectors as specified by the disk. + * It is therefore important to look at what numbers DOS thinks the + * disk has. Use these to disklabel your disk in an appropriate manner + * + * About ST02+IDE coexistence: the original Seagate ST02 + * BIOS cannot coexist with IDE or any other disk controller + * because it does not share BIOS disk drive numbers (80h, 81h) + * with others. New probing code allows using ST02 controller + * without BIOS: just unplug the ST02 BIOS chip from the board. + * + * Another problem is the floppy adapter on ST02 which could not be + * disabled by jumpers. I commonly use ST02 adapter as a cheap solution + * for atttaching the tape and CD-ROM drives, and an extra floppy controller + * is just a headache. I found a simple workaround: cutting off + * the AEN signal (A11 contact on ISA connector). AEN then goes high and + * disables the floppy adapter port address decoder. + * + * I also had a problem with ST02 conflicting with IDE during + * IDE data write phase. It seems than ST02 makes some noise + * on /IOW line. The /IOW line is used only for floppy controller + * part of ST02, and because I don't need it, I cut off the /IOW (contact B13) + * and it helped. (vak) + * + * Tested on the following hardware: + * Adapter: Seagate ST02 + * Disk: HP D1686 + * Streamers: Archive Viper 150, Wangtek 5525 + * CD-ROMs: Toshiba XM-3401, NEC CDR-25 + * + * Maximum data rate is about 270-280 kbytes/sec (on 386DX/40). + * (vak) + */ +#undef DEBUG + +#include "sea.h" +#if NSEA > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <machine/clock.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + +#include <i386/isa/isa_device.h> + +#include <scsi/scsiconf.h> + +#ifdef DEBUG +# define PRINT(s) printf s +#else +# define PRINT(s) /*void*/ +#endif + +#define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */ +#define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */ +#define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */ +#define SEA_BLINDTRANSFER 1 /* for quicker than quick xfers */ +/* + * Define config flags + */ +#define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */ + +/* + * Board CONTROL register + */ +#define CMD_RST 0x01 /* scsi reset */ +#define CMD_SEL 0x02 /* scsi select */ +#define CMD_BSY 0x04 /* scsi busy */ +#define CMD_ATTN 0x08 /* scsi attention */ +#define CMD_START_ARB 0x10 /* start arbitration bit */ +#define CMD_EN_PARITY 0x20 /* enable scsi parity generation */ +#define CMD_INTR 0x40 /* enable scsi interrupts */ +#define CMD_DRVR_ENABLE 0x80 /* scsi enable */ + +/* + * Board STATUS register + */ +#define STAT_BSY 0x01 /* scsi busy */ +#define STAT_MSG 0x02 /* scsi msg */ +#define STAT_IO 0x04 /* scsi I/O */ +#define STAT_CD 0x08 /* scsi C/D */ +#define STAT_REQ 0x10 /* scsi req */ +#define STAT_SEL 0x20 /* scsi select */ +#define STAT_PARITY 0x40 /* parity error bit */ +#define STAT_ARB_CMPL 0x80 /* arbitration complete bit */ +#define STAT_BITS "\20\1bsy\2msg\3i/o\4c/d\5req\6sel\7parity\10arb" + +/* + * SCSI bus phases + */ +#define PHASE_MASK (STAT_MSG | STAT_CD | STAT_IO) +#define PHASE_DATAOUT 0 +#define PHASE_DATAIN STAT_IO +#define PHASE_CMDOUT STAT_CD +#define PHASE_STATIN (STAT_CD | STAT_IO) +#define PHASE_MSGOUT (STAT_MSG | STAT_CD) +#define PHASE_MSGIN (STAT_MSG | STAT_CD | STAT_IO) +#define PHASE_NAME(ph) phase_name[(ph)>>2] + +static char *phase_name[] = { + "DATAOUT", "Phase1?", "Phase2?", "Phase3?", + "DATAIN", "Phase5?", "Phase6?", "Phase7?", + "CMDOUT", "Phase9?", "MSGOUT", "Phase11?", + "STATIN", "Phase13?", "MSGIN", "Phase15?", +}; + +/* + * SCSI message codes + */ +#define MSG_COMMAND_COMPLETE 0x00 +#define MSG_SAVE_POINTERS 0x02 +#define MSG_RESTORE_POINTERS 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_ABORT 0x06 +#define MSG_MESSAGE_REJECT 0x07 +#define MSG_NOP 0x08 +#define MSG_BUS_DEV_RESET 0x0c +#define MSG_IDENTIFY(lun) (0xc0 | ((lun) & 0x7)) +#define MSG_ISIDENT(m) ((m) & 0x80) + +/* + * SCSI control block used to keep info about a scsi command + */ +typedef struct scb { + int flags; /* status of the instruction */ +#define SCB_FREE 0x00 +#define SCB_ACTIVE 0x01 +#define SCB_ABORTED 0x02 +#define SCB_TIMEOUT 0x04 +#define SCB_ERROR 0x08 +#define SCB_TIMECHK 0x10 /* we have set a timeout on this one */ +#define SCB_SENSE 0x20 /* sensed data available */ +#define SCB_TBUSY 0x40 /* target busy */ + struct scb *next; /* in free list */ + struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */ + u_char *data; /* position in data buffer so far */ + int32_t datalen; /* bytes remaining to transfer */ +} scb_t; + +typedef enum { + CTLR_NONE, + CTLR_SEAGATE, + CTLR_FUTURE_DOMAIN +} ctlr_t; + +/* + * Flags for waiting for REQ deassert during some SCSI bus phases. + */ +typedef struct { + unsigned cmdout1 : 1; /* after CMDOUT[0] byte */ + unsigned cmdout : 1; /* after CMDOUT[1..N] bytes */ + unsigned msgout : 1; /* after MSGOUT byte */ + unsigned statin : 1; /* after STATIN byte */ +} phase_t; + +/* + * Data structure describing the target state. + */ +typedef struct { + struct adapter *adapter; /* pointer to the adapter structure */ + u_char busy; /* mask of busy luns at device target */ + u_long perrcnt; /* counter of target parity errors */ + phase_t ndelay; /* "don't delay" flags */ + phase_t init; /* "initialized" flags */ +} target_t; + +/* + * Data structure describing current status of the scsi bus. One for each + * controller card. + */ +typedef struct adapter { + ctlr_t type; /* Seagate or Future Domain */ + char *name; /* adapter name */ + volatile u_char *addr; /* base address for card */ + + volatile u_char *CONTROL; /* address of control register */ + volatile u_char *STATUS; /* address of status register */ + volatile u_char *DATA; /* address of data register */ + + u_char scsi_addr; /* our scsi address, 0..7 */ + u_char scsi_id; /* our scsi id mask */ + u_char parity; /* parity flag: CMD_EN_PARITY or 0 */ + u_char irq; /* IRQ number used or 0 if no IRQ */ + u_int timeout_active : 1; /* timeout() active (requested) */ + + struct scsi_link sc_link; /* struct connecting different data */ + scb_t *queue; /* waiting to be issued */ + scb_t *disconnected_queue; /* waiting to reconnect */ + + int numscb; /* number of scsi control blocks */ + scb_t *free_scb; /* free scb list */ + scb_t scbs[SCB_TABLE_SIZE]; + + target_t target[8]; /* target state data */ +} adapter_t; + +static adapter_t seadata[NSEA]; + +#define IS_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &\ + (1 << (b)->xfer->sc_link->lun)) +#define SET_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy |=\ + (1 << (b)->xfer->sc_link->lun)) +#define CLEAR_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &=\ + ~(1 << (b)->xfer->sc_link->lun)) + +/* + * Wait for condition, given as an boolean expression. + * Print the message on timeout. + */ +#define WAITFOR(condition,message) {\ + register u_long cnt = 100000; char *_msg = message;\ + while (cnt-- && ! (condition)) continue;\ + if (cnt == -1 && _msg)\ + printf ("sea: %s timeout\n", _msg); } + +#define WAITFOR10(condition,message) {\ + register u_long cnt = 1000000; char *_msg = message;\ + while (cnt-- && ! (condition)) continue;\ + if (cnt == -1 && _msg)\ + printf ("sea: %s timeout\n", _msg); } + +/* + * Seagate adapter does not support in hardware + * waiting for REQ deassert after transferring each data byte. + * We must do it in software. + * The problem is that some SCSI devices deassert REQ so fast that + * we can miss it. We the flag for each target sayind if we should (not) + * wait for REQ deassert. This flag is initialized when the first + * operation on the target is done. + * 1) Test if we don't need to wait for REQ deassert (`nodelay' flag). + * Initially the flag is off, i.e. wait. If the flag is set, + * go to the step 4. + * 2) Wait for REQ deassert (call sea_wait_for_req_deassert function). + * If REQ deassert got, go to the step 4. If REQ did not cleared + * during timeout period, go to the next step. + * 3) If `nodelay' flag did not initialized yet (`init' flag), + * then set `ndelay' flag. + * 4) Set `init' flag. Done. + */ +#define WAITREQ(t,op,cnt) {\ + if (! (t)->ndelay.op &&\ + ! sea_wait_for_req_deassert ((t)->adapter, cnt, #op) &&\ + ! (t)->init.op)\ + (t)->ndelay.op = 1;\ + (t)->init.op = 1; } + +static int sea_probe (struct isa_device *dev); +static int sea_detect (adapter_t *z, struct isa_device *dev); +static int sea_attach (struct isa_device *dev); +static int32_t sea_scsi_cmd (struct scsi_xfer *xs); +static u_int32_t sea_adapter_info (int unit); +static void sea_timeout (void *scb); +static void seaminphys (struct buf *bp); +static void sea_done (adapter_t *z, scb_t *scb); +static void sea_start (adapter_t *z); +static void sea_information_transfer (adapter_t *z, scb_t *scb); +static int sea_poll (adapter_t *z, scb_t *scb); +static int sea_init (adapter_t *z); +static int sea_reselect (adapter_t *z); +static int sea_select (volatile adapter_t *z, scb_t *scb); +static int sea_abort (adapter_t *z, scb_t *scb); +static void sea_send_abort (adapter_t *z); +static u_char sea_msg_input (adapter_t *z); +static void sea_tick (void *arg); +static int sea_sense (adapter_t *z, scb_t *scb); +static void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen); +static void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen); +static void sea_cmd_output (target_t *z, u_char *cmd, int cmdlen); + +static struct scsi_adapter sea_switch = { + sea_scsi_cmd, seaminphys, 0, 0, sea_adapter_info, "sea", {0}, +}; +static struct scsi_device sea_dev = { NULL, NULL, NULL, NULL, "sea", 0, {0} }; +struct isa_driver seadriver = { sea_probe, sea_attach, "sea" }; + +/* FD TMC885's can't handle detach & re-attach */ +static int sea_select_cmd = CMD_DRVR_ENABLE | CMD_ATTN; + +/* + * Check if the device can be found at the port given and if so, + * detect the type of board. Set it up ready for further work. + * Takes the isa_dev structure from autoconf as an argument. + * Returns 1 if card recognized, 0 if errors. + */ +int sea_probe (struct isa_device *dev) +{ + adapter_t *z = &seadata[dev->id_unit]; + static const int addrtab[] = { + 0xc8000, 0xca000, 0xcc000, 0xce000, 0xdc000, 0xde000, 0, + }; + int i; + + /* Init fields used by our routines */ + z->parity = (dev->id_flags & FLAG_NOPARITY) ? 0 : CMD_EN_PARITY; + z->scsi_addr = HOST_SCSI_ADDR; + z->scsi_id = 1 << z->scsi_addr; + z->irq = dev->id_irq ? ffs (dev->id_irq) - 1 : 0; + z->queue = 0; + z->disconnected_queue = 0; + for (i=0; i<8; i++) { + z->target[i].adapter = z; + z->target[i].busy = 0; + } + + /* Link up the free list of scbs */ + z->numscb = SCB_TABLE_SIZE; + z->free_scb = z->scbs; + for (i=1; i<SCB_TABLE_SIZE; i++) + z->scbs[i-1].next = z->scbs + i; + z->scbs[SCB_TABLE_SIZE-1].next = 0; + + /* Detect the adapter. */ + dev->id_msize = 0x4000; + if (! dev->id_maddr) + for (i=0; addrtab[i]; ++i) { + dev->id_maddr = (u_char*) KERNBASE + addrtab[i]; + if (sea_detect (z, dev)) + return (1); + } + else if (sea_detect (z, dev)) + return (1); + + bzero (z, sizeof (*z)); + return (0); +} + +int sea_detect (adapter_t *z, struct isa_device *dev) +{ + z->addr = dev->id_maddr; + + /* Try Seagate. */ + z->type = CTLR_SEAGATE; + z->name = "Seagate ST01/ST02"; + z->CONTROL = z->addr + 0x1a00; /* ST01/ST02 register offsets */ + z->STATUS = z->addr + 0x1a00; + z->DATA = z->addr + 0x1c00; + if (sea_init (z) == 0) + return (1); + + /* Try Future Domain. */ + z->type = CTLR_FUTURE_DOMAIN; + z->name = "Future Domain TMC-885/TMC-950"; + z->CONTROL = z->addr + 0x1c00; /* TMC-885/TMC-950 reg. offsets */ + z->STATUS = z->addr + 0x1c00; + z->DATA = z->addr + 0x1e00; + /* FD TMC885's can't handle detach & re-attach */ + sea_select_cmd = CMD_DRVR_ENABLE; + /* FD TMC-885 is supposed to be at id 6. How strange. */ + z->scsi_addr = HOST_SCSI_ADDR - 1; + z->scsi_id = 1 << z->scsi_addr; + if (sea_init (z) == 0) + return (1); + + return (0); +} + +/* + * Probe the adapter, and if found, reset the board and the scsi bus. + * Return 0 if the adapter found. + */ +int sea_init (adapter_t *z) +{ + volatile u_char *p; + int i, c; + + /* Check that STATUS..STATUS+200h are equal. */ + p = z->STATUS; + c = *p; + if (c == 0xff) + return (2); + while (++p < z->STATUS+0x200) + if (*p != c) + return (3); + + /* Check that DATA..DATA+200h are equal. */ + for (p=z->DATA, c= *p++; p<z->DATA+0x200; ++p) + if (*p != c) + return (4); + + /* Check that addr..addr+1800h are not writable. */ + for (p=z->addr; p<z->addr+0x1800; ++p) { + c = *p; + *p = ~c; + if (*p == ~c) { + *p = c; + return (5); + } + } + + /* Check that addr+1800h..addr+1880h are writable. */ + for (p=z->addr+0x1800; p<z->addr+0x1880; ++p) { + c = *p; + *p = 0x55; + if (*p != 0x55) { + *p = c; + return (6); + } + *p = 0xaa; + if (*p != 0xaa) { + *p = c; + return (7); + } + } + + /* Reset the scsi bus (I don't know if this is needed). */ + *z->CONTROL = CMD_RST | CMD_DRVR_ENABLE | z->parity | CMD_INTR; + /* Hold reset for at least 25 microseconds. */ + DELAY (25); + /* Check that status cleared. */ + if (*z->STATUS != 0) { + *z->CONTROL = 0; + return (8); + } + + /* Check that DATA register is writable. */ + for (i=0; i<256; ++i) { + *z->DATA = i; + if (*z->DATA != i) { + *z->CONTROL = 0; + return (9); + } + } + + /* Enable the adapter. */ + *z->CONTROL = CMD_INTR | z->parity; + /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */ + DELAY (10); + + /* Check that DATA register is NOT writable. */ + c = *z->DATA; + for (i=0; i<256; ++i) { + *z->DATA = i; + if (*z->DATA != c) { + *z->CONTROL = 0; + return (10); + } + } + + return (0); +} + +/* + * Attach all sub-devices we can find. + */ +int sea_attach (struct isa_device *dev) +{ + int unit = dev->id_unit; + adapter_t *z = &seadata[unit]; + struct scsibus_data *scbus; + + printf ("\nsea%d: type %s%s\n", unit, z->name, + (dev->id_flags & FLAG_NOPARITY) ? ", no parity" : ""); + + /* fill in the prototype scsi_link */ + z->sc_link.adapter_unit = unit; + z->sc_link.adapter_targ = z->scsi_addr; + z->sc_link.adapter_softc = z; + z->sc_link.adapter = &sea_switch; + z->sc_link.device = &sea_dev; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if(!scbus) + return 0; + scbus->adapter_link = &z->sc_link; + + /* ask the adapter what subunits are present */ + scsi_attachdevs (scbus); + + return (1); +} + +/* + * Return some information to the caller about + * the adapter and its capabilities. + */ +u_int32_t sea_adapter_info (int unit) +{ + return (1); +} + +void seaminphys (struct buf *bp) +{ +} + +/* + * Catch an interrupt from the adaptor. + */ +void seaintr (int unit) +{ + adapter_t *z = &seadata[unit]; + + PRINT (("sea%d: interrupt status=%b\n", unit, *z->STATUS, STAT_BITS)); + sea_start (z); +} + +/* + * This routine is used in the case when we have no IRQ line (z->irq == 0). + * It is called every timer tick and polls for reconnect from target. + */ +void sea_tick (void *arg) +{ + adapter_t *z = arg; + int x = splbio (); + + z->timeout_active = 0; + sea_start (z); + if (z->disconnected_queue && ! z->timeout_active) { + timeout (sea_tick, z, 1); + z->timeout_active = 1; + } + splx (x); +} + +/* + * Start a scsi operation given the command and the data address. + * Also needs the unit, target and lu. Get a free scb and set it up. + * Call send_scb. Either start timer or wait until done. + */ +int32_t sea_scsi_cmd (struct scsi_xfer *xs) +{ + int flags = xs->flags, x = 0; + adapter_t *z = (adapter_t *)xs->sc_link->adapter_softc; + scb_t *scb; + + PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target, + xs->sc_link->lun, xs->cmd->opcode)); + if (xs->bp) + flags |= SCSI_NOSLEEP; + if (flags & ITSDONE) { + printf ("sea%d: already done?", xs->sc_link->adapter_unit); + xs->flags &= ~ITSDONE; + } + if (! (flags & INUSE)) { + printf ("sea%d: not in use?", xs->sc_link->adapter_unit); + xs->flags |= INUSE; + } + if (flags & SCSI_RESET) + printf ("sea%d: SCSI_RESET not implemented\n", + xs->sc_link->adapter_unit); + + if (! (flags & SCSI_NOMASK)) + x = splbio (); + + /* Get a free scb. + * If we can and have to, sleep waiting for one to come free. */ + while (! (scb = z->free_scb)) { + if (flags & SCSI_NOSLEEP) { + xs->error = XS_DRIVER_STUFFUP; + if (! (flags & SCSI_NOMASK)) + splx (x); + return (TRY_AGAIN_LATER); + } + tsleep ((caddr_t)&z->free_scb, PRIBIO, "seascb", 0); + } + /* Get scb from free list. */ + z->free_scb = scb->next; + scb->next = 0; + scb->flags = SCB_ACTIVE; + + /* Put all the arguments for the xfer in the scb */ + scb->xfer = xs; + scb->datalen = xs->datalen; + scb->data = xs->data; + + /* Setup the scb to contain necessary values. + * The interesting values can be read from the xs that is saved. + * I therefore think that the structure can be kept very small. + * The driver doesn't use DMA so the scatter/gather is not needed? */ + if (! z->queue) { + scb->next = z->queue; + z->queue = scb; + } else { + scb_t *q; + + for (q=z->queue; q->next; q=q->next) + continue; + q->next = scb; + scb->next = 0; /* placed at the end of the queue */ + } + + /* Try to send this command to the board. */ + sea_start (z); + + /* Usually return SUCCESSFULLY QUEUED. */ + if (! (flags & SCSI_NOMASK)) { + splx (x); + if (xs->flags & ITSDONE) + /* Timeout timer not started, already finished. + * Tried to return COMPLETE but the machine hanged + * with this. */ + return (SUCCESSFULLY_QUEUED); + xs->timeout_ch = timeout (sea_timeout, (caddr_t) scb, + (xs->timeout * hz) / 1000); + scb->flags |= SCB_TIMECHK; + PRINT (("sea%d/%d/%d command queued\n", + xs->sc_link->adapter_unit, + xs->sc_link->target, xs->sc_link->lun)); + return (SUCCESSFULLY_QUEUED); + } + + /* If we can't use interrupts, poll on completion. */ + if (! sea_poll (z, scb)) { + /* We timed out, so call the timeout handler manually, + * accounting for the fact that the clock is not running yet + * by taking out the clock queue entry it makes. */ + sea_timeout ((void*) scb); + + /* Because we are polling, take out the timeout entry + * sea_timeout made. */ + untimeout (sea_timeout, (void*) scb, xs->timeout_ch); + + if (! sea_poll (z, scb)) + /* We timed out again... This is bad. Notice that + * this time there is no clock queue entry to remove. */ + sea_timeout ((void*) scb); + } + PRINT (("sea%d/%d/%d command %s\n", xs->sc_link->adapter_unit, + xs->sc_link->target, xs->sc_link->lun, + xs->error ? "failed" : "done")); + return (xs->error ? HAD_ERROR : COMPLETE); +} + +/* + * Coroutine that runs as long as more work can be done. + * Both scsi_cmd() and intr() will try to start it in + * case it is not running. + * Always called with interrupts disabled. + */ +void sea_start (adapter_t *z) +{ + scb_t *q, *prev; +again: + /* First check that if any device has tried + * a reconnect while we have done other things + * with interrupts disabled. */ + if (sea_reselect (z)) + goto again; + + /* Search through the queue for a command + * destined for a target that's not busy. */ + for (q=z->queue, prev=0; q; prev=q, q=q->next) { + /* Attempt to establish an I_T_L nexus here. */ + if (IS_BUSY (z, q) || ! sea_select (z, q)) + continue; + + /* Remove the command from the issue queue. */ + if (prev) + prev->next = q->next; + else + z->queue = q->next; + q->next = 0; + + /* We are connected. Do the task. */ + sea_information_transfer (z, q); + goto again; + } +} + +void sea_timeout (void *arg) +{ + scb_t *scb = (scb_t*) arg; + adapter_t *z = (adapter_t *)scb->xfer->sc_link->adapter_softc; + int x = splbio (); + + if (! (scb->xfer->flags & SCSI_NOMASK)) + printf ("sea%d/%d/%d (%s%d) timed out\n", + scb->xfer->sc_link->adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + scb->xfer->sc_link->device->name, + scb->xfer->sc_link->dev_unit); + + /* If it has been through before, then a previous abort has failed, + * don't try abort again. */ + if (! (scb->flags & SCB_ABORTED)) { + sea_abort (z, scb); + /* 2 seconds for the abort */ + scb->xfer->timeout_ch = timeout (sea_timeout, + (caddr_t)scb, 2*hz); + scb->flags |= (SCB_ABORTED | SCB_TIMECHK); + } else { + /* abort timed out */ + scb->flags |= SCB_ABORTED; + scb->xfer->retries = 0; + sea_done (z, scb); + } + splx (x); +} + +/* + * Wait until REQ goes down. This is needed for some devices (CDROMs) + * after every MSGOUT, MSGIN, CMDOUT, STATIN request. + * Return true if REQ deassert found. + */ +static __inline int sea_wait_for_req_deassert (adapter_t *z, int cnt, char *msg) +{ + __asm __volatile (" + 1: testb $0x10, %2 + jz 2f + loop 1b + 2:" + : "=c" (cnt) /* output */ + : "0" (cnt), "m" (*z->STATUS)); /* input */ + if (! cnt) { + PRINT (("sea%d (%s) timeout waiting for !REQ\n", + z->sc_link.adapter_unit, msg)); + return (0); + } + /* PRINT (("sea_wait_for_req_deassert %s count=%d\n", msg, cnt)); */ + return (1); +} + +/* + * Establish I_T_L or I_T_L_Q nexus for new or existing command + * including ARBITRATION, SELECTION, and initial message out + * for IDENTIFY and queue messages. + * Return 1 if selection succeded. + */ +int sea_select (volatile adapter_t *z, scb_t *scb) +{ + /* Start arbitration. */ + *z->CONTROL = z->parity | CMD_INTR; + *z->DATA = z->scsi_id; + *z->CONTROL = CMD_START_ARB | z->parity; + + /* Wait for arbitration to complete. */ + WAITFOR (*z->STATUS & STAT_ARB_CMPL, "arbitration"); + if (! (*z->STATUS & STAT_ARB_CMPL)) { + if (*z->STATUS & STAT_SEL) { + printf ("sea: arbitration lost\n"); + scb->flags |= SCB_ERROR; + } else { + printf ("sea: arbitration timeout\n"); + scb->flags |= SCB_TIMEOUT; + } + *z->CONTROL = CMD_INTR | z->parity; + return (0); + } + DELAY (1); + + *z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id; + *z->CONTROL = sea_select_cmd | CMD_SEL | z->parity; + DELAY (2); + + /* Wait for a bsy from target. + * If the target is not present on the bus, we get + * the timeout. Don't PRINT any message -- it's not an error. */ + WAITFOR (*z->STATUS & STAT_BSY, 0); + if (! (*z->STATUS & STAT_BSY)) { + /* The target does not respond. Not an error, though. */ + PRINT (("sea%d/%d/%d target does not respond\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + *z->CONTROL = CMD_INTR | z->parity; + scb->flags |= SCB_TIMEOUT; + return (0); + } + + /* Try to make the target to take a message from us. + * Should start a MSGOUT phase. */ + *z->CONTROL = sea_select_cmd | z->parity; + DELAY (15); + WAITFOR (*z->STATUS & STAT_REQ, 0); + + if (z->type == CTLR_FUTURE_DOMAIN) + *z->CONTROL = CMD_INTR | z->parity | CMD_DRVR_ENABLE; + + WAITFOR (*z->STATUS & STAT_REQ, 0); + if (! (*z->STATUS & STAT_REQ)) { + PRINT (("sea%d/%d/%d timeout waiting for REQ\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + scb->flags |= SCB_ERROR; + *z->CONTROL = CMD_INTR | z->parity; + return (0); + } + + /* Check for phase mismatch. FD 885 always seems to get this wrong! */ + if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT && z->type != CTLR_FUTURE_DOMAIN) { + PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + PHASE_NAME (*z->STATUS & PHASE_MASK))); + scb->flags |= SCB_ERROR; + *z->CONTROL = CMD_INTR | z->parity; + return (0); + } + + /* Allow disconnects. (except for FD controllers) */ + if (z->type == CTLR_SEAGATE) { + *z->CONTROL = CMD_DRVR_ENABLE | z->parity; + *z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun); + WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000); + } + *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity; + + SET_BUSY (z, scb); + return (1); +} + +int sea_reselect (adapter_t *z) +{ + scb_t *q = 0, *prev = 0; + u_char msg, target_mask, lun; +again: + /* Wait for a device to win the reselection phase. */ + /* Signals this by asserting the I/O signal. */ + if ((*z->STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) != + (STAT_SEL | STAT_IO)) + return (0); + + /* The data bus contains original initiator id ORed with target id. */ + /* See that we really are the initiator. */ + target_mask = *z->DATA; + if (! (target_mask & z->scsi_id)) { + PRINT (("sea%d reselect not for me: mask=0x%x, status=%b\n", + z->sc_link.adapter_unit, target_mask, + *z->STATUS, STAT_BITS)); + goto again; + } + + /* Find target who won. */ + /* Host responds by asserting the BSY signal. */ + /* Target should respond by deasserting the SEL signal. */ + target_mask &= ~z->scsi_id; + *z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity | CMD_INTR; + WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge"); + + /* Remove the busy status. */ + /* Target should set the MSGIN phase. */ + *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity; + WAITFOR (*z->STATUS & STAT_REQ, "identify message"); + + /* Hope we get an IDENTIFY message. */ + msg = sea_msg_input (z); + if (MSG_ISIDENT (msg)) { + /* Find the command corresponding to the I_T_L or I_T_L_Q + * nexus we just restablished, and remove it from + * the disconnected queue. */ + lun = (msg & 7); + for (q=z->disconnected_queue; q; prev=q, q=q->next) { + if (target_mask != (1 << q->xfer->sc_link->target)) + continue; + if (lun != q->xfer->sc_link->lun) + continue; + if (prev) + prev->next = q->next; + else + z->disconnected_queue = q->next; + q->next = 0; + PRINT (("sea%d/%d/%d reselect done\n", + z->sc_link.adapter_unit, + ffs (target_mask) - 1, lun)); + sea_information_transfer (z, q); + WAITFOR (! (*z->STATUS & STAT_BSY), "reselect !busy"); + return (1); + } + } else + printf ("sea%d reselect: expecting IDENTIFY, got 0x%x\n", + z->sc_link.adapter_unit, msg); + + /* Since we have an established nexus that we can't + * do anything with, we must abort it. */ + sea_send_abort (z); + PRINT (("sea%d reselect aborted\n", z->sc_link.adapter_unit)); + WAITFOR (! (*z->STATUS & STAT_BSY), "bus free after reselect abort"); + goto again; +} + +/* + * Send an abort to the target. + * Return 1 success, 0 on failure. + * Called on splbio level. + */ +int sea_abort (adapter_t *z, scb_t *scb) +{ + scb_t *q, **prev; + + /* If the command hasn't been issued yet, we simply remove it + * from the issue queue. */ + prev = &z->queue; + for (q=z->queue; q; q=q->next) { + if (scb == q) { + (*prev) = q->next; + q->next = 0; + return (1); + } + prev = &q->next; + } + + /* If the command is currently disconnected from the bus, + * we reconnect the I_T_L or I_T_L_Q nexus associated with it, + * go into message out, and send an abort message. */ + for (q=z->disconnected_queue; q; q=q->next) { + if (scb != q) + continue; + + if (! sea_select (z, scb)) + return (0); + sea_send_abort (z); + + prev = &z->disconnected_queue; + for (q=z->disconnected_queue; q; q=q->next) { + if (scb == q) { + *prev = q->next; + q->next = 0; + /* Set some type of error result + * for the operation. */ + return (1); + } + prev = &q->next; + } + } + + /* Command not found in any queue. */ + return (0); +} + +/* + * The task accomplished, mark the i/o control block as done. + * Always called with interrupts disabled. + */ +void sea_done (adapter_t *z, scb_t *scb) +{ + struct scsi_xfer *xs = scb->xfer; + + if (scb->flags & SCB_TIMECHK) + untimeout (sea_timeout, (caddr_t) scb, xs->timeout_ch); + + /* How much of the buffer was not touched. */ + xs->resid = scb->datalen; + + if (scb->flags != SCB_ACTIVE && ! (xs->flags & SCSI_ERR_OK)) + if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED)) + xs->error = XS_TIMEOUT; + else if (scb->flags & SCB_ERROR) + xs->error = XS_DRIVER_STUFFUP; + else if (scb->flags & SCB_TBUSY) + xs->error = XS_BUSY; + else if (scb->flags & SCB_SENSE) + xs->error = XS_SENSE; + + xs->flags |= ITSDONE; + + /* Free the control block. */ + scb->next = z->free_scb; + z->free_scb = scb; + scb->flags = SCB_FREE; + + /* If there were none, wake anybody waiting for one to come free, + * starting with queued entries. */ + if (! scb->next) + wakeup ((caddr_t) &z->free_scb); + + scsi_done (xs); +} + +/* + * Wait for completion of command in polled mode. + * Always called with interrupts masked out. + */ +int sea_poll (adapter_t *z, scb_t *scb) +{ + int count; + + for (count=0; count<30; ++count) { + DELAY (1000); /* delay for a while */ + sea_start (z); /* retry operation */ + if (scb->xfer->flags & ITSDONE) + return (1); /* all is done */ + if (scb->flags & SCB_TIMEOUT) + return (0); /* no target present */ + } + return (0); +} + +/* + * Send data to the target. + */ +void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen) +{ + volatile u_char *data = *pdata; + volatile u_int len = *plen; + +#ifdef SEA_BLINDTRANSFER + if (len && !(len % BLOCK_SIZE)) { + while (len) { + WAITFOR10 (*z->STATUS & STAT_REQ, "blind block read"); + __asm __volatile (" + shr $2, %%ecx; + cld; + rep; + movsl; " : : + "D" (z->DATA), "S" (data), "c" (BLOCK_SIZE) : + "cx", "si", "di" ); + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } + } else { +#endif + __asm __volatile ("cld + 1: movb (%%ebx), %%al + xorb $1, %%al + testb $0xf, %%al + jnz 2f + testb $0x10, %%al + jz 1b + lodsb + movb %%al, (%%edi) + loop 1b + 2:" + : "=S" (data), "=c" (len) /* output */ + : "D" (z->DATA), "b" (z->STATUS), /* input */ + "0" (data), "1" (len) + : "eax", "ebx", "edi"); /* clobbered */ +#ifdef SEA_BLINDTRANSFER + } +#endif + PRINT (("sea (DATAOUT) send %ld bytes\n", *plen - len)); + *plen = len; + *pdata = (u_char *)data; +} + +/* + * Receive data from the target. + */ +void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen) +{ + volatile u_char *data = *pdata; + volatile u_int len = *plen; + +#ifdef SEA_BLINDTRANSFER + if (len && !(len % BLOCK_SIZE)) { + while (len) { + WAITFOR10 (*z->STATUS & STAT_REQ, "blind block read"); + __asm __volatile (" + shr $2, %%ecx; + cld; + rep; + movsl; " : : + "S" (z->DATA), "D" (data), "c" (BLOCK_SIZE) : + "cx", "si", "di" ); + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } + } else { +#endif + if (len >= 512) { + __asm __volatile (" cld + 1: movb (%%esi), %%al + xorb $5, %%al + testb $0xf, %%al + jnz 2f + testb $0x10, %%al + jz 1b + movb (%%ebx), %%al + stosb + loop 1b + 2:" + : "=D" (data), "=c" (len) /* output */ + : "b" (z->DATA), "S" (z->STATUS), + "0" (data), "1" (len) /* input */ + : "eax", "ebx", "esi"); /* clobbered */ + } else { + __asm __volatile (" cld + 1: movb (%%esi), %%al + xorb $5, %%al + testb $0xf, %%al + jnz 2f + testb $0x10, %%al + jz 1b + movb (%%ebx), %%al + stosb + movb $1000, %%al + 3: testb $0x10, (%%esi) + jz 4f + dec %%al + jnz 3b + 4: loop 1b + 2:" + : "=D" (data), "=c" (len) /* output */ + : "b" (z->DATA), "S" (z->STATUS), + "0" (data), "1" (len) /* input */ + : "eax", "ebx", "esi"); /* clobbered */ + } +#ifdef SEA_BLINDTRANSFER + } +#endif + PRINT (("sea (DATAIN) got %ld bytes\n", *plen - len)); + *plen = len; + *pdata = (u_char *)data; +} + +/* + * Send the command to the target. + */ +void sea_cmd_output (target_t *t, u_char *cmd, int cmdlen) +{ + adapter_t *z = t->adapter; + + PRINT (("sea%d send command (%d bytes) ", z->sc_link.adapter_unit, + cmdlen)); + + PRINT (("%x", *cmd)); + *z->DATA = *cmd++; + if (z->type == CTLR_SEAGATE) + WAITREQ (t, cmdout1, 10000); + --cmdlen; + + while (cmdlen) { + /* Check for target disconnect. */ + u_char sts = *z->STATUS; + if (! (sts & STAT_BSY)) + break; + + /* Check for phase mismatch. FD 885 seems to get this wrong! */ + if ((sts & PHASE_MASK) != PHASE_CMDOUT && z->type != CTLR_FUTURE_DOMAIN) { + printf ("sea: sea_cmd_output: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + return; + } + + /* Wait for REQ. */ + if (! (sts & STAT_REQ)) + continue; + + PRINT (("-%x", *cmd)); + *z->DATA = *cmd++; + if (z->type == CTLR_SEAGATE) + WAITREQ (t, cmdout, 1000); + --cmdlen; + } + PRINT (("\n")); +} + +/* + * Send the message to the target. + */ +void sea_send_abort (adapter_t *z) +{ + u_char sts; + + *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | CMD_ATTN | z->parity; + + /* Wait for REQ, after which the phase bits will be valid. */ + WAITFOR (*z->STATUS & STAT_REQ, "abort message"); + sts = *z->STATUS; + if (! (sts & STAT_REQ)) + goto ret; + + /* Check for phase mismatch. */ + if ((sts & PHASE_MASK) != PHASE_MSGOUT) { + printf ("sea: sending MSG_ABORT: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + goto ret; + } + + *z->DATA = MSG_ABORT; + sea_wait_for_req_deassert (z, 1000, "MSG_OUTPUT"); + PRINT (("sea%d send abort message\n", z->sc_link.adapter_unit)); +ret: + *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity; +} + +/* + * Get the message from the target. + * Return the length of the received message. + */ +u_char sea_msg_input (adapter_t *z) +{ + u_char sts, msg; + + /* Wait for REQ, after which the phase bits will be valid. */ + WAITFOR (*z->STATUS & STAT_REQ, "message input"); + sts = *z->STATUS; + if (! (sts & STAT_REQ)) + return (MSG_ABORT); + + /* Check for phase mismatch. + * Reached if the target decides that it has finished the transfer. */ + if ((sts & PHASE_MASK) != PHASE_MSGIN) { + printf ("sea: sea_msg_input: invalid phase %s\n", + PHASE_NAME (sts & PHASE_MASK)); + return (MSG_ABORT); + } + + /* Do actual transfer from SCSI bus to/from memory. */ + msg = *z->DATA; + sea_wait_for_req_deassert (z, 1000, "MSG_INPUT"); + PRINT (("sea%d (MSG_INPUT) got 0x%x\n", z->sc_link.adapter_unit, msg)); + return (msg); +} + +/* + * Send request-sense op to the target. + * Return 1 success, 0 on failure. + * Called on splbio level. + */ +int sea_sense (adapter_t *z, scb_t *scb) +{ + u_char cmd[6], status, msg, *data; + u_long len; + + /* Wait for target to disconnect. */ + WAITFOR (! (*z->STATUS & STAT_BSY), "sense bus free"); + if (*z->STATUS & STAT_BSY) + return (0); + + /* Select the target again. */ + if (! sea_select (z, scb)) + return (0); + + /* Wait for CMDOUT phase. */ + WAITFOR (*z->STATUS & STAT_REQ, "sense CMDOUT"); + if (! (*z->STATUS & STAT_REQ) || + (*z->STATUS & PHASE_MASK) != PHASE_CMDOUT) + return (0); + + /* Send command. */ + len = sizeof (scb->xfer->sense); + cmd[0] = REQUEST_SENSE; + cmd[1] = scb->xfer->sc_link->lun << 5; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = len; + cmd[5] = 0; + sea_cmd_output (&z->target[scb->xfer->sc_link->target], + cmd, sizeof (cmd)); + + /* Wait for DATAIN phase. */ + WAITFOR (*z->STATUS & STAT_REQ, "sense DATAIN"); + if (! (*z->STATUS & STAT_REQ) || + (*z->STATUS & PHASE_MASK) != PHASE_DATAIN) + return (0); + + data = (u_char*) &scb->xfer->sense; + sea_data_input (z, &data, &len); + PRINT (("sea%d sense %x-%x-%x-%x-%x-%x-%x-%x\n", + z->sc_link.adapter_unit, scb->xfer->sense.error_code, + scb->xfer->sense.ext.extended.segment, + scb->xfer->sense.ext.extended.flags, + scb->xfer->sense.ext.extended.info[0], + scb->xfer->sense.ext.extended.info[1], + scb->xfer->sense.ext.extended.info[2], + scb->xfer->sense.ext.extended.info[3], + scb->xfer->sense.ext.extended.extra_len)); + + /* Wait for STATIN phase. */ + WAITFOR (*z->STATUS & STAT_REQ, "sense STATIN"); + if (! (*z->STATUS & STAT_REQ) || + (*z->STATUS & PHASE_MASK) != PHASE_STATIN) + return (0); + + status = *z->DATA; + + /* Wait for MSGIN phase. */ + WAITFOR (*z->STATUS & STAT_REQ, "sense MSGIN"); + if (! (*z->STATUS & STAT_REQ) || + (*z->STATUS & PHASE_MASK) != PHASE_MSGIN) + return (0); + + msg = *z->DATA; + + if (status != 0 || msg != 0) + printf ("sea%d: bad sense status=0x%x, msg=0x%x\n", + z->sc_link.adapter_unit, status, msg); + return (1); +} + +/* + * Do the transfer. We know we are connected. Update the flags, + * call sea_done when task accomplished. Dialog controlled by the target. + * Always called with interrupts disabled. + */ +void sea_information_transfer (adapter_t *z, scb_t *scb) +{ + u_char *data = scb->data; /* current data buffer */ + u_long datalen = scb->datalen; /* current data transfer size */ + target_t *t = &z->target[scb->xfer->sc_link->target]; + register u_char sts; + u_char msg; + + while ((sts = *z->STATUS) & STAT_BSY) { + /* We only have a valid SCSI phase when REQ is asserted. */ + if (! (sts & STAT_REQ)) + continue; + if (sts & STAT_PARITY) { + int target = scb->xfer->sc_link->target; + if (++z->target[target].perrcnt <= 8) + printf ("sea%d/%d/%d parity error\n", + z->sc_link.adapter_unit, target, + scb->xfer->sc_link->lun); + if (z->target[target].perrcnt == 8) + printf ("sea%d/%d/%d too many parity errors, not logging any more\n", + z->sc_link.adapter_unit, target, + scb->xfer->sc_link->lun); + } + switch (sts & PHASE_MASK) { + case PHASE_DATAOUT: + if (datalen <= 0) { + printf ("sea%d/%d/%d data length underflow\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun); + /* send zero byte */ + *z->DATA = 0; + break; + } + sea_data_output (z, &data, &datalen); + break; + case PHASE_DATAIN: + if (datalen <= 0) { + /* Get extra data. Some devices (e.g. CDROMs) + * use fixed-length blocks (e.g. 2k), + * even if we need less. */ + PRINT (("@")); + sts = *z->DATA; + break; + } + sea_data_input (z, &data, &datalen); + break; + case PHASE_CMDOUT: + sea_cmd_output (t, (u_char*) scb->xfer->cmd, + scb->xfer->cmdlen); + break; + case PHASE_STATIN: + scb->xfer->status = *z->DATA; + if (z->type == CTLR_SEAGATE) + WAITREQ (t, statin, 2000); + PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, + (u_char) scb->xfer->status)); + break; + case PHASE_MSGOUT: + /* Send no-op message. */ + *z->DATA = MSG_NOP; + sea_wait_for_req_deassert (z, 1000, "MSGOUT"); + PRINT (("sea%d/%d/%d (MSGOUT) send NOP\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + break; + case PHASE_MSGIN: + /* Don't handle multi-byte messages here, because they + * should not be present here. */ + msg = *z->DATA; + sea_wait_for_req_deassert (z, 2000, "MSGIN"); + PRINT (("sea%d/%d/%d (MSGIN) got 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, msg)); + switch (msg) { + case MSG_COMMAND_COMPLETE: + scb->data = data; + scb->datalen = datalen; + /* In the case of check-condition status, + * perform the request-sense op. */ + switch (scb->xfer->status & 0x1e) { + case SCSI_CHECK: + if (sea_sense (z, scb)) + scb->flags = SCB_SENSE; + break; + case SCSI_BUSY: + scb->flags = SCB_TBUSY; + break; + } + goto done; + case MSG_ABORT: + printf ("sea: command aborted by target\n"); + scb->flags = SCB_ABORTED; + goto done; + case MSG_MESSAGE_REJECT: + printf ("sea: message rejected\n"); + scb->flags = SCB_ABORTED; + goto done; + case MSG_DISCONNECT: + scb->next = z->disconnected_queue; + z->disconnected_queue = scb; + if (! z->irq && ! z->timeout_active) { + timeout (sea_tick, z, 1); + z->timeout_active = 1; + } + PRINT (("sea%d/%d/%d disconnected\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun)); + goto ret; + case MSG_SAVE_POINTERS: + scb->data = data; + scb->datalen = datalen; + break; + case MSG_RESTORE_POINTERS: + data = scb->data; + datalen = scb->datalen; + break; + default: + printf ("sea%d/%d/%d unknown message: 0x%x\n", + z->sc_link.adapter_unit, + scb->xfer->sc_link->target, + scb->xfer->sc_link->lun, msg); + break; + } + break; + default: + printf ("sea: unknown phase: %b\n", sts, STAT_BITS); + break; + } + } + printf ("sea%d/%d/%d unexpected target disconnect\n", + z->sc_link.adapter_unit, scb->xfer->sc_link->target, + scb->xfer->sc_link->lun); + scb->flags = SCB_ERROR; +done: + CLEAR_BUSY (z, scb); + sea_done (z, scb); +ret: + *z->CONTROL = CMD_INTR | z->parity; +} +#endif /* NSEA */ diff --git a/sys/i386/isa/si.c b/sys/i386/isa/si.c index 230e387267610..4f91d8a443303 100644 --- a/sys/i386/isa/si.c +++ b/sys/i386/isa/si.c @@ -30,7 +30,7 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHORS BE LIABLE. * - * $Id: si.c,v 1.77 1998/08/23 10:12:12 bde Exp $ + * $Id: si.c,v 1.76 1998/08/23 08:26:40 bde Exp $ */ #ifndef lint @@ -133,7 +133,7 @@ static u_long sipcieisacount = 0; #if NPCI > 0 -static const char *sipciprobe __P((pcici_t, pcidi_t)); +static char *sipciprobe __P((pcici_t, pcidi_t)); static void sipciattach __P((pcici_t, int)); static struct pci_device sipcidev = { @@ -316,7 +316,7 @@ static char *si_type[] = { #if NPCI > 0 -static const char * +static char * sipciprobe(configid, deviceid) pcici_t configid; pcidi_t deviceid; diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c index 7660965a930af..b0ad5fc67eea6 100644 --- a/sys/i386/isa/sio.c +++ b/sys/i386/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.223 1999/01/12 01:04:37 eivind Exp $ + * $Id: sio.c,v 1.214 1998/08/23 10:16:26 bde Exp $ */ #include "opt_comconsole.h" @@ -70,9 +70,6 @@ #include <machine/clock.h> #include <machine/ipl.h> -#ifndef SMP -#include <machine/lock.h> -#endif #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> @@ -86,7 +83,6 @@ #include "card.h" #if NCARD > 0 -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> #endif @@ -314,7 +310,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)); @@ -326,6 +321,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"; @@ -466,7 +464,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. @@ -873,7 +881,6 @@ sioattach(isdp) int s; int unit; - isdp->id_ointr = siointr; isdp->id_ri_flags |= RI_FAST; iobase = isdp->id_iobase; unit = isdp->id_unit; @@ -942,6 +949,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 */ #ifdef COM_MULTIPORT if (!COM_ISMULTIPORT(isdp) && !COM_IIR_TXRDYBUG(isdp)) @@ -1456,7 +1469,7 @@ siodtrwakeup(chan) wakeup(&com->dtr_wait); } -static void +void siointr(unit) int unit; { @@ -1506,6 +1519,7 @@ 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; @@ -1729,6 +1743,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); } @@ -1993,9 +2035,11 @@ comparam(tp, t) int divisor; u_char dlbh; u_char dlbl; + int error; Port_t iobase; int s; int unit; + int txtimeout; /* do historical conversions */ if (t->c_ispeed == 0) @@ -2061,8 +2105,54 @@ comparam(tp, t) outb(iobase + com_fifo, com->fifo_image); } + /* + * 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. + */ + disable_intr(); +retry: + com->state &= ~CS_TTGO; + txtimeout = tp->t_timeout; + enable_intr(); + while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) + != (LSR_TSRE | LSR_TXRDY)) { + 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 */ + /* + * 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. + */ + if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) + != (LSR_TSRE | LSR_TXRDY)) + goto retry; + if (divisor != 0) { outb(iobase + com_cfcr, cfcr | CFCR_DLAB); /* @@ -2254,6 +2344,7 @@ siostop(tp, rw) /* XXX avoid h/w bug. */ if (!com->esp) #endif + /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_XMT_RST | com->fifo_image); com->obufs[0].l_queued = FALSE; @@ -2269,6 +2360,7 @@ siostop(tp, rw) /* XXX avoid h/w bug. */ if (!com->esp) #endif + /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image); com_events -= (com->iptr - com->ibuf); @@ -2479,18 +2571,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() { @@ -2612,7 +2692,7 @@ siocnclose(sp) outb(iobase + com_ier, sp->ier); } -static void +void siocnprobe(cp) struct consdev *cp; { @@ -2678,14 +2758,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; { @@ -2743,6 +2823,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 @@ -2820,7 +3020,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; diff --git a/sys/i386/isa/sioreg.h b/sys/i386/isa/sioreg.h index bec807b0de420..4a0c4cf87d8e1 100644 --- a/sys/i386/isa/sioreg.h +++ b/sys/i386/isa/sioreg.h @@ -31,15 +31,12 @@ * SUCH DAMAGE. * * from: @(#)comreg.h 7.2 (Berkeley) 5/9/91 - * $Id: sioreg.h,v 1.10 1997/06/04 16:25:15 pst Exp $ + * $Id: sioreg.h,v 1.9 1997/06/04 04:52:40 pst Exp $ */ /* 16 bit baud rate divisor (lower byte in dca_data, upper in dca_ier) */ #define COMBRD(x) (1843200 / (16*(x))) -#ifdef PC98 -#define COMBRD_RSA(x) (14745600 / (16*(x))) -#endif /* interrupt enable register */ #define IER_ERXRDY 0x1 @@ -109,16 +106,6 @@ #define MSR_DDSR 0x02 #define MSR_DCTS 0x01 -#ifdef PC98 -/* Hardware extension mode register for RSB-2000/3000. */ -#define EMR_EXBUFF 0x04 -#define EMR_CTSFLW 0x08 -#define EMR_DSRFLW 0x10 -#define EMR_RTSFLW 0x20 -#define EMR_DTRFLW 0x40 -#define EMR_EFMODE 0x80 -#endif - /* speed to initialize to during chip tests */ #define SIO_TEST_SPEED 9600 diff --git a/sys/i386/isa/snd/CARDS b/sys/i386/isa/snd/CARDS index 5757be3f14c4a..91ca79b682297 100644 --- a/sys/i386/isa/snd/CARDS +++ b/sys/i386/isa/snd/CARDS @@ -1,97 +1,37 @@ -In this file I will try to build a database of cards supported by -this driver. I also include the command to use for manual configuration -of the card in case your BIOS is not PnP-aware. Of course it is -your responsibility to pick up free port ranges and irq and drq -channels. +In this file I will try to build a database of cards supported by this +driver. I also include the command to use for manual configuration of +the card in case your BIOS is not PnP-aware. Of course it is your +responsibility to pick up free prot ranges and irq and drq channels. For PnP cards, I also include the vendor_id and serial numbers of -cards I have encountered. Underscores in the PnP id mean that -(I believe) there is a large variety of values in those positions, -and the code in the audio driver generally masks those bits. +cards I have encountered. Underscores in the PnP id mean that there is +a large variety of values in those positions. Finally, where available, I have put the URL where you can find the data sheets of the chip. -To my knowledge, there are the following families of audio cards: - -* WSS (also called MSS) and clones: - these are true full duplex cards, have a very nice architecture and - are well documented. Chipsets implementing these functionalities - are made from Crystal, Analog Devices, Yamaha, OPTI. - -* SB16 and clones: - these cards have a higly asymmetric architecture, and are not very - well suited to full duplex operation. Made by Creative, Realtek. - There is no documentation on the newer codecs (Vibra16X and ALS100+), - so they are not fully working. - -* ESS - ESS builds cards that implement a superset of SB16. They are - often capable of full duplex, but my driver does not support them - other than in full duplex emulation. My fault, since documentation - on these cards _is_ available. - -* PCI cards. - There are a quite few PCI audio cards around based on a number of - different chipsets. Some of them are documented (e.g. S3 Sonic - Vibes, Ensoniq ES1370), some are not (e.g. Yamaha YMF724), - work is in progress to support such cards. See the notes below. - Note that CreativeLabs has recently (fall'97) acquired Ensoniq - and the audio division of OPTI, both of which had a PCI audio - chipset. I don't know if there are other manufacturers of PCI - audio cards. - -Finally, some people wrote patches for the following chips: - - AD1816 - MAD16 - ESS --------------------------- -CHIPSET: - CS4235: PnP id 0x25__630e - CS4236: PnP id 0x36__630e 0x35__630e - CS4237: PnP id 0x37__630e -MANUFACTURER: - A/Open (or AcerOpen) AW32, AW35, AW37 - Also, integrated on the motherboard on some machines. - -DATA SHEETS: +CS4236B: PnP id 0x35__630e +CS4236: PnP id 0x36__630e +CS4237: PnP id 0x37__630e + http://www.crystal.com/ 4237full.pdf -PNP CONFIG: pnp 1 0 os enable port0 0x534 port2 0x220 irq0 5 drq0 1 drq1 3 -COMMENTS: - Work like a charm. All modes, including full duplex, supported in + work like a charm. All modes, including full duplex, supported in MSS mode. - Cards based on the 4237, and possibly the 4236 as well, connect - the CD to AUX2. When used in MODE1/2 (as this driver does) - there is no route in the input mixer from AUX2 to the ADC. So, - to record directly from the CD, the only way is to set the - input to SOUND_MASK_IMIX. - - Some machines with the cs4235 in non-pnp mode map the codec at 0x530 - instead of 0x534. For those machines you need an unusual config line - - device pcm0 at isa ? port 0x52C ... + NOTE: cards based on the 4237, and possibly the 4236 as well, + connect the CD to AUX2. When used in MODE1/2 (as this driver + does) there is no route in the input mixer from AUX2 to the + ADC. So, to record directly from the CD, the only way is + to set the input to SOUND_MASK_IMIX. +CS4232: PnP id 0x3242630e --------------------------- -CHIPSET: - CS4232: PnP id 0x3242630e - -MANUFACTURER: - ??? - -DATA SHEETS: - http://www.crystal.com/ - -PNP CONFIG: pnp 1 0 os enable port0 0x534 port2 0x220 irq0 5 drq0 1 drq1 3 -COMMENTS: This chip is reported as broken in the OSS documentation. As a matter of fact, on my Intel Zappa motherboard, I have problems in make it use the secondary DMA channel. I have it working in @@ -101,31 +41,10 @@ COMMENTS: -------------------------- CHIPSET: - AD1815/1816 - -MANUFACTURER: - Analog Devices - -DOCUMENTATION: - http://www.analog.com - -COMMENTS: - This is a chip for ISA-PnP cards, and so should be configured - using the PnP interface. For full function configure port2, - irq0, drq0 and drq1 of ldn0. - The driver is contributed by German Tischler - -FORMATS: - ALAW/ULAW/8bit/16bit(le)/16bit(be),8kHz-55.2kHz,full duplex - --------------------------- -CHIPSET: OPTi931: PnP id 0x3109143e - OPTi933: PnP id 0x3109143e (yes, it's the same) MANUFACTURER: ExpertColor MED931 (europe) - Shuttle HOT-247 (uses the 933, $15 retail in the US) DATA SHEETS: http://www.opti.com/ opti931_21.pdf @@ -171,7 +90,6 @@ MANUFACTURER: DATA SHEETS: http://www.creative.com sbhwpg.pdf or SBHWPG.EXE - ftp://www.creaf.com/pub/creative/devinfo/ctsbhwpg.exe PNP CONFIG: pnp 1 0 os enable port0 0x220 irq0 5 drq0 1 drq1 5 @@ -238,8 +156,6 @@ MANUFACTURER: DATA SHEETS: http://www.yamaha.com ? YM711.pdf - ftp://ftp.yamahayst.com/pub/Fax_Back_Doc/Sound - http://www.imail.net.tw/qtronix/qumax_product_yamaha.htm This is a huge file containing a few pages scanned and converted to pdf. Not very detailed. Luckily, this chipset appears to do a @@ -330,27 +246,11 @@ CHIPSET: ------------------------- CHIPSET: - es1370 (ensoniq) - es1371 (ensoniq) - used on SB64 PCI, Shuttle HOT-255, and maybe others - - A driver for this is in the works. - see http://www.ensoniq.com/multimedia/semi_html/index.htm - for documentation. See also http://alsa.jcu.cz/alsa/ for a Linux - driver. - -------------------------- -CHIPSET: - YMF724 - used on various Yamaha (WaveForce) and other cards. - - NOT SUPPORTED. - - There is no public docs on this card, the closest thing being - http://www.imail.net.tw/qtronix/driver/qumax/yamaha/ds1e1110.pdf - http://www.imail.net.tw/qtronix/qumax_product_yamaha.htm - which however does not document how the card works in non-legacy - mode and how to make it talk to the AC97 codec. + various PCI cards from Ensoniq, OPTI, CreativeLabs. + This code _cannot_ work on these cards as it is now, since I + don't think they can use the ISA DMA controller. As there are + no data sheets available for these PCI cards, none of them is + supported at the moment. -------------------------------------------------------------------- diff --git a/sys/i386/isa/snd/README b/sys/i386/isa/snd/README index e45bde7f2dbcf..289f0442ad2ec 100644 --- a/sys/i386/isa/snd/README +++ b/sys/i386/isa/snd/README @@ -38,7 +38,7 @@ CARDS: The driver supports most clones of WSS, SB16 and SBPro cards. This includes those based on the Crystal CS423x, OPTI931, GUSPnP, Yamaha, SB16/32 (both plain ISA, PnP, and the various AWExx). - Many PnP cards are directly recognized, for others you might need + Many PnP cards are directly recognised, for others you might need manual configuration. See the file "CARDS" for more details. APPLICATIONS: @@ -69,7 +69,7 @@ APPLICATIONS: controller pnp0 # this is required for PnP support - device pcm0 at isa ? port? tty irq N drq D flags F + device pcm0 at isa ? port? tty irq N drq D flags F vector pcmintr where @@ -83,7 +83,7 @@ APPLICATIONS: since this is unsupported at the moment...). The code will probe for common port addresses (0x220, 0x240 - for SB and clones, 0x530 for WSS and clones), so you don't need + for SB and clonse, 0x530 for WSS and clones), so you don't need to specify them if your system uses one of them. In case you do, note that for WSS cards the code assumes that the board occupies 8 IO addresses, the first four used to configure @@ -95,13 +95,13 @@ APPLICATIONS: You can use multiple sound cards, in which case you need more lines like - device pcm1 at isa ? port? tty irq N drq D flags F - device pcm2 at isa ? port? tty irq N drq D flags F + device pcm1 at isa ? port? tty irq N drq D flags F vector pcmintr + device pcm2 at isa ? port? tty irq N drq D flags F vector pcmintr ... EXAMPLES: a typical "device" line for the SB16 (full duplex) is - device pcm0 at isa ? port? tty irq 5 drq 1 flags 0x15 + device pcm0 at isa ? port? tty irq 5 drq 1 flags 0x15 vector pcmintr The driver will check at the default addresses (or the one you specify) which type of SoundBlaster you have (1.5, 2.0, 3.X @@ -113,7 +113,7 @@ APPLICATIONS: For a WSS-compatible codec (non PnP) working in full duplex using dma channels 1 and 3, you can specify: - device pcm0 at isa ? port 0x530 tty irq 7 drq 1 flags 0x13 + device pcm0 at isa ? port 0x530 tty irq 7 drq 1 flags 0x13 vector pcmintr (0x530 is a default if no port address is specified). The "flags 0x13" specifies that you have a dual dma board with @@ -130,9 +130,10 @@ APPLICATIONS: For PnP cards, only the line for "pcm0" is needed (the code will allocate entries for more cards if found), but IT MUST - INCLUDE ALL FIELDS. You can use the following line: + INCLUDE ALL FIELDS, including "vector pcmintr". You can use + the following line: - device pcm0 at isa ? port? tty irq 7 drq 1 + device pcm0 at isa ? port? tty irq 7 drq 1 vector pcmintr NOTE that: - the parameters for the PnP device(s) will be read from the @@ -199,7 +200,7 @@ Common mistakes: expect. The mixer code still does not try to exploit the features of each card, and it just provides basic functionalities. ---- ACKNOWLEDGMENTS --- +--- ACKNWOLEDGEMENTS --- Several people helped, directly or indirectly, in the development of this driver. In particular I would like to thank: @@ -213,12 +214,12 @@ this driver. In particular I would like to thank: * Eric J. Schwertfeger for donating an ES1868 card for writing the driver (which i haven't done yet...). * and many people who had the patience to try the driver - on their cards and report success/failure and useful + on their cards and report success/fauilure and useful information. It was certainly helpful to have the data sheets for some of the devices I support available on the net, especially in the (unfortunately -rare) cases where the data sheets matched the actual behavior of +rare) cases where the data sheets matched the actual behaviour of the product. Too bad that no one of the chip/card manufacturers I have contacted by email regarding missing or inconsistent documentation on their products did even care to reply to my messages. diff --git a/sys/i386/isa/snd/ad1848.c b/sys/i386/isa/snd/ad1848.c index 0284995397a40..16599d6ae1368 100644 --- a/sys/i386/isa/snd/ad1848.c +++ b/sys/i386/isa/snd/ad1848.c @@ -56,7 +56,7 @@ static int mss_probe(struct isa_device *dev); static int mss_attach(struct isa_device *dev); -d_open_t mss_open; /* this is a generic full-duplex open routine */ +static d_open_t mss_open; static d_close_t mss_close; static d_ioctl_t mss_ioctl; static irq_proc_t mss_intr; @@ -79,27 +79,6 @@ static void ad_write(snddev_info *d, int reg, u_char data); static void ad_write_cnt(snddev_info *d, int reg, u_short data); static int ad_read(snddev_info *d, int reg); -#if NPNP > 0 /* the ad1816 is pnp only */ -/* ad1816 prototypes */ - -/* IO primitives */ -static int ad1816_wait_init(snddev_info * d, int x); -static u_short ad1816_read(snddev_info * d, u_int reg); -static void ad1816_write(snddev_info * d, u_int reg, u_short data); -/* intr and callback functions */ -static irq_proc_t ad1816_intr; -static snd_callback_t ad1816_callback; -/* device specific ioctl calls */ -static d_ioctl_t ad1816_ioctl; -/* parameter set functions */ -static void ad1816_reinit(snddev_info * d); -static int ad1816_mixer_set(snddev_info * d, int dev, int value); -static int ad1816_set_recsrc(snddev_info * d, int mask); -static void ad1816_mixer_reset(snddev_info * d); - -/* ad1816 prototypes end */ -#endif - /* * device descriptors for the boards supported by this module. */ @@ -204,33 +183,6 @@ mss_probe_end: return mss_detect(dev) ? 8 : 0 ; /* mss uses 8 regs */ } -#if NPNP > 0 -static int -ad1816_attach(struct isa_device *dev) -{ - snddev_info *d = &(pcm_info[dev->id_unit]); - - dev->id_alive = 16; /* number of io ports */ - - if (FULL_DUPLEX(d)) - d->audio_fmt |= AFMT_FULLDUPLEX; - - ad1816_write(d, 1, 0x2);/* disable interrupts */ - ad1816_write(d, 32, 0x90F0); /* SoundSystem Mode, split format */ - - ad1816_write(d, 5, 0x8080); /* FM volume mute */ - ad1816_write(d, 6, 0x8080); /* I2S1 volume mute */ - ad1816_write(d, 7, 0x8080); /* I2S0 volume mute */ - ad1816_write(d, 17, 0x8888); /* VID Volume mute */ - ad1816_write(d, 20, 0x5050); /* Source select Mic & auto gain ctrl - * off */ - /* adc gain is set to 0 */ - ad1816_reinit(d); - ad1816_mixer_reset(d); - return 0 ; -} -#endif /* NPNP */ - /* * the address passed as io_base for mss_attach is also the old * MSS base address (e.g. 0x530). The codec is four locations ahead. @@ -247,10 +199,6 @@ mss_attach(struct isa_device *dev) d->name, dev->id_unit, d->io_base, d->irq, d->dbuf_out.chan, d->dbuf_in.chan, dev->id_flags); -#if NPNP > 0 - if (d->bd_id == MD_AD1816) - return ad1816_attach(dev); -#endif dev->id_alive = 8 ; /* number of io ports */ /* should be already set but just in case... */ @@ -322,7 +270,7 @@ mss_attach(struct isa_device *dev) return 0; } -int +static int mss_open(dev_t dev, int flags, int mode, struct proc * p) { int unit; @@ -426,11 +374,7 @@ mss_close(dev_t dev, int flags, int mode, struct proc * p) d->flags |= SND_F_CLOSING ; splx(s); /* is this ok here ? */ snd_flush(d); - /* Clear interrupt status */ - if ( d->bd_id == MD_AD1816 ) - outb(ad1816_int(d), 0); - else - outb(io_Status(d), 0); + outb(io_Status(d), 0); /* Clear interrupt status */ d->flags = 0 ; } return 0 ; @@ -698,14 +642,12 @@ gus_write(int io_base, u_char reg, u_char value) outb(io_base + 5, value); } -#if 0 static void gus_writew(int io_base, u_char reg, u_short value) { outb(io_base + 3, reg); outb(io_base + 4, value); } -#endif static u_char gus_read(int io_base, u_char reg) @@ -714,14 +656,13 @@ gus_read(int io_base, u_char reg) return inb(io_base+5); } -#if 0 static u_short gus_readw(int io_base, u_char reg) { outb(io_base+3, reg); return inw(io_base+4); } -#endif + /* * AD_WAIT_INIT waits if we are initializing the board and @@ -888,6 +829,22 @@ mss_set_recsrc(snddev_info *d, int mask) } /* + * mixer conversion table: from 0..100 scale to codec values + * + * I don't understand what's this for... maybe achieve a log-scale + * volume control ? + */ + +static char mix_cvt[101] = { + 0, 1, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42, + 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65, + 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79, + 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90, + 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99, + 100 +}; + +/* * there are differences in the mixer depending on the actual sound * card. */ @@ -997,7 +954,7 @@ ad1848_mixer_reset(snddev_info *d) case MD_YM0020: /* set master volume to max */ - DDB(printf("set yamaha master volume to max\n"); ) + DDB(printf("set yamaha master volume to max"); ) outb(0x370, 7) ; outb(0x371, 0) ; outb(0x370, 8) ; @@ -1343,7 +1300,7 @@ mss_detect(struct isa_device *dev) } } BVDDB(printf("mss_detect() - Detected %s\n", name)); - snprintf(d->name, sizeof(d->name), "%s", name); + strcpy(d->name, name); dev->id_flags &= ~DV_F_DEV_MASK ; dev->id_flags |= (d->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK ; return 1; @@ -1426,12 +1383,11 @@ mss_reinit(snddev_info *d) #if NPNP > 0 static char * cs423x_probe(u_long csn, u_long vend_id); -static void -cs423x_attach(u_long csn, u_long vend_id, char *name, +static void cs423x_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); static struct pnp_device cs423x = { - "CS423x/Yamaha/AD1816", + "CS423x/Yamaha", cs423x_probe, cs423x_attach, &nsnd, /* use this for all sound cards */ @@ -1446,9 +1402,7 @@ cs423x_probe(u_long csn, u_long vend_id) u_long id = vend_id & 0xff00ffff; if ( id == 0x3700630e ) s = "CS4237" ; - else if ( id == 0x2500630e ) - s = "CS4235" ; - else if ( id == 0x3600630e ) + else if ( id == 0x3500630e || id == 0x3600630e ) s = "CS4236" ; else if ( id == 0x3500630e ) s = "CS4236B" ; @@ -1458,14 +1412,10 @@ cs423x_probe(u_long csn, u_long vend_id) s = "Yamaha SA2"; else if ( id == 0x3000a865) s = "Yamaha SA3"; - else if ( id == 0x0000a865) + else if (vend_id == 0x0000a865) s = "Yamaha YMF719 OPL-SA3"; else if (vend_id == 0x8140d315) s = "SoundscapeVIVO"; - else if (vend_id == 0x1114b250) - s = "Terratec Soundsystem BASE 1"; - else if (vend_id == 0x50719304) - s = "Generic AD1815"; if (s) { struct pnp_cinfo d; read_pnp_parms(&d, 0); @@ -1494,26 +1444,7 @@ cs423x_attach(u_long csn, u_long vend_id, char *name, return ; } snddev_last_probed = &tmp_d; - - /* AD1816 */ - if (vend_id == 0x1114b250 || vend_id == 0x50719304) { - dev->id_alive = 16; /* number of io ports ? */ - - tmp_d = mss_op_desc; /* copy it */ - - tmp_d.ioctl = ad1816_ioctl; - tmp_d.isr = ad1816_intr; - tmp_d.callback = ad1816_callback; - tmp_d.audio_fmt = AFMT_STEREO | AFMT_U8 | - AFMT_A_LAW | AFMT_MU_LAW | - AFMT_S16_LE | AFMT_S16_BE; - - dev->id_iobase = d.port[2]; - tmp_d.alt_base = d.port[0]; /* soundblaster comp. but we don't - * use that */ - tmp_d.bd_id = MD_AD1816; - strcpy(tmp_d.name, name); - } else if (d.flags & DV_PNP_SBCODEC) { /* use sb-compatible codec */ + if (d.flags & DV_PNP_SBCODEC) { /*** use sb-compatible codec ***/ dev->id_alive = 16 ; /* number of io ports ? */ tmp_d = sb_op_desc ; if (vend_id==0x2000a865 || vend_id==0x3000a865 || @@ -1554,24 +1485,18 @@ cs423x_attach(u_long csn, u_long vend_id, char *name, tmp_d.bd_id = MD_CS4237 ; break; - case 0x2500630e: /* AOpen AW37, CS4235 */ - tmp_d.bd_id = MD_CS4237 ; - break ; - case 0x3500630e: /* CS4236B */ case 0x3600630e: /* CS4236 */ tmp_d.bd_id = MD_CS4236 ; break; default: - tmp_d.bd_id = MD_CS4232; /* to short-circuit the - * detect routine */ + tmp_d.bd_id = MD_CS4232 ; /* to short-circuit the detect routine */ break; } - snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name); + strcpy(tmp_d.name, name); tmp_d.audio_fmt |= AFMT_FULLDUPLEX ; } - write_pnp_parms( &d, ldn ); enable_pnp_card(); @@ -1643,7 +1568,7 @@ opti931_attach(u_long csn, u_long vend_id, char *name, snddev_last_probed = &tmp_d; tmp_d = d.flags & DV_PNP_SBCODEC ? sb_op_desc : mss_op_desc ; - snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name); + strcpy(tmp_d.name, name); /* * My MED3931 v.1.0 allocates 3 bytes for the config space, @@ -1761,9 +1686,7 @@ opti925_attach(u_long csn, u_long vend_id, char *name, pcmattach(dev); } -#if 0 static void gus_mem_cfg(snddev_info *tmp); -#endif static char *guspnp_probe(u_long csn, u_long vend_id); static void guspnp_attach(u_long csn, u_long vend_id, char *name, @@ -1851,7 +1774,7 @@ guspnp_attach(u_long csn, u_long vend_id, char *name, gus_write(tmp_d.conf_base, 0x5b , tmp | 1 ); BVDDB(printf("GUS: silicon rev %c\n", 'A' + ( ( tmp & 0xf ) >> 4) );) - snprintf(tmp_d.name, sizeof(tmp_d.name), "%s", name); + strcpy(tmp_d.name, name); pcmattach(dev); } @@ -1896,440 +1819,5 @@ gus_mem_cfg(snddev_info *d) } #endif /* gus mem cfg... */ -static int -ad1816_ioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc * p) -{ - snddev_info *d; - int unit; - - dev = minor(dev); - unit = dev >> 4; - d = &pcm_info[unit]; - - if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { - cmd &= 0xff; - if (cmd == SOUND_MIXER_RECSRC) - return ad1816_set_recsrc(d, *(int *) arg); - else - return ad1816_mixer_set(d, cmd, *(int *) arg); - } - switch (cmd) { /* driver specific ioctls other than mixer - * calls */ - /* ad1816 has special features */ - case AIOGCAP: /* get capabilities */ - { - snd_capabilities *p = (snd_capabilities *) arg; - p->rate_min = 4000; - p->rate_max = 55200; - p->bufsize = d->bufsize; - p->formats = d->audio_fmt; - p->mixers = 1; - p->inputs = d->mix_devs; - p->left = p->right = 100; - return 0; - } - default: - { - return ENOSYS; /* fallback to default */ - } - break; - } -} - -static int -ad1816_callback(snddev_info * d, int reason) -{ - int wr, cnt; - - wr = reason & SND_CB_WR; - reason &= SND_CB_REASON_MASK; - - switch (reason) { - case SND_CB_INIT: - ad1816_reinit(d); - reset_dbuf(&(d->dbuf_in), SND_CHAN_RD); - reset_dbuf(&(d->dbuf_out), SND_CHAN_WR); - return 1; - break; - - case SND_CB_START: - cnt = wr ? d->dbuf_out.dl : d->dbuf_in.dl; - - cnt /= 4; - cnt--; - - /* start only if not already running */ - if (wr && !(inb(ad1816_play(d)) & AD1816_ENABLE)) { - /* set dma counter */ - ad1816_write(d, 8, cnt); /* playback count */ - /* int enable */ - ad1816_write(d, 1, ad1816_read(d, 1) | 0x8000); - /* enable playback */ - outb(ad1816_play(d), (inb(ad1816_play(d)) | AD1816_ENABLE)); - /* check if we succeeded */ - if (!(inb(ad1816_play(d)) & AD1816_ENABLE)) { - printf("ad1816: failed to start write (playback) DMA !\n"); - } - } else if (!wr && !(inb(ad1816_capt(d)) & AD1816_ENABLE)) { - /* same for capture */ - ad1816_write(d, 10, cnt); /* capture count */ - ad1816_write(d, 1, ad1816_read(d, 1) | 0x4000); /* int */ - outb(ad1816_capt(d), (inb(ad1816_capt(d)) | AD1816_ENABLE)); /* CEN */ - if (!(inb(ad1816_capt(d)) & AD1816_ENABLE)) { /* check */ - printf("ad1816: failed to start read (capture) DMA !\n"); - } - } - break; - - case SND_CB_STOP: - case SND_CB_ABORT: /* XXX check this... */ - /* we don't test here if it is running... */ - if (wr) { - ad1816_write(d, 1, ad1816_read(d, 1) & ~0x8000); - /* disable int */ - outb(ad1816_play(d), (inb(ad1816_play(d)) & ~AD1816_ENABLE)); - /* disable playback */ - if ((inb(ad1816_play(d)) & AD1816_ENABLE)) { - printf("ad1816: failed to stop write (playback) DMA !\n"); - } - ad1816_write(d, 8, 0); /* reset base counter */ - ad1816_write(d, 9, 0); /* reset cur counter */ - } else { - /* same for capture */ - ad1816_write(d, 1, ad1816_read(d, 1) & ~0x4000); - outb(ad1816_capt(d), (inb(ad1816_capt(d)) & ~AD1816_ENABLE)); - if ((inb(ad1816_capt(d)) & AD1816_ENABLE)) { - printf("ad1816: failed to stop read (capture) DMA !\n"); - } - ad1816_write(d, 10, 0); - ad1816_write(d, 11, 0); - } - break; - } - - return 0; -} - -static void -ad1816_intr(int unit) -{ - snddev_info *d = &pcm_info[unit]; - unsigned char c, served = 0; - - /* get interupt status */ - c = inb(ad1816_int(d)); - - /* check for stray interupts */ - if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) { - printf("ad1816: Stray interrupt 0x%x.\n", c); - c = c & (AD1816_INTRCI | AD1816_INTRPI); - outb(ad1816_int(d), c); /* ack it anyway */ - } - /* check for capture interupt */ - if (d->dbuf_in.dl && (c & AD1816_INTRCI)) { - outb(ad1816_int(d), c & ~AD1816_INTRCI); /* ack it */ - if (inb(ad1816_int(d)) & AD1816_INTRCI) - printf("ad1816: Failed to clear cp int !!!\n"); - dsp_rdintr(d); - served |= AD1816_INTRCI; /* cp served */ - } - /* check for playback interupt */ - if (d->dbuf_out.dl && (c & AD1816_INTRPI)) { - outb(ad1816_int(d), c & ~AD1816_INTRPI); /* ack it */ - if (inb(ad1816_int(d)) & AD1816_INTRPI != 0) - printf("ad1816: Failed to clear pb int !!!\n"); - dsp_wrintr(d); - served |= AD1816_INTRPI; /* pb served */ - } - if (served == 0) { - /* this probably means this is not a (working) ad1816 chip, */ - /* or an error in dma handling */ - printf("ad1816: raised an interrupt without reason 0x%x.\n", c); - outb(ad1816_int(d), 0); /* Clear interrupt status anyway */ - } -} - -static int -ad1816_wait_init(snddev_info * d, int x) -{ - int n = 0; /* to shut up the compiler... */ - - for (; x--;) - if (((n = (inb(ad1816_ale(d)) & AD1816_BUSY))) == 0) - DELAY(10); - else - return n; - printf("ad1816_wait_init failed 0x%02x.\n", inb(ad1816_ale(d))); - return n; -} - -static unsigned short -ad1816_read(snddev_info * d, unsigned int reg) -{ - int flags; - u_short x; - - /* we don't want to be blocked here */ - flags = spltty(); - if (ad1816_wait_init(d, 100) == 0) { - printf("ad1816_read: chip timeout before read.\n"); - return 0; - } - outb(ad1816_ale(d), (u_char) 0); - outb(ad1816_ale(d), (u_char) (reg & AD1816_ALEMASK)); - if (ad1816_wait_init(d, 100) == 0) { - printf("ad1816_read: chip timeout during read.\n"); - return 0; - } - x = (inb(ad1816_high(d)) << 8) | inb(ad1816_low(d)); - splx(flags); - return x; -} - -static void -ad1816_write(snddev_info * d, unsigned int reg, unsigned short data) -{ - int flags; - - flags = spltty(); - if (ad1816_wait_init(d, 100) == 0) { - printf("ad1816_write: chip timeout before write.\n"); - return; - } - outb(ad1816_ale(d), (u_char) (reg & AD1816_ALEMASK)); - outb(ad1816_low(d), (u_char) (data & 0x000000ff)); - outb(ad1816_high(d), (u_char) ((data & 0x0000ff00) >> 8)); - splx(flags); -} - -#if 0 /* unused right now..., and untested... */ -static void -ad1816_mute(snddev_info * d) -{ - ad1816_write(d, 14, ad1816_read(d, 14) | 0x8000 | 0x80); -} - -static void -ad1816_unmute(snddev_info * d) -{ - ad1816_write(d, 14, ad1816_read(d, 14) & ~(0x8000 | 0x80)); -} -#endif - -/* only one rec source is possible */ - -static int -ad1816_set_recsrc(snddev_info * d, int mask) -{ - mask &= d->mix_rec_devs; - - switch (mask) { - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x0000); - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x2020); - break; - - case SOUND_MASK_MIC: - default: - ad1816_write(d, 20, (ad1816_read(d, 20) & ~0x7070) | 0x5050); - } - - d->mix_recsrc = mask; - - return 0; /* success */ -} - -#define AD1816_MUTE 31 /* value for mute */ - -static int -ad1816_mixer_set(snddev_info * d, int dev, int value) -{ - u_char left = (value & 0x000000ff); - u_char right = (value & 0x0000ff00) >> 8; - u_short reg = 0; - - if (dev > 31) - return EINVAL; - - if (!(d->mix_devs & (1 << dev))) - return EINVAL; - - if (left > 100) - left = 100; - if (right > 100) - right = 100; - - d->mix_levels[dev] = left | (right << 8); - - /* Scale volumes */ - left = AD1816_MUTE - (AD1816_MUTE * left) / 100; - right = AD1816_MUTE - (AD1816_MUTE * right) / 100; - - reg = (left << 8) | right; - - /* do channel selective muting if volume is zero */ - if (left == AD1816_MUTE) - reg |= 0x8000; - if (right == AD1816_MUTE) - reg |= 0x0080; - - switch (dev) { - case SOUND_MIXER_VOLUME: /* Register 14 master volume */ - ad1816_write(d, 14, reg); - break; - case SOUND_MIXER_CD: /* Register 15 cd */ - case SOUND_MIXER_LINE1: - ad1816_write(d, 15, reg); - break; - case SOUND_MIXER_SYNTH: /* Register 16 synth */ - ad1816_write(d, 16, reg); - break; - case SOUND_MIXER_PCM: /* Register 4 pcm */ - ad1816_write(d, 4, reg); - break; - case SOUND_MIXER_LINE: - case SOUND_MIXER_LINE3: /* Register 18 line in */ - ad1816_write(d, 18, reg); - break; - case SOUND_MIXER_MIC: /* Register 19 mic volume */ - ad1816_write(d, 19, reg & ~0xff); /* mic is mono */ - break; - case SOUND_MIXER_IGAIN: - /* and now to something completely different ... */ - ad1816_write(d, 20, ((ad1816_read(d, 20) & ~0x0f0f) - | (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */ - | ((AD1816_MUTE - right) / 2))); - break; - default: - printf("ad1816_mixer_set(): unknown device.\n"); - break; - } - - return 0; /* success */ -} - -static void -ad1816_mixer_reset(snddev_info * d) -{ - int i; - - d->mix_devs = AD1816_MIXER_DEVICES; - d->mix_rec_devs = AD1816_REC_DEVICES; - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (d->mix_devs & (1 << i)) - ad1816_mixer_set(d, i, default_mixer_levels[i]); - ad1816_set_recsrc(d, SOUND_MASK_MIC); -} - -/* Set the playback and capture rates. */ - -static int -ad1816_speed(snddev_info * d) -{ - RANGE(d->play_speed,4000,55200); - RANGE(d->rec_speed,4000,55200); - - ad1816_write(d, 2, d->play_speed); - ad1816_write(d, 3, d->rec_speed); - - return d->play_speed; -} - -/* - * ad1816_format checks that the format is supported (or defaults to AFMT_U8) - * and sets the chip to the desired format. - */ - -static int -ad1816_format(snddev_info * d) -{ - int oldplay =inb(ad1816_play(d)) & ~AD1816_FORMASK; - int oldrec = inb(ad1816_capt(d)) & ~AD1816_FORMASK; - int play = (d->play_fmt & d->audio_fmt) ? d->play_fmt : AFMT_U8; - int rec = (d->rec_fmt & d->audio_fmt) ? d->rec_fmt : AFMT_U8; - - /* - * check that arg is one of the supported formats in d->format; otherwise - * fallback to AFMT_U8 - */ - - switch (play) { - case AFMT_A_LAW: - outb(ad1816_play(d), oldplay | AD1816_ALAW); - break; - case AFMT_MU_LAW: - outb(ad1816_play(d), oldplay | AD1816_MULAW); - break; - case AFMT_S16_LE: - outb(ad1816_play(d), oldplay | AD1816_S16LE); - break; - case AFMT_S16_BE: - outb(ad1816_play(d), oldplay | AD1816_S16BE); - break; - default: - /* unlikely to happen */ - printf("ad1816: unknown play format. defaulting to U8.\n"); - case AFMT_U8: - outb(ad1816_play(d), oldplay | AD1816_U8); - break; - } - - switch (rec) { - case AFMT_A_LAW: - outb(ad1816_capt(d), oldrec | AD1816_ALAW); - break; - case AFMT_MU_LAW: - outb(ad1816_capt(d), oldrec | AD1816_MULAW); - break; - case AFMT_S16_LE: - outb(ad1816_capt(d), oldrec | AD1816_S16LE); - break; - case AFMT_S16_BE: - outb(ad1816_capt(d), oldrec | AD1816_S16BE); - break; - default: - printf("ad1816: unknown capture format. defaulting to U8.\n"); - case AFMT_U8: - outb(ad1816_capt(d), oldrec | AD1816_U8); - break; - } - - d->play_fmt = play; - d->rec_fmt = rec; - - return (play); -} - -/* - * ad1816_reinit resets codec registers - */ -static void -ad1816_reinit(snddev_info * d) -{ - ad1816_write(d, 8, 0x0000); /* reset base and current counter */ - ad1816_write(d, 9, 0x0000); /* for playback and capture */ - ad1816_write(d, 10, 0x0000); - ad1816_write(d, 11, 0x0000); - - if (d->flags & SND_F_STEREO) { - outb((ad1816_play(d)), AD1816_STEREO); /* set playback to stereo */ - outb((ad1816_capt(d)), AD1816_STEREO); /* set capture to stereo */ - } else { - outb((ad1816_play(d)), 0x00); /* set playback to mono */ - outb((ad1816_capt(d)), 0x00); /* set capture to mono */ - } - - ad1816_format(d); - ad1816_speed(d); - - snd_set_blocksize(d); /* update blocksize if user did not force it */ -} - #endif /* NPNP > 0 */ #endif /* NPCM > 0 */ diff --git a/sys/i386/isa/snd/dmabuf.c b/sys/i386/isa/snd/dmabuf.c index 66f94ac552675..c69435c2cd5d4 100644 --- a/sys/i386/isa/snd/dmabuf.c +++ b/sys/i386/isa/snd/dmabuf.c @@ -4,7 +4,7 @@ * This file implements the new DMA routines for the sound driver. * AUTO DMA MODE (ISA DMA SIDE). * - * Copyright by Luigi Rizzo - 1997-99 + * Copyright by Luigi Rizzo - 1997 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +32,7 @@ */ #include <i386/isa/snd/sound.h> -#include <i386/isa/snd/ulaw.h> +#include <i386/isa/sound/ulaw.h> #define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ #define DMA_ALIGN_THRESHOLD 4 @@ -108,10 +108,7 @@ dsp_wr_dmadone(snddev_info *d) { snd_dbuf *b = & (d->dbuf_out) ; - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate(b); + dsp_wr_dmaupdate(b); /* * XXX here it would be more efficient to record if there * actually is a sleeping process, but this should still work. @@ -183,7 +180,7 @@ dsp_wrintr(snddev_info *d) * This happens if the size has changed _and_ the new size * is smaller, or it matches the blocksize. */ - if (l != b->dl && (b->dl == 0 || l<b->dl || l == d->play_blocksize) ) { + if (l != b->dl && (l < b->dl || l == d->play_blocksize) ) { /* for any reason, size has changed. Stop and restart */ DEB(printf("wrintr: bsz change from %d to %d, rp %d rl %d\n", b->dl, l, b->rp, b->rl)); @@ -194,10 +191,7 @@ dsp_wrintr(snddev_info *d) * at high speed, it might well be that the count * changes in the meantime. So we try to update b->rl */ - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate(b) ; + dsp_wr_dmaupdate(b) ; l = min(b->rl, d->play_blocksize ); l &= DMA_ALIGN_MASK ; /* realign things */ b->dl = l; /* record previous transfer size */ @@ -258,10 +252,7 @@ dsp_write_body(snddev_info *d, struct uio *buf) while ( (n = buf->uio_resid) ) { l = min (n, bsz); /* at most n bytes ... */ s = spltty(); /* no interrupts here ... */ - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate(b); + dsp_wr_dmaupdate(b); l = min( l, b->fl ); /* no more than avail. space */ DEB(printf("dsp_write_body: prepare %d bytes out of %d\n", l,n)); /* @@ -415,10 +406,7 @@ dsp_rd_dmadone(snddev_info *d) { snd_dbuf *b = & (d->dbuf_in) ; - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate(b); + dsp_rd_dmaupdate(b); wakeup(b) ; /* wakeup possibly sleeping processes */ if (b->sel.si_pid && ( !(d->flags & SND_F_HAS_SIZE) || b->rl >= d->rec_blocksize ) ) @@ -542,10 +530,7 @@ dsp_read_body(snddev_info *d, struct uio *buf) DEB(printf("dsp_read_body: start waiting for %d bytes\n", n)); l = min (n, bsz); s = spltty(); /* no interrupts here ! */ - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate(b); + dsp_rd_dmaupdate(b); l = min( l, b->rl ); /* no more than avail. data */ if (l == 0) { int timeout; @@ -658,8 +643,7 @@ reset_dbuf(snd_dbuf *b, int chan) chan = B_WRITE | B_RAW ; else chan = B_READ | B_RAW ; - if (b->chan != 4 && b->chan < 8) /* XXX hack for pci... */ - isa_dmastart( chan , b->buf, b->bufsize, b->chan); + isa_dmastart( chan , b->buf, b->bufsize, b->chan); } /* @@ -679,14 +663,10 @@ snd_sync(snddev_info *d, int chan, int threshold) for (;;) { s=spltty(); - if (d->special_dma) - d->callback(d, (chan==1? SND_CB_WR:SND_CB_RD) | SND_CB_DMAUPDATE); - else { - if ( chan==1 ) - dsp_wr_dmaupdate(b); - else - dsp_rd_dmaupdate(b); - } + if ( chan==1 ) + dsp_wr_dmaupdate(b); + else + dsp_rd_dmaupdate(b); if ( (chan == 1 && b->fl <= threshold) || (chan == 2 && b->rl <= threshold) ) { ret = tsleep((caddr_t)b, PRIBIO|PCATCH, "sndsyn", 1); @@ -721,15 +701,13 @@ dsp_wrabort(snddev_info *d, int restart) d->flags &= ~ SND_F_WRITING ; if (d->callback) d->callback(d, SND_CB_WR | SND_CB_ABORT); - if (!d->special_dma) - isa_dmastop(b->chan) ; + isa_dmastop(b->chan) ; dsp_wr_dmadone(d); DEB(printf("dsp_wrabort: stopped, %d bytes left\n", b->rl)); } missing = b->rl; - if (!d->special_dma) - isa_dmadone(B_WRITE, b->buf, b->bufsize, b->chan); /*free chan */ + isa_dmadone(B_WRITE, b->buf, b->bufsize, b->chan); /*free chan */ reset_dbuf(b, restart ? SND_CHAN_WR : SND_CHAN_NONE); splx(s); return missing; @@ -748,13 +726,11 @@ dsp_rdabort(snddev_info *d, int restart) d->flags &= ~ SND_F_READING ; if (d->callback) d->callback(d, SND_CB_RD | SND_CB_ABORT); - if (!d->special_dma) - isa_dmastop(b->chan) ; + isa_dmastop(b->chan) ; dsp_rd_dmadone(d); } missing = b->rl ; - if (!d->special_dma) - isa_dmadone(B_READ, b->buf, b->bufsize, b->chan); + isa_dmadone(B_READ, b->buf, b->bufsize, b->chan); reset_dbuf(b, restart ? SND_CHAN_RD : SND_CHAN_NONE); splx(s); return missing; @@ -782,10 +758,7 @@ snd_flush(snddev_info *d) * still pending output data. */ ret = tsleep( (caddr_t)b, PRIBIO|PCATCH, "dmafl1", hz); - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE); - else - dsp_wr_dmaupdate(b); + dsp_wr_dmaupdate(b); DEB( printf("snd_sync: now rl : fl %d : %d\n", b->rl, b->fl ) ); if (ret == EINTR) { printf("tsleep returns %d\n", ret); diff --git a/sys/i386/isa/snd/mss.h b/sys/i386/isa/snd/mss.h index 20ceaaf9da0c1..54efc3cc21950 100644 --- a/sys/i386/isa/snd/mss.h +++ b/sys/i386/isa/snd/mss.h @@ -105,55 +105,6 @@ ahead. #define BD_F_IRQ_OK 0x0002 #define BD_F_TMR_RUN 0x0004 -/* AD1816 register macros */ - -#define ad1816_ale(d) ((d)->io_base+0) /* indirect reg access */ -#define ad1816_int(d) ((d)->io_base+1) /* interupt status */ -#define ad1816_low(d) ((d)->io_base+2) /* indirect low byte */ -#define ad1816_high(d) ((d)->io_base+3) /* indirect high byte */ -/* unused */ -#define ad1816_pioD(d) ((d)->io_base+4) /* PIO debug */ -#define ad1816_pios(d) ((d)->io_base+5) /* PIO status */ -#define ad1816_piod(d) ((d)->io_base+6) /* PIO data */ -/* end of unused */ -/* values for playback/capture config: - bits: 0 enable/disable - 1 pio/dma - 2 stereo/mono - 3 companded/linearPCM - 4-5 format : 00 8bit linear (uncomp) - 00 8bit mulaw (comp) - 01 16bit le (uncomp) - 01 8bit alaw (comp) - 11 16bit be (uncomp) -*/ -#define ad1816_play(d) ((d)->io_base+8) /* playback config */ -#define ad1816_capt(d) ((d)->io_base+9) /* capture config */ - -#define AD1816_BUSY 0x80 /* chip is busy */ -#define AD1816_ALEMASK 0x3F /* mask for indirect adr. */ -/* unusud */ -#define AD1816_INTRSI 0x01 /* sb intr */ -#define AD1816_INTRGI 0x02 /* game intr */ -#define AD1816_INTRRI 0x04 /* ring intr */ -#define AD1816_INTRDI 0x08 /* dsp intr */ -#define AD1816_INTRVI 0x10 /* vol intr */ -#define AD1816_INTRTI 0x20 /* timer intr */ -/* used again */ -#define AD1816_INTRCI 0x40 /* capture intr */ -#define AD1816_INTRPI 0x80 /* playback intr */ -/* PIO stuff is not supplied here */ -/* playback / capture config */ -#define AD1816_ENABLE 0x01 /* enable pl/cp */ -#define AD1816_PIO 0x02 /* use pio */ -#define AD1816_STEREO 0x04 -#define AD1816_COMP 0x08 /* data is companded */ -#define AD1816_U8 0x00 /* 8 bit linear pcm */ -#define AD1816_MULAW 0x08 /* 8 bit mulaw */ -#define AD1816_ALAW 0x18 /* 8 bit alaw */ -#define AD1816_S16LE 0x10 /* 16 bit linear little endian */ -#define AD1816_S16BE 0x30 /* 16 bit linear big endian */ -#define AD1816_FORMASK 0x38 /* format mask */ /* * sound/ad1848_mixer.h @@ -274,12 +225,6 @@ MIX_NONE(SOUND_MIXER_LINE3), SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \ SOUND_MASK_IGAIN | SOUND_MASK_LINE1 ) -#define AD1816_REC_DEVICES \ - (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) - -#define AD1816_MIXER_DEVICES \ - (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH | \ - SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN) static u_short default_mixer_levels[SOUND_MIXER_NRDEVICES] = { 0x5a5a, /* Master Volume */ diff --git a/sys/i386/isa/snd/sb_dsp.c b/sys/i386/isa/snd/sb_dsp.c index 3c77f1f12bc5c..96d0e626b420c 100644 --- a/sys/i386/isa/snd/sb_dsp.c +++ b/sys/i386/isa/snd/sb_dsp.c @@ -324,10 +324,18 @@ again: if ( reason & 1 ) { /* possibly a write interrupt */ if ( d->dbuf_out.dl ) dsp_wrintr(d); + else { + if (PLAIN_SB16(d->bd_flags)) + printf("WARNING: wrintr but write DMA inactive!\n"); + } } if ( reason & 2 ) { if ( d->dbuf_in.dl ) dsp_rdintr(d); + else { + if (PLAIN_SB16(d->bd_flags)) + printf("WARNING: rdintr but read DMA inactive!\n"); + } } if ( c & 2 ) inb(DSP_DATA_AVL16); /* 16-bit int ack */ @@ -337,7 +345,7 @@ again: /* * the sb16 might have multiple sources etc. */ - if ((d->bd_flags & BD_F_SB16) && (c & 3)) + if (d->bd_flags & BD_F_SB16 && (c & 3) ) goto again; } @@ -382,6 +390,7 @@ sb_callback(snddev_info *d, int reason) * the proper initialization for each one. */ if (PLAIN_SB16(d->bd_flags)) { + u_char c, c1 ; /* the original SB16 (non-PnP, or PnP, or Vibra16C) * can do full duplex using one 16-bit channel @@ -427,63 +436,29 @@ sb_callback(snddev_info *d, int reason) d->dbuf_in.chan = d->dbuf_out.chan; d->dbuf_out.chan = c ; } - } - else if (d->bd_flags & BD_F_ESS) { - u_char c; - - DEB(printf("SND_CB_INIT, play_fmt == 0x%x, rec_fmt == 0x%x\n", - (int) d->play_fmt, (int) d->rec_fmt)); - - /* autoinit DMA mode */ - if (d->play_fmt) - ess_write(d->io_base, 0xb8, 0x04); - else - ess_write(d->io_base, 0xb8, 0x0e); - - c = (ess_read(d->io_base, 0xa8) & ~0x03) | 0x01; - if ((d->flags & SND_F_STEREO) == 0) - c++; - ess_write(d->io_base, 0xa8, c); /* select mono/stereo */ - ess_write(d->io_base, 0xb9, 2); /* demand 4 bytes/transfer */ - - switch (d->play_fmt ? d->play_fmt : d->rec_fmt) { - case AFMT_S16_LE: - if (d->flags & SND_F_STEREO) { - /* 16 bit stereo */ - if (d->play_fmt) - ess_write(d->io_base, 0xb6, 0x00); - ess_write(d->io_base, 0xb7, 0x71); - ess_write(d->io_base, 0xb7, 0xbc); - } - else { - /* 16 bit mono */ - if (d->play_fmt) - ess_write(d->io_base, 0xb6, 0x00); - ess_write(d->io_base, 0xb7, 0x71); - ess_write(d->io_base, 0xb7, 0xf4); - } - break; - case AFMT_U8: - if (d->flags & SND_F_STEREO) { - /* 8 bit stereo */ - if (d->play_fmt) - ess_write(d->io_base, 0xb6, 0x80); - ess_write(d->io_base, 0xb7, 0x51); - ess_write(d->io_base, 0xb7, 0x98); - } - else { - /* 8 bit mono */ - if (d->play_fmt) - ess_write(d->io_base, 0xb6, 0x80); - ess_write(d->io_base, 0xb7, 0x51); - ess_write(d->io_base, 0xb7, 0xd0); - } - break; - } - ess_write(d->io_base, 0xb1, - ess_read(d->io_base, 0xb1) | 0x50); - ess_write(d->io_base, 0xb2, - ess_read(d->io_base, 0xb1) | 0x50); + } else if (d->bd_flags & BD_F_ESS) { + u_char c ; + if (d->play_fmt == 0) { + /* initialize for record */ + static u_char cmd[] = { + 0x51,0xd0,0x71,0xf4,0x51,0x98,0x71,0xbc + }; + ess_write(d->io_base, 0xb8, 0x0e); + c = ( ess_read(d->io_base, 0xa8) & 0xfc ) | 1 ; + if (d->flags & SND_F_STEREO) + c++ ; + ess_write(d->io_base, 0xa8, c); + ess_write(d->io_base, 0xb9, 2); /* 4bytes/transfer */ + /* + * set format in b6, b7 + */ + } else { + /* initialize for play */ + static u_char cmd[] = { + 0x80,0x51,0xd0,0x00,0x71,0xf4, + 0x80,0x51,0x98,0x00,0x71,0xbc + }; + } } reset_dbuf(& (d->dbuf_in), SND_CHAN_RD ); reset_dbuf(& (d->dbuf_out), SND_CHAN_WR ); @@ -499,6 +474,7 @@ sb_callback(snddev_info *d, int reason) * the second one takes the next... * The default is to be ready for play. */ + int swap = 0 ; DEB(printf("start %s -- now dma %d:%d\n", rd ? "rd" : "wr", d->dbuf_out.chan, d->dbuf_in.chan);); @@ -544,18 +520,10 @@ sb_callback(snddev_info *d, int reason) sb_cmd(d->io_base, c ); sb_cmd3(d->io_base, c1 , l - 1) ; } else if (d->bd_flags & BD_F_ESS) { - u_long fmt = rd ? d->rec_fmt : d->play_fmt; - - DEB(printf("SND_CB_START: %s (%d)\n", rd ? "rd" : "wr", l)); - if (fmt == AFMT_S16_LE) - l >>= 1; - l--; - if (!rd) - sb_cmd(d->io_base, DSP_CMD_SPKON); - ess_write(d->io_base, 0xa4, l); - ess_write(d->io_base, 0xa5, l >> 8); - ess_write(d->io_base, 0xb8, - ess_read(d->io_base, 0xb8) | (rd ? 0x0f : 0x05)); + /* XXX this code is still incomplete */ + sb_cmd2(d->io_base, 0xb8, rd ? 4 : 0xe ) ; /* auto dma */ + sb_cmd2(d->io_base, 0xa8, d->flags & SND_F_STEREO ? 1 : 2) ; + sb_cmd2(d->io_base, 0xb9, 2) ; /* demand dma */ } else { /* SBPro -- stereo not supported */ u_char c ; if (!rd) @@ -586,7 +554,6 @@ sb_callback(snddev_info *d, int reason) case SND_CB_STOP : { int cmd = DSP_CMD_DMAPAUSE_8 ; /* default: halt 8 bit chan */ - DEB(printf("SND_CB_XXX: reason 0x%x\n", reason)); if ( b->chan > 4 || (rd && d->rec_fmt == AFMT_S16_LE) || (!rd && d->play_fmt == AFMT_S16_LE) @@ -763,20 +730,14 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) /* the ESS488 can be treated as an SBPRO */ printf("ESS488 (rev %d)\n", ess_minor & 0x0f); break ; - } - else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { - int rev = ess_minor & 0xf; - - if (rev >= 8) - printf("ESS1868 (rev %d)\n", rev); - else - printf("ESS688 (rev %d)\n", rev); - d->bd_flags |= BD_F_ESS; - d->audio_fmt |= AFMT_S16_LE; - - /* enable extended ESS mode */ - sb_cmd(d->io_base, 0xc6); - break; + } else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { + int rev = ess_minor & 0xf ; + if ( rev >= 8 ) + printf("ESS1868 (rev %d)\n", rev); + else + printf("ESS688 (rev %d)\n", rev); + /* d->audio_fmt |= AFMT_S16_LE; */ /* not yet... */ + break ; /* XXX */ } else { printf("Unknown card 0x%x 0x%x -- hope it is SBPRO\n", ess_major, ess_minor); @@ -786,8 +747,7 @@ sb_dsp_init(snddev_info *d, struct isa_device *dev) } - snprintf(d->name, sizeof(d->name), - fmt, (d->bd_id >> 8) &0xff, d->bd_id & 0xff); + sprintf(d->name, fmt, (d->bd_id >> 8) &0xff, d->bd_id & 0xff); sb_mix_init(d); } @@ -878,9 +838,9 @@ sb_setmixer(int io_base, u_int port, u_int value) u_long flags; flags = spltty(); - outb(io_base + SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ + outb(io_base + 4, (u_char) (port & 0xff)); /* Select register */ DELAY(10); - outb(io_base + SB_MIX_DATA, (u_char) (value & 0xff)); + outb(io_base + 5, (u_char) (value & 0xff)); DELAY(10); splx(flags); } @@ -1228,6 +1188,7 @@ ess1868_attach(u_long csn, u_long vend_id, char *name, { struct pnp_cinfo d ; snddev_info tmp_d ; /* patched copy of the basic snddev_info */ + int the_irq = 0 ; tmp_d = sb_op_desc; snddev_last_probed = &tmp_d; @@ -1256,12 +1217,10 @@ ess1868_attach(u_long csn, u_long vend_id, char *name, dev->id_drq = d.drq[0] ; /* primary dma */ dev->id_irq = (1 << d.irq[0] ) ; - dev->id_intr = (inthand2_t *)pcmintr ; + dev->id_intr = pcmintr ; dev->id_flags = 0 /* DV_F_DUAL_DMA | (d.drq[1] ) */; -#if 0 snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */ -#endif pcmattach(dev); } @@ -1339,7 +1298,7 @@ sb16pnp_attach(u_long csn, u_long vend_id, char *name, dev->id_drq = d.drq[0] ; /* primary dma */ dev->id_irq = (1 << d.irq[0] ) ; - dev->id_intr = (inthand2_t *)pcmintr ; + dev->id_intr = pcmintr ; dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ; pcm_info[dev->id_unit] = tmp_d; /* pcm_info[] will be reinitialized after */ diff --git a/sys/i386/isa/snd/sbcard.h b/sys/i386/isa/snd/sbcard.h index 481719961a78e..92ec966107911 100644 --- a/sys/i386/isa/snd/sbcard.h +++ b/sys/i386/isa/snd/sbcard.h @@ -264,15 +264,15 @@ static u_char sb16_recmasks_L[SOUND_MIXER_NRDEVICES]; static u_char sb16_recmasks_R[SOUND_MIXER_NRDEVICES]; #else /* __SB_MIXER_C__ defined */ mixer_tab sbpro_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), + PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), PMIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), - PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), + PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), + PMIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), PMIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), - PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), + PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), + PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) @@ -280,15 +280,15 @@ mixer_tab sbpro_mix = { #ifdef __SGNXPRO__ mixer_tab sgnxpro_mix = { - PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 4, 4, 0x22, 0, 4), - PMIX_ENT(SOUND_MIXER_BASS, 0x46, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 4, 4, 0x26, 0, 4), - PMIX_ENT(SOUND_MIXER_PCM, 0x04, 4, 4, 0x04, 0, 4), - PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 4, 4, 0x2e, 0, 4), - PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 0, 3, 0x00, 0, 0), - PMIX_ENT(SOUND_MIXER_CD, 0x28, 4, 4, 0x28, 0, 4), + PMIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), + PMIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), + PMIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), + PMIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), + PMIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), + PMIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), PMIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), PMIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), diff --git a/sys/i386/isa/snd/sound.c b/sys/i386/isa/snd/sound.c index 6a5a92d99a61c..ef724cd5121b3 100644 --- a/sys/i386/isa/snd/sound.c +++ b/sys/i386/isa/snd/sound.c @@ -229,7 +229,7 @@ synthprobe(struct isa_device * dev) } /* - * this is the ISA part of the generic attach routine + * this is the generic attach routine */ int @@ -238,8 +238,8 @@ pcmattach(struct isa_device * dev) snddev_info *d = NULL ; struct isa_device *dvp; int stat = 0; - - dev->id_ointr = pcmintr; + dev_t isadev; + void *cookie; if ( (dev->id_unit >= NPCM_MAX) || /* too many devs */ (snddev_last_probed == NULL) || /* last probe failed */ @@ -282,68 +282,19 @@ pcmattach(struct isa_device * dev) isa_dma_acquire(d->dbuf_out.chan); if (FULL_DUPLEX(d)) isa_dma_acquire(d->dbuf_in.chan); - - - /* - * should try and find a suitable value for id_id, otherwise - * the interrupt is not registered and dispatched properly. - * This is important for PnP devices, where "dev" is built on - * the fly and many field are not initialized. - */ - if (dev->id_driver == NULL) { - dev->id_driver = &pcmdriver ; - dvp=find_isadev(isa_devtab_tty, &pcmdriver, 0); - if (dvp) - dev->id_id = dvp->id_id; - } - - /* - * call the generic part of the attach - */ - pcminit(d, dev->id_unit); - /* - * and finally, call the device attach routine - * XXX I should probably use d->attach(dev) - */ - stat = snddev_last_probed->attach(dev); -#if 0 - /* - * XXX hooks for synt support. Try probe and attach... - */ - if (d->synth_base && opl3_probe(dev) ) { - opl3_attach(dev); - } -#endif - snddev_last_probed = NULL ; - - return stat ; -} - -/* - * This is the generic init routine - */ -int -pcminit(snddev_info *d, int unit) -{ -#ifdef DEVFS - void *cookie; -#endif - dev_t isadev; - - isadev = makedev(CDEV_MAJOR, 0); - cdevsw_add(&isadev, &snd_cdevsw, NULL); - /* * initialize standard parameters for the device. This can be * overridden by device-specific configurations but better do * here the generic things. */ - d->magic = MAGIC(unit); /* debugging... */ d->play_speed = d->rec_speed = 8000 ; d->play_blocksize = d->rec_blocksize = 2048 ; d->play_fmt = d->rec_fmt = AFMT_MU_LAW ; + isadev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&isadev, &snd_cdevsw, NULL); + #ifdef DEVFS #ifndef GID_GAMES #define GID_SND UID_ROOT @@ -359,40 +310,70 @@ pcminit(snddev_info *d, int unit) * Make links to first successfully probed unit. * Attempts by later devices to make these links will fail. */ - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_DSP, - DV_CHR, UID_SND, GID_SND, PERM_SND, "dsp%r", unit); - if (cookie) devfs_makelink(cookie, "dsp"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP, + DV_CHR, UID_SND, GID_SND, PERM_SND, "dsp%r", dev->id_unit); + if (cookie) devfs_link(cookie, "dsp"); - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_DSP16, - DV_CHR, UID_SND, GID_SND, PERM_SND, "dspW%r", unit); - if (cookie) devfs_makelink(cookie, "dspW"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP16, + DV_CHR, UID_SND, GID_SND, PERM_SND, "dspW%r", dev->id_unit); + if (cookie) devfs_link(cookie, "dspW"); - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_AUDIO, - DV_CHR, UID_SND, GID_SND, PERM_SND, "audio%r", unit); - if (cookie) devfs_makelink(cookie, "audio"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_AUDIO, + DV_CHR, UID_SND, GID_SND, PERM_SND, "audio%r", dev->id_unit); + if (cookie) devfs_link(cookie, "audio"); - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_CTL, - DV_CHR, UID_SND, GID_SND, PERM_SND, "mixer%r", unit); - if (cookie) devfs_makelink(cookie, "mixer"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_CTL, + DV_CHR, UID_SND, GID_SND, PERM_SND, "mixer%r", dev->id_unit); + if (cookie) devfs_link(cookie, "mixer"); - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_STATUS, - DV_CHR, UID_SND, GID_SND, PERM_SND, "sndstat%r", unit); - if (cookie) devfs_makelink(cookie, "sndstat"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_STATUS, + DV_CHR, UID_SND, GID_SND, PERM_SND, "sndstat%r", dev->id_unit); + if (cookie) devfs_link(cookie, "sndstat"); #if 0 /* these two are still unsupported... */ - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_MIDIN, - DV_CHR, UID_SND, GID_SND, PERM_SND, "midi%r", unit); - if (cookie) devfs_makelink(cookie, "midi"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_MIDIN, + DV_CHR, UID_SND, GID_SND, PERM_SND, "midi%r", dev->id_unit); + if (cookie) devfs_link(cookie, "midi"); - cookie = devfs_add_devswf(&snd_cdevsw, (unit << 4) | SND_DEV_SYNTH, - DV_CHR, UID_SND, GID_SND, PERM_SND, "sequencer%r", unit); - if (cookie) devfs_makelink(cookie, "sequencer"); + cookie = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_SYNTH, + DV_CHR, UID_SND, GID_SND, PERM_SND, "sequencer%r", dev->id_unit); + if (cookie) devfs_link(cookie, "sequencer"); #endif #endif /* DEVFS */ + + /* + * should try and find a suitable value for id_id, otherwise + * the interrupt is not registered and dispatched properly. + * This is important for PnP devices, where "dev" is built on + * the fly and many field are not initialized. + */ + if (dev->id_driver == NULL) { + dev->id_driver = &pcmdriver ; + dvp=find_isadev(isa_devtab_tty, &pcmdriver, 0); + if (dvp) + dev->id_id = dvp->id_id; + } + + d->magic = MAGIC(dev->id_unit); /* debugging... */ + /* + * and finally, call the device attach routine + * XXX I should probably use d->attach(dev) + */ + stat = snddev_last_probed->attach(dev); +#if 0 + /* + * XXX hooks for synt support. Try probe and attach... + */ + if (d->synth_base && opl3_probe(dev) ) { + opl3_attach(dev); + } +#endif + snddev_last_probed = NULL ; + #if NAPM > 0 - init_sound_apm(unit); + init_sound_apm(dev->id_unit); #endif - return 0 ; + return stat ; } int midiattach(struct isa_device * dev) { return 0 ; } @@ -605,14 +586,6 @@ sndread(dev_t i_dev, struct uio * buf, int flag) return uiomove(p, l, buf) ; } - /* - * XXX read from the ad1816 with a single DMA channel is unsupported. - * This is really not the place for machine-dependent functions, - * a proper device routine will be supplied in the future - luigi - */ - if ((d->bd_id == MD_AD1816) && (!(FULL_DUPLEX(d)))) - return EIO; - if (d->read) /* device-specific read */ return d->read(i_dev, buf, flag); @@ -810,12 +783,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) * we start with the new ioctl interface. */ case AIONWRITE : /* how many bytes can write ? */ - if (d->dbuf_out.dl) { - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate(&(d->dbuf_out)); - } + if (d->dbuf_out.dl) + dsp_wr_dmaupdate(&(d->dbuf_out)); *(int *)arg = d->dbuf_out.fl; break; @@ -901,7 +870,7 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) break ; case AIOSYNC: - printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n", + printf("AIOSYNC chan 0x%03lx pos %d unimplemented\n", ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); break; @@ -909,12 +878,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) * here follow the standard ioctls (filio.h etc.) */ case FIONREAD : /* get # bytes to read */ - if ( d->dbuf_in.dl ) { - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate(&(d->dbuf_in)); - } + if ( d->dbuf_in.dl ) + dsp_rd_dmaupdate(&(d->dbuf_in)); *(int *)arg = d->dbuf_in.rl; break; @@ -1071,12 +1036,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) { audio_buf_info *a = (audio_buf_info *)arg; snd_dbuf *b = &(d->dbuf_in); - if (b->dl) { - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate( b ); - } + if (b->dl) + dsp_rd_dmaupdate( b ); a->bytes = d->dbuf_in.fl ; a->fragments = 1 ; a->fragstotal = b->bufsize / d->rec_blocksize ; @@ -1089,12 +1050,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) { audio_buf_info *a = (audio_buf_info *)arg; snd_dbuf *b = &(d->dbuf_out); - if (b->dl) { - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate( b ); - } + if (b->dl) + dsp_wr_dmaupdate( b ); a->bytes = d->dbuf_out.fl ; a->fragments = 1 ; a->fragstotal = b->bufsize / d->play_blocksize ; @@ -1106,12 +1063,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) { count_info *a = (count_info *)arg; snd_dbuf *b = &(d->dbuf_in); - if (b->dl) { - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate( b ); - } + if (b->dl) + dsp_rd_dmaupdate( b ); a->bytes = b->total; a->blocks = (b->total - b->prev_total + d->rec_blocksize -1 ) / d->rec_blocksize ; @@ -1124,12 +1077,8 @@ sndioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc * p) { count_info *a = (count_info *)arg; snd_dbuf *b = &(d->dbuf_out); - if (b->dl) { - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate( b ); - } + if (b->dl) + dsp_wr_dmaupdate( b ); a->bytes = b->total; a->blocks = (b->total - b->prev_total /* +d->play_blocksize -1*/ ) / d->play_blocksize ; @@ -1217,12 +1166,8 @@ sndselect(dev_t i_dev, int rw, struct proc * p) /* XXX fix the test here for half duplex devices */ if (1 /* write is compatible with current mode */) { flags = spltty(); - if (d->dbuf_out.dl) { - if (d->special_dma) - d->callback(d, SND_CB_WR | SND_CB_DMAUPDATE) ; - else - dsp_wr_dmaupdate(&(d->dbuf_out)); - } + if (d->dbuf_out.dl) + dsp_wr_dmaupdate(&(d->dbuf_out)); c = d->dbuf_out.fl ; if (c < lim) /* no space available */ selrecord(p, & (d->wsel)); @@ -1239,12 +1184,8 @@ sndselect(dev_t i_dev, int rw, struct proc * p) flags = spltty(); if ( d->dbuf_in.dl == 0 ) /* dma idle, restart it */ dsp_rdintr(d); - else { - if (d->special_dma) - d->callback(d, SND_CB_RD | SND_CB_DMAUPDATE) ; - else - dsp_rd_dmaupdate(&(d->dbuf_in)); - } + else + dsp_rd_dmaupdate(&(d->dbuf_in)); c = d->dbuf_in.rl ; if (c < lim) /* no data available */ selrecord(p, & (d->rsel)); @@ -1283,7 +1224,7 @@ sndselect(dev_t i_dev, int rw, struct proc * p) #include <vm/vm_extern.h> static int -sndmmap(dev_t dev, vm_offset_t offset, int nprot) +sndmmap(dev_t dev, int offset, int nprot) { snddev_info *d = get_snddev_info(dev, NULL); @@ -1357,21 +1298,19 @@ init_status(snddev_info *d) if (status_len != 0) /* only do init once */ return ; - snprintf(status_buf, sizeof(status_buf), + sprintf(status_buf, "FreeBSD Audio Driver (981002) " __DATE__ " " __TIME__ "\n" "Installed devices:\n"); for (i = 0; i < NPCM_MAX; i++) { if (pcm_info[i].open) - snprintf(status_buf + strlen(status_buf), - sizeof(status_buf) - strlen(status_buf), + sprintf(status_buf + strlen(status_buf), "pcm%d: <%s> at 0x%x irq %d dma %d:%d\n", i, pcm_info[i].name, pcm_info[i].io_base, pcm_info[i].irq, pcm_info[i].dbuf_out.chan, pcm_info[i].dbuf_in.chan); if (midi_info[i].open) - snprintf(status_buf + strlen(status_buf), - sizeof(status_buf) - strlen(status_buf), + sprintf(status_buf + strlen(status_buf), "midi%d: <%s> at 0x%x irq %d dma %d:%d\n", i, midi_info[i].name, midi_info[i].io_base, midi_info[i].irq, @@ -1384,8 +1323,7 @@ init_status(snddev_info *d) case 4 : s = "OPL4"; break; } - snprintf(status_buf + strlen(status_buf), - sizeof(status_buf) - strlen(status_buf), + sprintf(status_buf + strlen(status_buf), "sequencer%d: <%s> at 0x%x (not functional)\n", i, s, pcm_info[i].synth_base); } @@ -1505,6 +1443,7 @@ change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval) * full-duplex) */ +#if 1 void translate_bytes (u_char *table, u_char *buff, int n) { @@ -1516,5 +1455,22 @@ translate_bytes (u_char *table, u_char *buff, int n) for (i = 0; i < n; ++i) buff[i] = table[buff[i]]; } +#else +/* inline */ +void +translate_bytes (const void *table, void *buff, int n) +{ + if (n > 0) { + __asm__ ( " cld\n" + "1: lodsb\n" + " xlatb\n" + " stosb\n" + " loop 1b\n": + : "b" (table), "c" (n), "D" (buff), "S" (buff) + : "bx", "cx", "di", "si", "ax"); + } +} + +#endif #endif /* NPCM > 0 */ diff --git a/sys/i386/isa/snd/sound.h b/sys/i386/isa/snd/sound.h index c404ce6503d4e..eea64c639f4c2 100644 --- a/sys/i386/isa/snd/sound.h +++ b/sys/i386/isa/snd/sound.h @@ -151,14 +151,6 @@ struct _snddev_info { #define SND_CB_STOP 0x03 /* stop dma op */ #define SND_CB_ABORT 0x04 /* abort dma op */ #define SND_CB_INIT 0x05 /* init board parameters */ - - /* - * callback extensions - */ -#define SND_CB_DMADONE 0x10 -#define SND_CB_DMAUPDATE 0x11 -#define SND_CB_DMASTOP 0x12 - /* init can only be called with int enabled and * no pending DMA activity. */ @@ -296,10 +288,6 @@ struct _snddev_info { int synth_base ; /* base for the synth */ int synth_type ; /* type of synth */ void *device_data ; /* just in case it is needed...*/ - int special_dma ; - /* when this is set, dsp_wr_dmaupdate etc. - * are processed using callback extensions. - */ } ; /* @@ -313,7 +301,6 @@ struct _snddev_info { */ #define MD_AD1848 0x91 #define MD_AD1845 0x92 -#define MD_AD1816 0x93 #define MD_CS4248 0xA1 #define MD_CS4231 0xA2 #define MD_CS4231A 0xA3 @@ -444,12 +431,9 @@ int pcmprobe(struct isa_device * dev); int midiprobe(struct isa_device * dev); int synthprobe(struct isa_device * dev); int pcmattach(struct isa_device * dev); -int pcminit(snddev_info *d, int unit); int midiattach(struct isa_device * dev); int synthattach(struct isa_device * dev); -ointhand2_t pcmintr; - /* * DMA buffer calls */ diff --git a/sys/i386/isa/snd/ulaw.h b/sys/i386/isa/snd/ulaw.h deleted file mode 100644 index 4b9916f3063e3..0000000000000 --- a/sys/i386/isa/snd/ulaw.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * on entry: ulaw, on exit: unsigned 8 bit. - */ -static unsigned char ulaw_dsp[] = { - 3, 7, 11, 15, 19, 23, 27, 31, - 35, 39, 43, 47, 51, 55, 59, 63, - 66, 68, 70, 72, 74, 76, 78, 80, - 82, 84, 86, 88, 90, 92, 94, 96, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 123, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -#ifndef DSP_ULAW_NOT_WANTED -static unsigned char dsp_ulaw[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 17, 17, 18, 18, 19, - 19, 20, 20, 21, 21, 22, 22, 23, - 23, 24, 24, 25, 25, 26, 26, 27, - 27, 28, 28, 29, 29, 30, 30, 31, - 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, - 47, 49, 51, 53, 55, 57, 59, 61, - 63, 66, 70, 74, 78, 84, 92, 104, - 254, 231, 219, 211, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, - 159, 159, 158, 158, 157, 157, 156, 156, - 155, 155, 154, 154, 153, 153, 152, 152, - 151, 151, 150, 150, 149, 149, 148, 148, - 147, 147, 146, 146, 145, 145, 144, 144, - 143, 143, 143, 143, 142, 142, 142, 142, - 141, 141, 141, 141, 140, 140, 140, 140, - 139, 139, 139, 139, 138, 138, 138, 138, - 137, 137, 137, 137, 136, 136, 136, 136, - 135, 135, 135, 135, 134, 134, 134, 134, - 133, 133, 133, 133, 132, 132, 132, 132, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 129, 128, 128, 128, 128, -}; -#endif /* !DSP_ULAW_NOT_WANTED */ diff --git a/sys/i386/isa/sound/README.FREEBSD b/sys/i386/isa/sound/README.FREEBSD index 9979d12fa8239..3603bfe040e90 100644 --- a/sys/i386/isa/sound/README.FREEBSD +++ b/sys/i386/isa/sound/README.FREEBSD @@ -90,7 +90,7 @@ Lugi also has Sujal's PnP driver . This is my kernel configuration for my SB16 PnP: controller snd0 -device sb0 at isa? port 0x220 irq 10 conflicts drq 3 +device sb0 at isa? port 0x220 irq 10 conflicts drq 3 vector sbintr device sbxvi0 at isa? port? irq? drq 5 conflicts device opl0 at isa? port 0x388 conflicts device sbmidi0 at isa? port 0x300 irq? conflicts @@ -123,13 +123,13 @@ To configure your guspnp PRO if you have a motherboard which supports PnP: controller snd0 - device gus0 at isa? + device gus0 at isa? vector gusintr NONPNP CONFIGURATION To configure your guspnp PRO if your motherboard does NOT support PnP: -device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 +device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 vector gusintr the gus pnp is fully software configurable and the above configuration diff --git a/sys/i386/isa/sound/ad1848.c b/sys/i386/isa/sound/ad1848.c index 243ed78d1f518..fbd5051342708 100644 --- a/sys/i386/isa/sound/ad1848.c +++ b/sys/i386/isa/sound/ad1848.c @@ -914,6 +914,7 @@ ad1848_start_input(int dev, u_long buf, int count, static int ad1848_prepare_for_IO(int dev, int bsize, int bcount) { + int timeout; u_char fs, old_fs; u_long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -1439,13 +1440,11 @@ ad1848_init(char *name, int io_base, int irq, outb(io_Status(devc), 0); /* Clear pending interrupts */ if (name != NULL && name[0] != 0) - snprintf(ad1848_pcm_operations[nr_ad1848_devs].name, - sizeof(ad1848_pcm_operations[nr_ad1848_devs].name), - "%s (%s)", name, devc->chip_name); + sprintf(ad1848_pcm_operations[nr_ad1848_devs].name, + "%s (%s)", name, devc->chip_name); else - snprintf(ad1848_pcm_operations[nr_ad1848_devs].name, - sizeof(ad1848_pcm_operations[nr_ad1848_devs].name), - "Generic audio codec (%s)", devc->chip_name); + sprintf(ad1848_pcm_operations[nr_ad1848_devs].name, + "Generic audio codec (%s)", devc->chip_name); conf_printf2(ad1848_pcm_operations[nr_ad1848_devs].name, devc->base, devc->irq, dma_playback, dma_capture); diff --git a/sys/i386/isa/sound/audio.c b/sys/i386/isa/sound/audio.c index d92dd49dc1645..31f952ea10fa9 100644 --- a/sys/i386/isa/sound/audio.c +++ b/sys/i386/isa/sound/audio.c @@ -57,6 +57,15 @@ static char *wr_dma_buf[MAX_AUDIO_DEV]; static int audio_format[MAX_AUDIO_DEV]; static int local_conversion[MAX_AUDIO_DEV]; +#if defined(NO_INLINE_ASM) || !defined(__i386__) +static void +translate_bytes(const u_char *table, u_char *buff, int n); + +#else +extern __inline void +translate_bytes(const void *table, void *buff, int n); +#endif + static int set_format(int dev, int fmt) { @@ -139,6 +148,7 @@ audio_release(int dev, struct fileinfo * file) } +#if defined(NO_INLINE_ASM) || !defined(__i386__) static void translate_bytes(const u_char *table, u_char *buff, int n) { @@ -151,6 +161,23 @@ translate_bytes(const u_char *table, u_char *buff, int n) buff[i] = table[buff[i]]; } +#else +extern __inline void +translate_bytes(const void *table, void *buff, int n) +{ + if (n > 0) { + __asm__("cld\n" + "1:\tlodsb\n\t" + "xlatb\n\t" + "stosb\n\t" + "loop 1b\n\t": + :"b"(table), "c"(n), "D"(buff), "S"(buff) + :"bx", "cx", "di", "si", "ax"); + } +} + +#endif + int audio_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count) { diff --git a/sys/i386/isa/sound/dmabuf.c b/sys/i386/isa/sound/dmabuf.c index 76494ad8dc686..613e30b862e5e 100644 --- a/sys/i386/isa/sound/dmabuf.c +++ b/sys/i386/isa/sound/dmabuf.c @@ -331,6 +331,7 @@ static int dma_sync(int dev) { u_long flags; + int i = 0; if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT)) return 0; @@ -1154,6 +1155,8 @@ DMAbuf_outputintr(int dev, int event_type) if (dmap->mapping_flags & DMA_MAP_MAPPED) { /* mmapped access */ + int p = dmap->fragment_size * dmap->qhead; + dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; dmap->qlen++; /* Yes increment it (don't decrement) */ dmap->flags &= ~DMA_ACTIVE; diff --git a/sys/i386/isa/sound/gus_wave.c b/sys/i386/isa/sound/gus_wave.c index 54d36cb531f0b..9b3ab0b48b4fc 100644 --- a/sys/i386/isa/sound/gus_wave.c +++ b/sys/i386/isa/sound/gus_wave.c @@ -4517,11 +4517,9 @@ gus_wave_init(struct address_info * hw_config) } if (gus_pnp_seen) { - snprintf(gus_info.name, sizeof(gus_info.name), - "Gravis %s (%dk)", model_num, (int) gus_mem_size / 1024); + sprintf(gus_info.name, "Gravis %s (%dk)", model_num, (int) gus_mem_size / 1024); } else { - snprintf(gus_info.name, sizeof(gus_info.name), - "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); + sprintf(gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024); } conf_printf(gus_info.name, hw_config); diff --git a/sys/i386/isa/sound/mmap_test.c b/sys/i386/isa/sound/mmap_test.c index c6afae932d470..62de9dfed648c 100644 --- a/sys/i386/isa/sound/mmap_test.c +++ b/sys/i386/isa/sound/mmap_test.c @@ -15,7 +15,7 @@ #ifndef lint static const char rcsid[] = - "$Id: mmap_test.c,v 1.2 1998/01/16 07:20:34 charnier Exp $"; + "$Id$"; #endif /* not lint */ #include <err.h> diff --git a/sys/i386/isa/sound/mpu401.c b/sys/i386/isa/sound/mpu401.c index 0bd1412b7b9e9..fdfb94d0b36d0 100644 --- a/sys/i386/isa/sound/mpu401.c +++ b/sys/i386/isa/sound/mpu401.c @@ -1002,8 +1002,7 @@ attach_mpu401(struct address_info * hw_config) MPU_CAP_CLS | MPU_CAP_2PORT; revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - snprintf(mpu_synth_info[num_midis].name, - sizeof(mpu_synth_info[num_midis].name), + sprintf(mpu_synth_info[num_midis].name, "MQX-%d%c MIDI Interface #%d", ports, revision_char, @@ -1016,8 +1015,7 @@ attach_mpu401(struct address_info * hw_config) devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - snprintf(mpu_synth_info[num_midis].name, - sizeof(mpu_synth_info[num_midis].name), + sprintf(mpu_synth_info[num_midis].name, "MPU-401 %d.%d%c Midi interface #%d", (int) (devc->version & 0xf0) >> 4, devc->version & 0x0f, diff --git a/sys/i386/isa/sound/pas2_card.c b/sys/i386/isa/sound/pas2_card.c index dc78afa5cea70..06ab9f2e38c13 100644 --- a/sys/i386/isa/sound/pas2_card.c +++ b/sys/i386/isa/sound/pas2_card.c @@ -325,7 +325,7 @@ attach_pas_card(struct address_info * hw_config) if ((pas_model = pas_read(CHIP_REV))) { char temp[100]; - snprintf(temp, sizeof(temp), + sprintf(temp, "%s rev %d", pas_model_names[(int) pas_model], pas_read(BOARD_REV_ID)); conf_printf(temp, hw_config); diff --git a/sys/i386/isa/sound/patmgr.c b/sys/i386/isa/sound/patmgr.c index 752b2e95dedda..60f0ed639d905 100644 --- a/sys/i386/isa/sound/patmgr.c +++ b/sys/i386/isa/sound/patmgr.c @@ -181,7 +181,7 @@ pmgr_access(int dev, struct patmgr_info * rec) if (mbox[dev]) printf(" PATMGR: Server %d mbox full. Why?\n", dev); else { - int chn; + int flag, chn; rec->key = PM_K_COMMAND; mbox[dev] = rec; @@ -235,7 +235,7 @@ pmgr_inform(int dev, int event, u_long p1, u_long p2, u_long p3, u_long p4) if (mbox[dev]) printf(" PATMGR: Server %d mbox full. Why?\n", dev); else { - int chn; + int flag, chn; mbox[dev] = tmp_mbox; mbox[dev]->key = PM_K_EVENT; diff --git a/sys/i386/isa/sound/pcm86.c b/sys/i386/isa/sound/pcm86.c index 9c16d9a44928e..0df86b1d31a9e 100644 --- a/sys/i386/isa/sound/pcm86.c +++ b/sys/i386/isa/sound/pcm86.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pcm86.c,v 1.5 1998/12/04 22:54:50 archie Exp $ + * $Id: pcm86.c,v 1.3 1997/02/22 09:38:14 peter Exp $ */ /* @@ -1890,8 +1890,7 @@ pcm86_detect(struct address_info *hw_config) outb(opna_iobase + 2, 0x30); /* Ok. Detection finished. */ - snprintf(pcm86_operations.name, sizeof(pcm86_operations.name), - "%s", board_name[pcm_s.board_type]); + sprintf(pcm86_operations.name, board_name[pcm_s.board_type]); pcm_initialized = NO; pcm_s.irq = irq; diff --git a/sys/i386/isa/sound/pss.c b/sys/i386/isa/sound/pss.c index a6a5b65b14499..17acfb2b41725 100644 --- a/sys/i386/isa/sound/pss.c +++ b/sys/i386/isa/sound/pss.c @@ -348,7 +348,7 @@ attach_pss(struct address_info * hw_config) #endif pss_initialized = 1; - snprintf(tmp, sizeof(tmp), "ECHO-PSS Rev. %d", id); + sprintf(tmp, "ECHO-PSS Rev. %d", id); conf_printf(tmp, hw_config); return; diff --git a/sys/i386/isa/sound/sb16_dsp.c b/sys/i386/isa/sound/sb16_dsp.c index e923176ed8753..ad9be54032ce8 100644 --- a/sys/i386/isa/sound/sb16_dsp.c +++ b/sys/i386/isa/sound/sb16_dsp.c @@ -197,6 +197,8 @@ sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local) static int sb16_dsp_open(int dev, int mode) { + int retval; + DEB(printf("sb16_dsp_open()\n")); if (!sb16_dsp_ok) { @@ -448,8 +450,8 @@ sb16_dsp_init(struct address_info * hw_config) if (sbc_major < 4) return; /* Not a SB16 */ - snprintf(sb16_dsp_operations.name, sizeof(sb16_dsp_operations.name), - "SoundBlaster 16 %d.%d", sbc_major, sbc_minor); + sprintf(sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", + sbc_major, sbc_minor); conf_printf(sb16_dsp_operations.name, hw_config); diff --git a/sys/i386/isa/sound/sb_dsp.c b/sys/i386/isa/sound/sb_dsp.c index 2facd331139f0..1cf52c5369954 100644 --- a/sys/i386/isa/sound/sb_dsp.c +++ b/sys/i386/isa/sound/sb_dsp.c @@ -539,6 +539,8 @@ sb_dsp_halt_xfer(int dev) static int sb_dsp_open(int dev, int mode) { + int retval; + if (!sb_dsp_ok) { printf("SB Error: SoundBlaster board not installed\n"); return -(ENXIO); @@ -1079,8 +1081,7 @@ sb_dsp_init(struct address_info * hw_config) fmt = "SoundBlaster %d.%d" ; } - snprintf(sb_dsp_operations.name, sizeof(sb_dsp_operations.name), - fmt, sbc_major, sbc_minor); + sprintf(sb_dsp_operations.name, fmt, sbc_major, sbc_minor); conf_printf(sb_dsp_operations.name, hw_config); #if defined(CONFIG_SB16) && defined(CONFIG_SBPRO) diff --git a/sys/i386/isa/sound/sequencer.c b/sys/i386/isa/sound/sequencer.c index 4990774833817..3639cf6f15c50 100644 --- a/sys/i386/isa/sound/sequencer.c +++ b/sys/i386/isa/sound/sequencer.c @@ -157,7 +157,7 @@ sequencer_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count) flags = splhigh(); if (!iqlen) { - int chn; + int flag, chn; midi_sleeper = &chn; diff --git a/sys/i386/isa/sound/sound.doc b/sys/i386/isa/sound/sound.doc index 2340d6079c185..0b43822fa3828 100644 --- a/sys/i386/isa/sound/sound.doc +++ b/sys/i386/isa/sound/sound.doc @@ -1,4 +1,4 @@ -$Id: sound.doc,v 1.9 1998/10/22 15:37:35 bde Exp $ +$Id$ Instructions on using audio on a FreeBSD 2.1 (or 2.0-current) system. See also /sys/i386/conf/LINT. @@ -14,10 +14,10 @@ Uncomment one or more of these device entries, depending on what type of sound card you have: # ProAudioSpectrum PCM and Midi - for PAS -#device pas0 at isa? port 0x388 irq 10 drq 6 +#device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr # SoundBlaster DSP driver - for SB, SB Pro, SB16, PAS(emulating SB) -#device sb0 at isa? port 0x220 irq 7 drq 1 +#device sb0 at isa? port 0x220 irq 7 drq 1 vector sbintr # SoundBlaster 16 DSP driver - for SB16 - requires sb0 device #device sbxvi0 at isa? drq 5 @@ -28,13 +28,13 @@ sound card you have: # Gravis UltraSound - for GUS, GUS16, GUSMAX # For cards that use 2 DMA Channels: # drq = Write DMA Channel, flags = Read DMA Channel -#device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 +#device gus0 at isa? port 0x220 irq 11 drq 1 flags 0x3 vector gusintr # Gravis UltraSound 16 bit option - for GUS16 - requires gus0 -#device gusxvi0 at isa? port 0x530 irq 7 drq 3 +#device gusxvi0 at isa? port 0x530 irq 7 drq 3 vector adintr # MS Sound System (AD1848 Based Boards) -#device mss0 at isa? port 0x530 irq 10 drq 1 +#device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr # Yamaha OPL-2/OPL-3 FM - for SB, SB Pro, SB16, PAS #device opl0 at isa? port 0x388 @@ -43,7 +43,7 @@ sound card you have: #device mpu0 at isa? port 0x330 irq 6 drq 0 # 6850 UART Midi -#device uart0 at isa? port 0x330 irq 5 +#device uart0 at isa? port 0x330 irq 5 vector "m6850intr" You may add one or more of the following depending on what you do and don't want compiled into your kernel. Note: Excluding things with EXCLUDE_... diff --git a/sys/i386/isa/sound/sound_calls.h b/sys/i386/isa/sound/sound_calls.h index cb00e30926a3a..62d95487e6894 100644 --- a/sys/i386/isa/sound/sound_calls.h +++ b/sys/i386/isa/sound/sound_calls.h @@ -99,7 +99,6 @@ int sb_dsp_detect (struct address_info *hw_config); void sb_dsp_init (struct address_info *hw_config); void sb_dsp_disable_midi(void); int sb_dsp_command (u_char val); -ointhand2_t sbintr; int sb_reset_dsp (void); /* From sb16_dsp.c */ @@ -141,7 +140,6 @@ int probe_adlib(struct address_info *hw_config); /* From pas_card.c */ void attach_pas_card(struct address_info *hw_config); int probe_pas(struct address_info *hw_config); -ointhand2_t pasintr; int pas_set_intr(int mask); int pas_remove_intr(int mask); u_char pas_read(int ioaddr); @@ -162,7 +160,7 @@ void pas_midi_interrupt(void); void attach_gus_card(struct address_info * hw_config); int probe_gus(struct address_info *hw_config); int gus_set_midi_irq(int num); -ointhand2_t gusintr; +/*void gusintr(int irq); */ void attach_gus_db16(struct address_info * hw_config); int probe_gus_db16(struct address_info *hw_config); @@ -188,7 +186,6 @@ void mpuintr(int irq); /* From uart6850.c */ void attach_uart6850(struct address_info * hw_config); -ointhand2_t m6850intr; int probe_uart6850(struct address_info *hw_config); /* From opl3.c */ @@ -212,7 +209,6 @@ void sound_timer_syncinterval(u_int new_usecs); /* From ad1848.c */ void ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, sound_os_info *osp); -ointhand2_t adintr; int ad1848_detect (int io_base, int *flags, sound_os_info *osp); #define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */ @@ -237,7 +233,6 @@ int probe_sscape (struct address_info *hw_config); void attach_sscape (struct address_info *hw_config); int probe_ss_mss(struct address_info *hw_config); void attach_ss_mss(struct address_info * hw_config); -ointhand2_t sscapeintr; int pss_read (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); int pss_write (int dev, struct fileinfo *file, snd_rw_buf *buf, int count); diff --git a/sys/i386/isa/sound/sound_timer.c b/sys/i386/isa/sound/sound_timer.c index cef7596f0962e..8450b2d73503d 100644 --- a/sys/i386/isa/sound/sound_timer.c +++ b/sys/i386/isa/sound/sound_timer.c @@ -335,7 +335,7 @@ sound_timer_init(struct sound_lowlev_timer * t, char *name) else n = num_sound_timers++; - snprintf(sound_timer.info.name, sizeof(sound_timer.info.name), "%s", name); + strcpy(sound_timer.info.name, name); sound_timer_devs[n] = &sound_timer; } diff --git a/sys/i386/isa/sound/soundcard.c b/sys/i386/isa/sound/soundcard.c index 3b6db0be26e53..52428b404e337 100644 --- a/sys/i386/isa/sound/soundcard.c +++ b/sys/i386/isa/sound/soundcard.c @@ -34,8 +34,6 @@ #endif /* DEVFS */ #if NSND > 0 /* from "snd.h" */ -#include "uart.h" - #include <vm/vm.h> #include <vm/pmap.h> #include <sys/mman.h> @@ -132,8 +130,6 @@ struct isa_driver sscape_mssdriver = {sndprobe, sndattach, "sscape_mss"}; short ipri_to_irq(u_short ipri); -static ointhand2_t sndintr; - u_long get_time(void) { @@ -147,6 +143,7 @@ get_time(void) static int sndmmap( dev_t dev, int offset, int nprot ) { + int unit; struct dma_buffparms * dmap; dev = minor(dev) >> 4; @@ -399,41 +396,8 @@ sndattach(struct isa_device * dev) static int midi_initialized = 0; static int seq_initialized = 0; struct address_info hw_config; - char *dname; void *tmp; - - /* - * Associate interrupt handlers with devices. XXX this may be incomplete. - */ - dname = dev->id_driver->name; -#if defined(CONFIG_AD1848) - if (strcmp(dname, "css") == 0 || strcmp(dname, "gusxvi") == 0 || - strcmp(dname, "mss") == 0) - dev->id_ointr = adintr; -#endif -#ifdef CONFIG_GUS - if (strcmp(dname, "gus") == 0) - dev->id_ointr = gusintr; -#endif -#ifdef CONFIG_PAS - if (strcmp(dname, "pas") == 0) - dev->id_ointr = pasintr; -#endif -#if NSB > 0 && (defined(CONFIG_MIDI) || defined(CONFIG_AUDIO)) - if (strcmp(dname, "sb") == 0) - dev->id_ointr = sbintr; -#endif - if (strcmp(dname, "sscape_mss") == 0) - dev->id_ointr = sndintr; -#if NSSCAPE > 0 - if (strcmp(dname, "sscape") == 0 || strcmp(dname, "trix") == 0) - dev->id_ointr = sscapeintr; -#endif -#if NUART > 0 - if (strcmp(dname, "uart0") == 0) - dev->id_ointr = m6850intr; -#endif - + unit = driver_to_voxunit(dev->id_driver); hw_config.io_base = dev->id_iobase; hw_config.irq = ipri_to_irq(dev->id_irq); @@ -499,35 +463,35 @@ sndattach(struct isa_device * dev) tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_SEQ, DV_CHR, UID_SND, GID_SND, PERM_SND, "sequencer%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "sequencer"); + if (tmp) devfs_link(tmp, "sequencer"); } else if (dev->id_driver == &mpudriver || dev->id_driver == &sbmididriver || dev->id_driver == &uartdriver){ tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_MIDIN, DV_CHR, UID_SND, GID_SND, PERM_SND, "midi%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "midi"); + if (tmp) devfs_link(tmp, "midi"); } else { tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP, DV_CHR, UID_SND, GID_SND, PERM_SND, "dsp%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "dsp"); + if (tmp) devfs_link(tmp, "dsp"); tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP16, DV_CHR, UID_SND, GID_SND, PERM_SND, "dspW%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "dspW"); + if (tmp) devfs_link(tmp, "dspW"); tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_AUDIO, DV_CHR, UID_SND, GID_SND, PERM_SND, "audio%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "audio"); + if (tmp) devfs_link(tmp, "audio"); tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_CTL, DV_CHR, UID_SND, GID_SND, PERM_SND, "mixer%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "mixer"); + if (tmp) devfs_link(tmp, "mixer"); tmp = devfs_add_devswf(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_STATUS, DV_CHR, UID_SND, GID_SND, PERM_SND, "sndstat%r", dev->id_unit); - if (tmp) devfs_makelink(tmp, "sndstat"); + if (tmp) devfs_link(tmp, "sndstat"); } #endif /* DEVFS */ return TRUE; @@ -612,7 +576,7 @@ snd_set_irq_handler(int int_lvl, void (*hndlr) (int), sound_os_info * osp) return 1; } -static void +void sndintr(int unit) { if ( (unit >= MAX_UNIT) || (irq_proc[unit] == NULL) ) diff --git a/sys/i386/isa/sound/sscape.c b/sys/i386/isa/sound/sscape.c index 28ef04467bcdd..bfd5abe8afd10 100644 --- a/sys/i386/isa/sound/sscape.c +++ b/sys/i386/isa/sound/sscape.c @@ -292,6 +292,7 @@ void sscapeintr(int irq) { u_char bits, tmp; + static int debug = 0; DEB(printf("sscapeintr(0x%02x)\n", (bits = sscape_read(devc, GA_INTSTAT_REG)))); if ((sscape_sleep_flag.mode & WK_SLEEP)) { @@ -303,8 +304,6 @@ sscapeintr(int irq) } #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) if (bits & 0x01) { - static int debug = 0; - mpuintr(irq); if (debug++ > 10) { /* Temporary debugging hack */ sscape_write(devc, GA_INTENA_REG, 0x00); /* Disable all interr. */ @@ -455,6 +454,7 @@ sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int fla done = 0; timeout_val = 100; while (!done && timeout_val-- > 0) { + int resid; int chn; sscape_sleeper = &chn; DO_SLEEP(chn, sscape_sleep_flag, 1); @@ -733,8 +733,6 @@ sscape_audio_reset(int dev) sscape_audio_halt(dev); } - -#if !defined(EXCLUDE_NATIVE_PCM) && defined(CONFIG_AUDIO) static struct audio_operations sscape_audio_operations = { "Not functional", @@ -753,13 +751,14 @@ static struct audio_operations sscape_audio_operations = NULL, NULL }; -#endif /* !defined(EXCLUDE_NATIVE_PCM) && defined(CONFIG_AUDIO) */ static int sscape_detected = 0; void attach_sscape(struct address_info * hw_config) { + int my_dev; + #ifndef SSCAPE_REGS /* * Config register values for Spea/V7 Media FX and Ensoniq S-2000. @@ -878,8 +877,6 @@ attach_sscape(struct address_info * hw_config) #ifdef CONFIG_AUDIO if (num_audiodevs < MAX_AUDIO_DEV) { - int my_dev; - audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations; audio_devs[my_dev]->dmachan1 = hw_config->dma; audio_devs[my_dev]->buffsize = DSP_BUFFSIZE; diff --git a/sys/i386/isa/spigot.c b/sys/i386/isa/spigot.c index e0f33a79f6652..50aebba2f18ca 100644 --- a/sys/i386/isa/spigot.c +++ b/sys/i386/isa/spigot.c @@ -107,8 +107,6 @@ static struct cdevsw spigot_cdevsw = spigot_ioctl, nostop, nullreset, nodevtotty,/* Spigot */ seltrue, spigot_mmap, NULL, "spigot", NULL, -1 }; -static ointhand2_t spigintr; - static int spigot_probe(struct isa_device *devp) { @@ -135,7 +133,6 @@ spigot_attach(struct isa_device *devp) int unit; struct spigot_softc *ss= &spigot_softc[unit = devp->id_unit]; - devp->id_ointr = spigintr; ss->maddr = kvtop(devp->id_maddr); ss->irq = devp->id_irq; #ifdef DEVFS @@ -249,7 +246,7 @@ struct spigot_info *info; * Interrupt procedure. * Just call a user level interrupt routine. */ -static void +void spigintr(int unit) { struct spigot_softc *ss = (struct spigot_softc *)&spigot_softc[unit]; @@ -259,7 +256,7 @@ struct spigot_softc *ss = (struct spigot_softc *)&spigot_softc[unit]; } static int -spigot_mmap(dev_t dev, vm_offset_t offset, int nprot) +spigot_mmap(dev_t dev, int offset, int nprot) { struct spigot_softc *ss = (struct spigot_softc *)&spigot_softc[0]; diff --git a/sys/i386/isa/stallion.c b/sys/i386/isa/stallion.c index e6697a17aaa1b..f85ae2eb26842 100644 --- a/sys/i386/isa/stallion.c +++ b/sys/i386/isa/stallion.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: stallion.c,v 1.23 1998/10/22 05:58:40 bde Exp $ + * $Id: stallion.c,v 1.21 1998/08/23 08:26:41 bde Exp $ */ /*****************************************************************************/ @@ -467,7 +467,6 @@ static int stl_brdinit(stlbrd_t *brdp); static int stl_initeio(stlbrd_t *brdp); static int stl_initech(stlbrd_t *brdp); static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); -static ointhand2_t stlintr; static __inline void stl_txisr(stlpanel_t *panelp, int ioaddr); static __inline void stl_rxisr(stlpanel_t *panelp, int ioaddr); static __inline void stl_mdmisr(stlpanel_t *panelp, int ioaddr); @@ -491,7 +490,7 @@ static int stl_clrportstats(stlport_t *portp, caddr_t data); static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); #if NPCI > 0 -static const char *stlpciprobe(pcici_t tag, pcidi_t type); +static char *stlpciprobe(pcici_t tag, pcidi_t type); static void stlpciattach(pcici_t tag, int unit); static void stlpciintr(void * arg); #endif @@ -635,8 +634,6 @@ static int stlattach(struct isa_device *idp) idp->id_unit, idp->id_iobase); #endif - idp->id_ointr = stlintr; - brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT); if (brdp == (stlbrd_t *) NULL) { printf("STALLION: failed to allocate memory (size=%d)\n", @@ -673,7 +670,7 @@ static int stlattach(struct isa_device *idp) * carefull here, since it looks sort like a Nat Semi IDE chip... */ -static const char *stlpciprobe(pcici_t tag, pcidi_t type) +char *stlpciprobe(pcici_t tag, pcidi_t type) { unsigned long class; @@ -1761,7 +1758,7 @@ static __inline void stl_mdmisr(stlpanel_t *panelp, int ioaddr) * io register. */ -static void stlintr(int unit) +void stlintr(int unit) { stlbrd_t *brdp; stlpanel_t *panelp; diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c new file mode 100644 index 0000000000000..eba0d36dc0abd --- /dev/null +++ b/sys/i386/isa/syscons.c @@ -0,0 +1,4688 @@ +/*- + * Copyright (c) 1992-1998 Søren 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. + * 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: syscons.c,v 1.283 1998/10/01 11:39:18 yokota Exp $ + */ + +#include "sc.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 +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/reboot.h> +#include <sys/conf.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/tty.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#include <machine/bootinfo.h> +#include <machine/clock.h> +#include <machine/cons.h> +#include <machine/console.h> +#include <machine/mouse.h> +#include <machine/md_var.h> +#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 <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.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/videoio.h> +#include <i386/isa/syscons.h> + +#if !defined(MAXCONS) +#define MAXCONS 16 +#endif + +#if !defined(SC_MAX_HISTORY_SIZE) +#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS) +#endif + +#if !defined(SC_HISTORY_SIZE) +#define SC_HISTORY_SIZE (ROW * 4) +#endif + +#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE +#undef SC_MAX_HISTORY_SIZE +#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS) +#endif + +#if !defined(SC_MOUSE_CHAR) +#define SC_MOUSE_CHAR (0xd0) +#endif + +#define COLD 0 +#define WARM 1 + +#define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ +#define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ + +/* for backward compatibility */ +#define OLD_CONS_MOUSECTL _IOWR('c', 10, old_mouse_info_t) + +typedef struct old_mouse_data { + int x; + int y; + int buttons; +} old_mouse_data_t; + +typedef struct old_mouse_info { + int operation; + union { + struct old_mouse_data data; + struct mouse_mode mode; + } u; +} old_mouse_info_t; + +/* XXX use sc_bcopy where video memory is concerned */ +extern void generic_bcopy(const void *, void *, size_t); +extern void generic_bzero(void *, size_t); + +static default_attr user_default = { + (FG_LIGHTGREY | BG_BLACK) << 8, + (FG_BLACK | BG_LIGHTGREY) << 8 +}; + +static default_attr kernel_default = { + (FG_WHITE | BG_BLACK) << 8, + (FG_BLACK | BG_LIGHTGREY) << 8 +}; + +static scr_stat main_console; +static scr_stat *console[MAXCONS]; +#ifdef DEVFS +static void *sc_devfs_token[MAXCONS]; +static void *sc_mouse_devfs_token; +static void *sc_console_devfs_token; +#endif + scr_stat *cur_console; +static scr_stat *new_scp, *old_scp; +static term_stat kernel_console; +static default_attr *current_default; +static int sc_flags; +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; +static char font_loading_in_progress = FALSE; +static char switch_in_progress = FALSE; +static char write_in_progress = FALSE; +static char blink_in_progress = FALSE; +static int blinkrate = 0; + u_int crtc_addr = MONO_BASE; + char crtc_type = KD_MONO; +static char crtc_vga = FALSE; +static int adp_flags; +static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; +static u_char accents = 0; +static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; +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 */ + 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 */ + u_char scr_map[256]; + u_char scr_rmap[256]; +static int initial_video_mode; /* initial video mode # */ +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]; +#ifdef STD8X16FONT +extern +#endif + u_char font_16[256*16]; + u_char palette[256*3]; +static u_char *cut_buffer; +static int cut_buffer_size; +static int mouse_level; /* sysmouse protocol level */ +static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; +static u_short mouse_and_mask[16] = { + 0xc000, 0xe000, 0xf000, 0xf800, + 0xfc00, 0xfe00, 0xff00, 0xff80, + 0xfe00, 0x1e00, 0x1f00, 0x0f00, + 0x0f00, 0x0000, 0x0000, 0x0000 + }; +static u_short mouse_or_mask[16] = { + 0x0000, 0x4000, 0x6000, 0x7000, + 0x7800, 0x7c00, 0x7e00, 0x6800, + 0x0c00, 0x0c00, 0x0600, 0x0600, + 0x0000, 0x0000, 0x0000, 0x0000 + }; + + int sc_history_size = SC_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; +static void (*default_saver)(int blank) = none_saver; + d_ioctl_t *sc_user_ioctl; + +static int sticky_splash = FALSE; + +/* OS specific stuff */ +#ifdef not_yet_done +#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) +struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) +struct MOUSE_TTY (sccons[MAXCONS+1] = ttymalloc(sccons[MAXCONS+1])) +struct tty *sccons[MAXCONS+2]; +#else +#define VIRTUAL_TTY(x) &sccons[x] +#define CONSOLE_TTY &sccons[MAXCONS] +#define MOUSE_TTY &sccons[MAXCONS+1] +static struct tty sccons[MAXCONS+2]; +#endif +#define SC_MOUSE 128 +#define SC_CONSOLE 255 +u_short *Crtat; +static const int nsccons = MAXCONS+2; + +#define WRAPHIST(scp, pointer, offset)\ + ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ + + (offset)) % (scp)->history_size)) +#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) + +/* prototypes */ +static int scattach(struct isa_device *dev); +static int scparam(struct tty *tp, struct termios *t); +static int scprobe(struct isa_device *dev); +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(u_int flags); +#define SCGETC_CN 1 +#define SCGETC_NONBLOCK 2 +static void sccnupdate(scr_stat *scp); +static scr_stat *alloc_scp(void); +static void init_scp(scr_stat *scp); +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); +static void scrn_saver(void (*saver)(int), int blank); +static void stop_scrn_saver(void (*saver)(int)); +static int wait_scrn_saver_stop(void); +static int switch_scr(scr_stat *scp, u_int next_scr); +static void exchange_scr(void); +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 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 void set_keyboard(int command, int data); +static void update_leds(int which); +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); +static int skip_spc_left(scr_stat *scp, u_short *p); +static void mouse_cut(scr_stat *scp); +static void mouse_cut_start(scr_stat *scp); +static void mouse_cut_end(scr_stat *scp); +static void mouse_cut_word(scr_stat *scp); +static void mouse_cut_line(scr_stat *scp); +static void mouse_cut_extend(scr_stat *scp); +static void mouse_paste(scr_stat *scp); +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 do_bell(scr_stat *scp, int pitch, int duration); +static timeout_t blink_screen; +#ifdef SC_SPLASH_SCREEN +static void scsplash_init(scr_stat *scp); +static void scsplash_term(scr_stat *scp); +static void scsplash_saver(int show); +#define scsplash_stick(stick) (sticky_splash = (stick)) +#else +#define scsplash_stick(stick) +#endif + +struct isa_driver scdriver = { + scprobe, scattach, "sc", 1 +}; + +static d_open_t scopen; +static d_close_t scclose; +static d_read_t scread; +static d_write_t scwrite; +static d_ioctl_t scioctl; +static d_mmap_t scmmap; + +#define CDEV_MAJOR 12 +static struct cdevsw sc_cdevsw = { + scopen, scclose, scread, scwrite, + scioctl, nullstop, noreset, scdevtotty, + ttpoll, scmmap, nostrategy, "sc", + NULL, -1, nodump, nopsize, + D_TTY, +}; + +static void +draw_cursor_image(scr_stat *scp) +{ + u_short cursor_image; + u_short *ptr; + u_short prev_image; + + if (ISPIXELSC(scp)) { + sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, + scp->cursor_pos - scp->scr_buf, 1); + return; + } + + ptr = (u_short *)(get_adapter(scp)->va_window) + + (scp->cursor_pos - scp->scr_buf); + + /* do we have a destructive cursor ? */ + if (sc_flags & CHAR_CURSOR) { + prev_image = scp->cursor_saveunder; + cursor_image = *ptr & 0x00ff; + if (cursor_image == DEAD_CHAR) + cursor_image = prev_image & 0x00ff; + cursor_image |= *(scp->cursor_pos) & 0xff00; + scp->cursor_saveunder = cursor_image; + /* update the cursor bitmap if the char under the cursor has changed */ + if (prev_image != cursor_image) + set_destructive_cursor(scp); + /* modify cursor_image */ + if (!(sc_flags & BLINK_CURSOR)||((sc_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 + * the cursor hasn't changed, because the mouse pionter may + * have moved by a few dots within the cursor cel. + */ + if ((prev_image == cursor_image) + && (cursor_image != *(scp->cursor_pos))) + set_destructive_cursor(scp); + cursor_image &= 0xff00; + cursor_image |= DEAD_CHAR; + } + } 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 ((cursor_image & 0x7000) == 0x7000) { + cursor_image &= 0x8fff; + if(!(cursor_image & 0x0700)) + cursor_image |= 0x0700; + } else { + cursor_image |= 0x7000; + if ((cursor_image & 0x0700) == 0x0700) + cursor_image &= 0xf0ff; + } + } + } + *ptr = cursor_image; +} + +static void +remove_cursor_image(scr_stat *scp) +{ + if (ISPIXELSC(scp)) + sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, + scp->cursor_oldpos - scp->scr_buf, 0); + else + *((u_short *)(get_adapter(scp)->va_window) + + (scp->cursor_oldpos - scp->scr_buf)) + = scp->cursor_saveunder; +} + +static void +move_crsr(scr_stat *scp, int x, int y) +{ + if (x < 0) + x = 0; + if (y < 0) + y = 0; + if (x >= scp->xsize) + x = scp->xsize-1; + if (y >= scp->ysize) + y = scp->ysize-1; + scp->xpos = x; + scp->ypos = y; + scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; +} + +static int +scprobe(struct isa_device *dev) +{ + if (!scvidprobe(dev->id_unit, dev->id_flags)) { + if (bootverbose) + printf("sc%d: no video adapter is found.\n", dev->id_unit); + return (0); + } + +#if defined(VESA) && defined(VM86) + if (vesa_load()) + return FALSE; +#endif + + (*biosvidsw.diag)(bootverbose); + + 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) +{ + video_adapter_t *adp; + + /* do this test only once */ + if (init_done != COLD) + return (crtc_type != -1); + + if ((*biosvidsw.init)() <= 0) + return FALSE; + if ((adp = (*biosvidsw.adapter)(V_ADP_PRIMARY)) == NULL) + return FALSE; + + crtc_type = adp->va_type; + crtc_vga = (crtc_type == KD_VGA); + crtc_addr = adp->va_crtc_addr; + Crtat = (u_short *)adp->va_window; + adp_flags = adp->va_flags; + initial_video_mode = adp->va_initial_mode; + bios_video_mode = adp->va_initial_bios_mode; + + return TRUE; +} + +/* probe the keyboard, return TRUE if found */ +static int +sckbdprobe(int unit, int flags) +{ + int codeset; + int c = -1; + int m; + int res, id; + + sc_kbdc = kbdc_open(sc_port); + + if (!kbdc_lock(sc_kbdc, TRUE)) { + /* driver error? */ + printf("sc%d: unable to lock the controller.\n", unit); + return ((flags & DETECT_KBD) ? FALSE : TRUE); + } + + /* flush any noise in the buffer */ + 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); + } + + kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), + kbdc_lock(sc_kbdc, FALSE); + return TRUE; + +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; +} + +#if NAPM > 0 +static int +scresume(void *dummy) +{ + shfts = ctls = alts = agrs = metas = accents = 0; + return 0; +} +#endif + +static int +scattach(struct isa_device *dev) +{ + scr_stat *scp; + video_info_t info; + dev_t cdev = makedev(CDEV_MAJOR, 0); +#ifdef DEVFS + int vc; +#endif + + scinit(); + sc_flags = dev->id_flags; + if (!ISFONTAVAIL(adp_flags)) + sc_flags &= ~CHAR_CURSOR; + + scp = console[0]; + + /* copy temporary buffer to final buffer */ + scp->scr_buf = NULL; + sc_alloc_scr_buffer(scp, FALSE, FALSE); + bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); + + /* cut buffer is available only when the mouse pointer is used */ + if (ISMOUSEAVAIL(adp_flags)) + sc_alloc_cut_buffer(scp, FALSE); + + /* initialize history buffer & pointers */ + sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); + +#if defined(VESA) && defined(VM86) + if ((sc_flags & VESA800X600) + && ((*biosvidsw.get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { +#ifdef SC_SPLASH_SCREEN + scsplash_term(scp); +#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; +#ifdef SC_SPLASH_SCREEN + scsplash_init(scp); +#endif + } +#endif /* VESA && VM86 */ + + /* initialize cursor stuff */ + if (!ISGRAPHSC(scp)) + draw_cursor_image(scp); + + /* get screen update going */ + scrn_timer((void *)TRUE); + + update_leds(scp->status); + + printf("sc%d: ", dev->id_unit); + switch(crtc_type) { + case KD_VGA: + printf("VGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); + break; + case KD_EGA: + printf("EGA %s", (adp_flags & V_ADP_COLOR) ? "color" : "mono"); + break; + case KD_CGA: + printf("CGA"); + break; + case KD_MONO: + case KD_HERCULES: + default: + printf("MDA/Hercules"); + break; + } + printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags); + +#if NAPM > 0 + scp->r_hook.ah_fun = scresume; + scp->r_hook.ah_arg = NULL; + scp->r_hook.ah_name = "system keyboard"; + scp->r_hook.ah_order = APM_MID_ORDER; + apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); +#endif + + at_shutdown(scshutdown, NULL, SHUTDOWN_PRE_SYNC); + + cdevsw_add(&cdev, &sc_cdevsw, NULL); + +#ifdef DEVFS + for (vc = 0; vc < MAXCONS; vc++) + sc_devfs_token[vc] = devfs_add_devswf(&sc_cdevsw, vc, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc); + sc_mouse_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_MOUSE, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, "sysmouse"); + sc_console_devfs_token = devfs_add_devswf(&sc_cdevsw, SC_CONSOLE, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, "consolectl"); +#endif + return 0; +} + +struct tty +*scdevtotty(dev_t dev) +{ + int unit = minor(dev); + + if (init_done == COLD) + return(NULL); + if (unit == SC_CONSOLE) + return CONSOLE_TTY; + if (unit == SC_MOUSE) + return MOUSE_TTY; + if (unit >= MAXCONS || unit < 0) + return(NULL); + return VIRTUAL_TTY(unit); +} + +int +scopen(dev_t dev, int flag, int mode, struct proc *p) +{ + struct tty *tp = scdevtotty(dev); + + if (!tp) + return(ENXIO); + + tp->t_oproc = (minor(dev) == SC_MOUSE) ? scmousestart : scstart; + tp->t_param = scparam; + tp->t_dev = dev; + if (!(tp->t_state & TS_ISOPEN)) { + ttychars(tp); + /* Use the current setting of the <-- key as default VERASE. */ + /* If the Delete key is preferable, an stty is necessary */ + 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; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + scparam(tp, &tp->t_termios); + (*linesw[tp->t_line].l_modem)(tp, 1); + if (minor(dev) == SC_MOUSE) + mouse_level = 0; /* XXX */ + } + 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; + tp->t_winsize.ws_row = console[minor(dev)]->ysize; + } + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +scclose(dev_t dev, int flag, int mode, struct proc *p) +{ + struct tty *tp = scdevtotty(dev); + struct scr_stat *scp; + + if (!tp) + return(ENXIO); + if (minor(dev) < MAXCONS) { + scp = sc_get_scr_stat(tp->t_dev); + if (scp->status & SWITCH_WAIT_ACQ) + wakeup((caddr_t)&scp->smode); +#if not_yet_done + if (scp == &main_console) { + scp->pid = 0; + scp->proc = NULL; + scp->smode.mode = VT_AUTO; + } + else { + free(scp->scr_buf, M_DEVBUF); + if (scp->history != NULL) { + free(scp->history, M_DEVBUF); + if (scp->history_size / scp->xsize + > imax(sc_history_size, scp->ysize)) + extra_history_size += scp->history_size / scp->xsize + - imax(sc_history_size, scp->ysize); + } + free(scp, M_DEVBUF); + console[minor(dev)] = NULL; + } +#else + scp->pid = 0; + scp->proc = NULL; + scp->smode.mode = VT_AUTO; +#endif + } + spltty(); + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + spl0(); + return(0); +} + +int +scread(dev_t dev, struct uio *uio, int flag) +{ + struct tty *tp = scdevtotty(dev); + + if (!tp) + return(ENXIO); + return((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +scwrite(dev_t dev, struct uio *uio, int flag) +{ + struct tty *tp = scdevtotty(dev); + + if (!tp) + return(ENXIO); + return((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +void +scintr(int unit) +{ + static struct tty *cur_tty; + int c, len; + u_char *cp; + + /* + * 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(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 (c & 0xff00) { + case 0x0000: /* normal key */ + (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); + break; + case FKEY: /* function key, return string */ + if (cp = get_fstr((u_int)c, (u_int *)&len)) { + while (len-- > 0) + (*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)(c & 0xFF, cur_tty); + break; + case BKEY: /* backtab fixed sequence (esc [ Z) */ + (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); + (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); + (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); + break; + } + } + +#if 0 + if (cur_console->status & MOUSE_ENABLED) { + cur_console->status &= ~MOUSE_VISIBLE; + remove_mouse_image(cur_console); + } +#else + if (cur_console->status & MOUSE_VISIBLE) { + remove_mouse_image(cur_console); + cur_console->status &= ~MOUSE_VISIBLE; + } +#endif +} + +static int +scparam(struct tty *tp, struct termios *t) +{ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + return 0; +} + +int +scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + u_int delta_ehs; + int error; + int i; + struct tty *tp; + scr_stat *scp; + video_adapter_t *adp; + int s; + + tp = scdevtotty(dev); + if (!tp) + return ENXIO; + scp = sc_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) + 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 */ + *(int*)data = (scp->term.cur_attr >> 8) & 0xFF; + return 0; + + case GIO_COLOR: /* is this a color console ? */ + *(int *)data = (adp_flags & V_ADP_COLOR) ? 1 : 0; + return 0; + + case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ + if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) + return EINVAL; + s = spltty(); + scrn_blank_time = *(int *)data; + run_scrn_saver = (scrn_blank_time != 0); + splx(s); + return 0; + + case CONS_CURSORTYPE: /* set cursor type blink/noblink */ + if ((*(int*)data) & 0x01) + sc_flags |= BLINK_CURSOR; + else + sc_flags &= ~BLINK_CURSOR; + if ((*(int*)data) & 0x02) { + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + sc_flags |= CHAR_CURSOR; + } else + sc_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)) { + remove_cursor_image(cur_console); + if (sc_flags & CHAR_CURSOR) + set_destructive_cursor(cur_console); + draw_cursor_image(cur_console); + } + return 0; + + case CONS_BELLTYPE: /* set bell type sound/visual */ + if ((*(int *)data) & 0x01) + sc_flags |= VISUAL_BELL; + else + sc_flags &= ~VISUAL_BELL; + if ((*(int *)data) & 0x02) + sc_flags |= QUIET_BELL; + else + sc_flags &= ~QUIET_BELL; + return 0; + + case CONS_HISTORY: /* set history size */ + if (*(int *)data > 0) { + int lines; /* buffer size to allocate */ + int lines0; /* current buffer size */ + + 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 (cur_console->status & BUFFER_SAVED) + return EBUSY; + sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE); + return 0; + } + else + return EINVAL; + + case CONS_MOUSECTL: /* control mouse arrow */ + case OLD_CONS_MOUSECTL: + { + /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ + static int 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, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + 0, + }; + mouse_info_t *mouse = (mouse_info_t*)data; + mouse_info_t buf; + + /* FIXME: */ + if (!ISMOUSEAVAIL(get_adapter(scp)->va_flags)) + return ENODEV; + + if (cmd == OLD_CONS_MOUSECTL) { + static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; + + mouse = &buf; + mouse->operation = old_mouse->operation; + switch (mouse->operation) { + case MOUSE_MODE: + mouse->u.mode = old_mouse->u.mode; + break; + case MOUSE_SHOW: + case MOUSE_HIDE: + break; + case MOUSE_MOVEABS: + case MOUSE_MOVEREL: + case MOUSE_ACTION: + mouse->u.data.x = old_mouse->u.data.x; + mouse->u.data.y = old_mouse->u.data.y; + mouse->u.data.z = 0; + mouse->u.data.buttons = swapb[old_mouse->u.data.buttons & 0x7]; + break; + case MOUSE_GETINFO: + old_mouse->u.data.x = scp->mouse_xpos; + old_mouse->u.data.y = scp->mouse_ypos; + old_mouse->u.data.buttons = swapb[scp->mouse_buttons & 0x7]; + break; + default: + return EINVAL; + } + } + + switch (mouse->operation) { + case MOUSE_MODE: + if (ISSIGVALID(mouse->u.mode.signal)) { + scp->mouse_signal = mouse->u.mode.signal; + scp->mouse_proc = p; + scp->mouse_pid = p->p_pid; + } + else { + scp->mouse_signal = 0; + scp->mouse_proc = NULL; + scp->mouse_pid = 0; + } + return 0; + + case MOUSE_SHOW: + if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { + scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); + scp->mouse_oldpos = scp->mouse_pos; + mark_all(scp); + return 0; + } + else + return EINVAL; + break; + + case MOUSE_HIDE: + if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { + scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); + mark_all(scp); + return 0; + } + else + return EINVAL; + break; + + case MOUSE_MOVEABS: + scp->mouse_xpos = mouse->u.data.x; + scp->mouse_ypos = mouse->u.data.y; + set_mouse_pos(scp); + break; + + case MOUSE_MOVEREL: + scp->mouse_xpos += mouse->u.data.x; + scp->mouse_ypos += mouse->u.data.y; + set_mouse_pos(scp); + break; + + case MOUSE_GETINFO: + mouse->u.data.x = scp->mouse_xpos; + mouse->u.data.y = scp->mouse_ypos; + mouse->u.data.z = 0; + mouse->u.data.buttons = scp->mouse_buttons; + return 0; + + case MOUSE_ACTION: + case MOUSE_MOTION_EVENT: + /* this should maybe only be settable from /dev/consolectl SOS */ + /* send out mouse event on /dev/sysmouse */ + + mouse_status.dx += mouse->u.data.x; + mouse_status.dy += mouse->u.data.y; + mouse_status.dz += mouse->u.data.z; + if (mouse->operation == MOUSE_ACTION) + mouse_status.button = mouse->u.data.buttons; + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + if (mouse_status.flags == 0) + return 0; + + if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) + cur_console->status |= MOUSE_VISIBLE; + + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { + u_char buf[MOUSE_SYS_PACKETSIZE]; + int j; + + /* the first five bytes are compatible with MouseSystems' */ + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + j = imax(imin(mouse->u.data.x, 255), -256); + buf[1] = j >> 1; + buf[3] = j - buf[1]; + j = -imax(imin(mouse->u.data.y, 255), -256); + buf[2] = j >> 1; + buf[4] = j - buf[2]; + for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + if (mouse_level >= 1) { /* extended part */ + j = imax(imin(mouse->u.data.z, 127), -128); + buf[5] = (j >> 1) & 0x7f; + buf[6] = (j - (j >> 1)) & 0x7f; + /* buttons 4-10 */ + buf[7] = (~mouse_status.button >> 3) & 0x7f; + for (j = MOUSE_MSC_PACKETSIZE; + j < MOUSE_SYS_PACKETSIZE; j++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + } + } + + if (cur_console->mouse_signal) { + cur_console->mouse_buttons = mouse->u.data.buttons; + /* has controlling process died? */ + if (cur_console->mouse_proc && + (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ + cur_console->mouse_signal = 0; + cur_console->mouse_proc = NULL; + cur_console->mouse_pid = 0; + } + else + psignal(cur_console->mouse_proc, cur_console->mouse_signal); + } + 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->mouse_buttons = mouse->u.data.buttons; + if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) + mouse_cut_start(cur_console); + else + mouse_cut_end(cur_console); + if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || + cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) + mouse_paste(cur_console); + } + } + + if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { + cur_console->mouse_xpos += mouse->u.data.x; + cur_console->mouse_ypos += mouse->u.data.y; + set_mouse_pos(cur_console); + } + + break; + + case MOUSE_BUTTON_EVENT: + if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) + return EINVAL; + if (mouse->u.event.value < 0) + return EINVAL; + + if (mouse->u.event.value > 0) { + cur_console->mouse_buttons |= mouse->u.event.id; + mouse_status.button |= mouse->u.event.id; + } else { + cur_console->mouse_buttons &= ~mouse->u.event.id; + mouse_status.button &= ~mouse->u.event.id; + } + mouse_status.flags |= mouse_status.obutton ^ mouse_status.button; + if (mouse_status.flags == 0) + return 0; + + if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) + cur_console->status |= MOUSE_VISIBLE; + + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { + u_char buf[8]; + int i; + + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + buf[7] = (~mouse_status.button >> 3) & 0x7f; + buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; + for (i = 0; + i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE + : MOUSE_MSC_PACKETSIZE); i++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); + } + + if (cur_console->mouse_signal) { + if (cur_console->mouse_proc && + (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ + cur_console->mouse_signal = 0; + cur_console->mouse_proc = NULL; + cur_console->mouse_pid = 0; + } + else + psignal(cur_console->mouse_proc, cur_console->mouse_signal); + break; + } + + if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) + break; + + switch (mouse->u.event.id) { + case MOUSE_BUTTON1DOWN: + switch (mouse->u.event.value % 4) { + case 0: /* up */ + mouse_cut_end(cur_console); + break; + case 1: + mouse_cut_start(cur_console); + break; + case 2: + mouse_cut_word(cur_console); + break; + case 3: + mouse_cut_line(cur_console); + break; + } + break; + case MOUSE_BUTTON2DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + break; + default: + mouse_paste(cur_console); + break; + } + break; + case MOUSE_BUTTON3DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) + mouse_cut_end(cur_console); + break; + default: + mouse_cut_extend(cur_console); + break; + } + break; + } + break; + + default: + return EINVAL; + } + /* make screensaver happy */ + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + return 0; + } + + /* MOUSE_XXX: /dev/sysmouse ioctls */ + case MOUSE_GETHWINFO: /* get device information */ + { + mousehw_t *hw = (mousehw_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + hw->buttons = 10; /* XXX unknown */ + hw->iftype = MOUSE_IF_SYSMOUSE; + hw->type = MOUSE_MOUSE; + hw->model = MOUSE_MODEL_GENERIC; + hw->hwid = 0; + return 0; + } + + case MOUSE_GETMODE: /* get protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + mode->level = mouse_level; + switch (mode->level) { + case 0: + /* at this level, sysmouse emulates MouseSystems protocol */ + mode->protocol = MOUSE_PROTO_MSC; + mode->rate = -1; /* unknown */ + mode->resolution = -1; /* unknown */ + mode->accelfactor = 0; /* disabled */ + mode->packetsize = MOUSE_MSC_PACKETSIZE; + mode->syncmask[0] = MOUSE_MSC_SYNCMASK; + mode->syncmask[1] = MOUSE_MSC_SYNC; + break; + + case 1: + /* at this level, sysmouse uses its own protocol */ + mode->protocol = MOUSE_PROTO_SYSMOUSE; + mode->rate = -1; + mode->resolution = -1; + mode->accelfactor = 0; + mode->packetsize = MOUSE_SYS_PACKETSIZE; + mode->syncmask[0] = MOUSE_SYS_SYNCMASK; + mode->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + return 0; + } + + case MOUSE_SETMODE: /* set protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + if ((mode->level < 0) || (mode->level > 1)) + return EINVAL; + mouse_level = mode->level; + return 0; + } + + case MOUSE_GETLEVEL: /* get operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + *(int *)data = mouse_level; + return 0; + + case MOUSE_SETLEVEL: /* set operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + if ((*(int *)data < 0) || (*(int *)data > 1)) + return EINVAL; + mouse_level = *(int *)data; + return 0; + + case MOUSE_GETSTATUS: /* get accumulated mouse events */ + if (tp != MOUSE_TTY) + return ENOTTY; + s = spltty(); + *(mousestatus_t *)data = mouse_status; + mouse_status.flags = 0; + mouse_status.obutton = mouse_status.button; + mouse_status.dx = 0; + mouse_status.dy = 0; + mouse_status.dz = 0; + splx(s); + return 0; + +#if notyet + case MOUSE_GETVARS: /* get internal mouse variables */ + case MOUSE_SETVARS: /* set internal mouse variables */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; +#endif + + case MOUSE_READSTATE: /* read status from the device */ + case MOUSE_READDATA: /* read data from the device */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; + + case CONS_GETINFO: /* get current (virtual) console info */ + { + vid_info_t *ptr = (vid_info_t*)data; + if (ptr->size == sizeof(struct vid_info)) { + ptr->m_num = get_scr_num(); + ptr->mv_col = scp->xpos; + ptr->mv_row = scp->ypos; + ptr->mv_csz = scp->xsize; + ptr->mv_rsz = scp->ysize; + ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; + ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; + ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; + ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; + ptr->mv_grfc.fore = 0; /* not supported */ + ptr->mv_grfc.back = 0; /* not supported */ + ptr->mv_ovscan = scp->border; + ptr->mk_keylock = scp->status & LOCK_KEY_MASK; + return 0; + } + return EINVAL; + } + + case CONS_GETVERS: /* get version number */ + *(int*)data = 0x200; /* version 2.0 */ + 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)); + 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); + saver_mode = *(int *)data; + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + 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; + } + return 0; + + case CONS_SAVERSTART: /* immediately start/stop the screen saver */ + /* + * Note that this ioctl does not guarantee the screen saver + * actually starts or stops. It merely attempts to do so... + */ + s = spltty(); + run_scrn_saver = (*(int *)data != 0); + if (run_scrn_saver) + scrn_time_stamp -= scrn_blank_time; + splx(s); + return 0; + + case VT_SETMODE: /* set screen switcher mode */ + { + struct vt_mode *mode; + + mode = (struct vt_mode *)data; + if (ISSIGVALID(mode->relsig) && ISSIGVALID(mode->acqsig) && + ISSIGVALID(mode->frsig)) { + bcopy(data, &scp->smode, sizeof(struct vt_mode)); + if (scp->smode.mode == VT_PROCESS) { + scp->proc = p; + scp->pid = scp->proc->p_pid; + } + return 0; + } else + return EINVAL; + } + + case VT_GETMODE: /* get screen switcher mode */ + bcopy(&scp->smode, data, sizeof(struct vt_mode)); + return 0; + + case VT_RELDISP: /* screen switcher ioctl */ + switch(*(int *)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; + switch_in_progress = FALSE; + return 0; + } + return EINVAL; + + case VT_TRUE: /* user has released screen, go on */ + if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { + scp->status &= ~SWITCH_WAIT_REL; + exchange_scr(); + if (new_scp->smode.mode == VT_PROCESS) { + new_scp->status |= SWITCH_WAIT_ACQ; + psignal(new_scp->proc, new_scp->smode.acqsig); + } + else + switch_in_progress = FALSE; + return 0; + } + return EINVAL; + + case VT_ACKACQ: /* acquire acknowledged, switch completed */ + if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { + scp->status &= ~SWITCH_WAIT_ACQ; + switch_in_progress = FALSE; + return 0; + } + return EINVAL; + + default: + return EINVAL; + } + /* NOT REACHED */ + + case VT_OPENQRY: /* return free virtual console */ + for (i = 0; i < MAXCONS; i++) { + tp = VIRTUAL_TTY(i); + if (!(tp->t_state & TS_ISOPEN)) { + *(int *)data = i + 1; + return 0; + } + } + return EINVAL; + + case VT_ACTIVATE: /* switch to screen *data */ + return switch_scr(scp, *(int *)data - 1); + + case VT_WAITACTIVE: /* wait for switch to occur */ + if (*(int *)data > MAXCONS || *(int *)data < 0) + return EINVAL; + if (minor(dev) == *(int *)data - 1) + return 0; + if (*(int *)data == 0) { + if (scp == cur_console) + return 0; + } + else + scp = console[*(int *)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; + return 0; + + case KDENABIO: /* allow io operations */ + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + return error; + if (securelevel > 0) + return EPERM; + p->p_md.md_regs->tf_eflags |= PSL_IOPL; + return 0; + + case KDDISABIO: /* disallow io operations (default) */ + p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; + return 0; + + case KDSKBSTATE: /* set keyboard state (locks) */ + if (*(int *)data & ~LOCK_KEY_MASK) + return EINVAL; + scp->status &= ~LOCK_KEY_MASK; + scp->status |= *(int *)data; + if (scp == cur_console) + update_leds(scp->status); + return 0; + + case KDGKBSTATE: /* get keyboard state (locks) */ + *(int *)data = scp->status & LOCK_KEY_MASK; + return 0; + + case KDSETRAD: /* set keyboard repeat & delay rates */ + if (*(int *)data & ~0x7f) + return EINVAL; + if (sc_kbdc != NULL) + set_keyboard(KBDC_SET_TYPEMATIC, *(int *)data); + return 0; + + case KDSKBMODE: /* set keyboard mode */ + switch (*(int *)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->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; + } + /* NOT REACHED */ + + case KDGKBMODE: /* get keyboard mode */ + *(int *)data = (scp->status & KBD_RAW_MODE) ? K_RAW : + ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); + return 0; + + case KDMKTONE: /* sound the bell */ + if (*(int*)data) + do_bell(scp, (*(int*)data)&0xffff, + (((*(int*)data)>>16)&0xffff)*hz/1000); + else + do_bell(scp, scp->bell_pitch, scp->bell_duration); + return 0; + + case KIOCSOUND: /* make tone (*data) hz */ + if (scp == cur_console) { + if (*(int*)data) { + int pitch = timer_freq / *(int*)data; + + /* set command for counter 2, 2 byte write */ + if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) + return EBUSY; + + /* set pitch */ + outb(TIMER_CNTR2, pitch); + outb(TIMER_CNTR2, (pitch>>8)); + + /* enable counter 2 output to speaker */ + outb(IO_PPI, inb(IO_PPI) | 3); + } + else { + /* disable counter 2 output to speaker */ + outb(IO_PPI, inb(IO_PPI) & 0xFC); + release_timer2(); + } + } + return 0; + + case KDGKBTYPE: /* get keyboard type */ + *(int *)data = 0; /* type not known (yet) */ + return 0; + + case KDSETLED: /* set keyboard LED status */ + if (*(int *)data & ~LED_MASK) + return EINVAL; + scp->status &= ~LED_MASK; + scp->status |= *(int *)data; + if (scp == cur_console) + update_leds(scp->status); + return 0; + + case KDGETLED: /* get keyboard LED status */ + *(int *)data = scp->status & LED_MASK; + return 0; + + 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 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; + } + else + return EINVAL; + + case GIO_SCRNMAP: /* get output translation table */ + bcopy(&scr_map, data, sizeof(scr_map)); + return 0; + + case PIO_SCRNMAP: /* set output translation table */ + bcopy(data, &scr_map, sizeof(scr_map)); + for (i=0; i<sizeof(scr_map); i++) + scr_rmap[scr_map[i]] = i; + return 0; + + 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; + + case PIO_FONT8x8: /* set 8x8 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + bcopy(data, font_8, 8*256); + fonts_loaded |= FONT_8; + /* + * FONT KLUDGE + * 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); + return 0; + + case GIO_FONT8x8: /* get 8x8 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + if (fonts_loaded & FONT_8) { + bcopy(font_8, data, 8*256); + return 0; + } + else + return ENXIO; + + case PIO_FONT8x14: /* set 8x14 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + bcopy(data, font_14, 14*256); + fonts_loaded |= FONT_14; + /* + * FONT KLUDGE + * 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); + return 0; + + case GIO_FONT8x14: /* get 8x14 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + if (fonts_loaded & FONT_14) { + bcopy(font_14, data, 14*256); + return 0; + } + else + return ENXIO; + + case PIO_FONT8x16: /* set 8x16 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + bcopy(data, font_16, 16*256); + fonts_loaded |= FONT_16; + /* + * FONT KLUDGE + * 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); + return 0; + + case GIO_FONT8x16: /* get 8x16 dot font */ + if (!ISFONTAVAIL(get_adapter(scp)->va_flags)) + return ENXIO; + if (fonts_loaded & FONT_16) { + bcopy(font_16, data, 16*256); + return 0; + } + else + return ENXIO; + default: + break; + } + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error != ENOIOCTL) + return(error); + error = ttioctl(tp, cmd, data, flag); + if (error != ENOIOCTL) + return(error); + return(ENOTTY); +} + +static void +scstart(struct tty *tp) +{ + struct clist *rbp; + int s, len; + u_char buf[PCBURST]; + scr_stat *scp = sc_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? */ + s = spltty(); + if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { + tp->t_state |= TS_BUSY; + rbp = &tp->t_outq; + while (rbp->c_cc) { + len = q_to_b(rbp, buf, PCBURST); + splx(s); + ansi_put(scp, buf, len); + s = spltty(); + } + tp->t_state &= ~TS_BUSY; + ttwwakeup(tp); + } + splx(s); +} + +static void +scmousestart(struct tty *tp) +{ + struct clist *rbp; + int s; + u_char buf[PCBURST]; + + s = spltty(); + if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { + tp->t_state |= TS_BUSY; + rbp = &tp->t_outq; + while (rbp->c_cc) { + q_to_b(rbp, buf, PCBURST); + } + tp->t_state &= ~TS_BUSY; + ttwwakeup(tp); + } + splx(s); +} + +void +sccnprobe(struct consdev *cp) +{ + struct isa_device *dvp; + + /* + * Take control if we are the highest priority enabled display device. + */ + dvp = find_display(); + if (dvp == NULL || dvp->id_driver != &scdriver) { + cp->cn_pri = CN_DEAD; + return; + } + + if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { + cp->cn_pri = CN_DEAD; + return; + } + + /* initialize required fields */ + cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); + cp->cn_pri = CN_INTERNAL; + + sc_kbdc = kbdc_open(sc_port); +} + +void +sccninit(struct consdev *cp) +{ + scinit(); +} + +void +sccnputc(dev_t dev, int c) +{ + u_char buf[1]; + int s; + scr_stat *scp = console[0]; + term_stat save = scp->term; + + scp->term = kernel_console; + current_default = &kernel_default; + if (scp == cur_console && !ISGRAPHSC(scp)) + remove_cursor_image(scp); + buf[0] = c; + ansi_put(scp, buf, 1); + kernel_console = scp->term; + current_default = &user_default; + scp->term = save; + + s = spltty(); /* block scintr and scrn_timer */ + sccnupdate(scp); + splx(s); +} + +int +sccngetc(dev_t dev) +{ + 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 + */ + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + sccnupdate(cur_console); + + c = scgetc(SCGETC_CN); + splx(s); + return(c); +} + +int +sccncheckc(dev_t dev) +{ + int s = spltty(); /* block scintr and scrn_timer while we poll */ + int c; + + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + sccnupdate(cur_console); + + c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); + splx(s); + return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ +} + +static void +sccnupdate(scr_stat *scp) +{ + /* this is a cut-down version of scrn_timer()... */ + + if (font_loading_in_progress) + return; + + if (panicstr || shutdown_in_progress) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + } else if (scp != cur_console) { + return; + } + + if (!run_scrn_saver) + scrn_idle = FALSE; + if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) + if (scp->status & SAVER_RUNNING) + stop_scrn_saver(current_saver); + + if (scp != cur_console || blink_in_progress || switch_in_progress) + return; + + if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) + scrn_update(scp, TRUE); +} + +scr_stat +*sc_get_scr_stat(dev_t dev) +{ + int unit = minor(dev); + + if (unit == SC_CONSOLE) + return console[0]; + if (unit >= MAXCONS || unit < 0) + return(NULL); + return console[unit]; +} + +static int +get_scr_num() +{ + int i = 0; + + while ((i < MAXCONS) && (cur_console != console[i])) + i++; + return i < MAXCONS ? i : 0; +} + +static void +scrn_timer(void *arg) +{ + struct timeval tv; + scr_stat *scp; + int s; + + /* don't do anything when we are touching font */ + if (font_loading_in_progress) { + if (arg) + timeout(scrn_timer, (void *)TRUE, hz / 10); + return; + } + 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); + } + + scp = cur_console; + + /* should we stop the screen saver? */ + getmicrouptime(&tv); + 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 { + scrn_time_stamp = tv.tv_sec; + scrn_idle = FALSE; + if (scrn_blank_time > 0) + run_scrn_saver = TRUE; + } + if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) + if (scp->status & SAVER_RUNNING) + stop_scrn_saver(current_saver); + + /* should we just return ? */ + if (blink_in_progress || switch_in_progress) { + if (arg) + timeout(scrn_timer, (void *)TRUE, hz / 10); + splx(s); + return; + } + + /* Update the screen */ + if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) + scrn_update(scp, TRUE); + + /* should we activate the screen saver? */ + if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) + if (!ISGRAPHSC(scp) || (scp->status & SAVER_RUNNING)) + scrn_saver(current_saver, TRUE); + + if (arg) + timeout(scrn_timer, (void *)TRUE, hz / 25); + splx(s); +} + +static void +scrn_update(scr_stat *scp, int show_cursor) +{ + /* update screen image */ + if (scp->start <= scp->end) + sc_bcopy(scp, scp->scr_buf, scp->start, scp->end, 0); + + /* we are not to show the cursor and the mouse pointer... */ + if (!show_cursor) { + scp->end = 0; + scp->start = scp->xsize*scp->ysize - 1; + return; + } + + /* update "pseudo" mouse pointer image */ + if (scp->status & MOUSE_VISIBLE) { + /* did mouse move since last time ? */ + if (scp->status & MOUSE_MOVED) { + /* do we need to remove old mouse pointer image ? */ + if (scp->mouse_cut_start != NULL || + (scp->mouse_pos-scp->scr_buf) <= scp->start || + (scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->end) { + remove_mouse_image(scp); + } + scp->status &= ~MOUSE_MOVED; + draw_mouse_image(scp); + } + else { + /* mouse didn't move, has it been overwritten ? */ + if ((scp->mouse_pos+scp->xsize + 1 - scp->scr_buf) >= scp->start && + (scp->mouse_pos - scp->scr_buf) <= scp->end) { + draw_mouse_image(scp); + } + } + } + + /* update cursor image */ + if (scp->status & CURSOR_ENABLED) { + /* did cursor move since last time ? */ + if (scp->cursor_pos != scp->cursor_oldpos) { + /* do we need to remove old cursor image ? */ + if ((scp->cursor_oldpos - scp->scr_buf) < scp->start || + ((scp->cursor_oldpos - scp->scr_buf) > scp->end)) { + remove_cursor_image(scp); + } + scp->cursor_oldpos = scp->cursor_pos; + draw_cursor_image(scp); + } + else { + /* cursor didn't move, has it been overwritten ? */ + if (scp->cursor_pos - scp->scr_buf >= scp->start && + scp->cursor_pos - scp->scr_buf <= scp->end) { + draw_cursor_image(scp); + } else { + /* if its a blinking cursor, we may have to update it */ + if (sc_flags & BLINK_CURSOR) + draw_cursor_image(scp); + } + } + blinkrate++; + } + + if (scp->mouse_cut_start != NULL) + draw_cutmarking(scp); + + scp->end = 0; + scp->start = scp->xsize*scp->ysize - 1; +} + +int +add_scrn_saver(void (*this_saver)(int)) +{ +#ifdef SC_SPLASH_SCREEN + if (current_saver == scsplash) { + scsplash_stick(FALSE); + stop_scrn_saver(scsplash); + } +#endif + + if (current_saver != default_saver) + return EBUSY; + run_scrn_saver = FALSE; + saver_mode = CONS_LKM_SAVER; + current_saver = this_saver; + return 0; +} + +int +remove_scrn_saver(void (*this_saver)(int)) +{ + if (current_saver != this_saver) + return EINVAL; + + /* + * In order to prevent `current_saver' from being called by + * the timeout routine `scrn_timer()' while we manipulate + * the saver list, we shall set `current_saver' to `none_saver' + * before stopping the current saver, rather than blocking by `splXX()'. + */ + current_saver = none_saver; + if (scrn_blanked > 0) + stop_scrn_saver(this_saver); + + if (scrn_blanked > 0) + return EBUSY; /* XXX */ + + current_saver = default_saver; + return 0; +} + +static void +scrn_saver(void (*saver)(int), int blank) +{ + static int busy = FALSE; + + if (busy) + return; + busy = TRUE; + (*saver)(blank); + busy = FALSE; +} + +static void +stop_scrn_saver(void (*saver)(int)) +{ + scrn_saver(saver, FALSE); + run_scrn_saver = FALSE; + /* the screen saver may have chosen not to stop after all... */ + if (scrn_blanked > 0) + return; + + mark_all(cur_console); + if (delayed_next_scr) + switch_scr(cur_console, delayed_next_scr - 1); + wakeup((caddr_t)&scrn_blanked); +} + +static int +wait_scrn_saver_stop(void) +{ + int error = 0; + + while (scrn_blanked > 0) { + run_scrn_saver = FALSE; + error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); + run_scrn_saver = FALSE; + if (error != ERESTART) + break; + } + return error; +} + +void +sc_clear_screen(scr_stat *scp) +{ + move_crsr(scp, 0, 0); + scp->cursor_oldpos = scp->cursor_pos; + fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, + scp->xsize * scp->ysize); + mark_all(scp); + remove_cutmarking(scp); +} + +static int +switch_scr(scr_stat *scp, u_int next_scr) +{ + /* delay switch if actively updating screen */ + if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + delayed_next_scr = next_scr+1; + return 0; + } + + if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) + switch_in_progress = FALSE; + + if (next_scr >= MAXCONS || switch_in_progress || + (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { + do_bell(scp, BELL_PITCH, BELL_DURATION); + return EINVAL; + } + + /* is the wanted virtual console open ? */ + if (next_scr) { + struct tty *tp = VIRTUAL_TTY(next_scr); + if (!(tp->t_state & TS_ISOPEN)) { + do_bell(scp, BELL_PITCH, BELL_DURATION); + return EINVAL; + } + } + + switch_in_progress = TRUE; + old_scp = cur_console; + new_scp = console[next_scr]; + wakeup((caddr_t)&new_scp->smode); + if (new_scp == old_scp) { + switch_in_progress = FALSE; + delayed_next_scr = FALSE; + return 0; + } + + /* has controlling process died? */ + if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) + old_scp->smode.mode = VT_AUTO; + if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) + new_scp->smode.mode = VT_AUTO; + + /* check the modes and switch appropriately */ + if (old_scp->smode.mode == VT_PROCESS) { + old_scp->status |= SWITCH_WAIT_REL; + psignal(old_scp->proc, old_scp->smode.relsig); + } + else { + exchange_scr(); + if (new_scp->smode.mode == VT_PROCESS) { + new_scp->status |= SWITCH_WAIT_ACQ; + psignal(new_scp->proc, new_scp->smode.acqsig); + } + else + switch_in_progress = FALSE; + } + return 0; +} + +static void +exchange_scr(void) +{ + move_crsr(old_scp, old_scp->xpos, old_scp->ypos); + cur_console = new_scp; + if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) + set_mode(new_scp); + move_crsr(new_scp, new_scp->xpos, new_scp->ypos); + if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) + set_destructive_cursor(new_scp); + if (ISGRAPHSC(old_scp)) + load_palette(new_scp, palette); + 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, new_scp->border); + update_leds(new_scp->status); + delayed_next_scr = FALSE; + mark_all(new_scp); +} + +static void +scan_esc(scr_stat *scp, u_char c) +{ + static u_char ansi_col[16] = + {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; + int i, n; + u_short *src, *dst, count; + + if (scp->term.esc == 1) { /* seen ESC */ + switch (c) { + + case '7': /* Save cursor position */ + scp->saved_xpos = scp->xpos; + scp->saved_ypos = scp->ypos; + break; + + case '8': /* Restore saved cursor position */ + if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) + move_crsr(scp, scp->saved_xpos, scp->saved_ypos); + break; + + case '[': /* Start ESC [ sequence */ + scp->term.esc = 2; + scp->term.last_param = -1; + for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) + scp->term.param[i] = 1; + scp->term.num_param = 0; + return; + + case 'M': /* Move cursor up 1 line, scroll if at top */ + if (scp->ypos > 0) + move_crsr(scp, scp->xpos, scp->ypos - 1); + else { + bcopy(scp->scr_buf, scp->scr_buf + scp->xsize, + (scp->ysize - 1) * scp->xsize * sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], + scp->scr_buf, scp->xsize); + mark_all(scp); + } + break; +#if notyet + case 'Q': + scp->term.esc = 4; + return; +#endif + case 'c': /* Clear screen & home */ + sc_clear_screen(scp); + break; + + case '(': /* iso-2022: designate 94 character set to G0 */ + scp->term.esc = 5; + return; + } + } + else if (scp->term.esc == 2) { /* seen ESC [ */ + if (c >= '0' && c <= '9') { + if (scp->term.num_param < MAX_ESC_PAR) { + if (scp->term.last_param != scp->term.num_param) { + scp->term.last_param = scp->term.num_param; + scp->term.param[scp->term.num_param] = 0; + } + else + scp->term.param[scp->term.num_param] *= 10; + scp->term.param[scp->term.num_param] += c - '0'; + return; + } + } + scp->term.num_param = scp->term.last_param + 1; + switch (c) { + + case ';': + if (scp->term.num_param < MAX_ESC_PAR) + return; + break; + + case '=': + scp->term.esc = 3; + scp->term.last_param = -1; + for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) + scp->term.param[i] = 1; + scp->term.num_param = 0; + return; + + case 'A': /* up n rows */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos, scp->ypos - n); + break; + + case 'B': /* down n rows */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos, scp->ypos + n); + break; + + case 'C': /* right n columns */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos + n, scp->ypos); + break; + + case 'D': /* left n columns */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos - n, scp->ypos); + break; + + case 'E': /* cursor to start of line n lines down */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, 0, scp->ypos + n); + break; + + case 'F': /* cursor to start of line n lines up */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, 0, scp->ypos - n); + break; + + case 'f': /* Cursor move */ + case 'H': + if (scp->term.num_param == 0) + move_crsr(scp, 0, 0); + else if (scp->term.num_param == 2) + move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); + break; + + case 'J': /* Clear all or part of display */ + if (scp->term.num_param == 0) + n = 0; + else + n = scp->term.param[0]; + switch (n) { + case 0: /* clear form cursor to end of display */ + fillw(scp->term.cur_color | scr_map[0x20], + scp->cursor_pos, + scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, scp->xsize * scp->ysize - 1); + remove_cutmarking(scp); + break; + case 1: /* clear from beginning of display to cursor */ + fillw(scp->term.cur_color | scr_map[0x20], + scp->scr_buf, + scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, 0); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + remove_cutmarking(scp); + break; + case 2: /* clear entire display */ + fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, + scp->xsize * scp->ysize); + mark_all(scp); + remove_cutmarking(scp); + break; + } + break; + + case 'K': /* Clear all or part of line */ + if (scp->term.num_param == 0) + n = 0; + else + n = scp->term.param[0]; + switch (n) { + case 0: /* clear form cursor to end of line */ + fillw(scp->term.cur_color | scr_map[0x20], + scp->cursor_pos, + scp->xsize - scp->xpos); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + + scp->xsize - 1 - scp->xpos); + break; + case 1: /* clear from beginning of line to cursor */ + fillw(scp->term.cur_color | scr_map[0x20], + scp->cursor_pos - scp->xpos, + scp->xpos + 1); + mark_for_update(scp, scp->ypos * scp->xsize); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + break; + case 2: /* clear entire line */ + fillw(scp->term.cur_color | scr_map[0x20], + scp->cursor_pos - scp->xpos, + scp->xsize); + mark_for_update(scp, scp->ypos * scp->xsize); + mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); + break; + } + break; + + case 'L': /* Insert n lines */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->ysize - scp->ypos) + n = scp->ysize - scp->ypos; + src = scp->scr_buf + scp->ypos * scp->xsize; + dst = src + n * scp->xsize; + count = scp->ysize - (scp->ypos + n); + bcopy(src, dst, count * scp->xsize * sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], src, + n * scp->xsize); + mark_for_update(scp, scp->ypos * scp->xsize); + mark_for_update(scp, scp->xsize * scp->ysize - 1); + break; + + case 'M': /* Delete n lines */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->ysize - scp->ypos) + n = scp->ysize - scp->ypos; + dst = scp->scr_buf + scp->ypos * scp->xsize; + src = dst + n * scp->xsize; + count = scp->ysize - (scp->ypos + n); + bcopy(src, dst, count * scp->xsize * sizeof(u_short)); + src = dst + count * scp->xsize; + fillw(scp->term.cur_color | scr_map[0x20], src, + n * scp->xsize); + mark_for_update(scp, scp->ypos * scp->xsize); + mark_for_update(scp, scp->xsize * scp->ysize - 1); + break; + + case 'P': /* Delete n chars */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->xsize - scp->xpos) + n = scp->xsize - scp->xpos; + dst = scp->cursor_pos; + src = dst + n; + count = scp->xsize - (scp->xpos + n); + bcopy(src, dst, count * sizeof(u_short)); + src = dst + count; + fillw(scp->term.cur_color | scr_map[0x20], src, n); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); + break; + + case '@': /* Insert n chars */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->xsize - scp->xpos) + n = scp->xsize - scp->xpos; + src = scp->cursor_pos; + dst = src + n; + count = scp->xsize - (scp->xpos + n); + bcopy(src, dst, count * sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], src, n); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); + break; + + case 'S': /* scroll up n lines */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->ysize) + n = scp->ysize; + bcopy(scp->scr_buf + (scp->xsize * n), + scp->scr_buf, + scp->xsize * (scp->ysize - n) * sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], + scp->scr_buf + scp->xsize * (scp->ysize - n), + scp->xsize * n); + mark_all(scp); + break; + + case 'T': /* scroll down n lines */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->ysize) + n = scp->ysize; + bcopy(scp->scr_buf, + scp->scr_buf + (scp->xsize * n), + scp->xsize * (scp->ysize - n) * + sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], + scp->scr_buf, scp->xsize * n); + mark_all(scp); + break; + + case 'X': /* erase n characters in line */ + n = scp->term.param[0]; if (n < 1) n = 1; + if (n > scp->xsize - scp->xpos) + n = scp->xsize - scp->xpos; + fillw(scp->term.cur_color | scr_map[0x20], + scp->cursor_pos, n); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); + break; + + case 'Z': /* move n tabs backwards */ + n = scp->term.param[0]; if (n < 1) n = 1; + if ((i = scp->xpos & 0xf8) == scp->xpos) + i -= 8*n; + else + i -= 8*(n-1); + if (i < 0) + i = 0; + move_crsr(scp, i, scp->ypos); + break; + + case '`': /* move cursor to column n */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, n - 1, scp->ypos); + break; + + case 'a': /* move cursor n columns to the right */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos + n, scp->ypos); + break; + + case 'd': /* move cursor to row n */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos, n - 1); + break; + + case 'e': /* move cursor n rows down */ + n = scp->term.param[0]; if (n < 1) n = 1; + move_crsr(scp, scp->xpos, scp->ypos + n); + break; + + case 'm': /* change attribute */ + if (scp->term.num_param == 0) { + scp->term.attr_mask = NORMAL_ATTR; + scp->term.cur_attr = + scp->term.cur_color = scp->term.std_color; + break; + } + for (i = 0; i < scp->term.num_param; i++) { + switch (n = scp->term.param[i]) { + case 0: /* back to normal */ + scp->term.attr_mask = NORMAL_ATTR; + scp->term.cur_attr = + scp->term.cur_color = scp->term.std_color; + break; + case 1: /* bold */ + scp->term.attr_mask |= BOLD_ATTR; + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 4: /* underline */ + scp->term.attr_mask |= UNDERLINE_ATTR; + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 5: /* blink */ + scp->term.attr_mask |= BLINK_ATTR; + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 7: /* reverse video */ + scp->term.attr_mask |= REVERSE_ATTR; + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 30: case 31: /* set fg color */ + case 32: case 33: case 34: + case 35: case 36: case 37: + scp->term.attr_mask |= FOREGROUND_CHANGED; + scp->term.cur_color = + (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 40: case 41: /* set bg color */ + case 42: case 43: case 44: + case 45: case 46: case 47: + scp->term.attr_mask |= BACKGROUND_CHANGED; + scp->term.cur_color = + (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); + scp->term.cur_attr = mask2attr(&scp->term); + break; + } + } + break; + + case 's': /* Save cursor position */ + scp->saved_xpos = scp->xpos; + scp->saved_ypos = scp->ypos; + break; + + case 'u': /* Restore saved cursor position */ + if (scp->saved_xpos >= 0 && scp->saved_ypos >= 0) + move_crsr(scp, scp->saved_xpos, scp->saved_ypos); + break; + + case 'x': + if (scp->term.num_param == 0) + n = 0; + else + n = scp->term.param[0]; + switch (n) { + case 0: /* reset attributes */ + scp->term.attr_mask = NORMAL_ATTR; + scp->term.cur_attr = + scp->term.cur_color = scp->term.std_color = + current_default->std_color; + scp->term.rev_color = current_default->rev_color; + break; + case 1: /* set ansi background */ + scp->term.attr_mask &= ~BACKGROUND_CHANGED; + scp->term.cur_color = scp->term.std_color = + (scp->term.std_color & 0x0F00) | + (ansi_col[(scp->term.param[1])&0x0F]<<12); + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 2: /* set ansi foreground */ + scp->term.attr_mask &= ~FOREGROUND_CHANGED; + scp->term.cur_color = scp->term.std_color = + (scp->term.std_color & 0xF000) | + (ansi_col[(scp->term.param[1])&0x0F]<<8); + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 3: /* set ansi attribute directly */ + scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); + scp->term.cur_color = scp->term.std_color = + (scp->term.param[1]&0xFF)<<8; + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 5: /* set ansi reverse video background */ + scp->term.rev_color = + (scp->term.rev_color & 0x0F00) | + (ansi_col[(scp->term.param[1])&0x0F]<<12); + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 6: /* set ansi reverse video foreground */ + scp->term.rev_color = + (scp->term.rev_color & 0xF000) | + (ansi_col[(scp->term.param[1])&0x0F]<<8); + scp->term.cur_attr = mask2attr(&scp->term); + break; + case 7: /* set ansi reverse video directly */ + scp->term.rev_color = + (scp->term.param[1]&0xFF)<<8; + scp->term.cur_attr = mask2attr(&scp->term); + break; + } + break; + + case 'z': /* switch to (virtual) console n */ + if (scp->term.num_param == 1) + switch_scr(scp, scp->term.param[0]); + break; + } + } + else if (scp->term.esc == 3) { /* seen ESC [0-9]+ = */ + if (c >= '0' && c <= '9') { + if (scp->term.num_param < MAX_ESC_PAR) { + if (scp->term.last_param != scp->term.num_param) { + scp->term.last_param = scp->term.num_param; + scp->term.param[scp->term.num_param] = 0; + } + else + scp->term.param[scp->term.num_param] *= 10; + scp->term.param[scp->term.num_param] += c - '0'; + return; + } + } + scp->term.num_param = scp->term.last_param + 1; + switch (c) { + + case ';': + if (scp->term.num_param < MAX_ESC_PAR) + return; + break; + + case 'A': /* set display border color */ + if (scp->term.num_param == 1) { + scp->border=scp->term.param[0] & 0xff; + if (scp == cur_console) + set_border(cur_console, scp->border); + } + break; + + case 'B': /* set bell pitch and duration */ + if (scp->term.num_param == 2) { + scp->bell_pitch = scp->term.param[0]; + scp->bell_duration = scp->term.param[1]; + } + break; + + 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; + if ((scp->term.param[0] & 0x02) + && ISFONTAVAIL(get_adapter(scp)->va_flags)) + sc_flags |= CHAR_CURSOR; + else + sc_flags &= ~CHAR_CURSOR; + } + else if (scp->term.num_param == 2) { + scp->cursor_start = scp->term.param[0] & 0x1F; + scp->cursor_end = scp->term.param[1] & 0x1F; + } + /* + * The cursor shape is global property; all virtual consoles + * are affected. Update the cursor in the current console... + */ + if (!ISGRAPHSC(cur_console)) { + remove_cursor_image(cur_console); + if (sc_flags & CHAR_CURSOR) + set_destructive_cursor(cur_console); + draw_cursor_image(cur_console); + } + break; + + case 'F': /* set ansi foreground */ + if (scp->term.num_param == 1) { + scp->term.attr_mask &= ~FOREGROUND_CHANGED; + scp->term.cur_color = scp->term.std_color = + (scp->term.std_color & 0xF000) + | ((scp->term.param[0] & 0x0F) << 8); + scp->term.cur_attr = mask2attr(&scp->term); + } + break; + + case 'G': /* set ansi background */ + if (scp->term.num_param == 1) { + scp->term.attr_mask &= ~BACKGROUND_CHANGED; + scp->term.cur_color = scp->term.std_color = + (scp->term.std_color & 0x0F00) + | ((scp->term.param[0] & 0x0F) << 12); + scp->term.cur_attr = mask2attr(&scp->term); + } + break; + + case 'H': /* set ansi reverse video foreground */ + if (scp->term.num_param == 1) { + scp->term.rev_color = + (scp->term.rev_color & 0xF000) + | ((scp->term.param[0] & 0x0F) << 8); + scp->term.cur_attr = mask2attr(&scp->term); + } + break; + + case 'I': /* set ansi reverse video background */ + if (scp->term.num_param == 1) { + scp->term.rev_color = + (scp->term.rev_color & 0x0F00) + | ((scp->term.param[0] & 0x0F) << 12); + scp->term.cur_attr = mask2attr(&scp->term); + } + break; + } + } +#if notyet + else if (scp->term.esc == 4) { /* seen ESC Q */ + /* to be filled */ + } +#endif + else if (scp->term.esc == 5) { /* seen ESC ( */ + switch (c) { + case 'B': /* iso-2022: desginate ASCII into G0 */ + break; + /* other items to be filled */ + default: + break; + } + } + scp->term.esc = 0; +} + +static void +ansi_put(scr_stat *scp, u_char *buf, int len) +{ + u_char *ptr = buf; + + /* make screensaver happy */ + if (!sticky_splash && scp == cur_console) + run_scrn_saver = FALSE; + + write_in_progress++; +outloop: + if (scp->term.esc) { + scan_esc(scp, *ptr++); + len--; + } + else if (PRINTABLE(*ptr)) { /* Print only printables */ + int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); + u_short cur_attr = scp->term.cur_attr; + u_short *cursor_pos = scp->cursor_pos; + do { + /* + * gcc-2.6.3 generates poor (un)sign extension code. Casting the + * pointers in the following to volatile should have no effect, + * but in fact speeds up this inner loop from 26 to 18 cycles + * (+ cache misses) on i486's. + */ +#define UCVP(ucp) ((u_char volatile *)(ucp)) + *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; + ptr++; + cnt--; + } while (cnt && PRINTABLE(*ptr)); + len -= (cursor_pos - scp->cursor_pos); + scp->xpos += (cursor_pos - scp->cursor_pos); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + mark_for_update(scp, cursor_pos - scp->scr_buf); + scp->cursor_pos = cursor_pos; + if (scp->xpos >= scp->xsize) { + scp->xpos = 0; + scp->ypos++; + } + } + else { + switch(*ptr) { + case 0x07: + do_bell(scp, scp->bell_pitch, scp->bell_duration); + break; + + case 0x08: /* non-destructive backspace */ + if (scp->cursor_pos > scp->scr_buf) { + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->cursor_pos--; + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + if (scp->xpos > 0) + scp->xpos--; + else { + scp->xpos += scp->xsize - 1; + scp->ypos--; + } + } + break; + + case 0x09: /* non-destructive tab */ + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->cursor_pos += (8 - scp->xpos % 8u); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { + scp->xpos = 0; + scp->ypos++; + } + break; + + case 0x0a: /* newline, same pos */ + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->cursor_pos += scp->xsize; + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->ypos++; + break; + + case 0x0c: /* form feed, clears screen */ + sc_clear_screen(scp); + break; + + case 0x0d: /* return, return to pos 0 */ + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->cursor_pos -= scp->xpos; + mark_for_update(scp, scp->cursor_pos - scp->scr_buf); + scp->xpos = 0; + break; + + case 0x1b: /* start escape sequence */ + scp->term.esc = 1; + scp->term.num_param = 0; + break; + } + ptr++; len--; + } + /* do we have to scroll ?? */ + if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { + remove_cutmarking(scp); + if (scp->history != NULL) { + bcopy(scp->scr_buf, scp->history_head, + scp->xsize * sizeof(u_short)); + scp->history_head += scp->xsize; + if (scp->history_head + scp->xsize > + scp->history + scp->history_size) + scp->history_head = scp->history; + } + bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, + scp->xsize * (scp->ysize - 1) * sizeof(u_short)); + fillw(scp->term.cur_color | scr_map[0x20], + scp->scr_buf + scp->xsize * (scp->ysize - 1), + scp->xsize); + scp->cursor_pos -= scp->xsize; + scp->ypos--; + mark_all(scp); + } + if (len) + goto outloop; + write_in_progress--; + if (delayed_next_scr) + switch_scr(scp, delayed_next_scr - 1); +} + +static void +scinit(void) +{ + int col; + int row; + u_int i; + + if (init_done != COLD) + return; + init_done = WARM; + + /* extract the hardware cursor location and move it out of the way */ + (*biosvidsw.read_hw_cursor)(V_ADP_PRIMARY, &col, &row); + (*biosvidsw.set_hw_cursor)(V_ADP_PRIMARY, -1, -1); + + /* set up the first console */ + current_default = &user_default; + console[0] = &main_console; + init_scp(console[0]); + cur_console = console[0]; + + /* copy screen to temporary buffer */ + if (ISTEXTSC(console[0])) + generic_bcopy((ushort *)(get_adapter(console[0])->va_window), 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; + console[0]->cursor_saveunder = *console[0]->cursor_pos; + for (i=1; i<MAXCONS; i++) + console[i] = NULL; + kernel_console.esc = 0; + kernel_console.attr_mask = NORMAL_ATTR; + kernel_console.cur_attr = + kernel_console.cur_color = kernel_console.std_color = + kernel_default.std_color; + kernel_console.rev_color = kernel_default.rev_color; + + /* initialize mapscrn arrays to a one to one map */ + for (i=0; i<sizeof(scr_map); i++) { + scr_map[i] = scr_rmap[i] = i; + } + + /* Save font and palette */ + if (ISFONTAVAIL(get_adapter(cur_console)->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); + } + /* + * FONT KLUDGE + * Always use the font page #0. XXX + */ + (*biosvidsw.show_font)(cur_console->adp, 0); + } + save_palette(cur_console, palette); + +#ifdef SC_SPLASH_SCREEN + /* put up the splash. */ + scsplash_init(cur_console); +#endif +} + +static void +scshutdown(int howto, void *arg) +{ + 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) +{ + int error; + + if ((error = wait_scrn_saver_stop())) + return error; + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + return 0; +} + +void +sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) +{ + 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); + + 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); +} + +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'; + } +} + +void +sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) +{ + u_short *usp; + + 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; + } + + 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; +} + +static scr_stat +*alloc_scp() +{ + scr_stat *scp; + + scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); + init_scp(scp); + sc_alloc_scr_buffer(scp, TRUE, TRUE); + if (ISMOUSEAVAIL(get_adapter(scp)->va_flags)) + sc_alloc_cut_buffer(scp, TRUE); + sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); +/* SOS + if (get_adapter(scp)->va_flags & V_ADP_MODECHANGE) + set_mode(scp); +*/ + sc_clear_screen(scp); + scp->cursor_saveunder = *scp->cursor_pos; + return scp; +} + +static void +init_scp(scr_stat *scp) +{ + video_info_t info; + + scp->adp = V_ADP_PRIMARY; + (*biosvidsw.get_info)(scp->adp, initial_video_mode, &info); + + scp->status = 0; + scp->mode = scp->initial_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; + } + scp->xoff = scp->yoff = 0; + scp->xpos = scp->ypos = 0; + scp->saved_xpos = scp->saved_ypos = -1; + scp->start = scp->xsize * scp->ysize; + scp->end = 0; + scp->term.esc = 0; + scp->term.attr_mask = NORMAL_ATTR; + scp->term.cur_attr = + scp->term.cur_color = scp->term.std_color = + current_default->std_color; + scp->term.rev_color = current_default->rev_color; + scp->border = BG_BLACK; + scp->cursor_start = *(u_int8_t *)pa_to_va(0x461); + scp->cursor_end = *(u_int8_t *)pa_to_va(0x460); + 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->bell_pitch = BELL_PITCH; + scp->bell_duration = BELL_DURATION; + scp->status |= (*(u_int8_t *)pa_to_va(0x417) & 0x20) ? NLKED : 0; + scp->status |= CURSOR_ENABLED; + scp->pid = 0; + scp->proc = NULL; + scp->smode.mode = VT_AUTO; + scp->history_head = scp->history_pos = scp->history = NULL; + scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; +} + +static u_char +*get_fstr(u_int c, u_int *len) +{ + 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 +history_to_screen(scr_stat *scp) +{ + int i; + + for (i=0; i<scp->ysize; i++) + bcopy(scp->history + (((scp->history_pos - scp->history) + + scp->history_size-((i+1)*scp->xsize))%scp->history_size), + scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), + scp->xsize * sizeof(u_short)); + mark_all(scp); +} + +static int +history_up_line(scr_stat *scp) +{ + if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != + scp->history_head) { + scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); + history_to_screen(scp); + return 0; + } + else + return -1; +} + +static int +history_down_line(scr_stat *scp) +{ + if (scp->history_pos != scp->history_head) { + scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); + history_to_screen(scp); + return 0; + } + else + return -1; +} + +/* + * scgetc(flags) - get character from keyboard. + * If flags & SCGETC_CN, then avoid harmful side effects. + * If flags & SCGETC_NONBLOCK, then wait until a key is pressed, else + * return NOKEY if there is nothing there. + */ +static u_int +scgetc(u_int flags) +{ + 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: + /* first see if there is something in the keyboard port */ + 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 (!(scancode & 0x80)) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + } + + if (!(flags & SCGETC_CN)) { + /* do the /dev/random device a favour */ + 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; + + /* 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 (cur_console->history && cur_console->status & SLKED) { + int i; + + cur_console->status &= ~CURSOR_ENABLED; + if (!(cur_console->status & BUFFER_SAVED)) { + cur_console->status |= BUFFER_SAVED; + cur_console->history_save = cur_console->history_head; + + /* copy screen into top of history buffer */ + for (i=0; i<cur_console->ysize; i++) { + bcopy(cur_console->scr_buf + (cur_console->xsize * i), + cur_console->history_head, + cur_console->xsize * sizeof(u_short)); + cur_console->history_head += cur_console->xsize; + if (cur_console->history_head + cur_console->xsize > + cur_console->history + cur_console->history_size) + cur_console->history_head=cur_console->history; + } + cur_console->history_pos = cur_console->history_head; + history_to_screen(cur_console); + } + switch (scancode) { + case 0x47: /* home key */ + cur_console->history_pos = cur_console->history_head; + history_to_screen(cur_console); + goto next_code; + + case 0x4F: /* end key */ + cur_console->history_pos = + WRAPHIST(cur_console, cur_console->history_head, + cur_console->xsize*cur_console->ysize); + history_to_screen(cur_console); + goto next_code; + + case 0x48: /* up arrow key */ + if (history_up_line(cur_console)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + goto next_code; + + case 0x50: /* down arrow key */ + if (history_down_line(cur_console)) + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + goto next_code; + + case 0x49: /* page up key */ + for (i=0; i<cur_console->ysize; i++) + if (history_up_line(cur_console)) { + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + break; + } + goto next_code; + + case 0x51: /* page down key */ + for (i=0; i<cur_console->ysize; i++) + if (history_down_line(cur_console)) { + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + break; + } + 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: + clkcnt = 0; + 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 (key->spcl & (0x80>>state)) { + switch (action) { + /* LOCKING KEYS */ + 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: + if (!clkcnt) { + clkcnt++; + if (cur_console->status & CLKED) + cur_console->status &= ~CLKED; + else + cur_console->status |= CLKED; + update_leds(cur_console->status); + } + break; + case SLK: + if (!slkcnt) { + slkcnt++; + if (cur_console->status & SLKED) { + cur_console->status &= ~SLKED; + if (cur_console->status & BUFFER_SAVED){ + int i; + u_short *ptr = cur_console->history_save; + + for (i=0; i<cur_console->ysize; i++) { + bcopy(ptr, + cur_console->scr_buf + + (cur_console->xsize*i), + cur_console->xsize * sizeof(u_short)); + ptr += cur_console->xsize; + if (ptr + cur_console->xsize > + cur_console->history + + cur_console->history_size) + ptr = 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); + } + 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: + break; + case SPSC: + /* force activatation/deactivation of the screen saver */ + accents = 0; + if (scrn_blanked <= 0) { + run_scrn_saver = TRUE; + scrn_time_stamp -= scrn_blank_time; + } +#ifdef SC_SPLASH_SCREEN + if (cold) { + /* + * While devices are being probed, the screen saver need + * to be invoked explictly. XXX + */ + if (scrn_blanked > 0) { + scsplash_stick(FALSE); + stop_scrn_saver(current_saver); + } else { + if (!ISGRAPHSC(cur_console)) { + scsplash_stick(TRUE); + scrn_saver(current_saver, TRUE); + } + } + } +#endif + break; + case RBT: +#ifndef SC_DISABLE_REBOOT + accents = 0; + shutdown_nice(); +#endif + break; + case SUSP: +#if NAPM > 0 + accents = 0; + apm_suspend(PMST_SUSPEND); +#endif + break; + + case STBY: +#if NAPM > 0 + accents = 0; + apm_suspend(PMST_STANDBY); +#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 + * the vty0. + */ + scrn_timer((void *)FALSE); + if (cur_console->smode.mode == VT_AUTO && + console[0]->smode.mode == VT_AUTO) + switch_scr(cur_console, 0); + Debugger("manual escape to debugger"); +#else + 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: + { + 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, next); + break; + } + } + } + break; + case BTAB: + accents = 0; + return(BKEY); + default: + 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; + } + if (action >= F_FN && action <= L_FN) + action |= FKEY; + return(action); + } + } + 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, int offset, int nprot) +{ + if (offset > 0x20000 - PAGE_SIZE) + return -1; + return i386_btop((VIDEOMEM + offset)); +} + +/* + * Calculate hardware attributes word using logical attributes mask and + * hardware colors + */ + +static int +mask2attr(struct term_stat *term) +{ + int attr, mask = term->attr_mask; + + if (mask & REVERSE_ATTR) { + attr = ((mask & FOREGROUND_CHANGED) ? + ((term->cur_color & 0xF000) >> 4) : + (term->rev_color & 0x0F00)) | + ((mask & BACKGROUND_CHANGED) ? + ((term->cur_color & 0x0F00) << 4) : + (term->rev_color & 0xF000)); + } else + attr = term->cur_color; + + /* XXX: underline mapping for Hercules adapter can be better */ + if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) + attr ^= 0x0800; + if (mask & BLINK_ATTR) + attr ^= 0x8000; + + return attr; +} + +static void +set_keyboard(int command, int data) +{ + int s; + + if (sc_kbdc == NULL) + return; + + /* prevent the timeout routine from polling the keyboard */ + if (!kbdc_lock(sc_kbdc, TRUE)) + return; + + /* 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; + } + /* + * 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 + + if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) + send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); + +#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 */ + } +#else + splx(s); +#endif + kbdc_lock(sc_kbdc, FALSE); +} + +static void +update_leds(int which) +{ + static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + /* 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]); +} + +int +set_mode(scr_stat *scp) +{ + video_info_t info; + video_adapter_t *adp; + + /* reject unsupported mode */ + if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) + return 1; + + /* if this vty is not currently showing, do nothing */ + if (scp != cur_console) + return 0; + + /* setup video hardware for the given mode */ + adp = get_adapter(scp); + (*biosvidsw.set_mode)(scp->adp, scp->mode); + Crtat = (u_short *)adp->va_window; + + if (!(scp->status & GRAPHICS_MODE)) { + /* load appropriate font */ + if (!(scp->status & PIXEL_MODE) + && ISFONTAVAIL(get_adapter(scp)->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 + */ + (*biosvidsw.show_font)(scp->adp, 0); + } + mark_all(scp); + } + + if (scp->status & PIXEL_MODE) + generic_bzero((u_char *)(adp->va_window), scp->xpixel*scp->ypixel/8); + set_border(scp, scp->border); + + /* move hardware cursor out of the way */ + (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); + + return 0; +} + +void +set_border(scr_stat *scp, int color) +{ + u_char *p; + int xoff; + int yoff; + int xlen; + int ylen; + int i; + + (*biosvidsw.set_border)(scp->adp, color); + + 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 *)(get_adapter(scp)->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 */ + } +} + +void +copy_font(scr_stat *scp, int operation, int font_size, 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 + */ + font_loading_in_progress = TRUE; + if (operation == LOAD) { + (*biosvidsw.load_font)(scp->adp, 0, font_size, buf, 0, 256); + if (sc_flags & CHAR_CURSOR) + set_destructive_cursor(scp); + } else if (operation == SAVE) { + (*biosvidsw.save_font)(scp->adp, 0, font_size, buf, 0, 256); + } + font_loading_in_progress = FALSE; +} + +static void +set_destructive_cursor(scr_stat *scp) +{ + u_char cursor[32]; + u_char *font_buffer; + int font_size; + int i; + + if (!ISFONTAVAIL(get_adapter(scp)->va_flags) + || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) + return; + + if (scp->font_size < 14) { + font_buffer = font_8; + font_size = 8; + } else if (scp->font_size >= 16) { + font_buffer = font_16; + font_size = 16; + } else { + font_buffer = font_14; + font_size = 14; + } + + if (scp->status & MOUSE_VISIBLE) { + if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) + bcopy(&scp->mouse_cursor[0], cursor, scp->font_size); + else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 1) + bcopy(&scp->mouse_cursor[32], cursor, scp->font_size); + else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 2) + bcopy(&scp->mouse_cursor[64], cursor, scp->font_size); + else if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR + 3) + bcopy(&scp->mouse_cursor[96], cursor, scp->font_size); + else + bcopy(font_buffer+((scp->cursor_saveunder & 0xff)*scp->font_size), + cursor, scp->font_size); + } + else + bcopy(font_buffer + ((scp->cursor_saveunder & 0xff) * scp->font_size), + cursor, scp->font_size); + for (i=0; i<32; i++) + if ((i >= scp->cursor_start && i <= scp->cursor_end) || + (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) + cursor[i] |= 0xff; +#if 1 + while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; +#endif + font_loading_in_progress = TRUE; + (*biosvidsw.load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); + font_loading_in_progress = FALSE; +} + +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) +{ + static int last_xpos = -1, last_ypos = -1; + + if (scp->mouse_xpos < 0) + scp->mouse_xpos = 0; + if (scp->mouse_ypos < 0) + scp->mouse_ypos = 0; + if (!ISTEXTSC(scp)) { + if (scp->mouse_xpos > scp->xpixel-1) + scp->mouse_xpos = scp->xpixel-1; + if (scp->mouse_ypos > scp->ypixel-1) + scp->mouse_ypos = scp->ypixel-1; + return; + } + if (scp->mouse_xpos > (scp->xsize*8)-1) + scp->mouse_xpos = (scp->xsize*8)-1; + if (scp->mouse_ypos > (scp->ysize*scp->font_size)-1) + scp->mouse_ypos = (scp->ysize*scp->font_size)-1; + + if (scp->mouse_xpos != last_xpos || scp->mouse_ypos != last_ypos) { + scp->status |= MOUSE_MOVED; + + scp->mouse_pos = scp->scr_buf + + ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); + + if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) + mouse_cut(scp); + } +} + +#define isspace(c) (((c) & 0xff) == ' ') + +static int +skip_spc_right(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + return i; +} + +static int +skip_spc_left(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { + if (!isspace(*p)) + break; + --p; + } + return i; +} + +static void +mouse_cut(scr_stat *scp) +{ + u_short *end; + u_short *p; + int i = 0; + int j = 0; + + scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? + scp->mouse_pos + 1 : scp->mouse_pos; + end = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_start : scp->mouse_cut_end; + for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { + cut_buffer[i] = *p & 0xff; + /* remember the position of the last non-space char */ + if (!isspace(cut_buffer[i++])) + j = i; + /* trim trailing blank when crossing lines */ + if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { + cut_buffer[j++] = '\r'; + i = j; + } + } + cut_buffer[i] = '\0'; + + /* scan towards the end of the last line */ + --p; + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + /* if there is nothing but blank chars, trim them, but mark towards eol */ + if (i >= scp->xsize) { + if (scp->mouse_cut_start > scp->mouse_cut_end) + scp->mouse_cut_start = p; + else + scp->mouse_cut_end = p; + cut_buffer[j++] = '\r'; + cut_buffer[j] = '\0'; + } + + mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); + mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); +} + +static void +mouse_cut_start(scr_stat *scp) +{ + int i; + + if (scp->status & MOUSE_VISIBLE) { + if (scp->mouse_pos == scp->mouse_cut_start && + scp->mouse_cut_start == scp->mouse_cut_end - 1) { + cut_buffer[0] = '\0'; + remove_cutmarking(scp); + } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { + /* if the pointer is on trailing blank chars, mark towards eol */ + i = skip_spc_left(scp, scp->mouse_pos) + 1; + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; + scp->mouse_cut_end = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; + cut_buffer[0] = '\r'; + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; + } else { + scp->mouse_cut_start = scp->mouse_pos; + scp->mouse_cut_end = scp->mouse_cut_start + 1; + cut_buffer[0] = *scp->mouse_cut_start & 0xff; + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; + } + mark_all(scp); + /* delete all other screens cut markings */ + for (i=0; i<MAXCONS; i++) { + if (console[i] == NULL || console[i] == scp) + continue; + remove_cutmarking(console[i]); + } + } +} + +static void +mouse_cut_end(scr_stat *scp) +{ + if (scp->status & MOUSE_VISIBLE) { + scp->status &= ~MOUSE_CUTTING; + } +} + +static void +mouse_cut_word(scr_stat *scp) +{ + u_short *p; + u_short *sol; + u_short *eol; + int i; + + /* + * Because we don't have locale information in the kernel, + * we only distinguish space char and non-space chars. Punctuation + * chars, symbols and other regular chars are all treated alike. + */ + if (scp->status & MOUSE_VISIBLE) { + sol = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + eol = sol + scp->xsize; + if (isspace(*scp->mouse_pos)) { + for (p = scp->mouse_pos; p >= sol; --p) + if (!isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (!isspace(*p)) + break; + scp->mouse_cut_end = p; + } else { + for (p = scp->mouse_pos; p >= sol; --p) + if (isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (isspace(*p)) + break; + scp->mouse_cut_end = p; + } + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_line(scr_stat *scp) +{ + u_short *p; + int i; + + if (scp->status & MOUSE_VISIBLE) { + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i++] = '\r'; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_extend(scr_stat *scp) +{ + if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) + && (scp->mouse_cut_start != NULL)) { + mouse_cut(scp); + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_paste(scr_stat *scp) +{ + if (scp->status & MOUSE_VISIBLE) { + struct tty *tp; + u_char *ptr = cut_buffer; + + tp = VIRTUAL_TTY(get_scr_num()); + while (*ptr) + (*linesw[tp->t_line].l_rint)(scr_rmap[*ptr++], tp); + } +} + +static void +draw_mouse_image(scr_stat *scp) +{ + u_short buffer[32]; + u_short xoffset, yoffset; + u_short *crt_pos = (u_short *)(get_adapter(scp)->va_window) + + (scp->mouse_pos - scp->scr_buf); + u_char *font_buffer; + int font_size; + int i; + + if (scp->font_size < 14) { + font_buffer = font_8; + font_size = 8; + } else if (scp->font_size >= 16) { + font_buffer = font_16; + font_size = 16; + } else { + font_buffer = font_14; + font_size = 14; + } + + xoffset = scp->mouse_xpos % 8; + yoffset = scp->mouse_ypos % scp->font_size; + + /* prepare mousepointer char's bitmaps */ + bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), + &scp->mouse_cursor[0], font_size); + bcopy(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), + &scp->mouse_cursor[32], font_size); + bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), + &scp->mouse_cursor[64], font_size); + bcopy(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), + &scp->mouse_cursor[96], font_size); + for (i=0; i<font_size; i++) { + buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; + buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; + } + + /* now and-or in the mousepointer image */ + for (i=0; i<16; i++) { + buffer[i+yoffset] = + ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) + | (mouse_or_mask[i] >> xoffset); + } + for (i=0; i<font_size; i++) { + scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; + scp->mouse_cursor[i+32] = buffer[i] & 0xff; + scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; + scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; + } + + scp->mouse_oldpos = scp->mouse_pos; + +#if 1 + /* wait for vertical retrace to avoid jitter on some videocards */ + while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; +#endif + font_loading_in_progress = TRUE; + (*biosvidsw.load_font)(scp->adp, 0, 32, scp->mouse_cursor, + SC_MOUSE_CHAR, 4); + font_loading_in_progress = FALSE; + + *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR; + *(crt_pos+scp->xsize) = + (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2); + if (scp->mouse_xpos < (scp->xsize-1)*8) { + *(crt_pos + 1) = (*(scp->mouse_pos + 1) & 0xff00) | (SC_MOUSE_CHAR + 1); + *(crt_pos+scp->xsize + 1) = + (*(scp->mouse_pos + scp->xsize + 1) & 0xff00) | (SC_MOUSE_CHAR + 3); + } + mark_for_update(scp, scp->mouse_pos - scp->scr_buf); + mark_for_update(scp, scp->mouse_pos + scp->xsize + 1 - scp->scr_buf); +} + +static void +remove_mouse_image(scr_stat *scp) +{ + u_short *crt_pos; + + if (!ISTEXTSC(scp)) + return; + + crt_pos = (u_short *)(get_adapter(scp)->va_window) + + (scp->mouse_oldpos - scp->scr_buf); + *(crt_pos) = *(scp->mouse_oldpos); + *(crt_pos+1) = *(scp->mouse_oldpos+1); + *(crt_pos+scp->xsize) = *(scp->mouse_oldpos+scp->xsize); + *(crt_pos+scp->xsize+1) = *(scp->mouse_oldpos+scp->xsize+1); + mark_for_update(scp, scp->mouse_oldpos - scp->scr_buf); + mark_for_update(scp, scp->mouse_oldpos + scp->xsize + 1 - scp->scr_buf); +} + +static void +draw_cutmarking(scr_stat *scp) +{ + u_short *crt_pos; + u_short *ptr; + u_short och, nch; + + crt_pos = (u_short *)(get_adapter(scp)->va_window); + 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) || + ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? + scp->mouse_cut_start : scp->mouse_cut_end)) { + if (ptr != scp->cursor_pos) + nch = (och & 0xff) | (*ptr & 0xff00); + } + else { + /* are we clear of the cursor image ? */ + if (ptr != scp->cursor_pos) + nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; + else { + if (sc_flags & CHAR_CURSOR) + nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; + else + if (!(sc_flags & BLINK_CURSOR)) + nch = (och & 0xff) | (*ptr & 0xff00); + } + } + if (nch != och) + *(crt_pos + (ptr - scp->scr_buf)) = nch; + } +} + +static void +remove_cutmarking(scr_stat *scp) +{ + scp->mouse_cut_start = scp->mouse_cut_end = NULL; + scp->status &= ~MOUSE_CUTTING; + mark_all(scp); +} + +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)) + return; + + if (sc_flags & VISUAL_BELL) { + if (blink_in_progress) + return; + blink_in_progress = 4; + if (scp != cur_console) + blink_in_progress += 2; + blink_screen(cur_console); + } else { + if (scp != cur_console) + pitch *= 2; + sysbeep(pitch, duration); + } +} + +static void +blink_screen(void *arg) +{ + scr_stat *scp = arg; + + if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { + blink_in_progress = FALSE; + mark_all(scp); + if (delayed_next_scr) + switch_scr(scp, delayed_next_scr - 1); + } + else { + if (blink_in_progress & 1) + fillw(kernel_default.std_color | scr_map[0x20], + (u_short *)(get_adapter(scp)->va_window), + scp->xsize * scp->ysize); + else + fillw(kernel_default.rev_color | scr_map[0x20], + (u_short *)(get_adapter(scp)->va_window), + scp->xsize * scp->ysize); + blink_in_progress--; + timeout(blink_screen, scp, hz / 10); + } +} + +void +sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) +{ + 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 (ISTEXTSC(scp)) { + generic_bcopy(p + from, (u_short *)(get_adapter(scp)->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 *)(get_adapter(scp)->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; + 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; + } + d++; + if ((i % xsize) == xsize - 1) + d += scp->xoff*2 + (font_size - 1)*line_length; + } + 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; + } + outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ + outw(GDCIDX, 0x0000); /* set/reset */ + outw(GDCIDX, 0x0001); /* set/reset enable */ +#endif /* 0 */ + } +} + +#ifdef SC_SPLASH_SCREEN + +static void +scsplash_init(scr_stat *scp) +{ + video_info_t info; + + if (scsplash_load(scp) == 0 && add_scrn_saver(scsplash_saver) == 0) { + default_saver = scsplash_saver; + scrn_blank_time = DEFAULT_BLANKTIME; + run_scrn_saver = TRUE; + if (!(boothowto & (RB_VERBOSE | RB_CONFIG))) { + scsplash_stick(TRUE); + scsplash_saver(TRUE); + } + } +} + +static void +scsplash_term(scr_stat *scp) +{ + default_saver = none_saver; + scsplash_stick(FALSE); + remove_scrn_saver(scsplash_saver); + scsplash_unload(scp); +} + +static void +scsplash_saver(int show) +{ + if (show) + scsplash(TRUE); + else if (!sticky_splash) + scsplash(FALSE); +} + +#endif /* SC_SPLASH_SCREEN */ + +#endif /* NSC */ diff --git a/sys/i386/isa/syscons.h b/sys/i386/isa/syscons.h new file mode 100644 index 0000000000000..0298cbbf2f400 --- /dev/null +++ b/sys/i386/isa/syscons.h @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 1995-1998 Søren 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. + * 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: syscons.h,v 1.43 1998/09/29 02:00:57 ache Exp $ + */ + +#ifndef _I386_ISA_SYSCONS_H_ +#define _I386_ISA_SYSCONS_H_ + +/* vm things */ +#define ISMAPPED(pa, width) \ + (((pa) <= (u_long)0x1000 - (width)) \ + || ((pa) >= 0xa0000 && (pa) <= 0x100000 - (width))) +#define pa_to_va(pa) (KERNBASE + (pa)) /* works if ISMAPPED(pa...) */ + +/* printable chars */ +#define PRINTABLE(ch) ((ch) > 0x1b || ((ch) > 0x0d && (ch) < 0x1b) \ + || (ch) < 0x07) + +/* macros for "intelligent" screen update */ +#define mark_for_update(scp, x) {\ + if ((x) < scp->start) scp->start = (x);\ + else if ((x) > scp->end) scp->end = (x);\ + } +#define mark_all(scp) {\ + scp->start = 0;\ + scp->end = scp->xsize * scp->ysize - 1;\ + } + +/* 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 +#define CURSOR_ENABLED 0x00400 +#define MOUSE_ENABLED 0x00800 +#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 +#define DETECT_KBD 0x00008 +#define XT_KEYBD 0x00010 +#define KBD_NORESET 0x00020 +#define QUIET_BELL 0x00040 +#define VESA800X600 0x00080 + +/* attribute flags */ +#define NORMAL_ATTR 0x00 +#define BLINK_ATTR 0x01 +#define BOLD_ATTR 0x02 +#define UNDERLINE_ATTR 0x04 +#define REVERSE_ATTR 0x08 +#define FOREGROUND_CHANGED 0x10 +#define BACKGROUND_CHANGED 0x20 + +/* misc defines */ +#define FALSE 0 +#define TRUE 1 +#define MAX_ESC_PAR 5 +#define LOAD 1 +#define SAVE 0 +#define COL 80 +#define ROW 25 +#define BELL_DURATION 5 +#define BELL_PITCH 800 +#define CONSOLE_BUFSIZE 1024 +#define PCBURST 128 +#define FONT_NONE 1 +#define FONT_8 2 +#define FONT_14 4 +#define FONT_16 8 + +/* special characters */ +#define cntlc 0x03 +#define cntld 0x04 +#define bs 0x08 +#define lf 0x0a +#define cr 0x0d +#define del 0x7f + +#define DEAD_CHAR 0x07 /* char used for cursor */ + +typedef struct term_stat { + int esc; /* processing escape sequence */ + int num_param; /* # of parameters to ESC */ + int last_param; /* last parameter # */ + int param[MAX_ESC_PAR]; /* contains ESC parameters */ + int cur_attr; /* current hardware attr word */ + int attr_mask; /* current logical attr mask */ + int cur_color; /* current hardware color */ + int std_color; /* normal hardware color */ + int rev_color; /* reverse hardware color */ +} term_stat; + +typedef struct scr_stat { + int adp; /* video adapter index */ + u_short *scr_buf; /* buffer when off screen */ + int xpos; /* current X position */ + int ypos; /* current Y position */ + int saved_xpos; /* saved X position */ + int saved_ypos; /* saved Y position */ + int xsize; /* X text size */ + 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) */ + u_short *cursor_pos; /* cursor buffer position */ + u_short *cursor_oldpos; /* cursor old buffer position */ + u_short cursor_saveunder; /* saved chars under cursor */ + char cursor_start; /* cursor start line # */ + char cursor_end; /* cursor end line # */ + u_short *mouse_pos; /* mouse buffer position */ + u_short *mouse_oldpos; /* mouse old buffer position */ + short mouse_xpos; /* mouse x coordinate */ + short mouse_ypos; /* mouse y coordinate */ + short mouse_buttons; /* mouse buttons */ + u_char mouse_cursor[128]; /* mouse cursor bitmap store */ + u_short *mouse_cut_start; /* mouse cut start pos */ + u_short *mouse_cut_end; /* mouse cut end pos */ + struct proc *mouse_proc; /* proc* of controlling proc */ + pid_t mouse_pid; /* pid of controlling proc */ + int mouse_signal; /* signal # to report with */ + 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 */ + struct vt_mode smode; /* switch mode */ + u_short *history; /* circular history buffer */ + u_short *history_head; /* current head position */ + u_short *history_pos; /* position shown on screen */ + u_short *history_save; /* save area index */ + int history_size; /* size of history buffer */ + struct apmhook r_hook; /* reconfiguration support */ +#ifdef SC_SPLASH_SCREEN + int splash_save_mode; /* saved mode for splash screen */ + int splash_save_status; /* saved status for splash screen */ +#endif +} scr_stat; + +typedef struct default_attr { + int std_color; /* normal hardware color */ + 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 */ + +/* 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(scp, pal) (*biosvidsw.save_palette)((scp)->adp, pal) +#define load_palette(scp, pal) (*biosvidsw.load_palette)((scp)->adp, pal) +#define get_adapter(scp) (*biosvidsw.adapter)((scp)->adp) + +int add_scrn_saver(void (*this)(int)); +int remove_scrn_saver(void (*this)(int)); + +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 +/* splash.c */ +void scsplash(int); +int scsplash_load(scr_stat *scp); +int scsplash_unload(scr_stat *scp); +#endif + +#endif /* !_I386_ISA_SYSCONS_H_ */ diff --git a/sys/i386/isa/syscons_isa.c b/sys/i386/isa/syscons_isa.c deleted file mode 100644 index e96542fba603e..0000000000000 --- a/sys/i386/isa/syscons_isa.c +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * Copyright (c) 1999 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:$ - */ - -#include "sc.h" -#include "opt_syscons.h" - -#if NSC > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> - -#include <machine/console.h> -#include <machine/apm_bios.h> - -#include <dev/syscons/syscons.h> - -#include <i386/isa/isa_device.h> - -static int scprobe(struct isa_device *dev); -static int scattach(struct isa_device *dev); - -struct isa_driver scdriver = { - scprobe, - scattach, - "sc", - 1 -}; - -static int -scprobe(struct isa_device *dev) -{ - int error; - - error = sc_probe_unit(dev->id_unit, dev->id_flags); - return ((error == 0) ? -1 : 0); -} - -static int -scattach(struct isa_device *dev) -{ - int error; - - error = sc_attach_unit(dev->id_unit, dev->id_flags); - return ((error == 0) ? 0 : 1); -} - -#endif /* NSC > 0 */ diff --git a/sys/i386/isa/tw.c b/sys/i386/isa/tw.c index ce98e65dfebe7..5c2a661ee810c 100644 --- a/sys/i386/isa/tw.c +++ b/sys/i386/isa/tw.c @@ -274,7 +274,6 @@ static void twdelayn(int n); static void twsetuptimes(int *a); static int wait_for_zero(struct tw_sc *sc); static int twputpkt(struct tw_sc *sc, u_char *p); -static ointhand2_t twintr; static int twgetbytes(struct tw_sc *sc, u_char *p, int cnt); static timeout_t twabortrcv; static int twsend(struct tw_sc *sc, int h, int k, int cnt); @@ -392,7 +391,6 @@ static int twattach(idp) struct tw_sc *sc; int unit; - idp->id_ointr = twintr; sc = &tw_sc[unit = idp->id_unit]; sc->sc_port = idp->id_iobase; sc->sc_state = 0; @@ -416,6 +414,7 @@ int twopen(dev, flag, mode, p) { struct tw_sc *sc = &tw_sc[TWUNIT(dev)]; int s; + int port; s = spltty(); if(sc->sc_state == 0) { @@ -436,6 +435,7 @@ int twclose(dev, flag, mode, p) { struct tw_sc *sc = &tw_sc[TWUNIT(dev)]; int s; + int port = sc->sc_port; s = spltty(); sc->sc_state = 0; @@ -918,7 +918,7 @@ tw_is_within(int value, int expected, int tolerance) * reconstruct the transmission without having to poll. */ -static void twintr(unit) +void twintr(unit) int unit; { struct tw_sc *sc = &tw_sc[unit]; diff --git a/sys/i386/isa/ultra14f.c b/sys/i386/isa/ultra14f.c new file mode 100644 index 0000000000000..8d01bef01fe2a --- /dev/null +++ b/sys/i386/isa/ultra14f.c @@ -0,0 +1,1362 @@ +/* + * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu) + * Slight fixes to timeouts to run with the 34F + * Thanks to Julian Elischer for advice and help with this port. + * + * Written by Julian Elischer (julian@tfs.com) + * for TRW Financial Systems for use under the MACH(2.5) operating system. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + * commenced: Sun Sep 27 18:14:01 PDT 1992 + * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993 + * + * today: Fri Jun 2 17:21:03 EST 1994 + * added 24F support ++sg + * + * $Id: ultra14f.c,v 1.60 1998/06/08 09:47:37 bde Exp $ + */ + +#ifdef KERNEL /* don't laugh.. this compiles to a program too.. look */ +#include "uha.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/kernel.h> + +#include <machine/clock.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <i386/isa/isa_device.h> +#endif /*KERNEL */ +#include <scsi/scsiconf.h> +#include <scsi/scsi_debug.h> + +/* */ + +#ifndef KERNEL +#define NUHA 1 +#endif /*KERNEL */ + +typedef struct { + unsigned char addr[4]; +} physaddr; +typedef struct { + unsigned char len[4]; +} physlen; + +#define KVTOPHYS(x) vtophys(x) + +#define UHA_MSCP_MAX 32 /* store up to 32MSCPs at any one time + * MAX = ? + */ +#define MSCP_HASH_SIZE 32 /* when we have a physical addr. for + * a mscp and need to find the mscp in + * space, look it up in the hash table + */ +#define MSCP_HASH_SHIFT 9 /* only hash on multiples of 512 */ +#define MSCP_HASH(x) ((((long int)(x))>>MSCP_HASH_SHIFT) % MSCP_HASH_SIZE) + +#define UHA_NSEG 33 /* number of dma segments supported */ + +/************************** board definitions *******************************/ +struct uha_reg +{ + int id; /* product id reg */ + int type; /* product type reg */ + int ectl; /* EISA expansion control bits */ + int config; /* configuration bits */ + int lmask; /* local doorbell mask reg */ + int lint; /* local doorbell int/stat reg */ + int smask; /* system doorbell mask reg */ + int sint; /* system doorbell int/stat reg */ + int ogmcmd; /* outgoing mail command */ + int ogmptr; /* outgoing mail ptr */ + int icmcmd; /* incoming mail command */ + int icmptr; /* incoming mail ptr */ +}; + +struct uha_bits +{ + /* uha_lint (read) */ + unsigned char ldip; + + /* uha_lint (write) */ + unsigned char adrst; + unsigned char sbrst; + unsigned char asrst; + unsigned char abort; + unsigned char ogmint; + + /* uha_sint (read) */ + unsigned char sintp; + unsigned char abort_succ; + unsigned char abort_fail; + + /* uha_sint (write) */ + unsigned char abort_ack; + unsigned char icm_ack; +}; + + +/* + * UHA_LINT bits (read) + */ + +#define UHA_LDIP 0x80 /* local doorbell int pending */ +#define U24_LDIP 0x02 + +/* + * UHA_LINT bits (write) + */ + +#define UHA_ADRST 0x40 /* adapter soft reset */ +#define UHA_SBRST 0x20 /* scsi bus reset */ +#define UHA_ASRST 0x60 /* adapter and scsi reset */ +#define UHA_ABORT 0x10 /* abort MSCP */ +#define UHA_OGMINT 0x01 /* tell adapter to get mail */ +#define U24_SBRST 0x40 /* scsi bus reset */ +#define U24_ADRST 0x80 /* adapter soft reset */ +#define U24_ASRST 0xc0 /* adapter and scsi reset */ +#define U24_ABORT 0x10 /* same? */ +#define U24_OGMINT 0x02 /* enable OGM interrupt */ + +/* + * UHA_SMASK bits (read) + */ + +#define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */ +#define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */ +#define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled */ + +/* + * UHA_SMASK bits (write) + */ + +#define UHA_ENSINT 0x80 /* enable system doorbell interrupt */ +#define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */ +#define UHA_ENICM 0x01 /* enable ICM interrupt */ + +/* + * UHA_SINT bits (read) + */ + +#define UHA_SINTP 0x80 /* system doorbell int pending */ +#define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */ +#define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */ +#define U24_SINTP 0x02 /* system doorbell int pending */ +#define U24_ABORT_SUCC 0x10 /* same? */ +#define U24_ABORT_FAIL 0x18 /* same? */ + +/* + * UHA_SINT bits (write) + */ + +#define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */ +#define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */ +#define U24_ABORT_ACK 0x18 /* same */ +#define U24_ICM_ACK 0x02 /* 24F acknowledge ICM and clear */ + +/* + * UHA_CONF1 bits (read only) + */ + +#define UHA_DMA_CH5 0x00 /* DMA channel 5 */ +#define UHA_DMA_CH6 0x40 /* 6 */ +#define UHA_DMA_CH7 0x80 /* 7 */ +#define UHA_IRQ15 0x00 /* IRQ 15 */ +#define UHA_IRQ14 0x10 /* 14 */ +#define UHA_IRQ11 0x20 /* 11 */ +#define UHA_IRQ10 0x30 /* 10 */ + +#define EISA_CONFIG 0x0c80 /* Configuration base port */ +#define EISA_DISABLE 0x01 /* EISA disable bit */ + +/* + * ha_status error codes + */ + +#define UHA_NO_ERR 0x00 /* No error supposedly */ +#define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */ +#define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */ +#define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */ +#define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */ +#define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */ +#define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */ +#define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */ + +struct uha_dma_seg { + physaddr addr; + physlen len; +}; + +struct mscp { + unsigned int opcode:3; +#define U14_HAC 0x01 /* host adapter command */ +#define U14_TSP 0x02 /* target scsi pass through command */ +#define U14_SDR 0x04 /* scsi device reset */ + unsigned int xdir:2; /* xfer direction */ +#define U14_SDET 0x00 /* determined by scsi command */ +#define U14_SDIN 0x01 /* scsi data in */ +#define U14_SDOUT 0x02 /* scsi data out */ +#define U14_NODATA 0x03 /* no data xfer */ + unsigned int dcn:1; /* disable disconnect for this command */ + unsigned int ca:1; /* cache control */ + unsigned int sgth:1; /* scatter gather flag */ + unsigned int target:3; + unsigned int chan:2; /* scsi channel (always 0 for 14f) */ + unsigned int lun:3; + physaddr data; + physlen datalen; + physaddr link; + unsigned char link_id; + unsigned char sg_num; /*number of scat gath segs */ + /*in s-g list if sg flag is */ + /*set. starts at 1, 8bytes per */ + unsigned char senselen; + unsigned char cdblen; + unsigned char cdb[12]; + unsigned char ha_status; + unsigned char targ_status; + physaddr sense; /* if 0 no auto sense */ + /*-----------------end of hardware supported fields----------------*/ + struct mscp *next; /* in free list */ + struct scsi_xfer *xs; /* the scsi_xfer for this cmd */ + int flags; +#define MSCP_FREE 0 +#define MSCP_ACTIVE 1 +#define MSCP_ABORTED 2 + struct uha_dma_seg uha_dma[UHA_NSEG]; + struct scsi_sense_data mscp_sense; + struct mscp *nexthash; + long int hashkey; +}; + +static struct uha_data { + int flags; +#define UHA_INIT 0x01 +#define UHA_24F 0x02 + int baseport; + struct mscp *mscphash[MSCP_HASH_SIZE]; + struct mscp *free_mscp; + int unit; + int our_id; /* our scsi id */ + int vect; + int dma; + int nummscps; + struct scsi_link sc_link; + struct uha_reg *ur; + struct uha_bits *ub; +} *uhadata[NUHA]; + +static int uha_abort __P((struct uha_data *uha, struct mscp *mscp)); +static u_int32_t uha_adapter_info __P((int unit)); +static int uha_attach __P((struct isa_device *dev)); +static void uha_done __P((struct uha_data *uha, struct mscp *mscp)); +static void uha_free_mscp __P((struct uha_data *uha, struct mscp *mscp, + int flags)); +static struct mscp * + uha_get_mscp __P((struct uha_data *uha, int flags)); +static int uha_init __P((struct uha_data *uha)); +static int uha24_init __P((struct uha_data *uha)); +static void uhaminphys __P((struct buf *bp)); +static struct mscp * + uha_mscp_phys_kv __P((struct uha_data *uha, long mscp_phys)); +static int uha_poll __P((struct uha_data *uha, int wait)); +#ifdef UHADEBUG +static void uha_print_active_mscp __P((struct uha_data *uha)); +static void uha_print_mscp __P((struct mscp *mscp)); +#endif +static int uhaprobe __P((struct isa_device *dev)); +static int32_t uha_scsi_cmd __P((struct scsi_xfer *xs)); +static void uha_send_mbox __P((struct uha_data *uha, struct mscp *mscp)); +static timeout_t + uha_timeout; + +static unsigned long int scratch; +#define EISA_MAX_SLOTS 16 /* XXX This should go into a comon header */ +static int uha_slot; /* slot last board was found in */ +static int uha_unit; +#define UHA_SHOWMSCPS 0x01 +#define UHA_SHOWINTS 0x02 +#define UHA_SHOWCMDS 0x04 +#define UHA_SHOWMISC 0x08 +#define FAIL 1 +#define SUCCESS 0 +#define PAGESIZ 4096 + +#ifdef KERNEL +struct isa_driver uhadriver = +{ + uhaprobe, + uha_attach, + "uha" +}; + +static struct scsi_adapter uha_switch = +{ + uha_scsi_cmd, + uhaminphys, + 0, + 0, + uha_adapter_info, + "uha", + { 0, 0 } +}; + +/* the below structure is so we have a default dev struct for out link struct */ +static struct scsi_device uha_dev = +{ + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "uha", + 0, + { 0, 0 } +}; + +#endif /*KERNEL */ + +#ifndef KERNEL +main() +{ + printf("uha_data is %d bytes\n", sizeof(struct uha_data)); + printf("mscp is %d bytes\n", sizeof(struct mscp)); +} + +#else /*KERNEL*/ +/* + * Function to send a command out through a mailbox + */ +static void +uha_send_mbox(struct uha_data *uha, struct mscp *mscp) +{ + int spincount = 100000; /* 1s should be enough */ + struct uha_reg *ur = uha->ur; + struct uha_bits *ub = uha->ub; + int s = splbio(); + + while (--spincount) { + if ((inb(ur->lint) & ub->ldip) == 0) + break; + DELAY(100); + } + if (spincount == 0) { + printf("uha%d: uha_send_mbox, board is not responding\n", + uha->unit); + Debugger("ultra14f"); + } + outl(ur->ogmptr, KVTOPHYS(mscp)); + if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1); + outb(ur->lint, ub->ogmint); + splx(s); +} + +/* + * Function to send abort to 14f + */ +int +uha_abort(struct uha_data *uha, struct mscp *mscp) +{ + int spincount = 100; /* 1 mSec */ + int abortcount = 200000; /*2 secs */ + struct uha_reg *ur = uha->ur; + struct uha_bits *ub = uha->ub; + int s = splbio(); + + while (--spincount) { + if ((inb(ur->lint) & ub->ldip) == 0) + break; + DELAY(10); + } + if (spincount == 0) { + printf("uha%d: uha_abort, board is not responding\n", uha->unit); + Debugger("ultra14f"); + } + outl(ur->ogmptr,KVTOPHYS(mscp)); + if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1); + outb(ur->lint, ub->abort); + + while (--abortcount) { + if (inb(ur->sint) & ub->abort_fail) + break; + DELAY(10); + } + if (abortcount == 0) { + printf("uha%d: uha_abort, board is not responding\n", uha->unit); + Debugger("ultra14f"); + } + if ((inb(ur->sint) & 0x10) != 0) { + outb(ur->sint, ub->abort_ack); + splx(s); + return (1); + } else { + outb(ur->sint, ub->abort_ack); + splx(s); + return (0); + } +} + +/* + * Function to poll for command completion when in poll mode. + * + * wait = timeout in msec + */ +static int +uha_poll(struct uha_data *uha, int wait) +{ + struct uha_reg *ur = uha->ur; + struct uha_bits *ub = uha->ub; + int stport = ur->sint; + + while (--wait) { + if (inb(stport) & ub->sintp) + break; + DELAY(1000); /* 1 mSec per loop */ + } + if (wait == 0) { + printf("uha%d: uha_poll, board is not responding\n", uha->unit); + return (EIO); + } + uhaintr(uha->unit); + return (0); +} + +/* + * Check if the device can be found at the port given and if so, set it up + * ready for further work as an argument, takes the isa_device structure + * from autoconf.c + */ +int +uhaprobe(dev) + struct isa_device *dev; +{ + int unit = uha_unit; + struct uha_data *uha; + + dev->id_unit = unit; /* XXX */ + + /* + * find unit and check we have that many defined + */ + if (unit >= NUHA) { + printf("uha: unit number (%d) too high\n", unit); + return (0); + } + dev->id_unit = unit; + + /* + * Allocate a storage area for us + */ + if (uhadata[unit]) { + printf("uha%d: memory already allocated\n", unit); + return 0; + } + uha = malloc(sizeof(struct uha_data), M_TEMP, M_NOWAIT); + if (!uha) { + printf("uha%d: cannot malloc!\n", unit); + return 0; + } + bzero(uha, sizeof(struct uha_data)); + + uha->ur = malloc(sizeof(struct uha_reg), M_TEMP, M_NOWAIT); + if (!uha->ur) { + printf("uha%d: cannot malloc!\n", unit); + return 0; + } + bzero(uha->ur, sizeof(struct uha_reg)); + + uha->ub = malloc(sizeof(struct uha_bits), M_TEMP, M_NOWAIT); + if (!uha->ub) { + printf("uha%d: cannot malloc!\n", unit); + return 0; + } + bzero(uha->ub, sizeof(struct uha_bits)); + + uhadata[unit] = uha; + uha->unit = unit; + uha->baseport = dev->id_iobase; + /* + * Try initialise a unit at this location + * sets up dma and bus speed, loads uha->vect + */ + if (uha_init(uha) != 0 && uha24_init(uha) != 0) { + uhadata[unit] = NULL; + free(uha->ur, M_TEMP); + free(uha->ub, M_TEMP); + free(uha, M_TEMP); + return (0); + } + /* if it's there put in its interrupt and DRQ vectors */ + dev->id_irq = (1 << uha->vect); + dev->id_drq = uha->dma; + dev->id_iobase = uha->baseport; + + uha_unit++; + return (16); +} + +/* + * Attach all the sub-devices we can find + */ +int +uha_attach(dev) + struct isa_device *dev; +{ + int unit = dev->id_unit; + struct uha_data *uha = uhadata[unit]; + struct scsibus_data *scbus; + + /* + * fill in the prototype scsi_link. + */ + uha->sc_link.adapter_unit = unit; + uha->sc_link.adapter_targ = uha->our_id; + uha->sc_link.adapter_softc = uha; + uha->sc_link.adapter = &uha_switch; + uha->sc_link.device = &uha_dev; + uha->sc_link.flags = SDEV_BOUNCE; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if(!scbus) + return 0; + scbus->adapter_link = &uha->sc_link; + + /* + * ask the adapter what subunits are present + */ + scsi_attachdevs(scbus); + + return 1; +} + +/* + * Return some information to the caller about + * the adapter and its capabilities + */ +u_int32_t +uha_adapter_info(unit) + int unit; +{ + return (2); /* 2 outstanding requests at a time per device */ +} + +/* + * Catch an interrupt from the adaptor + */ +void +uhaintr(unit) + int unit; +{ + struct uha_data *uha = uhadata[unit]; + struct mscp *mscp; + u_char uhastat; + unsigned long int mboxval; + struct uha_reg *ur; + struct uha_bits *ub; + int port; + + ur = uha->ur; + ub = uha->ub; + port = uha->baseport; + +#ifdef UHADEBUG + printf("uhaintr "); +#endif /*UHADEBUG */ + + while ((uhastat = inb(ur->sint)) & ub->sintp) { + /* + * First get all the information and then + * acknowledge the interrupt + */ + mboxval = inl(ur->icmptr); + outb(ur->sint, ub->icm_ack); + if (uha->flags & UHA_24F) outb(ur->icmcmd, 0); + +#ifdef UHADEBUG + printf("status = 0x%x ", uhastat); +#endif /*UHADEBUG*/ + /* + * Process the completed operation + */ + + mscp = uha_mscp_phys_kv(uha, mboxval); + if (!mscp) { + printf("uha: BAD MSCP RETURNED\n"); + return; /* whatever it was, it'll timeout */ + } + untimeout(uha_timeout, (caddr_t)mscp, mscp->xs->timeout_ch); + + uha_done(uha, mscp); + } +} + +/* + * We have a mscp which has been processed by the adaptor, now we look to see + * how the operation went. + */ +void +uha_done(uha, mscp) + struct uha_data *uha; + struct mscp *mscp; +{ + struct scsi_sense_data *s1, *s2; + struct scsi_xfer *xs = mscp->xs; + + SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n")); + /* + * Otherwise, put the results of the operation + * into the xfer and call whoever started it + */ + if (((mscp->ha_status != UHA_NO_ERR) || (mscp->targ_status != SCSI_OK)) + && ((xs->flags & SCSI_ERR_OK) == 0)) { + + s1 = &(mscp->mscp_sense); + s2 = &(xs->sense); + + if (mscp->ha_status != UHA_NO_ERR) { + switch (mscp->ha_status) { + case UHA_SBUS_ABORT_ERR: + case UHA_SBUS_TIMEOUT: /* No sel response */ + SC_DEBUG(xs->sc_link, SDEV_DB3, + ("abort or timeout; ha_status 0x%x\n", + mscp->ha_status)); + xs->error = XS_TIMEOUT; + break; + case UHA_SBUS_OVER_UNDER: + SC_DEBUG(xs->sc_link, SDEV_DB3, + ("scsi bus xfer over/underrun\n")); + xs->error = XS_DRIVER_STUFFUP; + break; + default: /* Other scsi protocol messes */ + xs->error = XS_DRIVER_STUFFUP; + printf("uha%d: unexpected ha_status 0x%x (target status 0x%x)\n", + uha->unit, mscp->ha_status, + mscp->targ_status); + break; + } + } else { + /* Target status problem */ + SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n", + mscp->targ_status)); + switch (mscp->targ_status) { + case 0x02: + *s2 = *s1; + xs->error = XS_SENSE; + break; + case 0x08: + xs->error = XS_BUSY; + break; + default: + printf("uha%d: unexpected targ_status 0x%x\n", + uha->unit, mscp->targ_status); + xs->error = XS_DRIVER_STUFFUP; + break; + } + } + } + else { + /* All went correctly OR errors expected */ + xs->resid = 0; + xs->error = 0; + } + xs->flags |= ITSDONE; + uha_free_mscp(uha, mscp, xs->flags); + scsi_done(xs); +} + +/* + * A mscp (and hence a mbx-out) is put onto the free list. + */ +void +uha_free_mscp(uha, mscp, flags) + struct uha_data *uha; + struct mscp *mscp; + int flags; +{ + unsigned int opri = 0; + + if (!(flags & SCSI_NOMASK)) + opri = splbio(); + + mscp->next = uha->free_mscp; + uha->free_mscp = mscp; + mscp->flags = MSCP_FREE; + /* + * If there were none, wake abybody waiting for + * one to come free, starting with queued entries + */ + if (!mscp->next) { + wakeup((caddr_t)&uha->free_mscp); + } + if (!(flags & SCSI_NOMASK)) + splx(opri); +} + +/* + * Get a free mscp + * + * If there are none, see if we can allocate a new one. If so, put it in the + * hash table too otherwise either return an error or sleep. + */ +static struct mscp * +uha_get_mscp(uha, flags) + struct uha_data *uha; + int flags; +{ + unsigned opri = 0; + struct mscp *mscpp; + int hashnum; + + if (!(flags & SCSI_NOMASK)) + opri = splbio(); + /* + * If we can and have to, sleep waiting for one to come free + * but only if we can't allocate a new one + */ + while (!(mscpp = uha->free_mscp)) { + if (uha->nummscps < UHA_MSCP_MAX) { + if (mscpp = (struct mscp *)malloc(sizeof(struct mscp), + M_TEMP, + M_NOWAIT)) { + bzero(mscpp, sizeof(struct mscp)); + uha->nummscps++; + mscpp->flags = MSCP_ACTIVE; + /* + * put in the phystokv hash table + * Never gets taken out. + */ + mscpp->hashkey = KVTOPHYS(mscpp); + hashnum = MSCP_HASH(mscpp->hashkey); + mscpp->nexthash = uha->mscphash[hashnum]; + uha->mscphash[hashnum] = mscpp; + } else { + printf("uha%d: Can't malloc MSCP\n", uha->unit); + } + goto gottit; + } else { + if (!(flags & SCSI_NOSLEEP)) { + tsleep((caddr_t)&uha->free_mscp, PRIBIO, + "uhamscp", 0); + } + } + } + if (mscpp) { + /* Get MSCP from from free list */ + uha->free_mscp = mscpp->next; + mscpp->flags = MSCP_ACTIVE; + } + gottit: + if (!(flags & SCSI_NOMASK)) + splx(opri); + + return (mscpp); +} + +/* + * given a physical address, find the mscp that it corresponds to. + */ +static struct mscp * +uha_mscp_phys_kv(uha, mscp_phys) + struct uha_data *uha; + long int mscp_phys; +{ + int hashnum = MSCP_HASH(mscp_phys); + struct mscp *mscpp = uha->mscphash[hashnum]; + + while (mscpp) { + if (mscpp->hashkey == mscp_phys) + break; + mscpp = mscpp->nexthash; + } + return mscpp; +} + +/* + * Start the board, ready for normal operation + */ +int +uha_init(uha) + struct uha_data *uha; +{ + volatile unsigned char model; + volatile unsigned char submodel; + unsigned char config_reg1; + unsigned char config_reg2; + unsigned char dma_ch; + unsigned char irq_ch; + unsigned char uha_id; + int port = uha->baseport; + int resetcount = 4000; /* 4 secs? */ + struct uha_reg *ur = uha->ur; + struct uha_bits *ub = uha->ub; + + /* + * Prepare to use a 14/34F. + */ + ur->id = port + 0x04; + ur->type = port + 0x00; /* 24F only */ + ur->ectl = port + 0x00; /* 24F only */ + ur->config = port + 0x06; /* 0-1 for 14F */ + ur->lmask = port + 0x00; + ur->lint = port + 0x01; + ur->smask = port + 0x02; + ur->sint = port + 0x03; + ur->ogmcmd = port + 0x00; /* 24F only */ + ur->ogmptr = port + 0x08; + ur->icmcmd = port + 0x00; /* 24F only */ + ur->icmptr = port + 0x0c; + + ub->ldip = UHA_LDIP; + ub->adrst = UHA_ADRST; + ub->sbrst = UHA_SBRST; + ub->asrst = UHA_ASRST; + ub->abort = UHA_ABORT; + ub->ogmint = UHA_OGMINT; + ub->sintp = UHA_SINTP; + ub->abort_succ = UHA_ABORT_SUCC; + ub->abort_fail = UHA_ABORT_FAIL; + ub->abort_ack = UHA_ABORT_ACK; + ub->icm_ack = UHA_ICM_ACK; + + model = inb(ur->id); + submodel = inb(ur->id + 1); + if ((model != 0x56) & (submodel != 0x40)) return(ENXIO); + printf("uha%d: reading board settings, ", uha->unit); + + config_reg1 = inb(ur->config); + config_reg2 = inb(ur->config + 1); + dma_ch = (config_reg1 & 0xc0); + irq_ch = (config_reg1 & 0x30); + uha_id = (config_reg2 & 0x07); + + switch (dma_ch) { + case UHA_DMA_CH5: + uha->dma = 5; + printf("dma=5 "); + break; + case UHA_DMA_CH6: + uha->dma = 6; + printf("dma=6 "); + break; + case UHA_DMA_CH7: + uha->dma = 7; + printf("dma=7 "); + break; + default: + printf("illegal dma jumper setting\n"); + return (EIO); + } + switch (irq_ch) { + case UHA_IRQ10: + uha->vect = 10; + printf("int=10 "); + break; + case UHA_IRQ11: + uha->vect = 11; + printf("int=11 "); + break; + case UHA_IRQ14: + uha->vect = 14; + printf("int=14 "); + break; + case UHA_IRQ15: + uha->vect = 15; + printf("int=15 "); + break; + default: + printf("illegal int jumper setting\n"); + return (EIO); + } + + /* who are we on the scsi bus */ + printf("id=%x\n", uha_id); + uha->our_id = uha_id; + + /* + * Note that we are going and return (to probe) + */ + outb(ur->lint, ub->asrst); + while (--resetcount) { + if (inb(ur->lint)) + break; + DELAY(1000); /* 1 mSec per loop */ + } + if (resetcount == 0) { + printf("uha%d: board timed out during reset\n", uha->unit); + return (ENXIO); + } + outb(ur->smask, 0x81); /* make sure interrupts are enabled */ + uha->flags |= UHA_INIT; + return (0); +} + + +/* + * Initialize an Ultrastor 24F + */ +int +uha24_init(uha) + struct uha_data *uha; +{ + unsigned char p0, p1, p2, p3, p5, p7; + unsigned char id[7], rev, haid; + int port = 0, irq; + int resetcount = 4000; + struct uha_reg *ur = uha->ur; + struct uha_bits *ub = uha->ub; + + /* Search for the 24F's product ID */ + uha_slot++; + while (uha_slot < EISA_MAX_SLOTS) { + /* + * Prepare to use a 24F. + */ + port = EISA_CONFIG | (uha_slot << 12); + ur->id = port + 0x00; + ur->type = port + 0x02; + ur->ectl = port + 0x04; + ur->config = port + 0x05; /* 0-2 for 24F */ + ur->lmask = port + 0x0c; + ur->lint = port + 0x0d; + ur->smask = port + 0x0e; + ur->sint = port + 0x0f; + ur->ogmcmd = port + 0x16; + ur->ogmptr = port + 0x17; + ur->icmcmd = port + 0x1b; + ur->icmptr = port + 0x1c; + + ub->ldip = U24_LDIP; + ub->adrst = U24_ADRST; + ub->sbrst = U24_SBRST; + ub->asrst = U24_ASRST; + ub->abort = U24_ABORT; + ub->ogmint = U24_OGMINT; + ub->sintp = U24_SINTP; + ub->abort_succ = U24_ABORT_SUCC; + ub->abort_fail = U24_ABORT_FAIL; + ub->abort_ack = U24_ABORT_ACK; + ub->icm_ack = U24_ICM_ACK; + + /* + * Make sure an EISA card is installed in this slot, + * and if it is make sure that the card is enabled. + */ + outb(ur->id, 0xff); + p0 = inb(ur->id); + if ((p0 == 0xff) || + ((p0 & 0x80) != 0) || + ((inb(ur->ectl) & EISA_DISABLE) == 0)) { + uha_slot++; + continue; + } + + /* Found an enabled card. Grab the product ID. */ + p1 = inb(ur->id+1); + p2 = inb(ur->type); + p3 = inb(ur->type+1); + id[0] = 0x40 + ((p0 >> 2) & 0x1f); + id[1] = 0x40 + (((p0 & 0x03) << 3) | ((p1 >> 5) & 0x07)); + id[2] = 0x40 + (p1 & 0x1f); + id[3] = hex2ascii((p2 >> 4) & 0x0f); + id[4] = hex2ascii(p2 & 0x0f); + id[5] = hex2ascii((p3 >> 4) & 0x0f); + id[6] = '\0'; + rev = p3 & 0xf; + + /* We only want the 24F product ID. */ + if (!strcmp(id, "USC024")) break; + uha_slot++; + } + if (uha_slot == EISA_MAX_SLOTS) return(ENODEV); + + /* We have the card! Grab remaining config. */ + p5 = inb(ur->config); + p7 = inb(ur->config+2); + + switch (p5 & 0xf0) { + case 0x10: irq = 15; break; + case 0x20: irq = 14; break; + case 0x40: irq = 11; break; + case 0x80: irq = 10; break; + default: + printf("uha%d: bad 24F irq\n", uha->unit); + return(ENXIO); + } + + haid = (p7 & 0x07); + printf("uha%d: UltraStor 24F int=%d id=%d\n", uha->unit, irq, haid); + + /* Issue SCSI and adapter reset */ + outb(ur->lint, ub->asrst); + while (--resetcount) { + if (inb(ur->lint)) + break; + DELAY(1000); /* 1 mSec per loop */ + } + if (resetcount == 0) { + printf("uha%d: board timed out during reset\n", uha->unit); + return (ENXIO); + } + outb(ur->smask, 0xc2); /* make sure interrupts are enabled */ + uha->flags |= (UHA_INIT | UHA_24F); + uha->baseport = port; + uha->our_id = haid; + uha->vect = irq; + uha->dma = -1; + return(0); +} + +#ifndef min +#define min(x,y) (x < y ? x : y) +#endif /* min */ + +void +uhaminphys(bp) + struct buf *bp; +{ + if (bp->b_bcount > ((UHA_NSEG - 1) * PAGESIZ)) { + bp->b_bcount = ((UHA_NSEG - 1) * PAGESIZ); + } +} + +/* + * start a scsi operation given the command and the data address. Also + * needs the unit, target and lu. + */ +static int32_t +uha_scsi_cmd(xs) + struct scsi_xfer *xs; +{ + struct mscp *mscp; + struct uha_dma_seg *sg; + int seg; /* scatter gather seg being worked on */ + int thiskv; + unsigned long int thisphys, nextphys; + int bytes_this_seg, bytes_this_page, datalen, flags; + struct uha_data *uha; + int s; + unsigned long int templen; + + uha = (struct uha_data *)xs->sc_link->adapter_softc; + SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_scsi_cmd\n")); + /* + * get a mscp (mbox-out) to use. If the transfer + * is from a buf (possibly from interrupt time) + * then we can't allow it to sleep + */ + flags = xs->flags; + if (xs->bp) + flags |= (SCSI_NOSLEEP); /* just to be sure */ + if (flags & ITSDONE) { + printf("uha%d: Already done?", uha->unit); + xs->flags &= ~ITSDONE; + } + if (!(flags & INUSE)) { + printf("uha%d: Not in use?", uha->unit); + xs->flags |= INUSE; + } + if (!(mscp = uha_get_mscp(uha, flags))) { + xs->error = XS_DRIVER_STUFFUP; + return (TRY_AGAIN_LATER); + } + SC_DEBUG(xs->sc_link, SDEV_DB3, ("start mscp(%p)\n", mscp)); + mscp->xs = xs; + + /* + * Put all the arguments for the xfer in the mscp + */ + if (flags & SCSI_RESET) { + mscp->opcode = 0x04; + mscp->ca = 0x01; + } else { + mscp->opcode = 0x02; + mscp->ca = 0x01; + } + if (flags & SCSI_DATA_IN) { + mscp->xdir = 0x01; + } + if (flags & SCSI_DATA_OUT) { + mscp->xdir = 0x02; + } +#ifdef GOTTABEJOKING + if (xs->sc_link->lun != 0) { + xs->error = XS_DRIVER_STUFFUP; + uha_free_mscp(uha, mscp, flags); + return (HAD_ERROR); + } +#endif + mscp->dcn = 0x00; + mscp->chan = 0x00; + mscp->target = xs->sc_link->target; + mscp->lun = xs->sc_link->lun; + mscp->link.addr[0] = 0x00; + mscp->link.addr[1] = 0x00; + mscp->link.addr[2] = 0x00; + mscp->link.addr[3] = 0x00; + mscp->link_id = 0x00; + mscp->cdblen = xs->cmdlen; + scratch = KVTOPHYS(&(mscp->mscp_sense)); + mscp->sense.addr[0] = (scratch & 0xff); + mscp->sense.addr[1] = ((scratch >> 8) & 0xff); + mscp->sense.addr[2] = ((scratch >> 16) & 0xff); + mscp->sense.addr[3] = ((scratch >> 24) & 0xff); + mscp->senselen = sizeof(mscp->mscp_sense); + mscp->ha_status = 0x00; + mscp->targ_status = 0x00; + + if (xs->datalen) { /* should use S/G only if not zero length */ + scratch = KVTOPHYS(mscp->uha_dma); + mscp->data.addr[0] = (scratch & 0xff); + mscp->data.addr[1] = ((scratch >> 8) & 0xff); + mscp->data.addr[2] = ((scratch >> 16) & 0xff); + mscp->data.addr[3] = ((scratch >> 24) & 0xff); + sg = mscp->uha_dma; + seg = 0; + mscp->sgth = 0x01; + +#ifdef TFS + if (flags & SCSI_DATA_UIO) { + iovp = ((struct uio *) xs->data)->uio_iov; + datalen = ((struct uio *) xs->data)->uio_iovcnt; + xs->datalen = 0; + while ((datalen) && (seg < UHA_NSEG)) { + scratch = (unsigned long) iovp->iov_base; + sg->addr.addr[0] = (scratch & 0xff); + sg->addr.addr[1] = ((scratch >> 8) & 0xff); + sg->addr.addr[2] = ((scratch >> 16) & 0xff); + sg->addr.addr[3] = ((scratch >> 24) & 0xff); + xs->datalen += *(unsigned long *) sg->len.len = iovp->iov_len; + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)", + iovp->iov_len, + iovp->iov_base)); + sg++; + iovp++; + seg++; + datalen--; + } + } else +#endif /*TFS */ + { + /* + * Set up the scatter gather block + */ + + SC_DEBUG(xs->sc_link, SDEV_DB4, + ("%ld @%p:- ", xs->datalen, xs->data)); + datalen = xs->datalen; + thiskv = (int) xs->data; + thisphys = KVTOPHYS(thiskv); + templen = 0; + + while ((datalen) && (seg < UHA_NSEG)) { + bytes_this_seg = 0; + + /* put in the base address */ + sg->addr.addr[0] = (thisphys & 0xff); + sg->addr.addr[1] = ((thisphys >> 8) & 0xff); + sg->addr.addr[2] = ((thisphys >> 16) & 0xff); + sg->addr.addr[3] = ((thisphys >> 24) & 0xff); + + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%lx", + thisphys)); + + /* do it at least once */ + nextphys = thisphys; + while ((datalen) && (thisphys == nextphys)) + /* + * This page is contiguous (physically) with + * the the last, just extend the length + */ + { + /* how far to the end of the page */ + nextphys = (thisphys & (~(PAGESIZ - 1))) + + PAGESIZ; + bytes_this_page = nextphys - thisphys; + /**** or the data ****/ + bytes_this_page = min(bytes_this_page + ,datalen); + bytes_this_seg += bytes_this_page; + datalen -= bytes_this_page; + + /* get more ready for the next page */ + thiskv = (thiskv & (~(PAGESIZ - 1))) + + PAGESIZ; + if (datalen) + thisphys = KVTOPHYS(thiskv); + } + /* + * next page isn't contiguous, finish the seg + */ + SC_DEBUGN(xs->sc_link, SDEV_DB4, + ("(0x%x)", bytes_this_seg)); + sg->len.len[0] = (bytes_this_seg & 0xff); + sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff); + sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff); + sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff); + templen += bytes_this_seg; + sg++; + seg++; + } + } + + /* end of iov/kv decision */ + mscp->datalen.len[0] = (templen & 0xff); + mscp->datalen.len[1] = ((templen >> 8) & 0xff); + mscp->datalen.len[2] = ((templen >> 16) & 0xff); + mscp->datalen.len[3] = ((templen >> 24) & 0xff); + mscp->sg_num = seg; + + SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n")); + if (datalen) { /* there's still data, must have run out of segs! */ + printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n", + uha->unit, UHA_NSEG); + xs->error = XS_DRIVER_STUFFUP; + uha_free_mscp(uha, mscp, flags); + return (HAD_ERROR); + } + } else { /* No data xfer, use non S/G values */ + mscp->data.addr[0] = 0x00; + mscp->data.addr[1] = 0x00; + mscp->data.addr[2] = 0x00; + mscp->data.addr[3] = 0x00; + mscp->datalen.len[0] = 0x00; + mscp->datalen.len[1] = 0x00; + mscp->datalen.len[2] = 0x00; + mscp->datalen.len[3] = 0x00; + mscp->xdir = 0x03; + mscp->sgth = 0x00; + mscp->sg_num = 0x00; + } + + /* + * Put the scsi command in the mscp and start it + */ + bcopy(xs->cmd, mscp->cdb, xs->cmdlen); + + /* + * Usually return SUCCESSFULLY QUEUED + */ + if (!(flags & SCSI_NOMASK)) { + s = splbio(); + uha_send_mbox(uha, mscp); + xs->timeout_ch = timeout(uha_timeout, (caddr_t)mscp, + (xs->timeout * hz) / 1000); + splx(s); + SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n")); + return (SUCCESSFULLY_QUEUED); + } + + /* + * If we can't use interrupts, poll on completion + */ + uha_send_mbox(uha, mscp); + SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n")); + do { + if (uha_poll(uha, xs->timeout)) { + if (!(xs->flags & SCSI_SILENT)) + printf("uha%d: cmd fail\n", uha->unit); + if (!(uha_abort(uha, mscp))) { + printf("uha%d: abort failed in wait\n", + uha->unit); + uha_free_mscp(uha, mscp, flags); + } + xs->error = XS_DRIVER_STUFFUP; + return (HAD_ERROR); + } + } + while (!(xs->flags & ITSDONE)); /* something (?) else finished */ + if (xs->error) { + return (HAD_ERROR); + } + return (COMPLETE); +} + +static void +uha_timeout(arg1) + void *arg1; +{ + struct mscp *mscp = (struct mscp *)arg1; + struct uha_data *uha; + int s = splbio(); + + uha = (struct uha_data *)mscp->xs->sc_link->adapter_softc; + printf("uha%d:%d:%d (%s%d) timed out ", uha->unit + ,mscp->xs->sc_link->target + ,mscp->xs->sc_link->lun + ,mscp->xs->sc_link->device->name + ,mscp->xs->sc_link->dev_unit); + +#ifdef UHADEBUG + uha_print_active_mscp(uha); +#endif /*UHADEBUG */ + + if ((uha_abort(uha, mscp) != 1) || (mscp->flags = MSCP_ABORTED)) { + printf("AGAIN"); + mscp->xs->retries = 0; /* I MEAN IT ! */ + uha_done(uha, mscp); + } else { /* abort the operation that has timed out */ + printf("\n"); + mscp->xs->timeout_ch = timeout(uha_timeout, (caddr_t)mscp, + 2 * hz); + mscp->flags = MSCP_ABORTED; + } + splx(s); +} + +#ifdef UHADEBUG +void +uha_print_mscp(mscp) + struct mscp *mscp; +{ + printf("mscp:%x op:%x cmdlen:%d senlen:%d\n" + ,mscp + ,mscp->opcode + ,mscp->cdblen + ,mscp->senselen); + printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n" + ,mscp->sgth + ,mscp->sg_num + ,mscp->datalen + ,mscp->ha_status + ,mscp->targ_status + ,mscp->flags); + show_scsi_cmd(mscp->xs); +} + +void +uha_print_active_mscp(struct uha_data *uha) +{ + struct mscp *mscp; + int i = 0; + + while (i < MSCP_HASH_SIZE) { + mscp = uha->mscphash[i]; + while (mscp) { + if (mscp->flags != MSCP_FREE) { + uha_print_mscp(mscp); + } + mscp = mscp->nexthash; + } + i++; + } +} +#endif /*UHADEBUG */ +#endif /*KERNEL */ diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c index a338fb59c2cfc..cfd1075bf04ef 100644 --- a/sys/i386/isa/vesa.c +++ b/sys/i386/isa/vesa.c @@ -23,25 +23,18 @@ * (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: vesa.c,v 1.14 1999/01/16 12:56:00 yokota Exp $ + * $Id: vesa.c,v 1.7 1998/10/01 11:39:18 yokota Exp $ */ -#include "vga.h" -#include "opt_vga.h" +#include "sc.h" #include "opt_vesa.h" #include "opt_vm86.h" -#include "opt_fb.h" -#ifdef VGA_NO_MODE_CHANGE -#undef VESA -#endif - -#if (NVGA > 0 && defined(VESA) && defined(VM86)) || defined(KLD_MODULE) +#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE) #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/module.h> #include <sys/malloc.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -52,17 +45,14 @@ #include <machine/pc/bios.h> #include <machine/pc/vesa.h> -#include <dev/fb/fbreg.h> -#include <dev/fb/vgareg.h> +#include <i386/isa/videoio.h> -#ifndef __i386__ -#include <isa/isareg.h> -#else -#include <i386/isa/isa.h> -#endif +#ifdef VESA_MODULE +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/lkm.h> -#ifndef VESA_DEBUG -#define VESA_DEBUG 0 +MOD_MISC(vesa); #endif /* VESA video adapter state buffer stub */ @@ -76,14 +66,11 @@ typedef struct adp_state adp_state_t; /* VESA video adapter */ static video_adapter_t *vesa_adp = NULL; static int vesa_state_buf_size = 0; -#if 0 static void *vesa_state_buf = NULL; -#endif /* VESA functions */ -static int vesa_nop(void); -static vi_probe_t vesa_probe; static vi_init_t vesa_init; +static vi_adapter_t vesa_adapter; static vi_get_info_t vesa_get_info; static vi_query_mode_t vesa_query_mode; static vi_set_mode_t vesa_set_mode; @@ -98,34 +85,17 @@ static vi_load_state_t vesa_load_state; static vi_set_win_org_t vesa_set_origin; static vi_read_hw_cursor_t vesa_read_hw_cursor; static vi_set_hw_cursor_t vesa_set_hw_cursor; -static vi_set_hw_cursor_shape_t vesa_set_hw_cursor_shape; -static vi_mmap_t vesa_mmap; static vi_diag_t vesa_diag; -static video_switch_t vesavidsw = { - vesa_probe, - vesa_init, - vesa_get_info, - vesa_query_mode, - vesa_set_mode, - vesa_save_font, - vesa_load_font, - vesa_show_font, - vesa_save_palette, - vesa_load_palette, - vesa_set_border, - vesa_save_state, - vesa_load_state, - vesa_set_origin, - vesa_read_hw_cursor, - vesa_set_hw_cursor, - vesa_set_hw_cursor_shape, - (vi_blank_display_t *)vesa_nop, - vesa_mmap, +static struct vidsw vesavidsw = { + vesa_init, vesa_adapter, vesa_get_info, vesa_query_mode, + vesa_set_mode, vesa_save_font, vesa_load_font, vesa_show_font, + vesa_save_palette,vesa_load_palette,vesa_set_border,vesa_save_state, + vesa_load_state,vesa_set_origin,vesa_read_hw_cursor,vesa_set_hw_cursor, vesa_diag, }; -static video_switch_t *prevvidsw; +static struct vidsw prevvidsw; /* VESA BIOS video modes */ #define VESA_MAXMODES 64 @@ -148,14 +118,11 @@ static char *vesa_revstr = NULL; /* local macros and functions */ #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) -static int int10_set_mode(int mode); static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode); static int vesa_bios_set_mode(int mode); static int vesa_bios_set_dac(int bits); -static int vesa_bios_save_palette(int start, int colors, u_char *palette, - int bits); -static int vesa_bios_load_palette(int start, int colors, u_char *palette, - int bits); +static int vesa_bios_save_palette(int start, int colors, u_char *palette); +static int vesa_bios_load_palette(int start, int colors, u_char *palette); #define STATE_SIZE 0 #define STATE_SAVE 1 #define STATE_LOAD 2 @@ -186,18 +153,6 @@ dump_buffer(u_char *buf, size_t len) } } -/* INT 10 BIOS calls */ -static int -int10_set_mode(int mode) -{ - struct vm86frame vmf; - - bzero(&vmf, sizeof(vmf)); - vmf.vmf_eax = 0x0000 | mode; - vm86_intcall(0x10, &vmf); - return 0; -} - /* VESA BIOS calls */ static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode) @@ -241,13 +196,11 @@ vesa_bios_set_dac(int bits) vmf.vmf_eax = 0x4f08; vmf.vmf_ebx = (bits << 8); err = vm86_intcall(0x10, &vmf); - if ((err != 0) || (vmf.vmf_eax != 0x4f)) - return 6; /* XXX */ - return ((vmf.vmf_ebx >> 8) & 0x00ff); + return ((err != 0) || (vmf.vmf_eax != 0x4f)); } static int -vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) +vesa_bios_save_palette(int start, int colors, u_char *palette) { struct vm86frame vmf; u_char *p; @@ -267,18 +220,17 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) return 1; } - bits = 8 - bits; for (i = 0; i < colors; ++i) { - palette[i*3] = p[i*4 + 2] << bits; - palette[i*3 + 1] = p[i*4 + 1] << bits; - palette[i*3 + 2] = p[i*4] << bits; + palette[i*3] = p[i*4 + 1]; + palette[i*3 + 1] = p[i*4 + 2]; + palette[i*3 + 2] = p[i*4 + 3]; } free(p, M_DEVBUF); return 0; } static int -vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) +vesa_bios_load_palette(int start, int colors, u_char *palette) { struct vm86frame vmf; u_char *p; @@ -286,12 +238,11 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) int i; p = malloc(colors*4, M_DEVBUF, M_WAITOK); - bits = 8 - bits; for (i = 0; i < colors; ++i) { - p[i*4] = palette[i*3 + 2] >> bits; - p[i*4 + 1] = palette[i*3 + 1] >> bits; - p[i*4 + 2] = palette[i*3] >> bits; - p[i*4 + 3] = 0; + p[i*4] = 0; + p[i*4 + 1] = palette[i*3]; + p[i*4 + 2] = palette[i*3 + 1]; + p[i*4 + 3] = palette[i*3 + 2]; } bzero(&vmf, sizeof(vmf)); @@ -367,7 +318,7 @@ vesa_translate_flags(u_int16_t vflags) } ftable[] = { { V_MODECOLOR, V_INFO_COLOR, 0 }, { V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 }, - { V_MODELFB, V_INFO_LINEAR, 0 }, + { V_MODELFB, V_INFO_LENEAR, 0 }, }; int flags; int i; @@ -398,6 +349,7 @@ vesa_bios_init(void) static u_char buf[512]; struct vm86frame vmf; struct vesa_mode vmode; + u_int32_t p; int modes; int err; int i; @@ -418,10 +370,8 @@ vesa_bios_init(void) if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", buf, 4)) return 1; vesa_adp_info = (struct vesa_info *)buf; - if (bootverbose) { - printf("VESA: information block\n"); + if (bootverbose) dump_buffer(buf, 64); - } if (vesa_adp_info->v_flags & V_NONVGA) return 1; @@ -504,101 +454,42 @@ vesa_clear_modes(video_info_t *info, int color) } } -/* entry points */ +/* exported functions */ static int -vesa_configure(int flags) +vesa_init(void) { - video_adapter_t *adp; int adapters; - int error; int i; - if (vesa_init_done) - return 0; - if (flags & VIO_PROBE_ONLY) - return 0; /* XXX */ - - /* - * If the VESA module has already been loaded, abort loading - * the module this time. - */ - for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) { - if (adp->va_flags & V_ADP_VESA) - return ENXIO; - if (adp->va_type == KD_VGA) - break; - } - /* - * The VGA adapter is not found. This is because either - * 1) the VGA driver has not been initialized, or 2) the VGA card - * is not present. If 1) is the case, we shall defer - * initialization for now and try again later. - */ - if (adp == NULL) { - vga_sub_configure = vesa_configure; - return ENODEV; - } - - /* count number of registered adapters */ - for (++i; vid_get_adapter(i) != NULL; ++i) - ; - adapters = i; - - /* call VESA BIOS */ - vesa_adp = adp; - if (vesa_bios_init()) { - vesa_adp = NULL; - return ENXIO; - } - vesa_adp->va_flags |= V_ADP_VESA; - - /* remove conflicting modes if we have more than one adapter */ - if (adapters > 1) { - vesa_clear_modes(vesa_vmode, - (vesa_adp->va_flags & V_ADP_COLOR) ? - V_INFO_COLOR : 0); - } - - if ((error = vesa_load_ioctl()) == 0) { - prevvidsw = vidsw[vesa_adp->va_index]; - vidsw[vesa_adp->va_index] = &vesavidsw; - vesa_init_done = TRUE; - } else { - vesa_adp = NULL; - return error; + adapters = (*prevvidsw.init)(); + for (i = 0; i < adapters; ++i) { + if ((vesa_adp = (*prevvidsw.adapter)(i)) == NULL) + continue; + if (vesa_adp->va_type == KD_VGA) { + vesa_adp->va_flags |= V_ADP_VESA; + return adapters; + } } - - return 0; -} - -static int -vesa_nop(void) -{ - return 0; -} - -static int -vesa_probe(int unit, video_adapter_t **adpp, void *arg, int flags) -{ - return (*prevvidsw->probe)(unit, adpp, arg, flags); + vesa_adp = NULL; + return adapters; } -static int -vesa_init(int unit, video_adapter_t *adp, int flags) +static video_adapter_t +*vesa_adapter(int ad) { - return (*prevvidsw->init)(unit, adp, flags); + return (*prevvidsw.adapter)(ad); } static int -vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) +vesa_get_info(int ad, int mode, video_info_t *info) { int i; - if ((*prevvidsw->get_info)(adp, mode, info) == 0) + if ((*prevvidsw.get_info)(ad, mode, info) == 0) return 0; - if (adp != vesa_adp) + if (ad != vesa_adp->va_index) return 1; mode = vesa_map_gen_mode_num(vesa_adp->va_type, @@ -615,13 +506,13 @@ vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) } static int -vesa_query_mode(video_adapter_t *adp, video_info_t *info) +vesa_query_mode(int ad, video_info_t *info) { int i; - if ((i = (*prevvidsw->query_mode)(adp, info)) != -1) + if ((i = (*prevvidsw.query_mode)(ad, info)) != -1) return i; - if (adp != vesa_adp) + if (ad != vesa_adp->va_index) return -1; for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) { @@ -653,19 +544,17 @@ vesa_query_mode(video_adapter_t *adp, video_info_t *info) } static int -vesa_set_mode(video_adapter_t *adp, int mode) +vesa_set_mode(int ad, int mode) { video_info_t info; -#if 0 size_t len; -#endif - if (adp != vesa_adp) - return (*prevvidsw->set_mode)(adp, mode); + if (ad != vesa_adp->va_index) + return (*prevvidsw.set_mode)(ad, mode); mode = vesa_map_gen_mode_num(vesa_adp->va_type, vesa_adp->va_flags & V_ADP_COLOR, mode); -#if VESA_DEBUG > 0 +#ifdef SC_VIDEO_DEBUG printf("VESA: set_mode(): %d(%x) -> %d(%x)\n", vesa_adp->va_mode, vesa_adp->va_mode, mode, mode); #endif @@ -673,40 +562,37 @@ vesa_set_mode(video_adapter_t *adp, int mode) * If the current mode is a VESA mode and the new mode is not, * restore the state of the adapter first, so that non-standard, * extended SVGA registers are set to the state compatible with - * the standard VGA modes. Otherwise (*prevvidsw->set_mode)() + * the standard VGA modes. Otherwise (*prevvidsw.set_mode)() * may not be able to set up the new mode correctly. */ if (VESA_MODE(vesa_adp->va_mode)) { - if ((*prevvidsw->get_info)(adp, mode, &info) == 0) { - int10_set_mode(vesa_adp->va_initial_bios_mode); -#if 0 + if ((*prevvidsw.get_info)(ad, mode, &info) == 0) { /* assert(vesa_state_buf != NULL); */ if ((vesa_state_buf == NULL) - || vesa_load_state(adp, vesa_state_buf)) + || vesa_load_state(ad, vesa_state_buf)) return 1; free(vesa_state_buf, M_DEVBUF); vesa_state_buf = NULL; -#if VESA_DEBUG > 0 +#ifdef SC_VIDEO_DEBUG printf("VESA: restored\n"); #endif -#endif /* 0 */ } /* - * once (*prevvidsw->get_info)() succeeded, - * (*prevvidsw->set_mode)() below won't fail... + * once (*prevvidsw.get_info)() succeeded, + * (*prevvidsw.set_mode)() below won't fail... */ } /* we may not need to handle this mode after all... */ - if ((*prevvidsw->set_mode)(adp, mode) == 0) + if ((*prevvidsw.set_mode)(ad, mode) == 0) return 0; /* is the new mode supported? */ - if (vesa_get_info(adp, mode, &info)) + if (vesa_get_info(ad, mode, &info)) return 1; /* assert(VESA_MODE(mode)); */ -#if VESA_DEBUG > 0 +#ifdef SC_VIDEO_DEBUG printf("VESA: about to set a VESA mode...\n"); #endif /* @@ -714,38 +600,35 @@ vesa_set_mode(video_adapter_t *adp, int mode) * so that the adapter state can be restored later when a non-VESA * mode is to be set up. See above. */ -#if 0 if (!VESA_MODE(vesa_adp->va_mode) && (vesa_state_buf == NULL)) { - len = vesa_save_state(adp, NULL, 0); + len = vesa_save_state(ad, NULL, 0); vesa_state_buf = malloc(len, M_DEVBUF, M_WAITOK); - if (vesa_save_state(adp, vesa_state_buf, len)) { -#if VESA_DEBUG > 0 + if (vesa_save_state(ad, vesa_state_buf, len)) { +#ifdef SC_VIDEO_DEBUG printf("VESA: state save failed! (len=%d)\n", len); #endif free(vesa_state_buf, M_DEVBUF); vesa_state_buf = NULL; return 1; } -#if VESA_DEBUG > 0 +#ifdef SC_VIDEO_DEBUG printf("VESA: saved (len=%d)\n", len); dump_buffer(vesa_state_buf, len); #endif } -#endif /* 0 */ if (vesa_bios_set_mode(mode)) return 1; -#if VESA_DEBUG > 0 +#ifdef SC_VIDEO_DEBUG printf("VESA: mode set!\n"); #endif vesa_adp->va_mode = mode; - vesa_adp->va_mode_flags = info.vi_flags; vesa_adp->va_flags &= ~V_ADP_COLOR; vesa_adp->va_flags |= (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; vesa_adp->va_crtc_addr = - (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; + (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE; vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); vesa_adp->va_window_size = info.vi_window_size; vesa_adp->va_window_gran = info.vi_window_gran; @@ -757,77 +640,58 @@ vesa_set_mode(video_adapter_t *adp, int mode) vesa_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; } static int -vesa_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, - int ch, int count) +vesa_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count) { - return (*prevvidsw->save_font)(adp, page, fontsize, data, ch, count); + return (*prevvidsw.save_font)(ad, page, fontsize, data, ch, count); } static int -vesa_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, - int ch, int count) +vesa_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count) { - return (*prevvidsw->load_font)(adp, page, fontsize, data, ch, count); + return (*prevvidsw.load_font)(ad, page, fontsize, data, ch, count); } static int -vesa_show_font(video_adapter_t *adp, int page) +vesa_show_font(int ad, int page) { - return (*prevvidsw->show_font)(adp, page); + return (*prevvidsw.show_font)(ad, page); } static int -vesa_save_palette(video_adapter_t *adp, u_char *palette) +vesa_save_palette(int ad, u_char *palette) { - int bits; - int error; - - if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8) - && ((bits = vesa_bios_set_dac(8)) > 6)) { - error = vesa_bios_save_palette(0, 256, palette, bits); - if (error == 0) - return 0; - vesa_bios_set_dac(6); - } + if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8) + || vesa_bios_set_dac(8)) + return (*prevvidsw.save_palette)(ad, palette); - return (*prevvidsw->save_palette)(adp, palette); + return vesa_bios_save_palette(0, 256, palette); } static int -vesa_load_palette(video_adapter_t *adp, u_char *palette) +vesa_load_palette(int ad, u_char *palette) { - int bits; - int error; - - if ((adp == vesa_adp) && (vesa_adp_info->v_flags & V_DAC8) - && ((bits = vesa_bios_set_dac(8)) > 6)) { - error = vesa_bios_load_palette(0, 256, palette, bits); - if (error == 0) - return 0; - vesa_bios_set_dac(6); - } + if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8) + || vesa_bios_set_dac(8)) + return (*prevvidsw.load_palette)(ad, palette); - return (*prevvidsw->load_palette)(adp, palette); + return vesa_bios_load_palette(0, 256, palette); } static int -vesa_set_border(video_adapter_t *adp, int color) +vesa_set_border(int ad, int color) { - return (*prevvidsw->set_border)(adp, color); + return (*prevvidsw.set_border)(ad, color); } static int -vesa_save_state(video_adapter_t *adp, void *p, size_t size) +vesa_save_state(int ad, void *p, size_t size) { - if (adp != vesa_adp) - return (*prevvidsw->save_state)(adp, p, size); + if (ad != vesa_adp->va_index) + return (*prevvidsw.save_state)(ad, p, size); if (vesa_state_buf_size == 0) vesa_state_buf_size = vesa_bios_state_buf_size(); @@ -843,17 +707,18 @@ vesa_save_state(video_adapter_t *adp, void *p, size_t size) } static int -vesa_load_state(video_adapter_t *adp, void *p) +vesa_load_state(int ad, void *p) { - if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG)) - return (*prevvidsw->load_state)(adp, p); + if ((ad != vesa_adp->va_index) + || (((adp_state_t *)p)->sig != V_STATE_SIG)) + return (*prevvidsw.load_state)(ad, p); return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, vesa_state_buf_size); } static int -vesa_set_origin(video_adapter_t *adp, off_t offset) +vesa_set_origin(int ad, off_t offset) { struct vm86frame vmf; int err; @@ -864,8 +729,8 @@ vesa_set_origin(video_adapter_t *adp, off_t offset) * error checking is kept minimal and let the VESA BIOS to * detect error. */ - if (adp != vesa_adp) - return (*prevvidsw->set_win_org)(adp, offset); + if (ad != vesa_adp->va_index) + return (*prevvidsw.set_win_org)(ad, offset); if (vesa_adp->va_window_gran == 0) return 1; @@ -878,45 +743,27 @@ vesa_set_origin(video_adapter_t *adp, off_t offset) } static int -vesa_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +vesa_read_hw_cursor(int ad, int *col, int *row) { - return (*prevvidsw->read_hw_cursor)(adp, col, row); + return (*prevvidsw.read_hw_cursor)(ad, col, row); } static int -vesa_set_hw_cursor(video_adapter_t *adp, int col, int row) +vesa_set_hw_cursor(int ad, int col, int row) { - return (*prevvidsw->set_hw_cursor)(adp, col, row); + return (*prevvidsw.set_hw_cursor)(ad, col, row); } static int -vesa_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, - int celsize, int blink) +vesa_diag(int level) { - return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize, - blink); -} - -static int -vesa_mmap(video_adapter_t *adp, vm_offset_t offset) -{ - return (*prevvidsw->mmap)(adp, offset); -} - -static int -vesa_diag(video_adapter_t *adp, int level) -{ -#if VESA_DEBUG > 1 struct vesa_mode vmode; + u_int32_t p; int i; -#endif - - if (adp != vesa_adp) - return 1; -#ifndef KLD_MODULE +#ifndef VESA_MODULE /* call the previous handler first */ - (*prevvidsw->diag)(adp, level); + (*prevvidsw.diag)(level); #endif /* general adapter information */ @@ -946,7 +793,6 @@ vesa_diag(video_adapter_t *adp, int level) printf("VESA: %s\n", vesa_revstr); } -#if VESA_DEBUG > 1 /* mode information */ for (i = 0; (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1)) @@ -981,40 +827,79 @@ vesa_diag(video_adapter_t *adp, int level) printf("size:%dk, gran:%dk\n", vmode.v_wsize, vmode.v_wgran); } -#endif return 0; } /* module loading */ +#ifdef VESA_MODULE static int +vesa_load(struct lkm_table *lkmtp, int cmd) +#else +int vesa_load(void) +#endif { + int adapters; int error; int s; + int i; if (vesa_init_done) return 0; - /* locate a VGA adapter */ - s = spltty(); + /* + * If the VESA module is statically linked to the kernel, or + * it has already been loaded, abort loading this module this time. + */ vesa_adp = NULL; - error = vesa_configure(0); + adapters = (*biosvidsw.init)(); + for (i = 0; i < adapters; ++i) { + if ((vesa_adp = (*biosvidsw.adapter)(i)) == NULL) + continue; + if (vesa_adp->va_flags & V_ADP_VESA) + return ENXIO; + if (vesa_adp->va_type == KD_VGA) + break; + } + /* if a VGA adapter is not found, abort */ + if (i >= adapters) + return ENXIO; + + if (vesa_bios_init()) + return ENXIO; + vesa_adp->va_flags |= V_ADP_VESA; + + /* remove conflicting modes if we have more than one adapter */ + if (adapters > 1) { + vesa_clear_modes(vesa_vmode, + (vesa_adp->va_flags & V_ADP_COLOR) ? + V_INFO_COLOR : 0); + } + +#ifdef VESA_MODULE + s = spltty(); +#endif + if ((error = vesa_load_ioctl()) == 0) { + bcopy(&biosvidsw, &prevvidsw, sizeof(prevvidsw)); + bcopy(&vesavidsw, &biosvidsw, sizeof(vesavidsw)); + vesa_init_done = TRUE; + } +#ifdef VESA_MODULE splx(s); -#ifdef KLD_MODULE if (error == 0) - vesa_diag(vesa_adp, bootverbose); + vesa_diag(bootverbose); #endif return error; } -#ifdef KLD_MODULE +#ifdef VESA_MODULE static int -vesa_unload(void) +vesa_unload(struct lkm_table *lkmtp, int cmd) { int error; int s; @@ -1029,42 +914,22 @@ vesa_unload(void) s = spltty(); if ((error = vesa_unload_ioctl()) == 0) { - if (vesa_adp != NULL) + if (vesa_adp) vesa_adp->va_flags &= ~V_ADP_VESA; - vidsw[vesa_adp->va_index] = prevvidsw; + bcopy(&prevvidsw, &biosvidsw, sizeof(biosvidsw)); } splx(s); return error; } -static int -vesa_mod_event(module_t mod, int type, void *data) +int +vesa_mod(struct lkm_table *lkmtp, int cmd, int ver) { - switch (type) { - case MOD_LOAD: - return vesa_load(); - case MOD_UNLOAD: - return vesa_unload(); - default: - break; - } - return 0; + MOD_DISPATCH(vesa, lkmtp, cmd, ver, + vesa_load, vesa_unload, lkm_nullcmd); } -static moduledata_t vesa_mod = { - "vesa", - vesa_mod_event, - NULL, -}; - -DECLARE_MODULE(vesa, vesa_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); - -#else /* KLD_MODULE */ - -SYSINIT(vesa, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, - (void (*)(void *))vesa_load, NULL); - -#endif /* KLD_MODULE */ +#endif /* VESA_MODULE */ -#endif /* (NVGA > 0 && VESA && VM86) || KLD_MODULE */ +#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */ diff --git a/sys/i386/isa/vga_isa.c b/sys/i386/isa/videoio.c index 0aaab5c0d8a4a..571008051fb5d 100644 --- a/sys/i386/isa/vga_isa.c +++ b/sys/i386/isa/videoio.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> + * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> * Copyright (c) 1992-1998 Søren Schmidt * All rights reserved. * @@ -26,252 +26,31 @@ * (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: $ + * $Id: videoio.c,v 1.5 1998/09/26 03:38:40 yokota Exp $ */ -#include "vga.h" -#include "opt_vga.h" -#include "opt_fb.h" -#include "opt_syscons.h" /* should be removed in the future, XXX */ +#include "sc.h" +#include "opt_syscons.h" -#if NVGA > 0 +#if NSC > 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/clock.h> #include <machine/console.h> #include <machine/md_var.h> #include <machine/pc/bios.h> -#include <dev/fb/fbreg.h> -#include <dev/fb/vgareg.h> - -#ifndef __i386__ -#include <isa/isareg.h> -#include <isa/isavar.h> -#else #include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#endif - -#define DRIVER_NAME "vga" - -/* cdev driver declaration */ - -#define ISAVGA_UNIT(dev) minor(dev) -#define ISAVGA_MKMINOR(unit) (unit) - -typedef struct isavga_softc { - video_adapter_t *adp; -} isavga_softc_t; - -#ifndef __i386__ - -#define ISAVGA_SOFTC(unit) \ - ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit)) - -devclass_t isavga_devclass; - -static int isavga_probe(device_t dev); -static int isavga_attach(device_t dev); - -static device_method_t isavga_methods[] = { - DEVMETHOD(device_probe, isavga_probe), - DEVMETHOD(device_attach, isavga_attach), - { 0, 0 } -}; - -static driver_t isavga_driver = { - DRIVER_NAME, - isavga_methods, - DRIVER_TYPE_TTY, - sizeof(isavga_softc_t), -}; - -#else /* __i386__ */ - -#define ISAVGA_SOFTC(unit) (isavga_softc[unit]) - -static isavga_softc_t *isavga_softc[NVGA]; - -static int isavga_probe(struct isa_device *dev); -static int isavga_attach(struct isa_device *dev); - -struct isa_driver vgadriver = { - isavga_probe, - isavga_attach, - DRIVER_NAME, - 0, -}; - -#endif /* __i386__ */ - -static int isavga_probe_unit(int unit, isavga_softc_t *sc, - int flags); -static int isavga_attach_unit(int unit, isavga_softc_t *sc, - int flags); - -#ifdef FB_INSTALL_CDEV - -static d_open_t isavgaopen; -static d_close_t isavgaclose; -static d_read_t isavgaread; -static d_ioctl_t isavgaioctl; - -static struct cdevsw vga_cdevsw = { - isavgaopen, isavgaclose, noread, nowrite, /* ?? */ - isavgaioctl, nostop, nullreset, nodevtotty, - seltrue, nommap, NULL, DRIVER_NAME, - NULL, -1, nodump, nopsize, -}; - -#endif /* FB_INSTALL_CDEV */ - -#ifndef __i386__ - -static int -isavga_probe(device_t dev) -{ - isavga_softc_t *sc; - - sc = device_get_softc(dev); - return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev)); -} - -static int -isavga_attach(device_t dev) -{ - isavga_softc_t *sc; - - sc = device_get_softc(dev); - return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev)); -} - -#else /* __i386__ */ - -static int -isavga_probe(struct isa_device *dev) -{ - isavga_softc_t *sc; - int error; - - if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) - return 0; - sc = isavga_softc[dev->id_unit] - = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return 0; - - error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags); - if (error) { - isavga_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 -isavga_attach(struct isa_device *dev) -{ - isavga_softc_t *sc; - - if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) - return 0; - sc = isavga_softc[dev->id_unit]; - if (sc == NULL) - return 0; - - return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1); -} - -#endif /* __i386__ */ - -static int -isavga_probe_unit(int unit, isavga_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 -isavga_attach_unit(int unit, isavga_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, ISAVGA_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 <machine/pc/vesa.h> - -#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) - -/* for compatibility with old kernel options */ -#ifdef SC_ALT_SEQACCESS -#undef SC_ALT_SEQACCESS -#undef VGA_ALT_SEQACCESS -#define VGA_ALT_SEQACCESS 1 -#endif - -#ifdef SLOW_VGA -#undef SLOW_VGA -#undef VGA_SLOW_IOACCESS -#define VGA_SLOW_IOACCESS 1 -#endif - -/* architecture dependent option */ -#ifdef __alpha__ -#define VGA_NO_BIOS 1 -#endif +#include <i386/isa/videoio.h> /* this should really be in `rtc.h' */ #define RTC_EQUIPMENT 0x14 -/* various sizes */ -#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) -#define V_MODE_PARAM_SIZE 64 - /* video adapter state buffer */ struct adp_state { int sig; @@ -294,169 +73,104 @@ typedef struct adp_state adp_state_t; * will perform address conversion at run-time. */ static video_adapter_t adapter_init_value[] = { - /* DCC_MONO */ - { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, - 0, 0, 0, 7, 0, 0, NULL }, - /* DCC_CGA40 */ - { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, - 0, 0, 0, 3, 0, 0, NULL }, - /* DCC_CGA80 */ - { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, - 0, 0, 0, 3, 0, 0, NULL }, - /* DCC_EGAMONO */ - { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC, - EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, - 0, 0, 0, 7, 0, 0, NULL }, - /* DCC_EGA40 */ - { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, - EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, - 0, 0, 0, 3, 0, 0, NULL }, - /* DCC_EGA80 */ - { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, - EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, - 0, 0, 0, 3, 0, 0, NULL }, + { 0, KD_MONO, 0, MONO_BASE, 0xb0000, 32*1024, 32*1024, 0, 0, 0, 7, 0 }, + { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32*1024, 32*1024, 0, 0, 0, 3, 0 }, + { 0, KD_CGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32*1024, 32*1024, 0, 0, 0, 3, 0 }, + { 0, KD_EGA, 0, MONO_BASE, 0xb0000, 32*1024, 32*1024, 0, 0, 0, 7, 0 }, + { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32*1024, 32*1024, 0, 0, 0, 3, 0 }, + { 0, KD_EGA, V_ADP_COLOR, COLOR_BASE, 0xb8000, 32*1024, 32*1024, 0, 0, 0, 3, 0 }, }; -static video_adapter_t biosadapter[2]; -static int biosadapters = 0; - -/* video driver declarations */ -static int vga_configure(int flags); - int (*vga_sub_configure)(int flags); -static int vga_nop(void); -static vi_probe_t vga_probe; -static vi_init_t vga_init; -static vi_get_info_t vga_get_info; -static vi_query_mode_t vga_query_mode; -static vi_set_mode_t vga_set_mode; -static vi_save_font_t vga_save_font; -static vi_load_font_t vga_load_font; -static vi_show_font_t vga_show_font; -static vi_save_palette_t vga_save_palette; -static vi_load_palette_t vga_load_palette; -static vi_set_border_t vga_set_border; -static vi_save_state_t vga_save_state; -static vi_load_state_t vga_load_state; -static vi_set_win_org_t vga_set_origin; -static vi_read_hw_cursor_t vga_read_hw_cursor; -static vi_set_hw_cursor_t vga_set_hw_cursor; -static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape; -static vi_mmap_t vga_mmap; -static vi_diag_t vga_diag; - -static video_switch_t vgavidsw = { - vga_probe, - vga_init, - vga_get_info, - vga_query_mode, - vga_set_mode, - vga_save_font, - vga_load_font, - vga_show_font, - vga_save_palette, - vga_load_palette, - vga_set_border, - vga_save_state, - vga_load_state, - vga_set_origin, - vga_read_hw_cursor, - vga_set_hw_cursor, - vga_set_hw_cursor_shape, - (vi_blank_display_t *)vga_nop, - vga_mmap, - vga_diag, +static video_adapter_t adapter[V_MAX_ADAPTERS]; +static int adapters = 0; + +/* VGA function entries */ +static vi_init_t vid_init; +static vi_adapter_t vid_adapter; +static vi_get_info_t vid_get_info; +static vi_query_mode_t vid_query_mode; +static vi_set_mode_t vid_set_mode; +static vi_save_font_t vid_save_font; +static vi_load_font_t vid_load_font; +static vi_show_font_t vid_show_font; +static vi_save_palette_t vid_save_palette; +static vi_load_palette_t vid_load_palette; +static vi_set_border_t vid_set_border; +static vi_save_state_t vid_save_state; +static vi_load_state_t vid_load_state; +static vi_set_win_org_t vid_set_origin; +static vi_read_hw_cursor_t vid_read_hw_cursor; +static vi_set_hw_cursor_t vid_set_hw_cursor; +static vi_diag_t vid_diag; + +struct vidsw biosvidsw = { + vid_init, vid_adapter, vid_get_info, vid_query_mode, + vid_set_mode, vid_save_font, vid_load_font, vid_show_font, + vid_save_palette,vid_load_palette,vid_set_border,vid_save_state, + vid_load_state, vid_set_origin, vid_read_hw_cursor, vid_set_hw_cursor, + vid_diag, }; -VIDEO_DRIVER(mda, vgavidsw, NULL); -VIDEO_DRIVER(cga, vgavidsw, NULL); -VIDEO_DRIVER(ega, vgavidsw, NULL); -VIDEO_DRIVER(vga, vgavidsw, vga_configure); - /* VGA BIOS standard video modes */ #define EOT (-1) #define NA (-2) static video_info_t bios_vmode[] = { /* CGA */ - { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, + { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* EGA */ - { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, + { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* VGA */ - { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, - { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, + { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, 0xb0000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* MDA */ - { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, + { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, 0xb0000, 32*1024, 32*1024, 0, 0 }, /* EGA */ - { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, + { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* VGA */ - { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, - { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, - { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, - MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, - { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, -#ifndef VGA_NO_MODE_CHANGE + { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, 0xb0000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, 0xb0000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, 0xb0000, 32*1024, 32*1024, 0, 0 }, + { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* CGA */ - { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, - { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1, - CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, + { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 2, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, + { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 200, 8, 8, 1, 1, 0xb8000, 32*1024, 32*1024, 0, 0 }, /* EGA */ - { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 }, - { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, + { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 200, 8, 8, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_EGAMONOAPA, V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_ENHMONOAPA2,V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 350, 8, 14, 2, 2, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 350, 8, 14, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, /* VGA */ - { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, - { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, -#endif /* VGA_NO_MODE_CHANGE */ + { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 480, 8, 16, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, + 640, 480, 8, 16, 4, 4, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 200, 8, 8, 8, 1, 0xa0000, 64*1024, 64*1024, 0, 0 }, + { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, + 320, 240, 8, 8, 8, 1, 0xa0000, 64*1024, 64*1024, 0, 0 }, { EOT }, }; @@ -472,69 +186,40 @@ static int rows_offset = 1; /* local macros and functions */ #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) static void map_mode_table(u_char *map[], u_char *table, int max); -#endif -static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max, - int color); -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) +static void clear_mode_map(int ad, u_char *map[], int max, int color); static int map_mode_num(int mode); -#endif static int map_gen_mode_num(int type, int color, int mode); static int map_bios_mode_num(int type, int color, int bios_mode); static u_char *get_mode_param(int mode); -#ifndef VGA_NO_BIOS static void fill_adapter_param(int code, video_adapter_t *adp); -#endif static int verify_adapter(video_adapter_t *adp); -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) #define COMP_IDENTICAL 0 #define COMP_SIMILAR 1 #define COMP_DIFFERENT 2 static int comp_adpregs(u_char *buf1, u_char *buf2); -#endif -static int probe_adapters(void); #define PARAM_BUFSIZE 6 static void set_font_mode(video_adapter_t *adp, u_char *buf); static void set_normal_mode(video_adapter_t *adp, u_char *buf); +static char *adapter_name(int type); +static void dump_adp_info(int ad, video_adapter_t *adp, int level); +static void dump_mode_info(int ad, video_info_t *info, int level); static void dump_buffer(u_char *buf, size_t len); -#define ISMAPPED(pa, width) \ +extern void generic_bcopy(const void *, void *, size_t); + +#define ISMAPPED(pa, width) \ (((pa) <= (u_long)0x1000 - (width)) \ || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width))) -#define prologue(adp, flag, err) \ - if (!init_done || !((adp)->va_flags & (flag))) \ +#define prologue(ad, flag, err) \ + if (!init_done \ + || ((ad) < 0) || ((ad) >= adapters) \ + || !(adapter[(ad)].va_flags & (flag))) \ return (err) -/* a backdoor for the console driver */ -static int -vga_configure(int flags) -{ - int i; - - probe_adapters(); - for (i = 0; i < biosadapters; ++i) { - if (!probe_done(&biosadapter[i])) - continue; - biosadapter[i].va_flags |= V_ADP_INITIALIZED; - if (!config_done(&biosadapter[i])) { - if (vid_register(&biosadapter[i]) < 0) - continue; - biosadapter[i].va_flags |= V_ADP_REGISTERED; - } - } - if (vga_sub_configure != NULL) - (*vga_sub_configure)(flags); - - return biosadapters; -} - -/* local subroutines */ - -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) /* construct the mode parameter map */ static void map_mode_table(u_char *map[], u_char *table, int max) @@ -546,10 +231,9 @@ map_mode_table(u_char *map[], u_char *table, int max) for(; i < V_MODE_MAP_SIZE; ++i) map[i] = NULL; } -#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ static void -clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color) +clear_mode_map(int ad, u_char *map[], int max, int color) { video_info_t info; int i; @@ -559,14 +243,13 @@ clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color) * by all adapters. */ for(i = 0; i < max; ++i) { - if (vga_get_info(adp, i, &info)) + if (vid_get_info(ad, i, &info)) continue; if ((info.vi_flags & V_INFO_COLOR) != color) map[i] = NULL; } } -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) /* map the non-standard video mode to a known mode number */ static int map_mode_num(int mode) @@ -593,7 +276,6 @@ map_mode_num(int mode) } return mode; } -#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ /* map a generic video mode to a known mode number */ static int @@ -725,17 +407,14 @@ map_bios_mode_num(int type, int color, int bios_mode) static u_char *get_mode_param(int mode) { -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) if (mode >= V_MODE_MAP_SIZE) mode = map_mode_num(mode); -#endif if ((mode >= 0) && (mode < V_MODE_MAP_SIZE)) return mode_map[mode]; else return NULL; } -#ifndef VGA_NO_BIOS static void fill_adapter_param(int code, video_adapter_t *adp) { @@ -765,21 +444,20 @@ fill_adapter_param(int code, video_adapter_t *adp) adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary]; } } -#endif /* VGA_NO_BIOS */ static int verify_adapter(video_adapter_t *adp) { - volatile u_int16_t *buf; - u_int16_t v; + u_short volatile *buf; + u_short v; u_int32_t p; - buf = (u_int16_t *)BIOS_PADDRTOVADDR(adp->va_window); - v = readw(buf); - writew(buf, 0xA55A); - if (readw(buf) != 0xA55A) + buf = (u_short *)BIOS_PADDRTOVADDR(adp->va_window); + v = *buf; + *buf = (u_short) 0xA55A; + if (*buf != 0xA55A) return 1; - writew(buf, v); + *buf = v; switch (adp->va_type) { @@ -787,13 +465,11 @@ verify_adapter(video_adapter_t *adp) outb(adp->va_crtc_addr, 7); if (inb(adp->va_crtc_addr) == 7) { adp->va_type = KD_VGA; - adp->va_name = "vga"; adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE; } - adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER; + adp->va_flags |= V_ADP_STATELOAD | V_ADP_FONT | V_ADP_BORDER; /* the color adapter may be in the 40x25 mode... XXX */ -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) /* get the BIOS video mode pointer */ p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8); p = BIOS_SADDRTOLADDR(p); @@ -803,34 +479,20 @@ verify_adapter(video_adapter_t *adp) if (ISMAPPED(p, V_MODE_PARAM_SIZE)) video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p); } -#endif break; case KD_CGA: adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER; /* may be in the 40x25 mode... XXX */ -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) - /* get the BIOS video mode pointer */ - p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); - p = BIOS_SADDRTOLADDR(p); - video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); -#endif break; case KD_MONO: -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) - /* get the BIOS video mode pointer */ - p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); - p = BIOS_SADDRTOLADDR(p); - video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); -#endif break; } return 0; } -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) /* compare two parameter table entries */ static int comp_adpregs(u_char *buf1, u_char *buf2) @@ -870,11 +532,17 @@ comp_adpregs(u_char *buf1, u_char *buf2) } return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; } -#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ -/* probe video adapters and return the number of detected adapters */ +/* entry points */ + +/* + * init() + * Return the # of video adapters found; usually 1 or 0. + * + * all adapters + */ static int -probe_adapters(void) +vid_init(void) { video_adapter_t *adp; video_info_t info; @@ -883,7 +551,7 @@ probe_adapters(void) /* do this test only once */ if (init_done) - return biosadapters; + return adapters; init_done = TRUE; /* @@ -906,98 +574,75 @@ probe_adapters(void) */ /* - * Check rtc and BIOS data area. + * Check rtc and BIOS date area. * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead - * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are + * copy of RTC_EQUIPMENT. Bits 4 and 5 of the ETC_EQUIPMENT are * zeros for EGA and VGA. However, the EGA/VGA BIOS sets * these bits in BIOSDATA_EQUIPMENT according to the monitor * type detected. */ -#ifndef VGA_NO_BIOS switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ case 0: /* EGA/VGA */ - fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, - biosadapter); + fill_adapter_param(*(u_int8_t *)BIOS_PADDRTOVADDR(0x488) & 0x0f, + adapter); break; case 1: /* CGA 40x25 */ /* FIXME: switch to the 80x25 mode? XXX */ - biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; - biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; break; case 2: /* CGA 80x25 */ - biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; - biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; break; case 3: /* MDA */ - biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; - biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; + adapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; + adapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; break; } -#else - /* assume EGA/VGA? XXX */ - biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80]; - biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; -#endif /* VGA_NO_BIOS */ - - biosadapters = 0; - if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) { - ++biosadapters; - biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED; - biosadapter[V_ADP_SECONDARY].va_mode = - biosadapter[V_ADP_SECONDARY].va_initial_mode = - map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type, - biosadapter[V_ADP_SECONDARY].va_flags - & V_ADP_COLOR, - biosadapter[V_ADP_SECONDARY].va_initial_bios_mode); + + adapters = 0; + if (verify_adapter(&adapter[V_ADP_SECONDARY]) == 0) { + ++adapters; + adapter[V_ADP_SECONDARY].va_mode = + adapter[V_ADP_SECONDARY].va_initial_mode = + map_bios_mode_num(adapter[V_ADP_SECONDARY].va_type, + adapter[V_ADP_SECONDARY].va_flags & V_ADP_COLOR, + adapter[V_ADP_SECONDARY].va_initial_bios_mode); } else { - biosadapter[V_ADP_SECONDARY].va_type = -1; + adapter[V_ADP_SECONDARY].va_type = -1; } - if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) { - ++biosadapters; - biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED; -#ifndef VGA_NO_BIOS - biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = - readb(BIOS_PADDRTOVADDR(0x449)); -#else - biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */ -#endif - biosadapter[V_ADP_PRIMARY].va_mode = - biosadapter[V_ADP_PRIMARY].va_initial_mode = - map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type, - biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, - biosadapter[V_ADP_PRIMARY].va_initial_bios_mode); + if (verify_adapter(&adapter[V_ADP_PRIMARY]) == 0) { + ++adapters; + adapter[V_ADP_PRIMARY].va_initial_bios_mode = + *(u_int8_t *)BIOS_PADDRTOVADDR(0x449); + adapter[V_ADP_PRIMARY].va_mode = + adapter[V_ADP_PRIMARY].va_initial_mode = + map_bios_mode_num(adapter[V_ADP_PRIMARY].va_type, + adapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, + adapter[V_ADP_PRIMARY].va_initial_bios_mode); } else { - biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY]; - biosadapter[V_ADP_SECONDARY].va_type = -1; + adapter[V_ADP_PRIMARY] = adapter[V_ADP_SECONDARY]; + adapter[V_ADP_SECONDARY].va_type = -1; } - if (biosadapters == 0) - return biosadapters; -#if 0 - biosadapter[V_ADP_PRIMARY].va_index = V_ADP_PRIMARY; - biosadapter[V_ADP_SECONDARY].va_index = V_ADP_SECONDARY; -#endif - biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY; - biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY; - -#if 0 /* we don't need these... */ - fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...); - fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...); -#endif + if (adapters == 0) + return adapters; + adapter[V_ADP_PRIMARY].va_index = V_ADP_PRIMARY; + adapter[V_ADP_SECONDARY].va_index = V_ADP_SECONDARY; #if 0 /* * We cannot have two video adapter of the same type; there must be * only one of color or mono adapter, or one each of them. */ - if (biosadapters > 1) { - if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags) - & V_ADP_COLOR)) + if (adapters > 1) { + if (!((adapter[0].va_flags ^ adapter[1].va_flags) & V_ADP_COLOR)) /* we have two mono or color adapters!! */ - return (biosadapters = 0); + return (adapters = 0); } #endif @@ -1006,36 +651,32 @@ probe_adapters(void) * switching from pcvt using userconfig(). The registers are w/o * for old hardware so it's too hard to relocate the active screen * memory. - * This must be done before vga_save_state() for VGA. + * This must be done before vid_save_state() for VGA. */ - outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12); - outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); - outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13); - outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 12); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr, 13); + outb(adapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); /* the video mode parameter table in EGA/VGA BIOS */ /* NOTE: there can be only one EGA/VGA, wheather color or mono, * recognized by the video BIOS. */ - if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) || - (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) { - adp = &biosadapter[V_ADP_PRIMARY]; - } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) || - (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) { - adp = &biosadapter[V_ADP_SECONDARY]; + if ((adapter[V_ADP_PRIMARY].va_type == KD_EGA) || + (adapter[V_ADP_PRIMARY].va_type == KD_VGA)) { + adp = &adapter[V_ADP_PRIMARY]; + } else if ((adapter[V_ADP_SECONDARY].va_type == KD_EGA) || + (adapter[V_ADP_SECONDARY].va_type == KD_VGA)) { + adp = &adapter[V_ADP_SECONDARY]; } else { adp = NULL; } bzero(mode_map, sizeof(mode_map)); if (adp != NULL) { if (adp->va_type == KD_VGA) { - vga_save_state(adp, &adpstate, sizeof(adpstate)); -#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) - mode_map[adp->va_initial_mode] = adpstate.regs; - rows_offset = 1; -#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ + vid_save_state(adp - adapter, &adpstate, sizeof(adpstate)); if (video_mode_ptr == NULL) { - mode_map[adp->va_initial_mode] = adpstate.regs; + mode_map[map_mode_num(adp->va_initial_mode)] = adpstate.regs; rows_offset = 1; } else { /* discard the table if we are not familiar with it... */ @@ -1065,7 +706,8 @@ probe_adapters(void) * for the initial mode and other modes which are * based on the initial mode. */ - mode_map[adp->va_initial_mode] = adpstate.regs; + mode_map[map_mode_num(adp->va_initial_mode)] = + adpstate.regs; rows_offset = adpstate.regs[1] + 1 - mp[1]; adpstate.regs[1] -= rows_offset - 1; break; @@ -1080,24 +722,16 @@ probe_adapters(void) */ video_mode_ptr = NULL; bzero(mode_map, sizeof(mode_map)); - mode_map[adp->va_initial_mode] = adpstate.regs; + mode_map[map_mode_num(adp->va_initial_mode)] = + adpstate.regs; rows_offset = 1; break; } } -#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ - -#ifndef VGA_NO_MODE_CHANGE adp->va_flags |= V_ADP_MODECHANGE; -#endif -#ifndef VGA_NO_FONT_LOADING - adp->va_flags |= V_ADP_FONT; -#endif } else if (adp->va_type == KD_EGA) { -#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) - rows_offset = 1; -#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ if (video_mode_ptr == NULL) { + adp->va_flags &= ~V_ADP_FONT; rows_offset = 1; } else { map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); @@ -1105,74 +739,48 @@ probe_adapters(void) mp = get_mode_param(adp->va_initial_mode); if (mp != NULL) { adp->va_flags |= V_ADP_MODECHANGE; -#ifndef VGA_NO_FONT_LOADING - adp->va_flags |= V_ADP_FONT; -#endif rows_offset = 1; } else { /* * This is serious. We will not be able to switch video * modes at all... */ + adp->va_flags &= ~V_ADP_FONT; video_mode_ptr = NULL; bzero(mode_map, sizeof(mode_map)); rows_offset = 1; } } -#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ } } /* remove conflicting modes if we have more than one adapter */ - if (biosadapters > 1) { - for (i = 0; i < biosadapters; ++i) { - if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE)) + if (adapters > 1) { + for (i = 0; i < adapters; ++i) { + if (!(adapter[i].va_flags & V_ADP_MODECHANGE)) continue; - clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1, - (biosadapter[i].va_flags & V_ADP_COLOR) ? + clear_mode_map(i, mode_map, M_VGA_CG320 + 1, + (adapter[i].va_flags & V_ADP_COLOR) ? V_INFO_COLOR : 0); - if ((biosadapter[i].va_type == KD_VGA) - || (biosadapter[i].va_type == KD_EGA)) { - biosadapter[i].va_io_base = - (biosadapter[i].va_flags & V_ADP_COLOR) ? - IO_VGA : IO_MDA; - biosadapter[i].va_io_size = 32; - } } } /* buffer address */ - vga_get_info(&biosadapter[V_ADP_PRIMARY], - biosadapter[V_ADP_PRIMARY].va_initial_mode, &info); - biosadapter[V_ADP_PRIMARY].va_mode_flags = info.vi_flags; - biosadapter[V_ADP_PRIMARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); - biosadapter[V_ADP_PRIMARY].va_window_size = info.vi_window_size; - biosadapter[V_ADP_PRIMARY].va_window_gran = info.vi_window_gran; - if (info.vi_buffer_size == 0) { - biosadapter[V_ADP_PRIMARY].va_buffer = 0; - biosadapter[V_ADP_PRIMARY].va_buffer_size = 0; - } else { - biosadapter[V_ADP_PRIMARY].va_buffer - = BIOS_PADDRTOVADDR(info.vi_buffer); - biosadapter[V_ADP_PRIMARY].va_buffer_size = info.vi_buffer_size; - } - - if (biosadapters > 1) { - vga_get_info(&biosadapter[V_ADP_SECONDARY], - biosadapter[V_ADP_SECONDARY].va_initial_mode, &info); - biosadapter[V_ADP_SECONDARY].va_mode_flags = info.vi_flags; - biosadapter[V_ADP_SECONDARY].va_window = - BIOS_PADDRTOVADDR(info.vi_window); - biosadapter[V_ADP_SECONDARY].va_window_size = info.vi_window_size; - biosadapter[V_ADP_SECONDARY].va_window_gran = info.vi_window_gran; - if (info.vi_buffer_size == 0) { - biosadapter[V_ADP_SECONDARY].va_buffer = 0; - biosadapter[V_ADP_SECONDARY].va_buffer_size = 0; - } else { - biosadapter[V_ADP_SECONDARY].va_buffer = - BIOS_PADDRTOVADDR(info.vi_buffer); - biosadapter[V_ADP_SECONDARY].va_buffer_size = info.vi_buffer_size; - } + vid_get_info(V_ADP_PRIMARY, + adapter[V_ADP_PRIMARY].va_initial_mode, &info); + adapter[V_ADP_PRIMARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[V_ADP_PRIMARY].va_window_size = info.vi_window_size; + adapter[V_ADP_PRIMARY].va_window_gran = info.vi_window_gran; + adapter[V_ADP_PRIMARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[V_ADP_PRIMARY].va_buffer_size = info.vi_buffer_size; + if (adapters > 1) { + vid_get_info(V_ADP_SECONDARY, + adapter[V_ADP_SECONDARY].va_initial_mode, &info); + adapter[V_ADP_SECONDARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[V_ADP_SECONDARY].va_window_size = info.vi_window_size; + adapter[V_ADP_SECONDARY].va_window_gran = info.vi_window_gran; + adapter[V_ADP_SECONDARY].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[V_ADP_SECONDARY].va_buffer_size = info.vi_buffer_size; } /* @@ -1186,49 +794,24 @@ probe_adapters(void) * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c); */ - return biosadapters; -} - -/* entry points */ - -static int -vga_nop(void) -{ - return 0; -} - -static int -vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags) -{ - probe_adapters(); - if (unit >= biosadapters) - return ENXIO; - - *adpp = &biosadapter[unit]; - - return 0; + return adapters; } -static int -vga_init(int unit, video_adapter_t *adp, int flags) +/* + * adapter(); + * Return a pointer to the video_adapter structure of the requested + * adapter. + * + * all adapters + */ +static video_adapter_t +*vid_adapter(int ad) { - if ((unit >= biosadapters) || (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; - } - if (vga_sub_configure != NULL) - (*vga_sub_configure)(0); - - return 0; + if (!init_done) + return NULL; + if ((ad < 0) || (ad >= adapters)) + return NULL; + return &adapter[ad]; } /* @@ -1238,31 +821,31 @@ vga_init(int unit, video_adapter_t *adp, int flags) * all adapters */ static int -vga_get_info(video_adapter_t *adp, int mode, video_info_t *info) +vid_get_info(int ad, int mode, video_info_t *info) { int i; if (!init_done) return 1; + if ((ad < 0) || (ad >= adapters)) + return 1; - mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); -#ifndef VGA_NO_MODE_CHANGE - if (adp->va_flags & V_ADP_MODECHANGE) { + mode = map_gen_mode_num(adapter[ad].va_type, + adapter[ad].va_flags & V_ADP_COLOR, mode); + if (adapter[ad].va_flags & V_ADP_MODECHANGE) { /* * If the parameter table entry for this mode is not found, * the mode is not supported... */ if (get_mode_param(mode) == NULL) return 1; - } else -#endif /* VGA_NO_MODE_CHANGE */ - { + } else { /* * Even if we don't support video mode switching on this adapter, * the information on the initial (thus current) video mode * should be made available. */ - if (mode != adp->va_initial_mode) + if (mode != adapter[ad].va_initial_mode) return 1; } @@ -1286,13 +869,15 @@ vga_get_info(video_adapter_t *adp, int mode, video_info_t *info) * all adapters */ static int -vga_query_mode(video_adapter_t *adp, video_info_t *info) +vid_query_mode(int ad, video_info_t *info) { video_info_t buf; int i; if (!init_done) return -1; + if ((ad < 0) || (ad >= adapters)) + return -1; for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { if (bios_vmode[i].vi_mode == NA) @@ -1322,7 +907,7 @@ vga_query_mode(video_adapter_t *adp, video_info_t *info) continue; /* verify if this mode is supported on this adapter */ - if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf)) + if (vid_get_info(ad, bios_vmode[i].vi_mode, &buf)) continue; return bios_vmode[i].vi_mode; } @@ -1336,17 +921,16 @@ vga_query_mode(video_adapter_t *adp, video_info_t *info) * EGA/VGA */ static int -vga_set_mode(video_adapter_t *adp, int mode) +vid_set_mode(int ad, int mode) { -#ifndef VGA_NO_MODE_CHANGE video_info_t info; adp_state_t params; - prologue(adp, V_ADP_MODECHANGE, 1); + prologue(ad, V_ADP_MODECHANGE, 1); - mode = map_gen_mode_num(adp->va_type, - adp->va_flags & V_ADP_COLOR, mode); - if (vga_get_info(adp, mode, &info)) + mode = map_gen_mode_num(adapter[ad].va_type, + adapter[ad].va_flags & V_ADP_COLOR, mode); + if (vid_get_info(ad, mode, &info)) return 1; params.sig = V_STATE_SIG; bcopy(get_mode_param(mode), params.regs, sizeof(params.regs)); @@ -1388,7 +972,7 @@ special_80x50: case M_EGAMONO80x25: setup_mode: - vga_load_state(adp, ¶ms); + vid_load_state(ad, ¶ms); break; case M_VGA_MODEX: @@ -1420,42 +1004,33 @@ setup_mode: case M_BG640x480: case M_CG640x480: case M_VGA_CG320: setup_grmode: - vga_load_state(adp, ¶ms); + vid_load_state(ad, ¶ms); break; default: return 1; } - adp->va_mode = mode; - adp->va_mode_flags = info.vi_flags; - adp->va_flags &= ~V_ADP_COLOR; - adp->va_flags |= + adapter[ad].va_mode = mode; + adapter[ad].va_flags &= ~V_ADP_COLOR; + adapter[ad].va_flags |= (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; - adp->va_crtc_addr = - (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; - adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); - adp->va_window_size = info.vi_window_size; - adp->va_window_gran = info.vi_window_gran; + adapter[ad].va_crtc_addr = + (adapter[ad].va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE; + adapter[ad].va_window = BIOS_PADDRTOVADDR(info.vi_window); + adapter[ad].va_window_size = info.vi_window_size; + adapter[ad].va_window_gran = info.vi_window_gran; if (info.vi_buffer_size == 0) { - adp->va_buffer = 0; - adp->va_buffer_size = 0; + adapter[ad].va_buffer = 0; + adapter[ad].va_buffer_size = 0; } else { - adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); - adp->va_buffer_size = info.vi_buffer_size; + adapter[ad].va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); + adapter[ad].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; -#else /* VGA_NO_MODE_CHANGE */ - return 1; -#endif /* VGA_NO_MODE_CHANGE */ } -#ifndef VGA_NO_FONT_LOADING - static void set_font_mode(video_adapter_t *adp, u_char *buf) { @@ -1493,31 +1068,31 @@ set_font_mode(video_adapter_t *adp, u_char *buf) inb(adp->va_crtc_addr + 6); /* reset flip-flop */ outb(ATC, 0x20); /* enable palette */ -#if VGA_SLOW_IOACCESS -#ifdef VGA_ALT_SEQACCESS +#if SLOW_VGA +#ifdef SC_ALT_SEQACCESS outb(TSIDX, 0x00); outb(TSREG, 0x01); #endif outb(TSIDX, 0x02); outb(TSREG, 0x04); outb(TSIDX, 0x04); outb(TSREG, 0x07); -#ifdef VGA_ALT_SEQACCESS +#ifdef SC_ALT_SEQACCESS 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 /* VGA_SLOW_IOACCESS */ -#ifdef VGA_ALT_SEQACCESS +#else +#ifdef SC_ALT_SEQACCESS outw(TSIDX, 0x0100); #endif outw(TSIDX, 0x0402); outw(TSIDX, 0x0704); -#ifdef VGA_ALT_SEQACCESS +#ifdef SC_ALT_SEQACCESS outw(TSIDX, 0x0300); #endif outw(GDCIDX, 0x0204); outw(GDCIDX, 0x0005); outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ -#endif /* VGA_SLOW_IOACCESS */ +#endif splx(s); } @@ -1535,44 +1110,42 @@ set_normal_mode(video_adapter_t *adp, u_char *buf) inb(adp->va_crtc_addr + 6); /* reset flip-flop */ outb(ATC, 0x20); /* enable palette */ -#if VGA_SLOW_IOACCESS -#ifdef VGA_ALT_SEQACCESS +#if SLOW_VGA +#ifdef SC_ALT_SEQACCESS outb(TSIDX, 0x00); outb(TSREG, 0x01); #endif outb(TSIDX, 0x02); outb(TSREG, buf[0]); outb(TSIDX, 0x04); outb(TSREG, buf[1]); -#ifdef VGA_ALT_SEQACCESS +#ifdef SC_ALT_SEQACCESS outb(TSIDX, 0x00); outb(TSREG, 0x03); #endif outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); - if (adp->va_crtc_addr == MONO_CRTC) { + if (adp->va_crtc_addr == MONO_BASE) { outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); } else { outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); } -#else /* VGA_SLOW_IOACCESS */ -#ifdef VGA_ALT_SEQACCESS +#else +#ifdef SC_ALT_SEQACCESS outw(TSIDX, 0x0100); #endif outw(TSIDX, 0x0002 | (buf[0] << 8)); outw(TSIDX, 0x0004 | (buf[1] << 8)); -#ifdef VGA_ALT_SEQACCESS +#ifdef SC_ALT_SEQACCESS outw(TSIDX, 0x0300); #endif outw(GDCIDX, 0x0004 | (buf[2] << 8)); outw(GDCIDX, 0x0005 | (buf[3] << 8)); - if (adp->va_crtc_addr == MONO_CRTC) + if (adp->va_crtc_addr == MONO_BASE) outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); else outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); -#endif /* VGA_SLOW_IOACCESS */ +#endif splx(s); } -#endif /* VGA_NO_FONT_LOADING */ - /* * save_font(): * Read the font data in the requested font page from the video adapter. @@ -1580,19 +1153,15 @@ set_normal_mode(video_adapter_t *adp, u_char *buf) * EGA/VGA */ static int -vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, - int ch, int count) +vid_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count) { -#ifndef VGA_NO_FONT_LOADING u_char buf[PARAM_BUFSIZE]; + u_char val = 0; u_int32_t segment; int c; -#ifdef VGA_ALT_SEQACCESS int s; - u_char val = 0; -#endif - prologue(adp, V_ADP_FONT, 1); + prologue(ad, V_ADP_FONT, 1); if (fontsize < 14) { /* FONT_8 */ @@ -1609,12 +1178,12 @@ vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, if (page < 0 || page >= 8) return 1; - segment = FONT_BUF + 0x4000*page; + segment = VIDEOMEM + 0x4000*page; if (page > 3) segment -= 0xe000; -#ifdef VGA_ALT_SEQACCESS - if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ +#ifdef SC_ALT_SEQACCESS + if (adapter[ad].va_type == KD_VGA) { /* what about EGA? XXX */ s = splhigh(); outb(TSIDX, 0x00); outb(TSREG, 0x01); outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ @@ -1624,19 +1193,21 @@ vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, } #endif - set_font_mode(adp, buf); + set_font_mode(&adapter[ad], buf); if (fontsize == 32) { - bcopy_fromio((void *)(segment + ch*32), data, fontsize*count); + generic_bcopy((void *)BIOS_PADDRTOVADDR(segment + ch*32), data, + fontsize*count); } else { for (c = ch; count > 0; ++c, --count) { - bcopy_fromio((void *)(segment + c*32), data, fontsize); + generic_bcopy((void *)BIOS_PADDRTOVADDR(segment + c*32), data, + fontsize); data += fontsize; } } - set_normal_mode(adp, buf); + set_normal_mode(&adapter[ad], buf); -#ifdef VGA_ALT_SEQACCESS - if (adp->va_type == KD_VGA) { +#ifdef SC_ALT_SEQACCESS + if (adapter[ad].va_type == KD_VGA) { s = splhigh(); outb(TSIDX, 0x00); outb(TSREG, 0x01); outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ @@ -1646,9 +1217,6 @@ vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, #endif return 0; -#else /* VGA_NO_FONT_LOADING */ - return 1; -#endif /* VGA_NO_FONT_LOADING */ } /* @@ -1660,19 +1228,15 @@ vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, * EGA/VGA */ static int -vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, - int ch, int count) +vid_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count) { -#ifndef VGA_NO_FONT_LOADING u_char buf[PARAM_BUFSIZE]; + u_char val = 0; u_int32_t segment; int c; -#ifdef VGA_ALT_SEQACCESS int s; - u_char val = 0; -#endif - prologue(adp, V_ADP_FONT, 1); + prologue(ad, V_ADP_FONT, 1); if (fontsize < 14) { /* FONT_8 */ @@ -1689,12 +1253,12 @@ vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, if (page < 0 || page >= 8) return 1; - segment = FONT_BUF + 0x4000*page; + segment = VIDEOMEM + 0x4000*page; if (page > 3) segment -= 0xe000; -#ifdef VGA_ALT_SEQACCESS - if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ +#ifdef SC_ALT_SEQACCESS + if (adapter[ad].va_type == KD_VGA) { /* what about EGA? XXX */ s = splhigh(); outb(TSIDX, 0x00); outb(TSREG, 0x01); outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ @@ -1704,19 +1268,21 @@ vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, } #endif - set_font_mode(adp, buf); + set_font_mode(&adapter[ad], buf); if (fontsize == 32) { - bcopy_toio(data, (void *)(segment + ch*32), fontsize*count); + generic_bcopy(data, (void *)BIOS_PADDRTOVADDR(segment + ch*32), + fontsize*count); } else { for (c = ch; count > 0; ++c, --count) { - bcopy_toio(data, (void *)(segment + c*32), fontsize); + generic_bcopy(data, (void *)BIOS_PADDRTOVADDR(segment + c*32), + fontsize); data += fontsize; } } - set_normal_mode(adp, buf); + set_normal_mode(&adapter[ad], buf); -#ifdef VGA_ALT_SEQACCESS - if (adp->va_type == KD_VGA) { +#ifdef SC_ALT_SEQACCESS + if (adapter[ad].va_type == KD_VGA) { s = splhigh(); outb(TSIDX, 0x00); outb(TSREG, 0x01); outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ @@ -1726,9 +1292,6 @@ vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, #endif return 0; -#else /* VGA_NO_FONT_LOADING */ - return 1; -#endif /* VGA_NO_FONT_LOADING */ } /* @@ -1740,13 +1303,12 @@ vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, * EGA/VGA */ static int -vga_show_font(video_adapter_t *adp, int page) +vid_show_font(int ad, int page) { -#ifndef VGA_NO_FONT_LOADING static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f }; int s; - prologue(adp, V_ADP_FONT, 1); + prologue(ad, V_ADP_FONT, 1); if (page < 0 || page >= 8) return 1; @@ -1755,9 +1317,6 @@ vga_show_font(video_adapter_t *adp, int page) splx(s); return 0; -#else /* VGA_NO_FONT_LOADING */ - return 1; -#endif /* VGA_NO_FONT_LOADING */ } /* @@ -1767,11 +1326,11 @@ vga_show_font(video_adapter_t *adp, int page) * VGA */ static int -vga_save_palette(video_adapter_t *adp, u_char *palette) +vid_save_palette(int ad, u_char *palette) { int i; - prologue(adp, V_ADP_PALETTE, 1); + prologue(ad, V_ADP_PALETTE, 1); /* * We store 8 bit values in the palette buffer, while the standard @@ -1780,7 +1339,7 @@ vga_save_palette(video_adapter_t *adp, u_char *palette) outb(PALRADR, 0x00); for (i = 0; i < 256*3; ++i) palette[i] = inb(PALDATA) << 2; - inb(adp->va_crtc_addr + 6); /* reset flip/flop */ + inb(adapter[ad].va_crtc_addr + 6); /* reset flip/flop */ return 0; } @@ -1791,17 +1350,17 @@ vga_save_palette(video_adapter_t *adp, u_char *palette) * VGA */ static int -vga_load_palette(video_adapter_t *adp, u_char *palette) +vid_load_palette(int ad, u_char *palette) { int i; - prologue(adp, V_ADP_PALETTE, 1); + prologue(ad, V_ADP_PALETTE, 1); outb(PIXMASK, 0xff); /* no pixelmask */ outb(PALWADR, 0x00); for (i = 0; i < 256*3; ++i) outb(PALDATA, palette[i] >> 2); - inb(adp->va_crtc_addr + 6); /* reset flip/flop */ + inb(adapter[ad].va_crtc_addr + 6); /* reset flip/flop */ outb(ATC, 0x20); /* enable palette */ return 0; } @@ -1813,18 +1372,18 @@ vga_load_palette(video_adapter_t *adp, u_char *palette) * CGA/EGA/VGA */ static int -vga_set_border(video_adapter_t *adp, int color) +vid_set_border(int ad, int color) { - prologue(adp, V_ADP_BORDER, 1); + prologue(ad, V_ADP_BORDER, 1); - switch (adp->va_type) { + switch (adapter[ad].va_type) { case KD_EGA: case KD_VGA: - inb(adp->va_crtc_addr + 6); /* reset flip-flop */ + inb(adapter[ad].va_crtc_addr + 6); /* reset flip-flop */ outb(ATC, 0x31); outb(ATC, color & 0xff); break; case KD_CGA: - outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */ + outb(adapter[ad].va_crtc_addr + 5, color & 0x0f); /* color select register */ break; case KD_MONO: case KD_HERCULES: @@ -1843,7 +1402,7 @@ vga_set_border(video_adapter_t *adp, int color) * VGA */ static int -vga_save_state(video_adapter_t *adp, void *p, size_t size) +vid_save_state(int ad, void *p, size_t size) { video_info_t info; u_char *buf; @@ -1853,10 +1412,10 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size) if (size == 0) { /* return the required buffer size */ - prologue(adp, V_ADP_STATESAVE, 0); + prologue(ad, V_ADP_STATESAVE, 0); return sizeof(adp_state_t); } else { - prologue(adp, V_ADP_STATESAVE, 1); + prologue(ad, V_ADP_STATESAVE, 1); if (size < sizeof(adp_state_t)) return 1; } @@ -1864,7 +1423,7 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size) ((adp_state_t *)p)->sig = V_STATE_SIG; buf = ((adp_state_t *)p)->regs; bzero(buf, V_MODE_PARAM_SIZE); - crtc_addr = adp->va_crtc_addr; + crtc_addr = adapter[ad].va_crtc_addr; s = splhigh(); @@ -1895,7 +1454,7 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size) splx(s); #if 1 - if (vga_get_info(adp, adp->va_mode, &info) == 0) { + if (vid_get_info(ad, adapter[ad].va_mode, &info) == 0) { if (info.vi_flags & V_INFO_GRAPHICS) { buf[0] = info.vi_width/info.vi_cwidth; /* COLS */ buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */ @@ -1906,15 +1465,15 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size) buf[2] = info.vi_cheight; /* POINTS */ } else { /* XXX: shouldn't be happening... */ - printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n", - adp->va_unit, adp->va_name); + printf("video#%d: failed to obtain mode info. (vid_save_state())\n", + ad); } #else - buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */ - buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */ - buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */ - buf[3] = readb(BIOS_PADDRTOVADDR(0x44c)); - buf[4] = readb(BIOS_PADDRTOVADDR(0x44d)); + buf[0] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); /* COLS */ + buf[1] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); /* ROWS */ + buf[2] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); /* POINTS */ + buf[3] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44c); + buf[4] = *(u_int8_t *)BIOS_PADDRTOVADDR(0x44d); #endif return 0; @@ -1929,19 +1488,19 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size) * EGA/VGA */ static int -vga_load_state(video_adapter_t *adp, void *p) +vid_load_state(int ad, void *p) { u_char *buf; int crtc_addr; int s; int i; - prologue(adp, V_ADP_STATELOAD, 1); + prologue(ad, V_ADP_STATELOAD, 1); if (((adp_state_t *)p)->sig != V_STATE_SIG) return 1; buf = ((adp_state_t *)p)->regs; - crtc_addr = adp->va_crtc_addr; + crtc_addr = adapter[ad].va_crtc_addr; s = splhigh(); @@ -1970,17 +1529,15 @@ vga_load_state(video_adapter_t *adp, void *p) inb(crtc_addr + 6); /* reset flip-flop */ outb(ATC, 0x20); /* enable palette */ -#ifndef VGA_NO_BIOS - if (adp->va_unit == V_ADP_PRIMARY) { - writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */ - writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */ - writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */ + if (ad == V_ADP_PRIMARY) { + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a) = buf[0]; /* COLS */ + *(u_int8_t *)BIOS_PADDRTOVADDR(0x484) = buf[1] + rows_offset - 1; /* ROWS */ + *(u_int8_t *)BIOS_PADDRTOVADDR(0x485) = buf[2]; /* POINTS */ #if 0 - writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]); - writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]); + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44c) = buf[3]; + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44d) = buf[4]; #endif } -#endif /* VGA_NO_BIOS */ splx(s); return 0; @@ -1991,7 +1548,7 @@ vga_load_state(video_adapter_t *adp, void *p) * Change the origin (window mapping) of the banked frame buffer. */ static int -vga_set_origin(video_adapter_t *adp, off_t offset) +vid_set_origin(int ad, off_t offset) { /* * The standard video modes do not require window mapping; @@ -2007,25 +1564,24 @@ vga_set_origin(video_adapter_t *adp, off_t offset) * all adapters */ static int -vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +vid_read_hw_cursor(int ad, int *col, int *row) { video_info_t info; u_int16_t off; - int s; if (!init_done) return 1; + if ((ad < 0) || (ad >= adapters)) + return 1; - (*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info); + (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info); if (info.vi_flags & V_INFO_GRAPHICS) return 1; - s = spltty(); - outb(adp->va_crtc_addr, 14); - off = inb(adp->va_crtc_addr + 1); - outb(adp->va_crtc_addr, 15); - off = (off << 8) | inb(adp->va_crtc_addr + 1); - splx(s); + outb(adapter[ad].va_crtc_addr, 14); + off = inb(adapter[ad].va_crtc_addr + 1); + outb(adapter[ad].va_crtc_addr, 15); + off = (off << 8) | inb(adapter[ad].va_crtc_addr + 1); *row = off / info.vi_width; *col = off % info.vi_width; @@ -2035,113 +1591,96 @@ vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row) /* * set_hw_cursor(): - * Move the hardware text cursor. If col and row are both -1, - * the cursor won't be shown. + * Move the hardware text cursor. If the requested position is (-1, -1), + * the text cursor won't be shown. * * all adapters */ static int -vga_set_hw_cursor(video_adapter_t *adp, int col, int row) +vid_set_hw_cursor(int ad, int col, int row) { video_info_t info; u_int16_t off; - int s; if (!init_done) return 1; + if ((ad < 0) || (ad >= adapters)) + 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; - } + (*biosvidsw.get_info)(ad, adapter[ad].va_mode, &info); + if (info.vi_flags & V_INFO_GRAPHICS) + return 1; - s = spltty(); - outb(adp->va_crtc_addr, 14); - outb(adp->va_crtc_addr + 1, off >> 8); - outb(adp->va_crtc_addr, 15); - outb(adp->va_crtc_addr + 1, off & 0x00ff); - splx(s); + if ((col == -1) || (row == -1)) + off = 0xffff; + else + off = row*info.vi_width + col; + outb(adapter[ad].va_crtc_addr, 14); + outb(adapter[ad].va_crtc_addr + 1, off >> 8); + outb(adapter[ad].va_crtc_addr, 15); + outb(adapter[ad].va_crtc_addr + 1, off & 0x00ff); 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. - * - * all adapters - */ -static int -vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, - int celsize, int blink) +static char +*adapter_name(int type) { - int s; - - if (!init_done) - return 1; + static struct { + int type; + char *name; + } names[] = { + { KD_MONO, "MDA" }, + { KD_HERCULES, "Hercules" }, + { KD_CGA, "CGA" }, + { KD_EGA, "EGA" }, + { KD_VGA, "VGA" }, + { KD_PC98, "PC-98xx" }, + { -1, "Unknown" }, + }; + int i; - s = spltty(); - switch (adp->va_type) { - case KD_VGA: - case KD_CGA: - case KD_MONO: - case KD_HERCULES: - default: - if (height <= 0) { - /* make the cursor invisible */ - outb(adp->va_crtc_addr, 10); - outb(adp->va_crtc_addr + 1, 32); - outb(adp->va_crtc_addr, 11); - outb(adp->va_crtc_addr + 1, 0); - } else { - outb(adp->va_crtc_addr, 10); - outb(adp->va_crtc_addr + 1, celsize - base - height); - outb(adp->va_crtc_addr, 11); - outb(adp->va_crtc_addr + 1, celsize - base - 1); - } - break; - case KD_EGA: - if (height <= 0) { - /* make the cursor invisible */ - outb(adp->va_crtc_addr, 10); - outb(adp->va_crtc_addr + 1, celsize); - outb(adp->va_crtc_addr, 11); - outb(adp->va_crtc_addr + 1, 0); - } else { - outb(adp->va_crtc_addr, 10); - outb(adp->va_crtc_addr + 1, celsize - base - height); - outb(adp->va_crtc_addr, 11); - outb(adp->va_crtc_addr + 1, celsize - base); - } - break; - } - splx(s); + for (i = 0; names[i].type != -1; ++i) + if (names[i].type == type) + break; + return names[i].name; +} - return 0; +static void +dump_adp_info(int ad, video_adapter_t *adp, int level) +{ + if (level <= 0) + return; + + printf("video#%d: adapter type:%s (%d), flags:0x%x, CRTC:0x%x\n", + ad, adapter_name(adp->va_type), adp->va_type, + adp->va_flags, adp->va_crtc_addr); + printf("video#%d: init mode:%d, bios mode:%d, current mode:%d\n", + ad, adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode); + printf("video#%d: window:0x%x size:%dk gran:%dk, buf:0x%x size:%dk\n", + ad, + adp->va_window, adp->va_window_size/1024, adp->va_window_gran/1024, + adp->va_buffer, adp->va_buffer_size/1024); } -/* - * mmap(): - * Mmap frame buffer. - * - * all adapters - */ -static int -vga_mmap(video_adapter_t *adp, vm_offset_t offset) +static void +dump_mode_info(int ad, video_info_t *info, int level) { - if (offset > 0x20000 - PAGE_SIZE) - return -1; -#ifdef __i386__ - return i386_btop((VIDEO_BUF_BASE + offset)); -#endif -#ifdef __alpha__ - return alpha_btop((VIDEO_BUF_BASE + offset)); -#endif + if (level <= 0) + return; + + printf("video#%d: mode:%d, flags:0x%x ", + ad, info->vi_mode, info->vi_flags); + if (info->vi_flags & V_INFO_GRAPHICS) + printf("G %dx%dx%d, %d plane(s), font:%dx%d, ", + info->vi_width, info->vi_height, + info->vi_depth, info->vi_planes, + info->vi_cwidth, info->vi_cheight); + else + printf("T %dx%d, font:%dx%d, ", + info->vi_width, info->vi_height, + info->vi_cwidth, info->vi_cheight); + printf("win:0x%x\n", info->vi_window); } static void @@ -2164,75 +1703,72 @@ dump_buffer(u_char *buf, size_t len) * all adapters */ static int -vga_diag(video_adapter_t *adp, int level) +vid_diag(int level) { -#if FB_DEBUG > 1 video_info_t info; -#endif u_char *mp; + int ad; + int i; if (!init_done) return 1; -#if FB_DEBUG > 1 -#ifndef VGA_NO_BIOS - printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n", - rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488))); - printf("vga: CRTC:0x%x, video option:0x%02x, ", - readw(BIOS_PADDRTOVADDR(0x463)), - readb(BIOS_PADDRTOVADDR(0x487))); - printf("rows:%d, cols:%d, font height:%d\n", - readb(BIOS_PADDRTOVADDR(0x44a)), - readb(BIOS_PADDRTOVADDR(0x484)) + 1, - readb(BIOS_PADDRTOVADDR(0x485))); -#endif /* VGA_NO_BIOS */ - printf("vga: param table EGA/VGA:%p", video_mode_ptr); - printf(", CGA/MDA:%p\n", video_mode_ptr2); - printf("vga: rows_offset:%d\n", rows_offset); -#endif /* FB_DEBUG > 1 */ - - fb_dump_adp_info(DRIVER_NAME, adp, level); - -#if FB_DEBUG > 1 - if (adp->va_flags & V_ADP_MODECHANGE) { - 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); - } - } else { - vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */ - fb_dump_mode_info(DRIVER_NAME, adp, &info, level); + if (level > 0) { + printf("video: RTC equip. code:0x%02x, DCC code:0x%02x\n", + rtcin(RTC_EQUIPMENT), *(u_int8_t *)BIOS_PADDRTOVADDR(0x488)); + printf("video: CRTC:0x%x, video option:0x%02x, ", + *(u_int16_t *)BIOS_PADDRTOVADDR(0x463), + *(u_int8_t *)BIOS_PADDRTOVADDR(0x487)); + printf("rows:%d, cols:%d, font height:%d\n", + *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a), + *(u_int8_t *)BIOS_PADDRTOVADDR(0x484) + 1, + *(u_int8_t *)BIOS_PADDRTOVADDR(0x485)); + printf("video: param table EGA/VGA:%p, CGA/MDA:%p\n", + video_mode_ptr, video_mode_ptr2); + printf("video: rows_offset:%d\n", rows_offset); } -#endif /* FB_DEBUG > 1 */ - - if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA)) - return 0; -#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) - if (video_mode_ptr == NULL) - printf("vga%d: %s: WARNING: video mode switching is not " - "fully supported on this adapter\n", - adp->va_unit, adp->va_name); -#endif - if (level <= 0) - return 0; - if (adp->va_type == KD_VGA) { - printf("VGA parameters upon power-up\n"); - dump_buffer(adpstate.regs, sizeof(adpstate.regs)); - printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode); - dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); - } + for (ad = 0; ad < adapters; ++ad) { + dump_adp_info(ad, &adapter[ad], level); - mp = get_mode_param(adp->va_initial_mode); - if (mp == NULL) /* this shouldn't be happening */ - return 0; - printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode); - dump_buffer(mp, V_MODE_PARAM_SIZE); + if (!(adapter[ad].va_flags & V_ADP_MODECHANGE)) { + vid_get_info(ad, adapter[ad].va_initial_mode, &info); + dump_mode_info(ad, &info, level); + } else { + 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; + dump_mode_info(ad, &bios_vmode[i], level); + } + } + if ((adapter[ad].va_type != KD_EGA) && (adapter[ad].va_type != KD_VGA)) + continue; + + if (video_mode_ptr == NULL) + printf("video#%d: WARNING: video mode switching is not fully supported on this adapter\n", ad); + + if (level <= 0) + continue; + + if (adapter[ad].va_type == KD_VGA) { + printf("VGA parameters upon power-up\n"); + dump_buffer(adpstate.regs, sizeof(adpstate.regs)); + printf("VGA parameters in BIOS for mode %d\n", + adapter[ad].va_initial_mode); + dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); + } + + mp = get_mode_param(adapter[ad].va_initial_mode); + if (mp == NULL) /* this shouldn't be happening */ + continue; + printf("EGA/VGA parameters to be used for mode %d\n", + adapter[ad].va_initial_mode); + dump_buffer(mp, V_MODE_PARAM_SIZE); + } return 0; } -#endif /* NVGA > 0 */ +#endif /* NSC > 0 */ diff --git a/sys/i386/isa/videoio.h b/sys/i386/isa/videoio.h new file mode 100644 index 0000000000000..a79ffbe97babe --- /dev/null +++ b/sys/i386/isa/videoio.h @@ -0,0 +1,104 @@ +/*- + * 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: videoio.h,v 1.1 1998/09/15 18:16:38 sos Exp $ + */ + +#ifndef _I386_ISA_VIDEOIO_H_ +#define _I386_ISA_VIDEOIO_H_ + +#ifdef KERNEL + +#define V_MAX_ADAPTERS 2 + +#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) +#define V_MODE_PARAM_SIZE 64 + +/* physical addresses */ +#define MONO_BUF BIOS_PADDRTOVADDR(0xb0000) +#define CGA_BUF BIOS_PADDRTOVADDR(0xb8000) +#define GRAPHICS_BUF BIOS_PADDRTOVADDR(0xa0000) +#define VIDEOMEM 0x000A0000 + +/* I/O port addresses */ +#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 */ + +/* video function table */ +typedef int vi_init_t(void); +typedef video_adapter_t *vi_adapter_t(int ad); +typedef int vi_get_info_t(int ad, int mode, video_info_t *info); +typedef int vi_query_mode_t(int ad, video_info_t *info); +typedef int vi_set_mode_t(int ad, int mode); +typedef int vi_save_font_t(int ad, int page, int size, u_char *data, + int c, int count); +typedef int vi_load_font_t(int ad, int page, int size, u_char *data, + int c, int count); +typedef int vi_show_font_t(int ad, int page); +typedef int vi_save_palette_t(int ad, u_char *palette); +typedef int vi_load_palette_t(int ad, u_char *palette); +typedef int vi_set_border_t(int ad, int border); +typedef int vi_save_state_t(int ad, void *p, size_t size); +typedef int vi_load_state_t(int ad, void *p); +typedef int vi_set_win_org_t(int ad, off_t offset); +typedef int vi_read_hw_cursor_t(int ad, int *col, int *row); +typedef int vi_set_hw_cursor_t(int ad, int col, int row); +typedef int vi_diag_t(int level); + +struct vidsw { + vi_init_t *init; /* all */ + vi_adapter_t *adapter; /* all */ + vi_get_info_t *get_info; /* all */ + vi_query_mode_t *query_mode; /* all */ + vi_set_mode_t *set_mode; /* EGA/VGA */ + vi_save_font_t *save_font; /* EGA/VGA */ + vi_load_font_t *load_font; /* EGA/VGA */ + vi_show_font_t *show_font; /* EGA/VGA */ + vi_save_palette_t *save_palette; /* VGA */ + vi_load_palette_t *load_palette; /* VGA */ + vi_set_border_t *set_border; /* CGA/EGA/VGA */ + vi_save_state_t *save_state; /* VGA */ + vi_load_state_t *load_state; /* EGA/VGA */ + vi_set_win_org_t *set_win_org; /* all */ + vi_read_hw_cursor_t *read_hw_cursor; /* all */ + vi_set_hw_cursor_t *set_hw_cursor; /* all */ + vi_diag_t *diag; /* all */ +}; + +extern struct vidsw biosvidsw; + +#endif /* KERNEL */ + +#endif /* !_I386_ISA_VIDEOIO_H_ */ diff --git a/sys/i386/isa/wcd.c b/sys/i386/isa/wcd.c new file mode 100644 index 0000000000000..1f22bfc7c8219 --- /dev/null +++ b/sys/i386/isa/wcd.c @@ -0,0 +1,1399 @@ +/* + * IDE CD-ROM driver for FreeBSD. + * Supports ATAPI-compatible drives. + * + * Copyright (C) 1995 Cronyx Ltd. + * Author Serge Vakulenko, <vak@cronyx.ru> + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + * + * From: Version 1.9, Mon Oct 9 20:27:42 MSK 1995 + * $Id: wcd.c,v 1.58 1998/09/08 20:57:47 sos Exp $ + */ + +#include "wdc.h" +#include "wcd.h" +#include "opt_atapi.h" +#include "opt_devfs.h" + +#if NWCD > 0 && NWDC > 0 && defined (ATAPI) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/devicestat.h> +#include <sys/disklabel.h> +#include <sys/cdio.h> +#include <sys/conf.h> +#include <sys/stat.h> +#ifdef DEVFS +#include <sys/devfsext.h> +#endif /*DEVFS*/ + +#include <i386/isa/atapi.h> + +static d_open_t wcdopen; +static d_read_t wcdread; +static d_close_t wcdclose; +static d_ioctl_t wcdioctl; +static d_strategy_t wcdstrategy; + +#define CDEV_MAJOR 69 +#define BDEV_MAJOR 19 +static struct cdevsw wcd_cdevsw = + { wcdopen, wcdclose, wcdread, nowrite, /*69*/ + wcdioctl, nostop, nullreset, nodevtotty,/* atapi */ + seltrue, nommap, wcdstrategy, "wcd", + NULL, -1, nodump, nopsize, + D_DISK, 0, -1 }; + +#ifndef ATAPI_STATIC +static +#endif +int wcdattach(struct atapi*, int, struct atapi_params*, int); + +#define NUNIT 16 /* Max. number of devices */ +#define SECSIZE 2048 /* CD-ROM sector size in bytes */ + +#define F_BOPEN 0x0001 /* The block device is opened */ +#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ +#define F_DEBUG 0x0004 /* Print debug info */ +#define F_LOCKED 0x0008 /* This unit is locked (or should be) */ + +/* + * Disc table of contents. + */ +#define MAXTRK 99 +struct toc { + struct ioc_toc_header hdr; + struct cd_toc_entry tab[MAXTRK+1]; /* One extra for the leadout */ +}; + +/* + * Volume size info. + */ +struct volinfo { + u_long volsize; /* Volume size in blocks */ + u_long blksize; /* Block size in bytes */ +}; + +/* + * Current subchannel status. + */ +struct subchan { + u_char void0; + u_char audio_status; + u_short data_length; + u_char data_format; + u_char control; + u_char track; + u_char indx; + u_long abslba; + u_long rellba; +}; + +/* + * Audio Control Parameters Page + */ +struct audiopage { + /* Mode data header */ + u_short data_length; + u_char medium_type; + u_char reserved1[5]; + + /* Audio control page */ + u_char page_code; +#define AUDIO_PAGE 0x0e +#define AUDIO_PAGE_MASK 0x4e /* changeable values */ + u_char param_len; + u_char flags; +#define CD_PA_SOTC 0x02 /* mandatory */ +#define CD_PA_IMMED 0x04 /* always 1 */ + u_char reserved3[3]; + u_short lb_per_sec; + struct port_control { + u_char channels : 4; +#define CHANNEL_0 1 /* mandatory */ +#define CHANNEL_1 2 /* mandatory */ +#define CHANNEL_2 4 /* optional */ +#define CHANNEL_3 8 /* optional */ + u_char volume; + } port[4]; +}; + +/* + * CD-ROM Capabilities and Mechanical Status Page + */ +struct cappage { + /* Mode data header */ + u_short data_length; + u_char medium_type; +#define MDT_UNKNOWN 0x00 +#define MDT_DATA_120 0x01 +#define MDT_AUDIO_120 0x02 +#define MDT_COMB_120 0x03 +#define MDT_PHOTO_120 0x04 +#define MDT_DATA_80 0x05 +#define MDT_AUDIO_80 0x06 +#define MDT_COMB_80 0x07 +#define MDT_PHOTO_80 0x08 +#define MDT_NO_DISC 0x70 +#define MDT_DOOR_OPEN 0x71 +#define MDT_FMT_ERROR 0x72 + u_char reserved1[5]; + + /* Capabilities page */ + u_char page_code; +#define CAP_PAGE 0x2a + u_char param_len; + u_char reserved2[2]; + + u_int audio_play : 1; /* audio play supported */ + u_int composite : 1; /* composite audio/video supported */ + u_int dport1 : 1; /* digital audio on port 1 */ + u_int dport2 : 1; /* digital audio on port 2 */ + u_int mode2_form1 : 1; /* mode 2 form 1 (XA) read */ + u_int mode2_form2 : 1; /* mode 2 form 2 format */ + u_int multisession : 1; /* multi-session photo-CD */ + u_int : 1; + u_int cd_da : 1; /* audio-CD read supported */ + u_int cd_da_stream : 1; /* CD-DA streaming */ + u_int rw : 1; /* combined R-W subchannels */ + u_int rw_corr : 1; /* R-W subchannel data corrected */ + u_int c2 : 1; /* C2 error pointers supported */ + u_int isrc : 1; /* can return the ISRC info */ + u_int upc : 1; /* can return the catalog number UPC */ + u_int : 1; + u_int lock : 1; /* could be locked */ + u_int locked : 1; /* current lock state */ + u_int prevent : 1; /* prevent jumper installed */ + u_int eject : 1; /* can eject */ + u_int : 1; + u_int mech : 3; /* loading mechanism type */ +#define MECH_CADDY 0 +#define MECH_TRAY 1 +#define MECH_POPUP 2 +#define MECH_CHANGER 4 +#define MECH_CARTRIDGE 5 + u_int sep_vol : 1; /* independent volume of channels */ + u_int sep_mute : 1; /* independent mute of channels */ + u_int : 6; + + u_short max_speed; /* max raw data rate in bytes/1000 */ + u_short max_vol_levels; /* number of discrete volume levels */ + u_short buf_size; /* internal buffer size in bytes/1024 */ + u_short cur_speed; /* current data rate in bytes/1000 */ + + /* Digital drive output format description (optional?) */ + u_char reserved3; + u_int bckf : 1; /* data valid on failing edge of BCK */ + u_int rch : 1; /* high LRCK indicates left channel */ + u_int lsbf : 1; /* set if LSB first */ + u_int dlen: 2; +#define DLEN_32 0 /* 32 BCKs */ +#define DLEN_16 1 /* 16 BCKs */ +#define DLEN_24 2 /* 24 BCKs */ +#define DLEN_24_I2S 3 /* 24 BCKs (I2S) */ + u_int : 3; + u_char reserved4[2]; +}; + +/* + * CDROM changer mechanism status structure + */ +struct changer { + u_int current_slot : 5; /* active changer slot */ + u_int mech_state : 2; /* current changer state */ +#define CH_READY 0 +#define CH_LOADING 1 +#define CH_UNLOADING 2 +#define CH_INITIALIZING 3 + u_int fault : 1; /* fault in last operation */ + u_int reserved0 : 5; + u_int cd_state : 3; /* current mechanism state */ +#define CD_IDLE 0 +#define CD_AUDIO_ACTIVE 1 +#define CD_AUDIO_SCAN 2 +#define CD_HOST_ACTIVE 3 +#define CD_NO_STATE 7 + u_char current_lba[3]; /* current LBA */ + u_char slots; /* number of available slots */ + u_short table_length; /* slot table length */ + struct { + u_int changed : 1; /* media has changed in this slot */ + u_int unused : 6; + u_int present : 1; /* slot has a CD present */ + u_char reserved0; + u_char reserved1; + u_char reserved2; + } slot[32]; +}; + +struct wcd { + struct atapi *ata; /* Controller structure */ + int unit; /* IDE bus drive unit */ + int lun; /* Logical device unit */ + int flags; /* Device state flags */ + int refcnt; /* The number of raw opens */ + struct buf_queue_head buf_queue;/* Queue of i/o requests */ + struct atapi_params *param; /* Drive parameters table */ + struct toc toc; /* Table of disc contents */ + struct volinfo info; /* Volume size info */ + struct audiopage au; /* Audio page info */ + struct cappage cap; /* Capabilities page info */ + struct audiopage aumask; /* Audio page mask */ + struct subchan subchan; /* Subchannel info */ + char description[80]; /* Device description */ + struct changer *changer_info; /* changer info */ + int slot; /* this lun's slot number */ + struct devstat device_stats; /* devstat parameters */ +#ifdef DEVFS + void *ra_devfs_token; + void *rc_devfs_token; + void *a_devfs_token; + void *c_devfs_token; +#endif +}; + +static struct wcd *wcdtab[NUNIT]; /* Drive info by unit number */ +static int wcdnlun = 0; /* Number of configured drives */ + +static struct wcd *wcd_init_lun(struct atapi *ata, int unit, + struct atapi_params *ap, int lun); +static void wcd_start (struct wcd *t); +static void wcd_done (struct wcd *t, struct buf *bp, int resid, + struct atapires result); +static void wcd_error (struct wcd *t, struct atapires result); +static int wcd_read_toc (struct wcd *t); +static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count); +static void wcd_describe (struct wcd *t); +static int wcd_setchan (struct wcd *t, + u_char c0, u_char c1, u_char c2, u_char c3); +static int wcd_eject (struct wcd *t, int closeit); +static void wcd_select_slot(struct wcd *cdp); + +/* + * Dump the array in hexadecimal format for debugging purposes. + */ +static void wcd_dump (int lun, char *label, void *data, int len) +{ + u_char *p = data; + + printf ("wcd%d: %s %x", lun, label, *p++); + while (--len > 0) + printf ("-%x", *p++); + printf ("\n"); +} + +struct wcd * +wcd_init_lun(struct atapi *ata, int unit, struct atapi_params *ap, int lun) +{ + struct wcd *ptr; + ptr = malloc(sizeof(struct wcd), M_TEMP, M_NOWAIT); + if (!ptr) + return NULL; + bzero(ptr, sizeof(struct wcd)); + bufq_init(&ptr->buf_queue); + ptr->ata = ata; + ptr->unit = unit; + ptr->lun = lun; + ptr->param = ap; + ptr->flags = F_MEDIA_CHANGED; + ptr->refcnt = 0; + ptr->slot = -1; + ptr->changer_info = NULL; +#ifdef DEVFS + ptr->ra_devfs_token = + devfs_add_devswf(&wcd_cdevsw, dkmakeminor(lun, 0, 0), + DV_CHR, UID_ROOT, GID_OPERATOR, 0640, + "rwcd%da", lun); + ptr->rc_devfs_token = + devfs_add_devswf(&wcd_cdevsw, dkmakeminor(lun, 0, RAW_PART), + DV_CHR, UID_ROOT, GID_OPERATOR, 0640, + "rwcd%dc", lun); + ptr->a_devfs_token = + devfs_add_devswf(&wcd_cdevsw, dkmakeminor(lun, 0, 0), + DV_BLK, UID_ROOT, GID_OPERATOR, 0640, + "wcd%da", lun); + ptr->c_devfs_token = + devfs_add_devswf(&wcd_cdevsw, dkmakeminor(lun, 0, RAW_PART), + DV_BLK, UID_ROOT, GID_OPERATOR, 0640, + "wcd%dc", lun); +#endif + /* + * Export the unit to the devstat interface. + */ + devstat_add_entry(&ptr->device_stats, "wcd", + lun, SECSIZE, + DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE); + return ptr; +} + +#ifndef ATAPI_STATIC +static +#endif +int +wcdattach (struct atapi *ata, int unit, struct atapi_params *ap, int debug) +{ + struct wcd *cdp; + struct atapires result; + struct changer *chp; + int i; + + if (wcdnlun >= NUNIT) { + printf ("wcd: too many units\n"); + return (0); + } + if (!atapi_request_immediate) { + printf("wcd: configuration error, ATAPI core code not present!\n"); + printf("wcd: check `options ATAPI_STATIC' in your kernel config file!\n"); + return (0); + } + if ((cdp = wcd_init_lun(ata, unit, ap, wcdnlun)) == NULL) { + printf("wcd: out of memory\n"); + return 0; + } + wcdtab[wcdnlun] = cdp; + + if (debug) { + cdp->flags |= F_DEBUG; + /* Print params. */ + wcd_dump (cdp->lun, "info", ap, sizeof *ap); + } + + /* Get drive capabilities. */ + result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE, + 0, CAP_PAGE, 0, 0, 0, 0, sizeof (cdp->cap) >> 8, sizeof (cdp->cap), + 0, 0, 0, 0, 0, 0, 0, (char*) &cdp->cap, sizeof (cdp->cap)); + + /* Do it twice to avoid the stale media changed state. */ + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) + result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE, + 0, CAP_PAGE, 0, 0, 0, 0, sizeof (cdp->cap) >> 8, + sizeof (cdp->cap), 0, 0, 0, 0, 0, 0, 0, + (char*) &cdp->cap, sizeof (cdp->cap)); + + /* Some drives have shorter capabilities page. */ + if (result.code == RES_UNDERRUN) + result.code = 0; + + if (result.code == 0) { + wcd_describe (cdp); + if (cdp->flags & F_DEBUG) + wcd_dump (cdp->lun, "cap", &cdp->cap, sizeof(cdp->cap)); + } + + /* If this is a changer device, allocate the neeeded lun's */ + if (cdp->cap.mech == MECH_CHANGER) { + chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT); + if (chp == NULL) { + printf("wcd: out of memory\n"); + return 0; + } + bzero(chp, sizeof(struct changer)); + result = atapi_request_immediate(ata, unit, ATAPI_MECH_STATUS, + 0, 0, 0, 0, 0, 0, 0, + sizeof(struct changer)> 8, sizeof(struct changer), + 0, 0, 0, 0, 0, 0, + (char*) chp, sizeof(struct changer)); + if (cdp->flags & F_DEBUG) { + printf("result.code=%d curr=%02x slots=%d len=%d\n", + result.code, chp->current_slot, chp->slots, + htons(chp->table_length)); + } + if (result.code == RES_UNDERRUN) + result.code = 0; + if (result.code == 0) { + chp->table_length = htons(chp->table_length); + for (i=0; i<chp->slots && wcdnlun<NUNIT; i++) { + if (i>0) { + cdp = wcd_init_lun(ata,unit,ap,wcdnlun); + if (cdp == NULL) { + printf("wcd: out of memory\n"); + return 0; + } + } + cdp->slot = i; + cdp->changer_info = chp; + printf("wcd%d: changer slot %d %s\n", + wcdnlun, + i, (chp->slot[i].present ? + "disk present" : "no disk")); + wcdtab[wcdnlun++] = cdp; + } + if (wcdnlun >= NUNIT) { + printf ("wcd: too many units\n"); + return (0); + } + } + } + else + wcdnlun++; + return (1); +} + +void wcd_describe (struct wcd *t) +{ + char *m; + + t->cap.max_speed = ntohs (t->cap.max_speed); + t->cap.max_vol_levels = ntohs (t->cap.max_vol_levels); + t->cap.buf_size = ntohs (t->cap.buf_size); + t->cap.cur_speed = ntohs (t->cap.cur_speed); + + printf ("wcd%d: ", t->lun); + if (t->cap.cur_speed != t->cap.max_speed) + printf ("%d/", t->cap.cur_speed * 1000 / 1024); + printf ("%dKb/sec", t->cap.max_speed * 1000 / 1024); + if (t->cap.buf_size) + printf (", %dKb cache", t->cap.buf_size); + + if (t->cap.audio_play) + printf (", audio play"); + if (t->cap.max_vol_levels) + printf (", %d volume levels", t->cap.max_vol_levels); + + switch (t->cap.mech) { + default: m = 0; break; + case MECH_CADDY: m = "caddy"; break; + case MECH_TRAY: m = "tray"; break; + case MECH_POPUP: m = "popup"; break; + case MECH_CHANGER: m = "changer"; break; + case MECH_CARTRIDGE: m = "cartridge"; break; + } + if (m) + printf (", %s%s", t->cap.eject ? "ejectable " : "", m); + else if (t->cap.eject) + printf (", eject"); + printf ("\n"); + + if (t->cap.mech != MECH_CHANGER) { + printf ("wcd%d: ", t->lun); + switch (t->cap.medium_type) { + case MDT_UNKNOWN: + printf ("medium type unknown"); break; + case MDT_DATA_120: + printf ("120mm data disc loaded"); break; + case MDT_AUDIO_120: + printf ("120mm audio disc loaded"); break; + case MDT_COMB_120: + printf ("120mm data/audio disc loaded"); break; + case MDT_PHOTO_120: + printf ("120mm photo disc loaded"); break; + case MDT_DATA_80: + printf ("80mm data disc loaded"); break; + case MDT_AUDIO_80: + printf ("80mm audio disc loaded"); break; + case MDT_COMB_80: + printf ("80mm data/audio disc loaded"); break; + case MDT_PHOTO_80: + printf ("80mm photo disc loaded"); break; + case MDT_NO_DISC: + printf ("no disc inside"); break; + case MDT_DOOR_OPEN: + printf ("door open"); break; + case MDT_FMT_ERROR: + printf ("medium format error"); break; + default: + printf ("medium type=0x%x", t->cap.medium_type); break; + } + } + if (t->cap.lock) + printf (t->cap.locked ? ", locked" : ", unlocked"); + if (t->cap.prevent) + printf (", lock protected"); + printf ("\n"); +} + +static int +wcdopen (dev_t dev, int flags, int fmt, struct proc *p) +{ + int lun = dkunit(dev); + struct wcd *t; + + /* Check device number is legal and ATAPI driver is loaded. */ + if (lun >= wcdnlun || ! atapi_request_immediate) + return (ENXIO); + t = wcdtab[lun]; + /* On the first open, read the table of contents. */ + if (! (t->flags & F_BOPEN) && ! t->refcnt) { + /* Read table of contents. */ + if (wcd_read_toc (t) < 0) + return (EIO); + + /* Lock the media. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + t->flags |= F_LOCKED; + } + if (fmt == S_IFCHR) + ++t->refcnt; + else + t->flags |= F_BOPEN; + return (0); +} + +/* + * Close the device. Only called if we are the LAST + * occurence of an open device. + */ +static int +wcdclose (dev_t dev, int flags, int fmt, struct proc *p) +{ + int lun = dkunit(dev); + struct wcd *t = wcdtab[lun]; + + if (fmt == S_IFBLK) { + /* If we were the last open of the entire device, release it. */ + if (! t->refcnt) + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + t->flags &= ~(F_BOPEN|F_LOCKED); + } else { + /* If we were the last open of the entire device, release it. */ + if (! (t->flags & F_BOPEN) && t->refcnt == 1) + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + t->flags &= ~F_LOCKED; + --t->refcnt; + } + return (0); +} + +static int +wcdread(dev_t dev, struct uio *uio, int ioflag) +{ + return (physio(wcdstrategy, NULL, dev, 1, minphys, uio)); +} + +/* + * Actually translate the requested transfer into one the physical driver can + * understand. The transfer is described by a buf and will include only one + * physical transfer. + */ +void wcdstrategy (struct buf *bp) +{ + int lun = dkunit(bp->b_dev); + struct wcd *t = wcdtab[lun]; + int x; + + /* Can't ever write to a CD. */ + if (! (bp->b_flags & B_READ)) { + bp->b_error = EROFS; + bp->b_flags |= B_ERROR; + biodone (bp); + return; + } + + /* If it's a null transfer, return immediatly. */ + if (bp->b_bcount == 0) { + bp->b_resid = 0; + biodone (bp); + return; + } + + /* Process transfer request. */ + bp->b_pblkno = bp->b_blkno; + bp->b_resid = bp->b_bcount; + x = splbio(); + + /* Place it in the queue of disk activities for this disk. */ + bufqdisksort (&t->buf_queue, bp); + + /* Tell the device to get going on the transfer if it's + * not doing anything, otherwise just wait for completion. */ + wcd_start (t); + splx(x); +} + +/* + * Look to see if there is a buf waiting for the device + * and that the device is not already busy. If both are true, + * It dequeues the buf and creates an ATAPI command to perform the + * transfer in the buf. + * The bufs are queued by the strategy routine (wcdstrategy). + * Must be called at the correct (splbio) level. + */ +static void wcd_start (struct wcd *t) +{ + struct buf *bp = bufq_first(&t->buf_queue); + u_long blkno, nblk; + + /* See if there is a buf to do and we are not already doing one. */ + if (! bp) + return; + + /* Unqueue the request. */ + bufq_remove(&t->buf_queue, bp); + + /* Should reject all queued entries if media have changed. */ + if (t->flags & F_MEDIA_CHANGED) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + biodone (bp); + return; + } + + /* Tell devstat we are starting on the transaction */ + devstat_start_transaction(&t->device_stats); + + wcd_select_slot(t); + + /* We have a buf, now we should make a command + * First, translate the block to absolute and put it in terms of the + * logical blocksize of the device. + * What if something asks for 512 bytes not on a 2k boundary? */ + blkno = bp->b_blkno / (SECSIZE / 512); + nblk = (bp->b_bcount + (SECSIZE - 1)) / SECSIZE; + + atapi_request_callback (t->ata, t->unit, ATAPI_READ_BIG, 0, + blkno>>24, blkno>>16, blkno>>8, blkno, 0, nblk>>8, nblk, 0, 0, + 0, 0, 0, 0, 0, (u_char*) bp->b_data, bp->b_bcount, + wcd_done, t, bp); +} + +static void wcd_done (struct wcd *t, struct buf *bp, int resid, + struct atapires result) +{ + if (result.code) { + wcd_error (t, result); + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + } else + bp->b_resid = resid; + + /* Tell devstat we have finished with the transaction */ + devstat_end_transaction(&t->device_stats, + bp->b_bcount - bp->b_resid, + DEVSTAT_TAG_NONE, + (bp->b_flags & B_READ) ? DEVSTAT_READ : DEVSTAT_WRITE); + biodone (bp); + wcd_start (t); +} + +static void wcd_error (struct wcd *t, struct atapires result) +{ + if (result.code != RES_ERR) + return; + switch (result.error & AER_SKEY) { + case AER_SK_NOT_READY: + if (result.error & ~AER_SKEY) { + /* Audio disc. */ + printf ("wcd%d: cannot read audio disc\n", t->lun); + return; + } + /* Tray open. */ + if (! (t->flags & F_MEDIA_CHANGED)) + printf ("wcd%d: tray open\n", t->lun); + t->flags |= F_MEDIA_CHANGED; + return; + + case AER_SK_UNIT_ATTENTION: + /* Media changed. */ + if (! (t->flags & F_MEDIA_CHANGED)) + printf ("wcd%d: media changed\n", t->lun); + t->flags |= F_MEDIA_CHANGED; + return; + + case AER_SK_ILLEGAL_REQUEST: + /* Unknown command or invalid command arguments. */ + if (t->flags & F_DEBUG) + printf ("wcd%d: invalid command\n", t->lun); + return; + } + printf ("wcd%d: i/o error, status=%b, error=%b\n", t->lun, + result.status, ARS_BITS, result.error, AER_BITS); +} + +static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count) +{ + struct atapires result; + + result = atapi_request_wait (t->ata, t->unit, cmd, + a1, a2, a3, a4, a5, a6, a7, a8, a9, 0, 0, 0, 0, 0, 0, + addr, count); + if (result.code) { + wcd_error (t, result); + return (EIO); + } + return (0); +} + +static __inline void lba2msf (int lba, u_char *m, u_char *s, u_char *f) +{ + lba += 150; /* offset of first logical frame */ + lba &= 0xffffff; /* negative lbas use only 24 bits */ + *m = lba / (60 * 75); + lba %= (60 * 75); + *s = lba / 75; + *f = lba % 75; +} + +/* + * Perform special action on behalf of the user. + * Knows about the internals of this device + */ +int wcdioctl (dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) +{ + int lun = dkunit(dev); + struct wcd *t = wcdtab[lun]; + int error = 0; + + if (t->flags & F_MEDIA_CHANGED) + switch (cmd) { + case CDIOCSETDEBUG: + case CDIOCCLRDEBUG: + case CDIOCRESET: + /* These ops are media change transparent. */ + break; + default: + /* Read table of contents. */ + wcd_read_toc (t); + + /* Lock the media. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + t->flags |= F_LOCKED; + break; + } + switch (cmd) { + default: + return (ENOTTY); + + case CDIOCSETDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + t->flags |= F_DEBUG; + atapi_debug (t->ata, 1); + return 0; + + case CDIOCCLRDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + t->flags &= ~F_DEBUG; + atapi_debug (t->ata, 0); + return 0; + + case CDIOCRESUME: + return wcd_request_wait (t, ATAPI_PAUSE, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0); + + case CDIOCPAUSE: + return wcd_request_wait (t, ATAPI_PAUSE, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCSTART: + return wcd_request_wait (t, ATAPI_START_STOP, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCSTOP: + return wcd_request_wait (t, ATAPI_START_STOP, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCALLOW: + wcd_select_slot(t); + t->flags &= ~F_LOCKED; + return wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCPREVENT: + wcd_select_slot(t); + t->flags |= F_LOCKED; + return wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCRESET: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + return wcd_request_wait (t, ATAPI_TEST_UNIT_READY, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCEJECT: + /* Don't allow eject if the device is opened + * by somebody (not us) in block mode. */ + if ((t->flags & F_BOPEN) && t->refcnt) + return (EBUSY); + return wcd_eject (t, 0); + + case CDIOCCLOSE: + if ((t->flags & F_BOPEN) && t->refcnt) + return (0); + return wcd_eject (t, 1); + + case CDIOREADTOCHEADER: + if (! t->toc.hdr.ending_track) + return (EIO); + bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr); + break; + + case CDIOREADTOCENTRYS: { + struct ioc_read_toc_entry *te = + (struct ioc_read_toc_entry*) addr; + struct toc *toc = &t->toc; + struct toc buf; + u_long len; + u_char starting_track = te->starting_track; + + if (! t->toc.hdr.ending_track) + return (EIO); + + if ( te->data_len < sizeof(toc->tab[0]) + || (te->data_len % sizeof(toc->tab[0])) != 0 + || te->address_format != CD_MSF_FORMAT + && te->address_format != CD_LBA_FORMAT + ) + return EINVAL; + + if (starting_track == 0) + starting_track = toc->hdr.starting_track; + else if (starting_track == 170) /* Handle leadout request */ + starting_track = toc->hdr.ending_track + 1; + else if (starting_track < toc->hdr.starting_track || + starting_track > toc->hdr.ending_track + 1) + return (EINVAL); + + len = ((toc->hdr.ending_track + 1 - starting_track) + 1) * + sizeof(toc->tab[0]); + if (te->data_len < len) + len = te->data_len; + if (len > sizeof(toc->tab)) + return EINVAL; + + /* Convert to MSF format, if needed. */ + if (te->address_format == CD_MSF_FORMAT) { + struct cd_toc_entry *e; + + buf = t->toc; + toc = &buf; + e = toc->tab + (toc->hdr.ending_track + 1 - + toc->hdr.starting_track) + 1; + while (--e >= toc->tab) + lba2msf (ntohl(e->addr.lba), &e->addr.msf.minute, + &e->addr.msf.second, &e->addr.msf.frame); + } + return copyout (toc->tab + starting_track - + toc->hdr.starting_track, te->data, len); + } + case CDIOREADTOCENTRY: { + struct ioc_read_toc_single_entry *te = + (struct ioc_read_toc_single_entry*) addr; + struct toc *toc = &t->toc; + struct toc buf; + u_char track = te->track; + + if (! t->toc.hdr.ending_track) + return (EIO); + + if (te->address_format != CD_MSF_FORMAT + && te->address_format != CD_LBA_FORMAT) + return EINVAL; + + if (track == 0) + track = toc->hdr.starting_track; + else if (track == 170) /* Handle leadout request */ + track = toc->hdr.ending_track + 1; + else if (track < toc->hdr.starting_track || + track > toc->hdr.ending_track + 1) + return (EINVAL); + + /* Convert to MSF format, if needed. */ + if (te->address_format == CD_MSF_FORMAT) { + struct cd_toc_entry *e; + + buf = t->toc; + toc = &buf; + e = toc->tab + (track - toc->hdr.starting_track); + lba2msf (ntohl(e->addr.lba), &e->addr.msf.minute, + &e->addr.msf.second, &e->addr.msf.frame); + } + bcopy(toc->tab + track - toc->hdr.starting_track, + &te->entry, sizeof(struct cd_toc_entry)); + } + case CDIOCREADSUBCHANNEL: { + struct ioc_read_subchannel *args = + (struct ioc_read_subchannel*) addr; + struct cd_sub_channel_info data; + u_long len = args->data_len; + int abslba, rellba; + + if (len > sizeof(data) || + len < sizeof(struct cd_sub_channel_header)) + return (EINVAL); + + if (wcd_request_wait (t, ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, + 0, 0, sizeof (t->subchan) >> 8, sizeof (t->subchan), + 0, (char*)&t->subchan, sizeof (t->subchan)) != 0) + return (EIO); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "subchan", &t->subchan, sizeof t->subchan); + + abslba = t->subchan.abslba; + rellba = t->subchan.rellba; + if (args->address_format == CD_MSF_FORMAT) { + lba2msf (ntohl(abslba), + &data.what.position.absaddr.msf.minute, + &data.what.position.absaddr.msf.second, + &data.what.position.absaddr.msf.frame); + lba2msf (ntohl(rellba), + &data.what.position.reladdr.msf.minute, + &data.what.position.reladdr.msf.second, + &data.what.position.reladdr.msf.frame); + } else { + data.what.position.absaddr.lba = abslba; + data.what.position.reladdr.lba = rellba; + } + data.header.audio_status = t->subchan.audio_status; + data.what.position.control = t->subchan.control & 0xf; + data.what.position.addr_type = t->subchan.control >> 4; + data.what.position.track_number = t->subchan.track; + data.what.position.index_number = t->subchan.indx; + + return copyout (&data, args->data, len); + } + case CDIOCPLAYMSF: { + struct ioc_play_msf *args = (struct ioc_play_msf*) addr; + + return wcd_request_wait (t, ATAPI_PLAY_MSF, 0, 0, + args->start_m, args->start_s, args->start_f, + args->end_m, args->end_s, args->end_f, 0, 0, 0); + } + case CDIOCPLAYBLOCKS: { + struct ioc_play_blocks *args = (struct ioc_play_blocks*) addr; + + return wcd_request_wait (t, ATAPI_PLAY_BIG, 0, + args->blk >> 24 & 0xff, args->blk >> 16 & 0xff, + args->blk >> 8 & 0xff, args->blk & 0xff, + args->len >> 24 & 0xff, args->len >> 16 & 0xff, + args->len >> 8 & 0xff, args->len & 0xff, 0, 0); + } + case CDIOCPLAYTRACKS: { + struct ioc_play_track *args = (struct ioc_play_track*) addr; + u_long start, len; + int t1, t2; + + if (! t->toc.hdr.ending_track) + return (EIO); + + /* Ignore index fields, + * play from start_track to end_track inclusive. */ + if (args->end_track < t->toc.hdr.ending_track+1) + ++args->end_track; + if (args->end_track > t->toc.hdr.ending_track+1) + args->end_track = t->toc.hdr.ending_track+1; + t1 = args->start_track - t->toc.hdr.starting_track; + t2 = args->end_track - t->toc.hdr.starting_track; + if (t1 < 0 || t2 < 0) + return (EINVAL); + start = ntohl(t->toc.tab[t1].addr.lba); + len = ntohl(t->toc.tab[t2].addr.lba) - start; + + return wcd_request_wait (t, ATAPI_PLAY_BIG, 0, + start >> 24 & 0xff, start >> 16 & 0xff, + start >> 8 & 0xff, start & 0xff, + len >> 24 & 0xff, len >> 16 & 0xff, + len >> 8 & 0xff, len & 0xff, 0, 0); + } + case CDIOCGETVOL: { + struct ioc_vol *arg = (struct ioc_vol*) addr; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + arg->vol[0] = t->au.port[0].volume; + arg->vol[1] = t->au.port[1].volume; + arg->vol[2] = t->au.port[2].volume; + arg->vol[3] = t->au.port[3].volume; + break; + } + case CDIOCSETVOL: { + struct ioc_vol *arg = (struct ioc_vol*) addr; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, + AUDIO_PAGE_MASK, 0, 0, 0, 0, sizeof (t->aumask) >> 8, + sizeof (t->aumask), 0, (char*) &t->aumask, + sizeof (t->aumask)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "mask", &t->aumask, sizeof t->aumask); + + /* Sony-55E requires the data length field to be zeroed. */ + t->au.data_length = 0; + + t->au.port[0].channels = CHANNEL_0; + t->au.port[1].channels = CHANNEL_1; + t->au.port[0].volume = arg->vol[0] & t->aumask.port[0].volume; + t->au.port[1].volume = arg->vol[1] & t->aumask.port[1].volume; + t->au.port[2].volume = arg->vol[2] & t->aumask.port[2].volume; + t->au.port[3].volume = arg->vol[3] & t->aumask.port[3].volume; + return wcd_request_wait (t, ATAPI_MODE_SELECT, 0x10, + 0, 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), + 0, (char*) &t->au, - sizeof (t->au)); + } + case CDIOCSETPATCH: { + struct ioc_patch *arg = (struct ioc_patch*) addr; + + return wcd_setchan (t, arg->patch[0], arg->patch[1], + arg->patch[2], arg->patch[3]); + } + case CDIOCSETMONO: + return wcd_setchan (t, CHANNEL_0 | CHANNEL_1, + CHANNEL_0 | CHANNEL_1, 0, 0); + + case CDIOCSETSTERIO: + return wcd_setchan (t, CHANNEL_0, CHANNEL_1, 0, 0); + + case CDIOCSETMUTE: + return wcd_setchan (t, 0, 0, 0, 0); + + case CDIOCSETLEFT: + return wcd_setchan (t, CHANNEL_0, CHANNEL_0, 0, 0); + + case CDIOCSETRIGHT: + return wcd_setchan (t, CHANNEL_1, CHANNEL_1, 0, 0); + } + return (error); +} + +/* + * Read the entire TOC for the disc into our internal buffer. + */ +static int wcd_read_toc (struct wcd *t) +{ + int ntracks, len; + struct atapires result; + + bzero (&t->toc, sizeof (t->toc)); + bzero (&t->info, sizeof (t->info)); + + wcd_select_slot(t); + + /* Check for the media. + * Do it twice to avoid the stale media changed state. */ + result = atapi_request_wait (t->ata, t->unit, ATAPI_TEST_UNIT_READY, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) { + t->flags |= F_MEDIA_CHANGED; + result = atapi_request_wait (t->ata, t->unit, + ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + if (result.code) { + wcd_error (t, result); + return (EIO); + } + t->flags &= ~F_MEDIA_CHANGED; + + /* First read just the header, so we know how long the TOC is. */ + len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry); + if (wcd_request_wait (t, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0, + len >> 8, len & 0xff, 0, (char*)&t->toc, len) != 0) { +err: bzero (&t->toc, sizeof (t->toc)); + return (0); + } + + ntracks = t->toc.hdr.ending_track - t->toc.hdr.starting_track + 1; + if (ntracks <= 0 || ntracks > MAXTRK) + goto err; + + /* Now read the whole schmeer. */ + len = sizeof(struct ioc_toc_header) + + ntracks * sizeof(struct cd_toc_entry); + if (wcd_request_wait (t, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0, + len >> 8, len & 0xff, 0, (char*)&t->toc, len) & 0xff) + goto err; + + NTOHS(t->toc.hdr.len); + + /* Read disc capacity. */ + if (wcd_request_wait (t, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, + 0, sizeof(t->info), 0, (char*)&t->info, sizeof(t->info)) != 0) + bzero (&t->info, sizeof (t->info)); + + /* make fake leadout entry */ + t->toc.tab[ntracks].control = t->toc.tab[ntracks-1].control; + t->toc.tab[ntracks].addr_type = t->toc.tab[ntracks-1].addr_type; + t->toc.tab[ntracks].track = 170; /* magic */ + t->toc.tab[ntracks].addr.lba = t->info.volsize; + + NTOHL(t->info.volsize); + NTOHL(t->info.blksize); + + /* Print the disc description string on every disc change. + * It would help to track the history of disc changes. */ + if (t->info.volsize && t->toc.hdr.ending_track && + (t->flags & F_MEDIA_CHANGED) && (t->flags & F_DEBUG)) { + printf ("wcd%d: ", t->lun); + if (t->toc.tab[0].control & 4) + printf ("%ldMB ", t->info.volsize / 512); + else + printf ("%ld:%ld audio ", t->info.volsize/75/60, + t->info.volsize/75%60); + printf ("(%ld sectors), %d tracks\n", t->info.volsize, + t->toc.hdr.ending_track - t->toc.hdr.starting_track + 1); + } + return (0); +} + +/* + * Set up the audio channel masks. + */ +static int wcd_setchan (struct wcd *t, + u_char c0, u_char c1, u_char c2, u_char c3) +{ + int error; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + + /* Sony-55E requires the data length field to be zeroed. */ + t->au.data_length = 0; + + t->au.port[0].channels = c0; + t->au.port[1].channels = c1; + t->au.port[2].channels = c2; + t->au.port[3].channels = c3; + return wcd_request_wait (t, ATAPI_MODE_SELECT, 0x10, + 0, 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), + 0, (char*) &t->au, - sizeof (t->au)); +} + +static int wcd_eject (struct wcd *t, int closeit) +{ + struct atapires result; + + wcd_select_slot(t); + + /* Try to stop the disc. */ + result = atapi_request_wait (t->ata, t->unit, ATAPI_START_STOP, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + if (result.code == RES_ERR && + ((result.error & AER_SKEY) == AER_SK_NOT_READY || + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION)) { + int err; + + if (!closeit) + return (0); + /* + * The disc was unloaded. + * Load it (close tray). + * Read the table of contents. + */ + err = wcd_request_wait (t, ATAPI_START_STOP, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0); + if (err) + return (err); + + /* Read table of contents. */ + wcd_read_toc (t); + + /* Lock the media. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + t->flags |= F_LOCKED; + return (0); + } + + if (result.code) { + wcd_error (t, result); + return (EIO); + } + + if (closeit) + return (0); + + /* Give it some time to stop spinning. */ + tsleep ((caddr_t)&lbolt, PRIBIO, "wcdej1", 0); + tsleep ((caddr_t)&lbolt, PRIBIO, "wcdej2", 0); + + /* Unlock. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + t->flags &= ~F_LOCKED; + + /* Eject. */ + t->flags |= F_MEDIA_CHANGED; + return wcd_request_wait (t, ATAPI_START_STOP, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0); +} + +static void +wcd_select_slot(struct wcd *cdp) +{ + if (cdp->slot < 0 || cdp->changer_info->current_slot == cdp->slot) + return; + + /* Unlock (might not be needed but its cheaper than asking) */ + wcd_request_wait (cdp, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + /* Unload the current media from player */ + wcd_request_wait (cdp, ATAPI_LOAD_UNLOAD, + 0, 0, 0, 2, 0, 0, 0, cdp->changer_info->current_slot, 0, 0, 0); + + /* load the wanted slot */ + wcd_request_wait (cdp, ATAPI_LOAD_UNLOAD, + 0, 0, 0, 3, 0, 0, 0, cdp->slot, 0, 0, 0); + + cdp->changer_info->current_slot = cdp->slot; + + /* Lock the media if needed */ + if (cdp->flags & F_LOCKED) { + wcd_request_wait (cdp, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + } +} + +#ifdef WCD_MODULE +/* + * Loadable ATAPI CD-ROM driver stubs. + */ +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/lkm.h> + +/* + * Construct lkm_dev structures (see lkm.h). + * Our bdevsw/cdevsw slot numbers are 19/69. + */ + + +MOD_DEV(wcd, LM_DT_BLOCK, BDEV_MAJOR, &wcd_cdevsw); +MOD_DEV(rwcd, LM_DT_CHAR, CDEV_MAJOR, &wcd_cdevsw); + +/* + * Function called when loading the driver. + */ +int wcd_load (struct lkm_table *lkmtp, int cmd) +{ + struct atapi *ata; + int n, u; + + if (! atapi_start) + /* No ATAPI driver available. */ + return EPROTONOSUPPORT; + n = 0; + for (ata=atapi_tab; ata<atapi_tab+2; ++ata) + if (ata->port) + for (u=0; u<2; ++u) + /* Probing controller ata->ctrlr, unit u. */ + if (ata->params[u] && ! ata->attached[u] && + wcdattach (ata, u, ata->params[u], + ata->debug) >= 0) + { + /* Drive found. */ + ata->attached[u] = 1; + ++n; + } + if (! n) + /* No IDE CD-ROMs found. */ + return ENXIO; + return 0; +} + +/* + * Function called when unloading the driver. + */ +int wcd_unload (struct lkm_table *lkmtp, int cmd) +{ + struct wcd **t; + + for (t=wcdtab; t<wcdtab+wcdnlun; ++t) + if (((*t)->flags & F_BOPEN) || (*t)->refcnt) + /* The device is opened, cannot unload the driver. */ + return EBUSY; + for (t=wcdtab; t<wcdtab+wcdnlun; ++t) { + (*t)->ata->attached[(*t)->unit] = 0; + free (*t, M_TEMP); + } + wcdnlun = 0; + bzero (wcdtab, sizeof(wcdtab)); + return 0; +} + +/* + * Dispatcher function for the module (load/unload/stat). + */ +int wcd_mod (struct lkm_table *lkmtp, int cmd, int ver) +{ + int err = 0; + + if (ver != LKM_VERSION) + return EINVAL; + + if (cmd == LKM_E_LOAD) + err = wcd_load (lkmtp, cmd); + else if (cmd == LKM_E_UNLOAD) + err = wcd_unload (lkmtp, cmd); + if (err) + return err; + + /* XXX Poking around in the LKM internals like this is bad. + */ + /* Register the cdevsw entry. */ + lkmtp->private.lkm_dev = & MOD_PRIVATE(rwcd); + err = lkmdispatch (lkmtp, cmd); + if (err) + return err; + + /* Register the bdevsw entry. */ + lkmtp->private.lkm_dev = & MOD_PRIVATE(wcd); + return lkmdispatch (lkmtp, cmd); +} +#endif /* WCD_MODULE */ + +static wcd_devsw_installed = 0; + +static void wcd_drvinit(void *unused) +{ + + if( ! wcd_devsw_installed ) { + cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &wcd_cdevsw); + wcd_devsw_installed = 1; + } +} + +SYSINIT(wcddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wcd_drvinit,NULL) + + +#endif /* NWCD && NWDC && ATAPI */ diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 488615575464f..6a5f73023a177 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.185 1999/01/16 01:06:23 bde Exp $ + * $Id: wd.c,v 1.176 1998/09/15 08:15:30 gibbs 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> @@ -106,11 +106,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 */ @@ -311,16 +307,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 */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ @@ -423,8 +422,6 @@ wdattach(struct isa_device *dvp) struct disk *du; struct wdparams *wp; - dvp->id_intr = wdintr; - if (dvp->id_unit >= NWDC) return (0); @@ -665,17 +662,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 @@ -1033,12 +1030,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; @@ -1087,7 +1083,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); } @@ -1879,8 +1876,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? */ @@ -2253,11 +2249,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); } diff --git a/sys/i386/isa/wd7000.c b/sys/i386/isa/wd7000.c new file mode 100644 index 0000000000000..5722aeeed1cf6 --- /dev/null +++ b/sys/i386/isa/wd7000.c @@ -0,0 +1,725 @@ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Written by Olof Johansson (offe@ludd.luth.se) 1995. + * Based on code written by Theo de Raadt (deraadt@fsa.ca). + * + * 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 at Ludd, University of Lule}. + * 4. 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. + */ + + /* All bugs are subject to removal without further notice */ + +/* + * offe 01/07/95 + * + * This version of the driver _still_ doesn't implement scatter/gather for the + * WD7000-FASST2. This is due to the fact that my controller doesn't seem to + * support it. That, and the lack of documentation makes it impossible for + * me to implement it. + * What I've done instead is allocated a local buffer, contiguous buffer big + * enough to handle the requests. I haven't seen any read/write bigger than 64k, + * so I allocate a buffer of 64+16k. The data that needs to be DMA'd to/from + * the controller is copied to/from that buffer before/after the command is + * sent to the card. + */ + +#include "wds.h" +#if NWDS > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> + +#include <scsi/scsiconf.h> + +#include <machine/clock.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <i386/isa/isa_device.h> + +static struct scsi_device wds_dev = +{ + NULL, + NULL, + NULL, + NULL, + "wds", + 0, + { 0, 0 } +}; + +/* + XXX THIS SHOULD BE FIXED! + I haven't got the KERNBASE-version to work, but on my system the kernel + is at virtual address 0xFxxxxxxx, responding to physical address + 0x0xxxxxxx. +#define PHYSTOKV(x) ((x) + KERNBASE) +*/ +#define PHYSTOKV(x) ((x) | 0xf0000000) +#define KVTOPHYS(x) vtophys(x) +/* 0x10000 (64k) should be enough. But just to be sure... */ +#define BUFSIZ 0x12000 + + +/* WD7000 registers */ +#define WDS_STAT 0 /* read */ +#define WDS_IRQSTAT 1 /* read */ + +#define WDS_CMD 0 /* write */ +#define WDS_IRQACK 1 /* write */ +#define WDS_HCR 2 /* write */ + +/* WDS_STAT (read) defs */ +#define WDS_IRQ 0x80 +#define WDS_RDY 0x40 +#define WDS_REJ 0x20 +#define WDS_INIT 0x10 + +/* WDS_IRQSTAT (read) defs */ +#define WDSI_MASK 0xc0 +#define WDSI_ERR 0x00 +#define WDSI_MFREE 0x80 +#define WDSI_MSVC 0xc0 + +/* WDS_CMD (write) defs */ +#define WDSC_NOOP 0x00 +#define WDSC_INIT 0x01 +#define WDSC_DISUNSOL 0x02 +#define WDSC_ENAUNSOL 0x03 +#define WDSC_IRQMFREE 0x04 +#define WDSC_SCSIRESETSOFT 0x05 +#define WDSC_SCSIRESETHARD 0x06 +#define WDSC_MSTART(m) (0x80 + (m)) +#define WDSC_MMSTART(m) (0xc0 + (m)) + +/* WDS_HCR (write) defs */ +#define WDSH_IRQEN 0x08 +#define WDSH_DRQEN 0x04 +#define WDSH_SCSIRESET 0x02 +#define WDSH_ASCRESET 0x01 + +struct wds_cmd { + u_char cmd; + u_char targ; + u_char scb[12]; /*u_char scb[12];*/ + u_char stat; + u_char venderr; + u_char len[3]; + u_char data[3]; + u_char next[3]; + u_char write; + u_char xx[6]; +}; + +struct wds_req { + struct wds_cmd cmd; + struct wds_cmd sense; + struct scsi_xfer *sxp; + int busy, polled; + int done, ret, ombn; +}; + +#define WDSX_SCSICMD 0x00 +#define WDSX_OPEN_RCVBUF 0x80 +#define WDSX_RCV_CMD 0x81 +#define WDSX_RCV_DATA 0x82 +#define WDSX_RCV_DATASTAT 0x83 +#define WDSX_SND_DATA 0x84 +#define WDSX_SND_DATASTAT 0x85 +#define WDSX_SND_CMDSTAT 0x86 +#define WDSX_READINIT 0x88 +#define WDSX_READSCSIID 0x89 +#define WDSX_SETUNSOLIRQMASK 0x8a +#define WDSX_GETUNSOLIRQMASK 0x8b +#define WDSX_GETFIRMREV 0x8c +#define WDSX_EXECDIAG 0x8d +#define WDSX_SETEXECPARM 0x8e +#define WDSX_GETEXECPARM 0x8f + +struct wds_mb { + u_char stat; + u_char addr[3]; +}; +/* ICMB status value */ +#define ICMB_OK 0x01 +#define ICMB_OKERR 0x02 +#define ICMB_ETIME 0x04 +#define ICMB_ERESET 0x05 +#define ICMB_ETARCMD 0x06 +#define ICMB_ERESEL 0x80 +#define ICMB_ESEL 0x81 +#define ICMB_EABORT 0x82 +#define ICMB_ESRESET 0x83 +#define ICMB_EHRESET 0x84 + +struct wds_setup { + u_char cmd; + u_char scsi_id; + u_char buson_t; + u_char busoff_t; + u_char xx; + u_char mbaddr[3]; + u_char nomb; + u_char nimb; +}; + +#define WDS_NOMB 8 +#define WDS_NIMB 8 +#define MAXSIMUL 8 + +static int wdsunit=0; + +static u_char wds_data[NWDS][BUFSIZ]; +static u_char wds_data_in_use[NWDS]; + +static struct wds { + int addr; + struct wds_req wdsr[MAXSIMUL]; + struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB]; + struct scsi_link sc_link; +} wds[NWDS]; + +static int wdsprobe(struct isa_device *); +static void wds_minphys(struct buf *); +static struct wds_req *wdsr_alloc(int); +static int32_t wds_scsi_cmd(struct scsi_xfer *); +static u_int32_t wds_adapter_info(int); +static int wds_done(int, struct wds_cmd *, u_char); +static int wdsattach(struct isa_device *); +static int wds_init(struct isa_device *); +static int wds_cmd(int, u_char *, int); +static void wds_wait(int, int, int); + +struct isa_driver wdsdriver = +{ + wdsprobe, + wdsattach, + "wds" +}; + +static struct scsi_adapter wds_switch = +{ + wds_scsi_cmd, + wds_minphys, + 0, + 0, + wds_adapter_info, + "wds", + {0,0} +}; + +int +wdsprobe(struct isa_device *dev) +{ + if(wdsunit > NWDS) + return 0; + + dev->id_unit = wdsunit; /* XXX WRONG! */ + wds[wdsunit].addr = dev->id_iobase; + + if(wds_init(dev) != 0) + return 0; + wdsunit++; + return 8; +} + +void +wds_minphys(struct buf *bp) +{ + if(bp->b_bcount > BUFSIZ) + bp->b_bcount = BUFSIZ; +} + +struct wds_req * +wdsr_alloc(int unit) +{ + struct wds_req *r; + int x; + int i; + + r = NULL; + x = splbio(); + for(i=0; i<MAXSIMUL; i++) + if(!wds[unit].wdsr[i].busy) + { + r = &wds[unit].wdsr[i]; + r->busy = 1; + break; + } + if(!r) + { + splx(x); + return NULL; + } + + r->ombn = -1; + for(i=0; i<WDS_NOMB; i++) + if(!wds[unit].ombs[i].stat) + { + wds[unit].ombs[i].stat = 1; + r->ombn = i; + break; + } + if(r->ombn == -1 ) + { + r->busy = 0; + splx(x); + return NULL; + } + splx(x); + return r; +} + +int32_t +wds_scsi_cmd(struct scsi_xfer *sxp) +{ + struct wds_req *r; + int unit = sxp->sc_link->adapter_unit; + int base; + u_char c; + int i; + + base = wds[unit].addr; + + if( sxp->flags & SCSI_RESET) + { + printf("reset!\n"); + return COMPLETE; + } + + r = wdsr_alloc(unit); + if(r==NULL) + { + printf("no request slot available!\n"); + sxp->error = XS_DRIVER_STUFFUP; + return TRY_AGAIN_LATER; + } + r->done = 0; + r->sxp = sxp; + + if(sxp->flags & SCSI_DATA_UIO) + { + printf("UIO!\n"); + sxp->error = XS_DRIVER_STUFFUP; + return TRY_AGAIN_LATER; + } + + scsi_uto3b(KVTOPHYS(&r->cmd),wds[unit].ombs[r->ombn].addr); + + bzero(&r->cmd, sizeof r->cmd); + r->cmd.cmd = WDSX_SCSICMD; + r->cmd.targ = (sxp->sc_link->target << 5) | sxp->sc_link->lun; + bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12); + scsi_uto3b(sxp->datalen, r->cmd.len); + + if(wds_data_in_use[unit]) + { + sxp->error = XS_DRIVER_STUFFUP; + return TRY_AGAIN_LATER; + } + else + wds_data_in_use[unit] = 1; + + if(sxp->datalen && !(sxp->flags&SCSI_DATA_IN)) + bcopy(sxp->data, wds_data[unit], sxp->datalen); + + scsi_uto3b(sxp->datalen ? KVTOPHYS(wds_data[unit]) : 0, r->cmd.data); + + r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00; + + scsi_uto3b(KVTOPHYS(&r->sense),r->cmd.next); + + bzero(&r->sense, sizeof r->sense); + r->sense.cmd = r->cmd.cmd; + r->sense.targ = r->cmd.targ; + r->sense.scb[0] = REQUEST_SENSE; + scsi_uto3b(KVTOPHYS(&sxp->sense),r->sense.data); + scsi_uto3b(sizeof(sxp->sense), r->sense.len); + r->sense.write = 0x80; + + if(sxp->flags & SCSI_NOMASK) + { + outb(base+WDS_HCR, WDSH_DRQEN); + r->polled = 1; + } else + { + outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN); + r->polled = 0; + } + + c = WDSC_MSTART(r->ombn); + + if( wds_cmd(base, &c, sizeof c) != 0) + { + printf("wds%d: unable to start outgoing mbox\n", unit); + r->busy = 0; + wds[unit].ombs[r->ombn].stat = 0; + + return TRY_AGAIN_LATER; + } + + if(sxp->flags & SCSI_NOMASK) + { + repoll: + + i = 0; + while(!(inb(base+WDS_STAT) & WDS_IRQ)) + { + + DELAY(20000); + if(++i == 20) + { + outb(base + WDS_IRQACK, 0); + /*r->busy = 0;*/ + sxp->error = XS_TIMEOUT; + return HAD_ERROR; + } + } + wdsintr(unit); + if(r->done) + { + r->sxp->flags |= ITSDONE; + r->busy = 0; + return r->ret; + } + goto repoll; + } + + return SUCCESSFULLY_QUEUED; +} + +u_int32_t +wds_adapter_info(int unit) +{ + return 1; +} + +void +wdsintr(int unit) +{ + struct wds_cmd *pc, *vc; + struct wds_mb *in; + u_char stat; + u_char c; + + if(!inb(wds[unit].addr+WDS_STAT) & WDS_IRQ) + { + outb(wds[unit].addr + WDS_IRQACK, 0); + return; + } + + c = inb(wds[unit].addr + WDS_IRQSTAT); + if( (c&WDSI_MASK) == WDSI_MSVC) + { + c = c & ~WDSI_MASK; + in = &wds[unit].imbs[c]; + + pc = (struct wds_cmd *)scsi_3btou(in->addr); + vc = (struct wds_cmd *)PHYSTOKV((intptr_t)(void *)pc); + stat = in->stat; + + wds_done(unit, vc, stat); + in->stat = 0; + + outb(wds[unit].addr + WDS_IRQACK, 0); + } +} + +int +wds_done(int unit, struct wds_cmd *c, u_char stat) +{ + struct wds_req *r; + int i; + + r = (struct wds_req *)NULL; + + for(i=0; i<MAXSIMUL; i++) + if( c == &wds[unit].wdsr[i].cmd && !wds[unit].wdsr[i].done) + { + r = &wds[unit].wdsr[i]; + break; + } + if(r == (struct wds_req *)NULL) + { + /* failed to find request! */ + return 1; + } + + r->done = 1; + wds[unit].ombs[r->ombn].stat = 0; + r->ret = HAD_ERROR; + switch(stat) + { + case ICMB_OK: + r->ret = COMPLETE; + if(r->sxp) + r->sxp->resid = 0; + break; + case ICMB_OKERR: + if(!(r->sxp->flags & SCSI_ERR_OK) && c->stat) + { + r->sxp->sense.error_code = c->venderr; + r->sxp->error=XS_SENSE; + } + else + r->sxp->error=XS_NOERROR; + r->ret = COMPLETE; + break; + case ICMB_ETIME: + r->sxp->error = XS_TIMEOUT; + r->ret = HAD_ERROR; + break; + case ICMB_ERESET: + case ICMB_ETARCMD: + case ICMB_ERESEL: + case ICMB_ESEL: + case ICMB_EABORT: + case ICMB_ESRESET: + case ICMB_EHRESET: + r->sxp->error = XS_DRIVER_STUFFUP; + r->ret = HAD_ERROR; + break; + } + + if(r->sxp) + if(r->sxp->datalen && (r->sxp->flags&SCSI_DATA_IN)) + bcopy(wds_data[unit],r->sxp->data,r->sxp->datalen); + + wds_data_in_use[unit] = 0; + + if(!r->polled) + { + r->sxp->flags |= ITSDONE; + scsi_done(r->sxp); + } + + r->busy = 0; + + return 0; +} + +static int +wds_getvers(int unit) +{ + struct wds_req *r; + int base; + u_char c; + int i; + + base = wds[unit].addr; + + r = wdsr_alloc(unit); + if(!r) + { + printf("wds%d: no request slot available!\n", unit); + return -1; + } + + r->done = 0; + r->sxp = NULL; + + scsi_uto3b(KVTOPHYS(&r->cmd), wds[unit].ombs[r->ombn].addr); + + bzero(&r->cmd, sizeof r->cmd); + r->cmd.cmd = WDSX_GETFIRMREV; + + outb(base+WDS_HCR, WDSH_DRQEN); + r->polled = 1; + + c = WDSC_MSTART(r->ombn); + if(wds_cmd(base, (u_char *)&c, sizeof c)) + { + printf("wds%d: version request failed\n", unit); + r->busy = 0; + wds[unit].ombs[r->ombn].stat = 0; + return -1; + } + + while(1) + { + i = 0; + while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) + { + DELAY(9000); + if(++i == 20) + return -1; + } + wdsintr(unit); + if(r->done) + { + printf("wds%d: firmware version %d.%02d\n", unit, + r->cmd.targ, r->cmd.scb[0]); + r->busy = 0; + return 0; + } + } +} + +int +wdsattach(struct isa_device *dev) +{ + int masunit; + static u_long versprobe=0; /* max 32 controllers */ + int unit = dev->id_unit; + struct scsibus_data *scbus; + + masunit = dev->id_unit; + + if( !(versprobe & (1<<masunit))) + { + versprobe |= (1<<masunit); + if(wds_getvers(masunit)==-1) + printf("wds%d: getvers failed\n", masunit); + } + + printf("wds%d: using %d bytes for dma buffer\n",unit,BUFSIZ); + + wds[unit].sc_link.adapter_unit = unit; + wds[unit].sc_link.adapter_targ = 7; + wds[unit].sc_link.adapter = &wds_switch; + wds[unit].sc_link.device = &wds_dev; + wds[unit].sc_link.flags = SDEV_BOUNCE; + + /* + * Prepare the scsibus_data area for the upperlevel + * scsi code. + */ + scbus = scsi_alloc_bus(); + if(!scbus) + return 0; + scbus->adapter_link = &wds[unit].sc_link; + + scsi_attachdevs(scbus); + + return 1; +} + +int +wds_init(struct isa_device *dev) +{ + struct wds_setup init; + int base; + int unit, i; + struct wds_cmd wc; + + unit = dev->id_unit; + base = wds[unit].addr; + + /* + * Sending a command causes the CMDRDY bit to clear. + */ + + outb(base+WDS_CMD, WDSC_NOOP); + if( inb(base+WDS_STAT) & WDS_RDY) + return 1; + + /* + * the controller exists. reset and init. + */ + outb(base+WDS_HCR, WDSH_ASCRESET|WDSH_SCSIRESET); + DELAY(30); + outb(base+WDS_HCR, 0); + + outb(base+WDS_HCR, WDSH_DRQEN); + + isa_dmacascade(dev->id_drq); + + if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) + { + for(i=0; i<10; i++) + { + if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY) + break; + DELAY(40000); + } + if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) /* probe timeout */ + return 1; + } + + bzero(&init, sizeof init); + init.cmd = WDSC_INIT; + init.scsi_id = 7; + init.buson_t = 24; + init.busoff_t = 48; + scsi_uto3b(KVTOPHYS(wds[unit].ombs), init.mbaddr); + init.xx = 0; + init.nomb = WDS_NOMB; + init.nimb = WDS_NIMB; + + wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY); + if( wds_cmd(base, (u_char *)&init, sizeof init) != 0) + { + printf("wds%d: wds_cmd failed\n", unit); + return 1; + } + + wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT); + + wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY); + + bzero(&wc,sizeof wc); + wc.cmd = WDSC_DISUNSOL; + if( wds_cmd(base, (char *)&wc, sizeof wc) != 0) + { + printf("wds%d: wds_cmd failed\n", unit); + return 1; + } + + return 0; +} + +int +wds_cmd(int base, u_char *p, int l) +{ + int s=splbio(); + + while(l--) + { + do + { + outb(base+WDS_CMD,*p); + wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY); + } while (inb(base+WDS_STAT) & WDS_REJ); + p++; + } + + wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY); + + splx(s); + + return 0; +} + +void +wds_wait(int reg, int mask, int val) +{ + while((inb(reg) & mask) != val); +} + +#endif diff --git a/sys/i386/isa/wdreg.h b/sys/i386/isa/wdreg.h index 88a0fecb2b278..f8520bf566162 100644 --- a/sys/i386/isa/wdreg.h +++ b/sys/i386/isa/wdreg.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wdreg.h 7.1 (Berkeley) 5/9/91 - * $Id: wdreg.h,v 1.24 1999/01/12 01:04:38 eivind Exp $ + * $Id: wdreg.h,v 1.21 1998/01/14 08:08:42 kato Exp $ */ /* @@ -262,7 +262,7 @@ int wdformat(struct buf *bp); */ struct wddma { void *(*wdd_candma) /* returns a cookie if PCI */ - __P((int iobase_wd, int ctlr, int unit)); + __P((int ctlr, int drive)); int (*wdd_dmaverify) /* verify that request is DMA-able */ __P((void *cookie, char *vaddr, u_long len, int direction)); int (*wdd_dmaprep) /* prepare DMA hardware */ @@ -312,6 +312,4 @@ struct wddma { extern struct wddma wddma[]; -void wdintr __P((void *unit)); - #endif /* KERNEL */ diff --git a/sys/i386/isa/wfd.c b/sys/i386/isa/wfd.c index 60ceb0b81a13d..67d570a37e5d4 100644 --- a/sys/i386/isa/wfd.c +++ b/sys/i386/isa/wfd.c @@ -23,7 +23,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: wfd.c,v 1.16 1998/09/15 08:15:30 gibbs Exp $ + * $Id: wfd.c,v 1.15 1998/08/23 20:16:34 phk Exp $ */ /* @@ -661,6 +661,9 @@ int wfdioctl (dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) struct wfd *t = wfdtab[lun]; int error = 0; + struct disklabel *dl; + char buffer[DEV_BSIZE]; + error = dsioctl("wfd", dev, cmd, addr, flag, &t->dk_slices, wfdstrategy1, (ds_setgeom_t *)NULL); if (error != -1) diff --git a/sys/i386/isa/wst.c b/sys/i386/isa/wst.c index 3d2f4e8e59149..ff5f5435f31ec 100644 --- a/sys/i386/isa/wst.c +++ b/sys/i386/isa/wst.c @@ -25,13 +25,12 @@ * (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: wst.c,v 1.14 1999/01/12 00:36:36 eivind Exp $ + * $Id$ */ #include "wdc.h" #include "wst.h" #include "opt_atapi.h" -#include "opt_ddb.h" #include "opt_devfs.h" #if NWST > 0 && NWDC > 0 && defined(ATAPI) @@ -200,6 +199,7 @@ static int wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug); static int wst_sense(struct wst *t); static void wst_describe(struct wst *t); +static int wst_open(dev_t dev, int chardev); static void wst_poll_dsc(struct wst *t); static void wst_start(struct wst *t); static void wst_done(struct wst *t, struct buf *bp, int resid, struct atapires result); @@ -212,10 +212,7 @@ static int wst_load_unload(struct wst *t, u_char finction); static int wst_rewind(struct wst *t); static void wst_reset(struct wst *t); -#ifdef DDB -void wst_dump(int lun, char *label, void *data, int len); - -void +static void wst_dump(int lun, char *label, void *data, int len) { u_char *p = data; @@ -225,7 +222,6 @@ wst_dump(int lun, char *label, void *data, int len) printf("-%x", *p++); printf("\n"); } -#endif #ifndef ATAPI_STATIC static @@ -234,7 +230,9 @@ int wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug) { struct wst *t; - int lun; + struct atapires result; + int lun, i; + char buffer[255]; if (wstnlun >= NUNIT) { printf("wst: too many units\n"); @@ -350,7 +348,9 @@ int wstopen(dev_t dev, int flags, int fmt, struct proc *p) { int lun = UNIT(dev); + char buffer[255]; struct wst *t; + struct atapires result; /* Check that the device number and that the ATAPI driver is loaded. */ if (lun >= wstnlun || !atapi_request_immediate) { diff --git a/sys/i386/isa/wt.c b/sys/i386/isa/wt.c index c8712ca4603d7..481397e39abb9 100644 --- a/sys/i386/isa/wt.c +++ b/sys/i386/isa/wt.c @@ -20,7 +20,7 @@ * the original CMU copyright notice. * * Version 1.3, Thu Nov 11 12:09:13 MSK 1993 - * $Id: wt.c,v 1.46 1998/10/22 05:58:41 bde Exp $ + * $Id: wt.c,v 1.44 1998/06/07 17:11:07 dfr Exp $ * */ @@ -178,7 +178,6 @@ static void wtclock (wtinfo_t *t); static int wtreset (wtinfo_t *t); static int wtsense (wtinfo_t *t, int verb, int ignor); static int wtstatus (wtinfo_t *t); -static ointhand2_t wtintr; static void wtrewind (wtinfo_t *t); static int wtreadfm (wtinfo_t *t); static int wtwritefm (wtinfo_t *t); @@ -189,6 +188,8 @@ static d_read_t wtread; static d_write_t wtwrite; static d_close_t wtclose; static d_ioctl_t wtioctl; +static d_dump_t wtdump; +static d_psize_t wtsize; static d_strategy_t wtstrategy; #define CDEV_MAJOR 10 @@ -255,7 +256,6 @@ wtattach (struct isa_device *id) { wtinfo_t *t = wttab + id->id_unit; - id->id_ointr = wtintr; if (t->type == ARCHIVE) { printf ("wt%d: type <Archive>\n", t->unit); outb (t->RDMAPORT, 0); /* reset dma */ @@ -275,10 +275,24 @@ wtattach (struct isa_device *id) struct isa_driver wtdriver = { wtprobe, wtattach, "wt", }; +int +wtdump (dev_t dev) +{ + /* Not implemented */ + return (EINVAL); +} + +int +wtsize (dev_t dev) +{ + /* Not implemented */ + return (-1); +} + /* * Open routine, called on every device open. */ -static int +int wtopen (dev_t dev, int flag, int fmt, struct proc *p) { int u = minor (dev) & T_UNIT; @@ -359,7 +373,7 @@ wtopen (dev_t dev, int flag, int fmt, struct proc *p) /* * Close routine, called on last device close. */ -static int +int wtclose (dev_t dev, int flags, int fmt, struct proc *p) { int u = minor (dev) & T_UNIT; @@ -408,7 +422,7 @@ done: * ioctl (int fd, MTIOCGET, struct mtget *buf) -- get status * ioctl (int fd, MTIOCTOP, struct mtop *buf) -- do BSD-like op */ -static int +int wtioctl (dev_t dev, u_long cmd, caddr_t arg, int flags, struct proc *p) { int u = minor (dev) & T_UNIT; @@ -511,7 +525,7 @@ wtwrite(dev_t dev, struct uio *uio, int ioflag) /* * Strategy routine. */ -static void +void wtstrategy (struct buf *bp) { int u = minor (bp->b_dev) & T_UNIT; @@ -589,7 +603,7 @@ xit: biodone (bp); /* * Interrupt routine. */ -static void +void wtintr (int u) { wtinfo_t *t = wttab + u; diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 59ee24737b737..72f846cb447c3 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -28,7 +28,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: imgact_linux.c,v 1.30 1998/10/16 03:55:00 peter Exp $ + * $Id: imgact_linux.c,v 1.29 1998/08/16 01:21:50 bde Exp $ */ #include <sys/param.h> @@ -234,8 +234,8 @@ exec_linux_imgact(imgp) /* * Tell kern_execve.c about it, with a little help from the linker. * Since `const' objects end up in the text segment, TEXT_SET is the - * correct directive to use. + * correct directive to use. Do not staticize; used by Linux LKM. */ -static const struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" }; +const struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" }; EXEC_SET(linuxaout, linux_execsw); diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index eaffa614c6b8c..db96f2e025d59 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -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: linux.h,v 1.25 1998/12/19 02:55:32 julian Exp $ + * $Id: linux.h,v 1.22 1998/09/30 01:42:53 jfieber Exp $ */ #ifndef _I386_LINUX_LINUX_H_ @@ -418,7 +418,6 @@ struct trapframe; #define LINUX_MAP_PRIVATE 0x0002 #define LINUX_MAP_FIXED 0x0010 #define LINUX_MAP_ANON 0x0020 -#define LINUX_MAP_GROWSDOWN 0x0100 /* SystemV ipc defines */ #define LINUX_SEMOP 1 @@ -472,8 +471,6 @@ struct trapframe; #define LINUX_SHUTDOWN 13 #define LINUX_SETSOCKOPT 14 #define LINUX_GETSOCKOPT 15 -#define LINUX_SENDMSG 16 -#define LINUX_RECVMSG 17 #define LINUX_AF_UNSPEC 0 #define LINUX_AF_UNIX 1 @@ -515,21 +512,6 @@ struct trapframe; #define LINUX_IP_DROP_MEMBERSHIP 36 /* Sound system defines */ -#define LINUX_SNDCTL_SEQ_RESET 0x5100 -#define LINUX_SNDCTL_SEQ_SYNC 0x5101 -#define LINUX_SNDCTL_SYNTH_INFO 0x5102 -#define LINUX_SNDCTL_SEQ_CTRLRATE 0x5103 -#define LINUX_SNDCTL_SEQ_GETOUTCOUNT 0x5104 -#define LINUX_SNDCTL_SEQ_GETINCOUNT 0x5105 -#define LINUX_SNDCTL_SEQ_PERCMODE 0x5106 -#define LINUX_SNDCTL_FM_LOAD_INSTR 0x5107 -#define LINUX_SNDCTL_SEQ_TESTMIDI 0x5108 -#define LINUX_SNDCTL_SEQ_RESETSAMPLES 0x5109 -#define LINUX_SNDCTL_SEQ_NRSYNTHS 0x510A -#define LINUX_SNDCTL_SEQ_NRMIDIS 0x510B -#define LINUX_SNDCTL_MIDI_INFO 0x510C -#define LINUX_SNDCTL_SEQ_TRESHOLD 0x510D -#define LINUX_SNDCTL_SYNTH_MEMAVL 0x510E #define LINUX_SNDCTL_DSP_RESET 0x5000 #define LINUX_SNDCTL_DSP_SYNC 0x5001 #define LINUX_SNDCTL_DSP_SPEED 0x5002 diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c index 6a7ce1e828023..30a0dba494493 100644 --- a/sys/i386/linux/linux_dummy.c +++ b/sys/i386/linux/linux_dummy.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: linux_dummy.c,v 1.8 1997/11/06 19:28:52 phk Exp $ + * $Id: linux_dummy.c,v 1.7 1997/10/29 08:17:09 kato Exp $ */ #include <sys/param.h> @@ -212,6 +212,13 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args) } int +linux_clone(struct proc *p, struct linux_clone_args *args) +{ + printf("Linux-emul(%d): clone() not supported\n", p->p_pid); + return ENOSYS; +} + +int linux_uname(struct proc *p, struct linux_uname_args *args) { printf("Linux-emul(%d): uname() not supported\n", p->p_pid); diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c index 16f12ed4d7bea..6a80d4c5ec665 100644 --- a/sys/i386/linux/linux_file.c +++ b/sys/i386/linux/linux_file.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: linux_file.c,v 1.22 1998/10/05 16:37:36 jfieber Exp $ + * $Id: linux_file.c,v 1.21 1998/07/29 16:43:00 bde Exp $ */ #include "opt_compat.h" @@ -812,7 +812,7 @@ linux_readlink(struct proc *p, struct linux_readlink_args *args) int linux_truncate(struct proc *p, struct linux_truncate_args *args) { - struct truncate_args bsd; + struct otruncate_args bsd; caddr_t sg; sg = stackgap_init(); @@ -825,6 +825,6 @@ linux_truncate(struct proc *p, struct linux_truncate_args *args) bsd.path = args->path; bsd.length = args->length; - return truncate(p, &bsd); + return otruncate(p, &bsd); } diff --git a/sys/i386/linux/linux_ioctl.c b/sys/i386/linux/linux_ioctl.c index 3010f74116bdf..26bb5ab710fc8 100644 --- a/sys/i386/linux/linux_ioctl.c +++ b/sys/i386/linux/linux_ioctl.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: linux_ioctl.c,v 1.29 1998/09/30 01:42:53 jfieber Exp $ + * $Id: linux_ioctl.c,v 1.28 1998/08/31 10:53:33 jkh Exp $ */ #include <sys/param.h> @@ -683,66 +683,6 @@ linux_ioctl(struct proc *p, struct linux_ioctl_args *args) return copyout(&linux_line, (caddr_t)args->arg, sizeof(int)); - case LINUX_SNDCTL_SEQ_RESET: - args->cmd = SNDCTL_SEQ_RESET; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_SYNC: - args->cmd = SNDCTL_SEQ_SYNC; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SYNTH_INFO: - args->cmd = SNDCTL_SYNTH_INFO; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_CTRLRATE: - args->cmd = SNDCTL_SEQ_CTRLRATE; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_GETOUTCOUNT: - args->cmd = SNDCTL_SEQ_GETOUTCOUNT; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_GETINCOUNT: - args->cmd = SNDCTL_SEQ_GETINCOUNT; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_PERCMODE: - args->cmd = SNDCTL_SEQ_PERCMODE; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_FM_LOAD_INSTR: - args->cmd = SNDCTL_FM_LOAD_INSTR; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_TESTMIDI: - args->cmd = SNDCTL_SEQ_TESTMIDI; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_RESETSAMPLES: - args->cmd = SNDCTL_SEQ_RESETSAMPLES; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_NRSYNTHS: - args->cmd = SNDCTL_SEQ_NRSYNTHS; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_NRMIDIS: - args->cmd = SNDCTL_SEQ_NRMIDIS; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_MIDI_INFO: - args->cmd = SNDCTL_MIDI_INFO; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SEQ_TRESHOLD: - args->cmd = SNDCTL_SEQ_TRESHOLD; - return ioctl(p, (struct ioctl_args *)args); - - case LINUX_SNDCTL_SYNTH_MEMAVL: - args->cmd = SNDCTL_SYNTH_MEMAVL; - return ioctl(p, (struct ioctl_args *)args); - case LINUX_SNDCTL_DSP_GETOPTR : args->cmd = SNDCTL_DSP_GETOPTR; return ioctl(p, (struct ioctl_args *)args); diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c index 02f9785fa8a36..9fdd923276749 100644 --- a/sys/i386/linux/linux_misc.c +++ b/sys/i386/linux/linux_misc.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: linux_misc.c,v 1.50 1998/12/30 21:01:33 sos Exp $ + * $Id: linux_misc.c,v 1.44 1998/09/24 13:25:43 jkh Exp $ */ #include <sys/param.h> @@ -41,9 +41,6 @@ #include <sys/resourcevar.h> #include <sys/stat.h> #include <sys/sysctl.h> -#ifdef COMPAT_LINUX_THREADS -#include <sys/unistd.h> -#endif /* COMPAT_LINUX_THREADS */ #include <sys/vnode.h> #include <sys/wait.h> #include <sys/time.h> @@ -563,79 +560,6 @@ linux_fork(struct proc *p, struct linux_fork_args *args) return 0; } -#ifndef COMPAT_LINUX_THREADS -int -linux_clone(struct proc *p, struct linux_clone_args *args) -{ - printf("linux_clone(%d): Not enabled\n", p->p_pid); - return (EOPNOTSUPP); -} - -#else -#define CLONE_VM 0x100 -#define CLONE_FS 0x200 -#define CLONE_FILES 0x400 -#define CLONE_SIGHAND 0x800 -#define CLONE_PID 0x1000 - -int -linux_clone(struct proc *p, struct linux_clone_args *args) -{ - int error, ff = RFPROC; - struct proc *p2; - int exit_signal; - vm_offset_t start; - struct rfork_args rf_args; - -#ifdef SMP - printf("linux_clone(%d): does not work with SMP yet\n", p->p_pid); - return (EOPNOTSUPP); -#endif -#ifdef DEBUG - if (args->flags & CLONE_PID) - printf("linux_clone(%d): CLONE_PID not yet supported\n", p->p_pid); - printf ("linux_clone(%d): invoked with flags %x and stack %x\n", p->p_pid, - (unsigned int)args->flags, (unsigned int)args->stack); -#endif - - if (!args->stack) - return (EINVAL); - exit_signal = args->flags & 0x000000ff; - if (exit_signal >= LINUX_NSIG) - return EINVAL; - exit_signal = linux_to_bsd_signal[exit_signal]; - - /* RFTHREAD probably not necessary here, but it shouldn't hurt either */ - ff |= RFTHREAD; - - if (args->flags & CLONE_VM) - ff |= RFMEM; - if (args->flags & CLONE_SIGHAND) - ff |= RFSIGSHARE; - if (!(args->flags & CLONE_FILES)) - ff |= RFFDG; - - error = 0; - start = 0; - - rf_args.flags = ff; - if (error = rfork(p, &rf_args)) - return error; - - p2 = pfind(p->p_retval[0]); - if (p2 == 0) - return ESRCH; - - p2->p_sigparent = exit_signal; - p2->p_md.md_regs->tf_esp = (unsigned int)args->stack; - -#ifdef DEBUG - printf ("linux_clone(%d): successful rfork to %d\n", p->p_pid, p2->p_pid); -#endif - return 0; -} - -#endif /* COMPAT_LINUX_THREADS */ /* XXX move */ struct linux_mmap_argv { linux_caddr_t addr; @@ -646,11 +570,6 @@ struct linux_mmap_argv { int pos; }; -#ifdef COMPAT_LINUX_THREADS -#define STACK_SIZE (2 * 1024 * 1024) -#define GUARD_SIZE (4 * PAGE_SIZE) - -#endif /* COMPAT_LINUX_THREADS */ int linux_mmap(struct proc *p, struct linux_mmap_args *args) { @@ -683,69 +602,8 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args) bsd_args.flags |= MAP_FIXED; if (linux_args.flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; -#ifndef COMPAT_LINUX_THREADS bsd_args.addr = linux_args.addr; bsd_args.len = linux_args.len; -#else - -#ifndef VM_STACK - /* Linux Threads will map into the proc stack space, unless - * we prevent it. This causes problems if we're not using - * our VM_STACK options. - */ - if ((unsigned int)linux_args.addr + linux_args.len > (USRSTACK - MAXSSIZ)) - return (EINVAL); -#endif - - if (linux_args.flags & LINUX_MAP_GROWSDOWN) { - -#ifdef VM_STACK - bsd_args.flags |= MAP_STACK; -#endif - - /* The linux MAP_GROWSDOWN option does not limit auto - * growth of the region. Linux mmap with this option - * takes as addr the inital BOS, and as len, the initial - * region size. It can then grow down from addr without - * limit. However, linux threads has an implicit internal - * limit to stack size of STACK_SIZE. Its just not - * enforced explicitly in linux. But, here we impose - * a limit of (STACK_SIZE - GUARD_SIZE) on the stack - * region, since we can do this with our mmap. - * - * Our mmap with MAP_STACK takes addr as the maximum - * downsize limit on BOS, and as len the max size of - * the region. It them maps the top SGROWSIZ bytes, - * and autgrows the region down, up to the limit - * in addr. - * - * If we don't use the MAP_STACK option, the effect - * of this code is to allocate a stack region of a - * fixed size of (STACK_SIZE - GUARD_SIZE). - */ - - /* This gives us TOS */ - bsd_args.addr = linux_args.addr + linux_args.len; - - /* This gives us our maximum stack size */ - if (linux_args.len > STACK_SIZE - GUARD_SIZE) - bsd_args.len = linux_args.len; - else - bsd_args.len = STACK_SIZE - GUARD_SIZE; - - /* This gives us a new BOS. If we're using VM_STACK, then - * mmap will just map the top SGROWSIZ bytes, and let - * the stack grow down to the limit at BOS. If we're - * not using VM_STACK we map the full stack, since we - * don't have a way to autogrow it. - */ - bsd_args.addr -= bsd_args.len; - - } else { - bsd_args.addr = linux_args.addr; - bsd_args.len = linux_args.len; - } -#endif /* COMPAT_LINUX_THREADS */ bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ bsd_args.fd = linux_args.fd; bsd_args.pos = linux_args.pos; @@ -801,23 +659,14 @@ int linux_pipe(struct proc *p, struct linux_pipe_args *args) { int error; - int reg_edx; #ifdef DEBUG printf("Linux-emul(%d): pipe(*)\n", p->p_pid); #endif - reg_edx = p->p_retval[1]; - if (error = pipe(p, 0)) { - p->p_retval[1] = reg_edx; + if (error = pipe(p, 0)) return error; - } - - if (error = copyout(p->p_retval, args->pipefds, 2*sizeof(int))) { - p->p_retval[1] = reg_edx; + if (error = copyout(p->p_retval, args->pipefds, 2*sizeof(int))) return error; - } - - p->p_retval[1] = reg_edx; p->p_retval[0] = 0; return 0; } @@ -897,18 +746,12 @@ linux_newuname(struct proc *p, struct linux_newuname_args *args) printf("Linux-emul(%d): newuname(*)\n", p->p_pid); #endif bzero(&linux_newuname, sizeof(struct linux_newuname_t)); - strncpy(linux_newuname.sysname, ostype, - sizeof(linux_newuname.sysname) - 1); - strncpy(linux_newuname.nodename, hostname, - sizeof(linux_newuname.nodename) - 1); - strncpy(linux_newuname.release, osrelease, - sizeof(linux_newuname.release) - 1); - strncpy(linux_newuname.version, version, - sizeof(linux_newuname.version) - 1); - strncpy(linux_newuname.machine, machine, - sizeof(linux_newuname.machine) - 1); - strncpy(linux_newuname.domainname, domainname, - sizeof(linux_newuname.domainname) - 1); + strncpy(linux_newuname.sysname, ostype, 64); + strncpy(linux_newuname.nodename, hostname, 64); + strncpy(linux_newuname.release, osrelease, 64); + strncpy(linux_newuname.version, version, 64); + strncpy(linux_newuname.machine, machine, 64); + strncpy(linux_newuname.domainname, domainname, 64); return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf, sizeof(struct linux_newuname_t))); } @@ -972,25 +815,11 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args) #endif tmp.pid = args->pid; tmp.status = args->status; -#ifndef COMPAT_LINUX_THREADS tmp.options = args->options; -#else - /* This filters out the linux option _WCLONE. I don't - * think we need it, but I could be wrong. If we need - * it, we need to fix wait4, since it will give us an - * error return of EINVAL if we pass in _WCLONE, and - * of course, it won't do anything with it. - */ - tmp.options = (args->options & (WNOHANG | WUNTRACED)); -#endif /* COMPAT_LINUX_THREADS */ tmp.rusage = NULL; if (error = wait4(p, &tmp)) -#ifndef COMPAT_LINUX_THREADS - return error; -#else return error; -#endif /* COMPAT_LINUX_THREADS */ if (args->status) { if (error = copyin(args->status, &tmpstat, sizeof(int))) return error; @@ -1023,17 +852,7 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args) #endif tmp.pid = args->pid; tmp.status = args->status; -#ifndef COMPAT_LINUX_THREADS tmp.options = args->options; -#else - /* This filters out the linux option _WCLONE. I don't - * think we need it, but I could be wrong. If we need - * it, we need to fix wait4, since it will give us an - * error return of EINVAL if we pass in _WCLONE, and - * of course, it won't do anything with it. - */ - tmp.options = (args->options & (WNOHANG | WUNTRACED)); -#endif /* COMPAT_LINUX_THREADS */ tmp.rusage = args->rusage; if (error = wait4(p, &tmp)) @@ -1170,75 +989,3 @@ linux_nice(struct proc *p, struct linux_nice_args *args) return setpriority(p, &bsd_args); } -int -linux_setgroups(p, uap) - struct proc *p; - struct linux_setgroups_args *uap; -{ - struct pcred *pc = p->p_cred; - linux_gid_t linux_gidset[NGROUPS]; - gid_t *bsd_gidset; - int ngrp, error; - - if ((error = suser(pc->pc_ucred, &p->p_acflag))) - return error; - - if (uap->gidsetsize > NGROUPS) - return EINVAL; - - ngrp = uap->gidsetsize; - pc->pc_ucred = crcopy(pc->pc_ucred); - if (ngrp >= 1) { - if ((error = copyin((caddr_t)uap->gidset, - (caddr_t)linux_gidset, - ngrp * sizeof(linux_gid_t)))) - return error; - - pc->pc_ucred->cr_ngroups = ngrp; - - bsd_gidset = pc->pc_ucred->cr_groups; - ngrp--; - while (ngrp >= 0) { - bsd_gidset[ngrp] = linux_gidset[ngrp]; - ngrp--; - } - } - else - pc->pc_ucred->cr_ngroups = 1; - - setsugid(p); - return 0; -} - -int -linux_getgroups(p, uap) - struct proc *p; - struct linux_getgroups_args *uap; -{ - struct pcred *pc = p->p_cred; - linux_gid_t linux_gidset[NGROUPS]; - gid_t *bsd_gidset; - int ngrp, error; - - if ((ngrp = uap->gidsetsize) == 0) { - p->p_retval[0] = pc->pc_ucred->cr_ngroups; - return 0; - } - - if (ngrp < pc->pc_ucred->cr_ngroups) - return EINVAL; - - ngrp = 0; - bsd_gidset = pc->pc_ucred->cr_groups; - while (ngrp < pc->pc_ucred->cr_ngroups) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } - - if ((error = copyout((caddr_t)linux_gidset, (caddr_t)uap->gidset, - ngrp * sizeof(linux_gid_t)))) - return error; - - p->p_retval[0] = ngrp; - return (0); -} diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h index cda56c279d8b4..eedb56606a4c3 100644 --- a/sys/i386/linux/linux_proto.h +++ b/sys/i386/linux/linux_proto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.16 1998/12/30 20:58:28 sos Exp + * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp */ #ifndef _LINUX_SYSPROTO_H_ @@ -195,14 +195,6 @@ struct linux_sigsuspend_args { struct linux_sigpending_args { linux_sigset_t * mask; char mask_[PAD_(linux_sigset_t *)]; }; -struct linux_getgroups_args { - u_int gidsetsize; char gidsetsize_[PAD_(u_int)]; - linux_gid_t * gidset; char gidset_[PAD_(linux_gid_t *)]; -}; -struct linux_setgroups_args { - u_int gidsetsize; char gidsetsize_[PAD_(u_int)]; - linux_gid_t * gidset; char gidset_[PAD_(linux_gid_t *)]; -}; struct linux_select_args { struct linux_select_argv * ptr; char ptr_[PAD_(struct linux_select_argv *)]; }; @@ -309,8 +301,7 @@ struct linux_sigreturn_args { struct linux_sigcontext * scp; char scp_[PAD_(struct linux_sigcontext *)]; }; struct linux_clone_args { - int flags; char flags_[PAD_(int)]; - void * stack; char stack_[PAD_(void *)]; + register_t dummy; }; struct linux_newuname_args { struct linux_newuname_t * buf; char buf_[PAD_(struct linux_newuname_t *)]; @@ -437,8 +428,6 @@ int linux_siggetmask __P((struct proc *, struct linux_siggetmask_args *)); int linux_sigsetmask __P((struct proc *, struct linux_sigsetmask_args *)); int linux_sigsuspend __P((struct proc *, struct linux_sigsuspend_args *)); int linux_sigpending __P((struct proc *, struct linux_sigpending_args *)); -int linux_getgroups __P((struct proc *, struct linux_getgroups_args *)); -int linux_setgroups __P((struct proc *, struct linux_setgroups_args *)); int linux_select __P((struct proc *, struct linux_select_args *)); int linux_symlink __P((struct proc *, struct linux_symlink_args *)); int linux_readlink __P((struct proc *, struct linux_readlink_args *)); diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c index 1f71bf53df09b..481ed7f177536 100644 --- a/sys/i386/linux/linux_signal.c +++ b/sys/i386/linux/linux_signal.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: linux_signal.c,v 1.13 1998/10/11 04:54:16 jdp Exp $ + * $Id: linux_signal.c,v 1.12 1998/08/15 22:29:43 bde Exp $ */ #include <sys/param.h> @@ -310,7 +310,7 @@ linux_kill(struct proc *p, struct linux_kill_args *args) printf("Linux-emul(%d): kill(%d, %d)\n", p->p_pid, args->pid, args->signum); #endif - if (args->signum < 0 || args->signum >= LINUX_NSIG) + if (args->signum <= 0 || args->signum >= LINUX_NSIG) return EINVAL; tmp.pid = args->pid; tmp.signum = linux_to_bsd_signal[args->signum]; diff --git a/sys/i386/linux/linux_socket.c b/sys/i386/linux/linux_socket.c index e757fc13c7f81..b50cf5860e319 100644 --- a/sys/i386/linux/linux_socket.c +++ b/sys/i386/linux/linux_socket.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: linux_socket.c,v 1.14 1998/12/30 21:20:00 sos Exp $ + * $Id: linux_socket.c,v 1.12 1998/02/07 02:13:27 msmith Exp $ */ /* XXX we use functions that might not exist. */ @@ -810,44 +810,6 @@ linux_socketcall(struct proc *p, struct linux_socketcall_args *args) return linux_setsockopt(p, args->args); case LINUX_GETSOCKOPT: return linux_getsockopt(p, args->args); - case LINUX_SENDMSG: - do { - int error; - int level; - caddr_t control; - struct { - int s; - const struct msghdr *msg; - int flags; - } *uap = args->args; - - error = copyin(&uap->msg->msg_control, - &control, sizeof(caddr_t)); - if (error) - return error; - if (control == NULL) - goto done; - error = copyin(&((struct cmsghdr *)control)->cmsg_level, - &level, sizeof(int)); - if (error) - return error; - if (level == 1) { - /* - * Linux thinks that SOL_SOCKET is 1; we know that it's really - * 0xffff, of course. - */ - level = SOL_SOCKET; - error = copyout(&level, &((struct cmsghdr *)control)-> - cmsg_level, sizeof(int)); - if (error) - return error; - } - done: - return sendmsg(p, args->args); - } while (0); - case LINUX_RECVMSG: - return recvmsg(p, args->args); - default: uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); return ENOSYS; diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h index e30d836f2406e..c0b7147531562 100644 --- a/sys/i386/linux/linux_syscall.h +++ b/sys/i386/linux/linux_syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.16 1998/12/30 20:58:28 sos Exp + * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp */ #define LINUX_SYS_linux_setup 0 @@ -85,8 +85,8 @@ #define LINUX_SYS_getrusage 77 #define LINUX_SYS_gettimeofday 78 #define LINUX_SYS_settimeofday 79 -#define LINUX_SYS_linux_getgroups 80 -#define LINUX_SYS_linux_setgroups 81 +#define LINUX_SYS_getgroups 80 +#define LINUX_SYS_setgroups 81 #define LINUX_SYS_linux_select 82 #define LINUX_SYS_linux_symlink 83 #define LINUX_SYS_ostat 84 @@ -162,6 +162,5 @@ #define LINUX_SYS_sched_rr_get_interval 161 #define LINUX_SYS_nanosleep 162 #define LINUX_SYS_linux_mremap 163 -#define LINUX_SYS_poll 168 #define LINUX_SYS_linux_chown 182 #define LINUX_SYS_MAXSYSCALL 183 diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c index a5e8bdbf7bc72..da9ac246a517b 100644 --- a/sys/i386/linux/linux_sysent.c +++ b/sys/i386/linux/linux_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.16 1998/12/30 20:58:28 sos Exp + * created from Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp */ #include "opt_compat.h" @@ -94,8 +94,8 @@ struct sysent linux_sysent[] = { { 2, (sy_call_t *)getrusage }, /* 77 = getrusage */ { 2, (sy_call_t *)gettimeofday }, /* 78 = gettimeofday */ { 2, (sy_call_t *)settimeofday }, /* 79 = settimeofday */ - { 2, (sy_call_t *)linux_getgroups }, /* 80 = linux_getgroups */ - { 2, (sy_call_t *)linux_setgroups }, /* 81 = linux_setgroups */ + { 2, (sy_call_t *)getgroups }, /* 80 = getgroups */ + { 2, (sy_call_t *)setgroups }, /* 81 = setgroups */ { 1, (sy_call_t *)linux_select }, /* 82 = linux_select */ { 2, (sy_call_t *)linux_symlink }, /* 83 = linux_symlink */ { 2, (sy_call_t *)ostat }, /* 84 = ostat */ @@ -134,7 +134,7 @@ struct sysent linux_sysent[] = { { 5, (sy_call_t *)linux_ipc }, /* 117 = linux_ipc */ { 1, (sy_call_t *)fsync }, /* 118 = fsync */ { 1, (sy_call_t *)linux_sigreturn }, /* 119 = linux_sigreturn */ - { 2, (sy_call_t *)linux_clone }, /* 120 = linux_clone */ + { 0, (sy_call_t *)linux_clone }, /* 120 = linux_clone */ { 2, (sy_call_t *)setdomainname }, /* 121 = setdomainname */ { 1, (sy_call_t *)linux_newuname }, /* 122 = linux_newuname */ { 3, (sy_call_t *)linux_modify_ldt }, /* 123 = linux_modify_ldt */ @@ -182,7 +182,7 @@ struct sysent linux_sysent[] = { { 0, (sy_call_t *)nosys }, /* 165 = getresuid */ { 0, (sy_call_t *)nosys }, /* 166 = new_vm86 */ { 0, (sy_call_t *)nosys }, /* 167 = query_module */ - { 3, (sy_call_t *)poll }, /* 168 = poll */ + { 0, (sy_call_t *)nosys }, /* 168 = poll */ { 0, (sy_call_t *)nosys }, /* 169 = nfsservctl */ { 0, (sy_call_t *)nosys }, /* 170 = setresgid */ { 0, (sy_call_t *)nosys }, /* 171 = getresgid */ diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index fd80f1d438e86..cf8c021c53fe8 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.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: linux_sysvec.c,v 1.43 1999/01/06 23:05:38 julian Exp $ + * $Id: linux_sysvec.c,v 1.36 1998/10/11 21:08:02 alex Exp $ */ /* XXX we use functions that might not exist. */ @@ -70,7 +70,7 @@ static void linux_sendsig __P((sig_t catcher, int sig, int mask, /* * Linux syscalls return negative errno's, we do positive and map them */ -static int bsd_to_linux_errno[ELAST + 1] = { +static int bsd_to_linux_errno[ELAST] = { -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, @@ -79,7 +79,7 @@ static int bsd_to_linux_errno[ELAST + 1] = { -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, - -6, -6, -43, -42, -75, -6, -84 + -6, -43, -42 }; int bsd_to_linux_signal[NSIG] = { @@ -217,11 +217,7 @@ linux_sendsig(sig_t catcher, int sig, int mask, u_long 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 linux_sigframe), B_WRITE) == FALSE)) { /* * Process has trashed its stack; give it an illegal @@ -285,7 +281,7 @@ linux_sendsig(sig_t catcher, int sig, int mask, u_long code) * Build context to run handler in. */ 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_eflags &= ~PSL_VM; regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; @@ -399,7 +395,7 @@ struct sysentvec linux_sysvec = { 0xff, NSIG, bsd_to_linux_signal, - ELAST + 1, + ELAST, bsd_to_linux_errno, translate_traps, linux_fixup, @@ -417,7 +413,7 @@ struct sysentvec elf_linux_sysvec = { 0xff, NSIG, bsd_to_linux_signal, - ELAST + 1, + ELAST, bsd_to_linux_errno, translate_traps, elf_linux_fixup, @@ -429,6 +425,9 @@ struct sysentvec elf_linux_sysvec = { elf_coredump }; +/* + * Installed either via SYSINIT() or via LKM stubs. + */ static Elf32_Brandinfo linux_brand = { "Linux", "/compat/linux", @@ -449,8 +448,14 @@ Elf32_Brandinfo *linux_brandlist[] = { NULL }; +/* + * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the + * "proof of concept" stage and will be fixed shortly + */ +static int linux_elf_modevent __P((module_t mod, modeventtype_t type, void *data)); + static int -linux_elf_modevent(module_t mod, int type, void *data) +linux_elf_modevent(module_t mod, modeventtype_t type, void *data) { Elf32_Brandinfo **brandinfo; int error; diff --git a/sys/i386/linux/linux_util.h b/sys/i386/linux/linux_util.h index 07a2d3ce686e8..58a477d67e9b9 100644 --- a/sys/i386/linux/linux_util.h +++ b/sys/i386/linux/linux_util.h @@ -28,7 +28,7 @@ * * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp - * $Id: linux_util.h,v 1.6 1998/06/30 08:40:33 jmg Exp $ + * $Id: linux_util.h,v 1.5 1997/02/22 09:38:30 peter Exp $ */ /* @@ -60,7 +60,7 @@ static __inline caddr_t stackgap_init() { #define szsigcode (*(curproc->p_sysent->sv_szsigcode)) - return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE); + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); } diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master index c4cc425be69a0..912cb3244597e 100644 --- a/sys/i386/linux/syscalls.master +++ b/sys/i386/linux/syscalls.master @@ -1,4 +1,4 @@ - $Id: syscalls.master,v 1.15 1998/12/22 08:59:19 sos Exp $ + $Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 ; System call name/number master file (or rather, slave, from LINUX). @@ -119,10 +119,8 @@ struct timezone *tzp); } 79 NOPROTO LINUX { int settimeofday(struct timeval *tp, \ struct timezone *tzp); } -80 STD LINUX { int linux_getgroups(u_int gidsetsize, \ - linux_gid_t *gidset); } -81 STD LINUX { int linux_setgroups(u_int gidsetsize, \ - linux_gid_t *gidset); } +80 NOPROTO LINUX { int getgroups(u_int gidsetsize, gid_t *gidset); } +81 NOPROTO LINUX { int setgroups(u_int gidsetsize, gid_t *gidset); } 82 STD LINUX { int linux_select(struct linux_select_argv *ptr); } 83 STD LINUX { int linux_symlink(char *path, char *to); } 84 NOPROTO LINUX { int ostat(char *path, struct ostat *up); } @@ -173,7 +171,7 @@ caddr_t ptr); } 118 NOPROTO LINUX { int fsync(int fd); } 119 STD LINUX { int linux_sigreturn(struct linux_sigcontext *scp); } -120 STD LINUX { int linux_clone(int flags, void *stack); } +120 STD LINUX { int linux_clone(void); } 121 NOPROTO LINUX { int setdomainname(char *name, \ int len); } 122 STD LINUX { int linux_newuname(struct linux_newuname_t *buf); } @@ -241,8 +239,7 @@ 165 UNIMPL LINUX getresuid 166 UNIMPL LINUX new_vm86 167 UNIMPL LINUX query_module -168 NOPROTO LINUX { int poll(struct pollfd*, unsigned int nfds, \ - long timeout); } +168 UNIMPL LINUX poll 169 UNIMPL LINUX nfsservctl 170 UNIMPL LINUX setresgid 171 UNIMPL LINUX getresgid |
