diff options
Diffstat (limited to 'sys/arch/vax')
134 files changed, 30422 insertions, 0 deletions
diff --git a/sys/arch/vax/BUGS_MISSINGS b/sys/arch/vax/BUGS_MISSINGS new file mode 100644 index 00000000000..cc39325f8bd --- /dev/null +++ b/sys/arch/vax/BUGS_MISSINGS @@ -0,0 +1,10 @@ +Programs may be hanging with the D flag set, even if they (HIGH) +don't do I/O at all. (ps, ...) User PTE problem? +950304/Ragge + +Uba & devices should be converted to use new style config (MEDIUM) +instead of emulating it. MSCP routines should also be +fixed so that they can support both uda and kdb disks +as device ra?. +/Ragge + diff --git a/sys/arch/vax/INSTALL b/sys/arch/vax/INSTALL new file mode 100644 index 00000000000..635034c26d6 --- /dev/null +++ b/sys/arch/vax/INSTALL @@ -0,0 +1,145 @@ + $NetBSD: INSTALL,v 1.1 1995/09/16 12:00:21 ragge Exp $ + + +How to install NetBSD/vax +------------------------- + +1. Device conventions. + NetBSD standalone system addresses devices like + 'devicename(adapter, controller, unit, partition)' + Known devicenames are: + tms - TMSCP tape. + ts - TSV05/TS11 tape. + ra - RA??/RD?? disks/floppies. + hp - RP??/RM?? disks. + + You can omit parameters; ra(0,0) refers to disk 0 partition a + on default controller. On tapes partition refers to file # + on the tape. + + Example: DUB1 (DEC syntax) swap partition will be referred as + ra(1,0,1), DRA2 root partition is hp(2,0). + + + +2. Installation. + This document only covers installation of a miniroot + filesystem on the swap partition of a disk. Installation + of the remaining system is best done over network or + from tape, but this is your own decision. + The installation principle is to label the root disk, + copy a miniroot filesystem onto the swap partition, + boot up from that miniroot filesystem, then create + root and the other wanted partitions and put system + to it. + You will have to deal with 2 files, one is just a boot + filesystem containing 3 files: boot, copy and edlabel, + the other is an image of a miniroot filesystem and can + be split into several pieces depending of what you are + going to install from. + + + +2.1 INSTALLATION + +2.1.1 Installation from TK50. (MicroVAX II) + You will need a file called tk50-file1-???.fs and a + file called tk50-file2-???.fs, where ??? is the + revision og NetBSD. These files must be written on tape + in sequential order; file 1 first and then file2. + _Blocksize_must_be_512!_ Otherwise the tape will not be + bootable. Then type: + + >>> B/3 MUA0 + + This means that you will bring upp boot for asking + from TK50. (MUA0 is DEC naming). It will come up + something like + + 2..1..0.. + + + howto 0x3, bdev 0x12, booting... + 9852+456+34916 start 0x0 + + Nboot + : + + + At the prompt you type edlabel to label the disk, see + README.edlabel about how to use it. + When labeling is finished, halt the computer, bring up + the Nboot prompt again and this time load copy, see + README.copy about how to use it. Remember that you are + copying from file 1 on the tape. + + Now go to step 3. + + +2.2 Installation from RX33/RX50. (MicroVAX II) + The difference between RX33 and RX50 is its size. RX50 + is 400k and RX33 is 1200k. + You will need a file called rxDD-bootdisk-???.fs and + a couple of files called rxDD-copy?-???.fs, where DD + is 33 or 50 and ??? is the revision of NetBSD. + The RX33 installation will be 3 floppies and RX50 + installation will be 7 floppies. + + To boot from floppy type: + + >>> B/3 DUxy + + where x is the controller number and y is device number. + You will now get up a prompt like + + Nboot + : + + At the prompt you type edlabel to label the disk, see + README.edlabel about how to use it. + When labeling is finished, halt the computer, bring up + the Nboot prompt again and this time load copy, see + README.copy about how to use it. Remember that you are + copying from partition 0 when using floppies. + + Now go to step 3. + + +2.3 Installation from TU58. (VAX 11/750). + + Not yet :-( But will be... + + +3. Booting up miniroot. + When copying is ready, bring the boot program up a third + time, and this time bring up a real system by telling + boot where you put your miniroot _and_ also the generic + kernel name. Example: ra(0,1)gennetbsd, boots gennetbsd + from swap partition on ra0. + + When kernel is loaded, you will after a while get a + question about Root device?. Respond to this with + xx?*, where xx is the device name, ? is the unit + number and * tells that the system shall use the swap + partition as root partition. Example: + + Root device? ra0* + + After that a second question: + + Enter pathname of shell or RETURN for sh: + + Just type return. Now you will be in a normal single-user + shell, and it's just to newfs your partitions, and start + installation. + + A few things that you must remember to do from miniroot: + disklabel -B <diskname> to install boot blocks. + MAKEDEV devices in the newly created root filesystem. + Copy gennetbsd and boot from miniroot filesystem + to the newly created root filesystem. + + + Good luck! (You may need it) + Ragge + diff --git a/sys/arch/vax/README b/sys/arch/vax/README new file mode 100644 index 00000000000..1dc4199312c --- /dev/null +++ b/sys/arch/vax/README @@ -0,0 +1,50 @@ + $NetBSD: README,v 1.9 1995/09/16 12:00:21 ragge Exp $ + +Devices supported in kernel and _known_ to work: +CPU: VAX 11/750 with 2-14MB of memory. + KA630 (MicroVAX II) with 2-16 MB memory. + +Net: DEUNA/DELUA Unibus ethernet cards. + DEQNA/DELQA Q22 bus ethernet cards. + +Disks: UDA50 Unibus MSCP controller. + KDA50/RQDX3 Q22 bus MSCP controller. + RA??-disks on UDA50 or KDA50. + RD??-disks on RQDX3. (known as RA?? by system). + +Tapes: DILOG Q22 bus tape ctlr w/ Exabyte. (TMSCP emulating) + TSV05 Q22 bus tape ctlr. + TK50 (TMSCP) on Q22 bus. + Other TMSCP ctlrs may also work, but haven't tried. + + +To install and run NetBSD/vax you need a MicroVAX II or VAX 11/750 +with at least 4MB of memory, and a usable install media. Supported +install media is TK50 tape and RX33/RX50 floppy. If you do initial +installation from floppy then you need a way to load the rest of +the system, like tape or ethernet. +NOTE! TU58 INSTALLATION IS NOT YET SUPPORTED, BUT WILL BE. + +Actually, the system will run fine on only 2MB of memory, but +installation program needs 4MB. If this causes trouble for someone +tell me and I'll fix it. + +Differences between the NetBSD/vax port and other ports: + * It uses gcc 2.7.0 as default compiler. + * libm is not the same as the other ports; instead it is 4.4BSD libm. + * No dynamic linked libraries, all binaries is statically linked. +These things will be fixed in the future. + + +We who have done parts of the VAX port is: + Joachim Isaksson, first pmap and lots of help with gcc functionality. + Mattias Gr|nlund, locore assembler and interrupt handling. + Mattias ]slund, lots of help and ideas everywhere. + Bertram Barth, bootblocks and boot routines for MicroVAX. + Rick Macklem, fixed all MicroVAX II, TMSCP and DEQNA support. + Anders Magnusson (ragge), that's me, who put things together + and wrote the rest. + +Have fun with it, + ragge@ludd.luth.se + diff --git a/sys/arch/vax/README.copy b/sys/arch/vax/README.copy new file mode 100644 index 00000000000..610ea12e6ea --- /dev/null +++ b/sys/arch/vax/README.copy @@ -0,0 +1,80 @@ + $NetBSD: README.copy,v 1.2 1995/09/29 16:33:38 ragge Exp $ + + How to use copy + ------------------ + + +Edlabel is a standalone program that can copy multiple volumes +from disk/tape to disk/tape. Mostly it is used to copy the +miniroot filesystem onto the swap partition during initial +installation. +You will here be guided through a session, things with ^^^^ under +is typed in by the user, comments are within /* */. +This is an installation from TK50. + + +Nboot +: copy + ^^^^ +10480+468+34868 start 0x0 + +copy: +This program will read miniroot from tape/floppy/disk +and install this miniroot onto disk. + +Specify the device to read from as xx(N,0), where +xx is the device-name and N is the unit-number, e.g. +"tms(0,1)" for the first TMSCP-tape (TK50), +"ra(2,0)" for the third MSCP-disk/floppy (RX33/RX50) + +device to read from ? tms(0,1) /* Tape 0, file 1 */ + ^^^^^^^^ +Specify number of blocks to transfer. Usually this is +sizeof(miniroot) / 512. +It's safe to transfer more blocks than just the miniroot. + +number of blocks ? 4096 /* Miniroot size is 4096 block */ + ^^^^ +If your miniroot is split into volumes, then you must +specify the number of blocks per volume. +(e.g. 800 blocks per RX50, 2400 blocks per RX33) + +number of blocks per volume ? [4096] + +Make sure unit tms(0,1) is online and holds the proper volume. +Then type 'g' to Go or 'a' to Abort. + +OK to go on ? [g/a] g /* g == go, a == abort */ + ^ +Reading ... Reading of miniroot done. (4096 blocks read) + + +Now specify the device to write miniroot to as xx(N,1) +where xx is the drive type and N is the drive number. +For example: ra(0,1) refers to MSCP drive #0, b partition + +Root disk ? : ra(0,1) /* Actually DUA0, partition b (swap) */ + ^^^^^^^^^ +Initializing partition ... done. +(4096 blocks written.) + +Halt the machine and reboot from distribution media, +giving second partition as part to mount as root. Ex: +: ra(0,1) for ra disk 0, hp(2,1) for massbuss disk 2 + +Halt/Reboot the machine NOW. +?02 EXT HLT + PC = 001005F3 +>>> + + + + +-- Ragge + + + + + + + diff --git a/sys/arch/vax/README.edlabel b/sys/arch/vax/README.edlabel new file mode 100644 index 00000000000..1a6c3d92746 --- /dev/null +++ b/sys/arch/vax/README.edlabel @@ -0,0 +1,137 @@ + $NetBSD: README.edlabel,v 1.1 1995/09/16 12:00:19 ragge Exp $ + + + How to use edlabel + ------------------ + + +Edlabel is a program to edit disklabels on any disks in a standalone +environment. Mostly it is used to set labels when doing initial +installation procedure. It is started from boot program prompt. +You will here be guided through a session, things with ^^^^ under +is typed in by the user, comments are within /* */. + +Nboot +: edlabel + ^^^^^^^ +11700+576+43200 start 0x0 +With this program you can modify everything in the on-disk +disklabel. To do something useful you must know the exact +geometry of your disk, and have ideas about how you want +your partitions to be placed on disk. Some hints: +The a partition should be at least ~20000 blocks, the +b (swap) is depending on your use of the machine but it +should almost never be less than ~32000 blocks. + +Disk geometry for most DEC disks can be found in the disktab +file, and disknames is listed in the installation notes. + +Remember that disk names is given as disk(adapt, ctrl, disk, part) +when using the installation tools. + +Label which disk? ra(1,0,0) /* See INSTALL text for device types */ + ^^^^^^^^^ +getdisklabel: no disk label +ra(1,0,0): no disk label +(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : e + ^ +First set disk type. Valid types are: +0 unknown +1 SMD +2 MSCP +3 old DEC +4 SCSI +5 ESDI +6 ST506 +7 HP-IB +8 HP-FL +9 type 9 +10 floppy +11 ccd +12 vnd + +Numeric disk type? [0] 2 /* All disks supported this far is MSCP */ +Disk name? [] rd54 ^ /* You must know what type your disk is */ +badsect? [n] ^^^^ /* No badsectoring yet */ +ecc? [n] /* ECC is automatic, don't care */ +removable? [n] /* Removable or not, like RA60 */ +Interleave? [0] 1 /* All MSCP disks is seen like 1 interleave */ +rpm? [0] 3600 ^ /* 3600 rpm is normal */ +trackskew? [0] /* don't care */ +cylinderskew? [0] /* don't care */ +headswitch? [0] /* don't care */ +track-to-track? [0] /* don't care */ +drivedata 0? [0] /* don't care */ +drivedata 1? [0] /* don't care */ +drivedata 2? [0] /* don't care */ +drivedata 3? [0] /* don't care */ +drivedata 4? [0] /* don't care */ + +bytes/sector? [0] 512 /* Probably only sive on VAX systems */ + ^^^ +sectors/track? [0] 17 /* You must know this, check disktab file */ + ^^ +tracks/cylinder? [0] 15 /* You must know this, check disktab file */ + ^^ +sectors/cylinder? [0] 255 /* sectors/track * tracks/cylinder */ + ^^^ +cylinders? [0] 1221 /* You must know this, check disktab file */ + ^^^^ +a partition: offset? [0] /* Partition sizes are set by you. */ + size? [0] 20000 /* Take default sizes from disktab or */ +b partition: offset? [0] 20000 /* calculate your own partition sizes */ + size? [0] 20000 +c partition: offset? [0] + size? [0] 311200 +d partition: offset? [0] + size? [0] +e partition: offset? [0] 40000 + size? [0] 271200 +f partition: offset? [0] + size? [0] +g partition: offset? [0] + size? [0] +h partition: offset? [0] + size? [0] + +(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : s /* Show what you've typed */ + ^ + +disk type 2 (MSCP), rd54: +interleave 1, rpm 3600, trackskew 0, cylinderskew 0 +headswitch 0, track-to-track 0, drivedata: 0 0 0 0 0 + +bytes/sector: 512 +sectors/track: 17 +tracks/cylinder: 15 +sectors/cylinder: 255 +cylinders: 1221 + +8 partitions: + size offset +a: 20000, 0 +b: 20000, 20000 +c: 311200, 0 +d: 0, 0 +e: 271200, 40000 +f: 0, 0 +g: 0, 0 +h: 0, 0 + +(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : w /* Write label to disk */ + +This program does not (yet) write bootblocks, only disklabel. +Remember to write the bootblocks from the miniroot later with the +command "disklabel -B <diskname>". +(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : q + + + +-- Ragge + + + + + + + diff --git a/sys/arch/vax/boot/Makefile b/sys/arch/vax/boot/Makefile new file mode 100644 index 00000000000..b54fa987f1f --- /dev/null +++ b/sys/arch/vax/boot/Makefile @@ -0,0 +1,103 @@ +# $NetBSD: Makefile,v 1.4 1995/09/16 13:18:27 ragge Exp $ +# + +INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa + +CC= cc +AS= as + +S= ../../.. +RELOC= 100000 +CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_ + +DEVS= autoconf.o hp.o ra.o tmscp.o + +.include "$S/lib/libkern/Makefile.inc" +LIBKERN= ${KERNLIB} + +.include "$S/lib/libsa/Makefile.inc" +LIBSA= ${SA_LIB} + +all: xxboot boot copy edlabel + +libsvax.a: consio.o urem.o udiv.o + ar crv $@ $? + ranlib $@ + +urem.o: ../vax/urem.s + ${CC} -x assembler-with-cpp -E ../vax/urem.s | as -o urem.o + +udiv.o: ../vax/udiv.s + ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o + +# startups + +start.o: start.s + ${CC} -x assembler-with-cpp -E start.s | as -o start.o + +srt0.o: srt0.s + ${CC} -x assembler-with-cpp -E srt0.s | as -o srt0.o + +# + +xxboot: start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a + ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \ + ${LIBSA} ${LIBKERN} libsvax.a + @strip a.out + @size a.out + @dd if=a.out of=xxboot bs=32 skip=1 + @rm -f a.out + +boot: boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip boot + @size boot + +edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip edlabel + @size edlabel + +copy: copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip copy + @size copy + +# + +hp.o: hp.c + ${CC} -c ${CFLAGS} $*.c + +ra.o: ra.c + ${CC} -c ${CFLAGS} $*.c + +autoconf.o: autoconf.c + ${CC} -c ${CFLAGS} $*.c + +conf.o: conf.c + ${CC} -c ${CFLAGS} $*.c + +boot.o: boot.c + ${CC} -c ${CFLAGS} $*.c + +copy.o: copy.c + ${CC} -c ${CFLAGS} $*.c + +romread.o: romread.s + ${CC} -x assembler-with-cpp -E romread.s | as -o romread.o + +init.o: init.c + ${CC} -c ${CFLAGS} $*.c + +bootxx.o: bootxx.c + ${CC} -c ${CFLAGS} $*.c + +clean:: + rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \ + libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o + rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \ + copy copy.o + diff --git a/sys/arch/vax/boot/autoconf.c b/sys/arch/vax/boot/autoconf.c new file mode 100644 index 00000000000..654d6a68680 --- /dev/null +++ b/sys/arch/vax/boot/autoconf.c @@ -0,0 +1,92 @@ +/* $NetBSD: autoconf.c,v 1.3 1995/09/16 13:34:20 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" +#include "../include/mtpr.h" +#include "../include/sid.h" +#include "vaxstand.h" + +int nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0; +int *mbaaddr, *ubaaddr; +int *udaaddr, *uioaddr, tmsaddr; + +static int mba750[]={0xf28000,0xf2a000,0xf2c000}; +static int uba750[]={0xf30000,0xf32000}; +static int uio750[]={0xfc0000,0xf80000}; +static int uda750[]={0772150}; + +static int uba630[]={0x20087800}; +static int uio630[]={0x30000000}; +#define qbdev(csr) (((csr) & 017777)-0x10000000) +static int uda630[]={qbdev(0772150),qbdev(0760334)}; +/* + * Autoconf routine is really stupid; but it actually don't + * need any intelligence. We just assume that all possible + * devices exists on each cpu. Fast & easy. + */ + +autoconf() +{ + int i = MACHID(mfpr(PR_SID)); + + switch (i) { + + default: + printf("CPU type %d not supported by boot\n",i); + asm("halt"); + + case VAX_750: + nmba = 3; + nuba = 2; + nuda = 1; + mbaaddr = mba750; + ubaaddr = uba750; + udaaddr = uda750; + uioaddr = uio750; + tmsaddr = 0774500; + break; + + case VAX_650: /* the same for uvaxIII */ + case VAX_78032: + nuba = 1; + nuda = 2; + ubaaddr = uba630; + udaaddr = uda630; + uioaddr = uio630; + tmsaddr = qbdev(0774500); + break; + } +} + diff --git a/sys/arch/vax/boot/boot.c b/sys/arch/vax/boot/boot.c new file mode 100644 index 00000000000..d85ddabdf5d --- /dev/null +++ b/sys/arch/vax/boot/boot.c @@ -0,0 +1,249 @@ +/* $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "lib/libsa/stand.h" + +#include <a.out.h> + +/* + * Boot program... arguments passed in r10 and r11 determine + * whether boot stops to ask for system name and which device + * boot comes from. + */ + +char line[100]; +volatile u_int devtype, bootdev; +extern unsigned opendev; + +main() +{ + register howto asm("r11"); + register bdev asm("r10"); + int io, retry, type; + + io=0; + bootdev=bdev; + autoconf(); + + if ((howto & RB_ASKNAME) == 0) { + type = (devtype >> B_TYPESHIFT) & B_TYPEMASK; + if ((unsigned)type < ndevs && devsw[type].dv_name) + strcpy(line, "/netbsd"); + else + howto |= RB_SINGLE|RB_ASKNAME; + } + + for (retry = 0;;) { + if (io >= 0) + printf("\nNboot\n"); + if (howto & RB_ASKNAME) { + printf(": "); + gets(line); + if (line[0] == 0) { + strcpy(line, "/netbsd"); + printf(": %s\n", line); + } + } else + printf(": %s\n", line); + io = open(line, 0); + if (io >= 0) { + loadpcs(); + copyunix(howto, opendev, io); + close(io); + howto |= RB_SINGLE|RB_ASKNAME; + } else { + printf("%s\n",strerror(errno)); + } + if (++retry > 2) + howto |= RB_SINGLE|RB_ASKNAME; + } +} + +/*ARGSUSED*/ +copyunix(howto, devtype, aio) + register howto, devtype; /* howto=r11, devtype=r10 */ + int aio; +{ + register int esym; /* must be r9 */ + struct exec x; + register int io = aio, i; + char *addr; + + if (read(io, (char *)&x, sizeof(x)) != sizeof(x) || N_BADMAG(x)) { + printf("Bad format\n"); + return; + } + printf("%d", x.a_text); + if (N_GETMAGIC(x) == ZMAGIC && lseek(io, 0x400, SEEK_SET) == -1) + goto shread; + if (read(io, (char *)0, x.a_text) != x.a_text) + goto shread; + addr = (char *)x.a_text; + if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) + while ((int)addr & CLOFSET) + *addr++ = 0; + printf("+%d", x.a_data); + if (read(io, addr, x.a_data) != x.a_data) + goto shread; + addr += x.a_data; + printf("+%d", x.a_bss); + for (i = 0; i < x.a_bss; i++) + *addr++ = 0; + if (howto & RB_KDB && x.a_syms) { + *(int *)addr = x.a_syms; /* symbol table size */ + addr += sizeof (int); + printf("[+%d", x.a_syms); + if (read(io, addr, x.a_syms) != x.a_syms) + goto shread; + addr += x.a_syms; + if (read(io, addr, sizeof (int)) != sizeof (int)) + goto shread; + i = *(int *)addr - sizeof (int); /* string table size */ + addr += sizeof (int); + printf("+%d]", i); + if (read(io, addr, i) != i) + goto shread; + addr += i; + esym = roundup((int)addr, sizeof (int)); + x.a_bss = 0; + } else + howto &= ~RB_KDB; + for (i = 0; i < 128*512; i++) /* slop */ + *addr++ = 0; + printf(" start 0x%x\n", (x.a_entry&0x7fffffff)); + hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym); + return; +shread: + printf("Short read\n"); + return; +} + +/* 750 Patchable Control Store magic */ + +#include "../include/mtpr.h" +#include "../include/cpu.h" +#include "../include/sid.h" +#define PCS_BITCNT 0x2000 /* number of patchbits */ +#define PCS_MICRONUM 0x400 /* number of ucode locs */ +#define PCS_PATCHADDR 0xf00000 /* start addr of patchbits */ +#define PCS_PCSADDR (PCS_PATCHADDR+0x8000) /* start addr of pcs */ +#define PCS_PATCHBIT (PCS_PATCHADDR+0xc000) /* patchbits enable reg */ +#define PCS_ENABLE 0xfff00000 /* enable bits for pcs */ + +#define extzv(one, two, three,four) \ +({ \ + asm __volatile (" extzv %0,%3,(%1),(%2)+" \ + : \ + : "g"(one),"g"(two),"g"(three),"g"(four)); \ +}) + + +loadpcs() +{ + register int *ip; /* known to be r11 below */ + register int i; /* known to be r10 below */ + register int *jp; /* known to be r9 below */ + register int j; + static int pcsdone = 0; + int mid = mfpr(PR_SID); + char pcs[100]; + char *cp; + + if ((mid >> 24) != VAX_750 || ((mid >> 8) & 255) < 95 || pcsdone) + return; + printf("Updating 11/750 microcode: "); + for (cp = line; *cp; cp++) + if (*cp == ')' || *cp == ':') + break; + if (*cp) { + strncpy(pcs, line, 99); + pcs[99] = 0; + i = cp - line + 1; + } else + i = 0; + strcpy(pcs + i, "pcs750.bin"); + i = open(pcs, 0); + if (i < 0) { + printf("bad luck - missing pcs750.bin :-(\n"); + return; + } + /* + * We ask for more than we need to be sure we get only what we expect. + * After read: + * locs 0 - 1023 packed patchbits + * 1024 - 11264 packed microcode + */ + if (read(i, (char *)0, 23*512) != 22*512) { + printf("Error reading %s\n", pcs); + close(i); + return; + } + close(i); + + /* + * Enable patchbit loading and load the bits one at a time. + */ + *((int *)PCS_PATCHBIT) = 1; + ip = (int *)PCS_PATCHADDR; + jp = (int *)0; + for (i=0; i < PCS_BITCNT; i++) { + extzv(i,jp,ip,1); + } + *((int *)PCS_PATCHBIT) = 0; + + /* + * Load PCS microcode 20 bits at a time. + */ + ip = (int *)PCS_PCSADDR; + jp = (int *)1024; + for (i=j=0; j < PCS_MICRONUM * 4; i+=20, j++) { + extzv(i,jp,ip,20); + } + + /* + * Enable PCS. + */ + i = *jp; /* get 1st 20 bits of microcode again */ + i &= 0xfffff; + i |= PCS_ENABLE; /* reload these bits with PCS enable set */ + *((int *)PCS_PCSADDR) = i; + + mid = mfpr(PR_SID); + printf("new rev level=%d\n", V750UCODE(mid)); + pcsdone = 1; +} diff --git a/sys/arch/vax/boot/bootxx.c b/sys/arch/vax/boot/bootxx.c new file mode 100644 index 00000000000..b2f01417c95 --- /dev/null +++ b/sys/arch/vax/boot/bootxx.c @@ -0,0 +1,399 @@ +/* $NetBSD: bootxx.c,v 1.3 1995/09/16 13:01:06 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../mba/mbareg.h" +#include "../mba/hpreg.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "data.h" +#include "vaxstand.h" + +#include <a.out.h> + +int romstrategy(), romopen(); +int command(int, int); + +/* + * Boot program... argume passed in r10 and r11 determine whether boot + * stops to ask for system name and which device boot comes from. + */ + +volatile u_int devtype, bootdev; +unsigned opendev, boothowto, bootset; +int cpu_type, cpunumber; +unsigned *bootregs; +int is_750 = 0, is_mvax = 0, is_tmscp = 0; +struct rpb *rpb; + +main() +{ + int io; + char *hej = "/boot"; + + cpu_type = mfpr(PR_SID); + cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; + + switch (cpunumber) { + + case VAX_78032: + case VAX_650: + { + int cpu_sie; /* sid-extension */ + + is_mvax = 1; + cpu_sie = *((int *) 0x20040004) >> 24; + cpu_type |= cpu_sie; + rpb = bootregs[11]; + bootdev = rpb->devtyp; + + break; + } + case VAX_750: + is_750 = 1; + bootdev = bootregs[10]; + + break; + } + + bootset = getbootdev(); + + printf("\nhowto 0x%x, bdev 0x%x, booting...\n", boothowto, bootdev); + io = open(hej, 0); + + if (io >= 0 && io < SOPEN_MAX) { + copyunix(io); + } else { + printf("Boot failed. errno %d (%s)\n", errno, strerror(errno)); + } +} + +/* ARGSUSED */ +copyunix(aio) +{ + struct exec x; + register int io = aio, i; + char *addr; + + i = read(io, (char *) &x, sizeof(x)); + if (i != sizeof(x) || N_BADMAG(x)) { + printf("Bad format: errno %s\n", strerror(errno)); + return; + } + printf("%d", x.a_text); + if (N_GETMAGIC(x) == ZMAGIC && lseek(io, N_TXTADDR(x), SEEK_SET) == -1) + goto shread; + if (read(io, (char *) 0x10000, x.a_text) != x.a_text) + goto shread; + addr = (char *) x.a_text; + if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) + while ((int) addr & CLOFSET) + *addr++ = 0; + printf("+%d", x.a_data); + if (read(io, addr + 0x10000, x.a_data) != x.a_data) + goto shread; + addr += x.a_data; + bcopy((void *) 0x10000, 0, (int) addr); + printf("+%d", x.a_bss); + for (i = 0; i < x.a_bss; i++) + *addr++ = 0; + for (i = 0; i < 128 * 512; i++) /* slop */ + *addr++ = 0; + printf(" start 0x%x\n", x.a_entry); + hoppabort(x.a_entry, boothowto, bootset); + (*((int (*) ()) x.a_entry)) (); + return; +shread: + printf("Short read\n"); + return; +} + +getbootdev() +{ + int i, major, adaptor, controller, unit, partition; + + + switch (cpunumber) { + case VAX_78032: + case VAX_650: + adaptor = 0; + controller = ((rpb->csrphy & 017777) == 0xDC)?1:0; + unit = rpb->unit; /* DUC, DUD? */ + + break; + + case VAX_750: + controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */ + unit = bootregs[3]; + break; + } + + partition = 0; + + switch (bootdev) { + case 0: /* massbuss boot */ + major = 0; /* hp / ... */ + adaptor = (bootregs[1] & 0x6000) >> 17; + break; + + case 17: /* UDA50 boot */ + major = 9; /* ra / mscp */ + if (is_750) + adaptor = (bootregs[1] & 0x40000 ? 0 : 1); + break; + + case 18: /* TK50 boot */ + major = 15; /* tms / tmscp */ + is_tmscp = 1; /* use tape spec in mscp routines */ + break; + + default: + printf("Unsupported boot device %d, trying anyway.\n", bootdev); + boothowto |= (RB_SINGLE | RB_ASKNAME); + } + return MAKEBOOTDEV(major, adaptor, controller, unit, partition); +} + +struct devsw devsw[] = { + SADEV("rom", romstrategy,nullsys,nullsys, noioctl), +}; + +int ndevs = (sizeof(devsw) / sizeof(devsw[0])); + +struct fs_ops file_system[] = { + {ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat} +}; + +int nfsys = (sizeof(file_system) / sizeof(struct fs_ops)); + +struct disklabel lp; +int part_off = 0; /* offset into partition holding /boot */ +char io_buf[MAXBSIZE]; +volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; +volatile struct udadevice *csr; + +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + char *msg; + int i, err, off; + char line[64]; + + f->f_dev = &devsw[0]; + *file = fname; + + /* + * On uVAX we need to init [T]MSCP ctlr to be able to use it. + */ + if (is_mvax) { + switch (bootdev) { + case 17: /* MSCP */ + case 18: /* TMSCP */ + csr = (struct udadevice *)rpb->csrphy; + + csr->udaip = 0; /* Start init */ + while((csr->udasa & UDA_STEP1) == 0); + csr->udasa = 0x8000; + while((csr->udasa & UDA_STEP2) == 0); + csr->udasa = (short)(((u_int)&uda)&0xffff) + 8; + while((csr->udasa & UDA_STEP3) == 0); + csr->udasa = 0x10; + while((csr->udasa & UDA_STEP4) == 0); + csr->udasa = 0x0001; + + uda.uda_ca.ca_rspdsc = + (int) &uda.uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc = + (int) &uda.uda_cmd.mscp_cmdref; + if (is_tmscp) + uda.uda_cmd.mscp_vcid = 1; + command(M_OP_SETCTLRC, 0); + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_ONLINE, 0); + } + } + + /* + * the disklabel _shall_ be at address LABELOFFSET + RELOC in + * phys memory now, no need at all to reread it again. + * Actually disklabel is only needed when using hp disks, + * but it doesn't hurt to always get it. + */ + if (!is_tmscp) { + msg = getdisklabel(LABELOFFSET + RELOC, &lp); + if (msg) { + printf("getdisklabel: %s\n", msg); + } + } + return 0; +} + +command(cmd, arg) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_modifier = arg; + + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej = csr->udaip; + while (uda.uda_ca.ca_rspdsc < 0); + +} + +int curblock = 0; + +romstrategy(sc, func, dblk, size, buf, rsize) + void *sc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + int i; + int block = dblk; + int nsize = size; + + switch (cpunumber) { + + case VAX_650: + case VAX_78032: + switch (bootdev) { + + case 17: /* MSCP */ + uda.uda_cmd.mscp_seq.seq_lbn = dblk; + uda.uda_cmd.mscp_seq.seq_bytecount = size; + uda.uda_cmd.mscp_seq.seq_buffer = buf; + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_READ, 0); + break; + + case 18: /* TMSCP */ + if (dblk < curblock) { + uda.uda_cmd.mscp_seq.seq_bytecount = + curblock - dblk; + command(M_OP_POS, 12); + } else { + uda.uda_cmd.mscp_seq.seq_bytecount = + dblk - curblock; + command(M_OP_POS, 4); + } + curblock = size/512 + dblk; + for (i = 0 ; i < size/512 ; i++) { + uda.uda_cmd.mscp_seq.seq_lbn = 1; + uda.uda_cmd.mscp_seq.seq_bytecount = 512; + uda.uda_cmd.mscp_seq.seq_buffer = buf + i * 512; + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_READ, 0); + } + break; + + } + break; + + case VAX_750: + if (bootdev) { + while (size > 0) { + if ((read750(block, bootregs) & 0x01) == 0) + return 1; + + bcopy(0, buf, 512); + size -= 512; + buf += 512; + block++; + } + } else + hpread(block, size, buf); + break; + } + + *rsize = nsize; + return 0; +} + +hpread(block, size, buf) + char *buf; +{ + volatile struct mba_regs *mr = (void *) bootregs[1]; + volatile struct hp_drv *hd = (void*)&mr->mba_md[bootregs[3]]; + struct disklabel *dp = &lp; + u_int pfnum, nsize, mapnr, bn, cn, sn, tn; + + pfnum = (u_int) buf >> PGSHIFT; + + for (mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + mr->mba_map[mapnr++] = PG_V | pfnum++; + mr->mba_var = ((u_int) buf & PGOFSET); + mr->mba_bc = (~size) + 1; + bn = block; + cn = bn / dp->d_secpercyl; + sn = bn % dp->d_secpercyl; + tn = sn / dp->d_nsectors; + sn = sn % dp->d_nsectors; + hd->hp_dc = cn; + hd->hp_da = (tn << 8) | sn; + hd->hp_cs1 = HPCS_READ; + while (mr->mba_sr & MBASR_DTBUSY); + if (mr->mba_sr & MBACR_ABORT){ + return 1; + } + return 0; +} diff --git a/sys/arch/vax/boot/conf.c b/sys/arch/vax/boot/conf.c new file mode 100644 index 00000000000..15236d763df --- /dev/null +++ b/sys/arch/vax/boot/conf.c @@ -0,0 +1,72 @@ +/* $NetBSD: conf.c,v 1.4 1995/09/16 13:18:28 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#include "sys/param.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "vaxstand.h" + +int raopen(), rastrategy(); +int hpopen(), hpstrategy(); +int tmscpopen(), tmscpstrategy(); + +struct devsw devsw[]={ + SADEV("hp",hpstrategy, hpopen, nullsys, noioctl), + SADEV("ht",nullsys, nodev, nullsys, noioctl), + SADEV("up",nullsys, nodev, nullsys, noioctl), + SADEV("hk",nullsys, nodev, nullsys, noioctl), + SADEV( 0 ,nullsys, nodev, nullsys, noioctl), + SADEV("tm",nullsys, nodev, nullsys, noioctl), + SADEV("ts",nullsys, nodev, nullsys, noioctl), + SADEV("mt",nullsys, nodev, nullsys, noioctl), + SADEV("tu",nullsys, nodev, nullsys, noioctl), + SADEV("ra",rastrategy, raopen, nullsys, noioctl), + SADEV("ut",nullsys, nodev, nullsys, noioctl), + SADEV("id",nullsys, nodev, nullsys, noioctl), + SADEV("rx",nullsys, nodev, nullsys, noioctl), + SADEV("uu",nullsys, nodev, nullsys, noioctl), + SADEV("rl",nullsys, nodev, nullsys, noioctl), + SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl), + SADEV("kra",nullsys, nodev, nullsys, noioctl), +}; + +int ndevs = (sizeof(devsw)/sizeof(devsw[0])); + +struct fs_ops file_system[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat } +}; + +int nfsys = (sizeof(file_system) / sizeof(struct fs_ops)); + diff --git a/sys/arch/vax/boot/consio.c b/sys/arch/vax/boot/consio.c new file mode 100644 index 00000000000..39402cc1d44 --- /dev/null +++ b/sys/arch/vax/boot/consio.c @@ -0,0 +1,61 @@ +/* $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" + +#include "../vax/gencons.h" + +#include "../include/mtpr.h" + +putchar(ch) + int ch; +{ + while ((mfpr(PR_TXCS) & GC_RDY) == 0); /* Wait until xmit ready */ + mtpr(ch, PR_TXDB); /* xmit character */ + if (ch == 10) + putchar(13); /* CR/LF */ + +} + +getchar() +{ + int ch; + + do { + while ((mfpr(PR_RXCS) & GC_DON) == 0); /* wait for char */ + ch = mfpr(PR_RXDB); /* now get it */ + } while (ch == 17 || ch == 19); + return ch; +} diff --git a/sys/arch/vax/boot/copy.c b/sys/arch/vax/boot/copy.c new file mode 100644 index 00000000000..a67721d7458 --- /dev/null +++ b/sys/arch/vax/boot/copy.c @@ -0,0 +1,243 @@ +/* $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "lib/libsa/stand.h" + +#include <a.out.h> + +char line[100]; +volatile u_int devtype, bootdev; +extern unsigned opendev; + +static char *progname = "copy"; +static char *iobuf = NULL; +static char *bufp = NULL; +static int bufsize = 0; +static int partlist[8]; + +int fill_buffer (void); +int write_disk (void); + +main() +{ + int adapt, ctlr, unit, part; + int res, i, loops; + char line[64]; + + autoconf (); + + printf ("\n"); + printf ("%s: \n", progname); + printf ("This program will read miniroot from tape/floppy/disk \n"); + printf ("and install this miniroot onto disk.\n"); + printf ("\n"); + + res = fill_buffer (); + if (res < 0) { + printf ("errors occured during read. Continue at your own risk.\n"); + printf ("Do you want to continue ? [y/n] "); + gets (line); + if (*line != 'y' && *line != 'Y') { + printf ("bye.\n"); + return (-1); + } + } + + printf ("\n"); + res = write_disk (); + + printf ("\n"); + printf ("Halt/Reboot the machine NOW.\n"); + for (;;) + ; + /* NOTREACHED */ +} + +int +fill_buffer (void) +{ + char devname[64]; + int numblocks; + int blocksize = 512; + int bpv = 0; /* blocks per volume */ + int bpt = 8; /* blocks per transfer */ + struct open_file file; + char *filename; + int i, loops; + int size, rsize; + int res, errors = 0; + +again: + printf("\n"); + printf("Specify the device to read from as xx(N,?), where\n"); + printf("xx is the device-name, ? is file/partition number\n"); + printf("and N is the unit-number, e.g.\n"); + printf("\"tms(0,1)\" for the first TMSCP-tape (TK50),\n"); + printf("\"ra(2,0)\" for the third MSCP-disk/floppy (RX33/RX50)\n"); + printf("\n"); + printf("device to read from ? "); + gets(devname); + + printf("\n"); + printf("Specify number of blocks to transfer. Usually this is\n"); + printf("sizeof(miniroot) / 512.\n"); + printf("It's safe to transfer more blocks than just the miniroot.\n"); + printf("\n"); + while (1) { + printf ("number of blocks ? "); + gets (line); + if (atoi(line) > 0) { + if (iobuf && bufsize) + free (iobuf, bufsize); + numblocks = atoi (line); + bufsize = 512 * numblocks; + iobuf = alloc (bufsize); + bufp = iobuf; + if (iobuf == NULL) { + printf ("cannot allocate this much memory.\n"); + continue; + } + break; + } + printf ("invalid number %d.\n", atoi(line)); + } + + printf ("\n"); + printf ("If your miniroot is split into volumes, then you must\n"); + printf ("specify the number of blocks per volume.\n"); + printf ("(e.g. 800 blocks per RX50, 2400 blocks per RX33)\n"); + printf ("\n"); + while (1) { + printf ("number of blocks per volume ? [%d] ", numblocks); + gets (line); + if (!*line || atoi(line) > 0) { + bpv = (atoi(line) > 0 ? atoi(line) : numblocks); + break; + } + printf ("invalid number %d.\n", atoi(line)); + } + + printf ("\n"); + do { + printf ("Make sure unit %s is online and holds the proper volume.\n", devname); + printf ("Then type \'g\' to Go or \'a\' to Abort.\n"); + printf ("\n"); + printf ("OK to go on ? [g/a] "); + gets (line); + if (*line == 'g' || *line == 'G') { + printf ("Reading ... "); + if (devopen (&file, devname, &filename)) { + printf ("cannot open unit %s.\n", devname); + goto again; + } + loops = bpv / bpt + (bpv % bpt != 0); + for (i=0; i<loops; i++) { + twiddle (); + size = 512 * min (bpt, bpv - (i*bpt)); + res = (*file.f_dev->dv_strategy) + (file.f_devdata, F_READ, + (daddr_t)i*bpt, size, bufp, &rsize); + if (res != 0) { + printf ("error %d in read.\n", res); + errors++; + /* continue ? halt ??? */ + } + bufp += size; + } + numblocks -= bpv; + } + if (numblocks > 0) { + int vn = ((bufp - iobuf) / 512) / bpv; + printf ("\n"); + printf ("volume #%d done. Now insert volume #%d\n", + vn - 1, vn); + } + } while (numblocks > 0); + printf ("Reading of miniroot done. (%d blocks read)\n", + (bufp - iobuf) / 512); + + return (-errors); +} + +int +write_disk (void) +{ + char line[64]; + char devname[64]; + struct open_file file; + char *fname; + int rsize, res; + int i, errors = 0; + + printf ("\n"); + printf ("Now specify the device to write miniroot to as xx(N,1)\n"); + printf ("where xx is the drive type and N is the drive number.\n"); + printf ("For example: ra(0,1) refers to MSCP drive #0, b partition\n"); + printf ("\n"); + do { + printf ("Root disk ? : "); + gets (devname); + } while (devopen (&file, devname, &fname)); + + /* + * next: initialize the partition + */ + printf ("Initializing partition ... "); + bufp = iobuf + (16 * 512); + for (i=16; i<bufsize/512; i++) { + twiddle (); + res = (*file.f_dev->dv_strategy) (file.f_devdata, F_WRITE, + (daddr_t)i, 512, bufp, &rsize); + if (res != 0) { + errors++; + printf ("error writing block %d.\n"); + printf ("trying to continue ...\n"); + } + bufp += 512; + } + printf ("done.\n"); + printf ("(%d blocks written.)\n", bufsize/512); + + printf ("\n"); + printf ("Halt the machine and reboot from distribution media,\n"); + printf ("giving second partition as part to mount as root. Ex:\n"); + printf (": ra(0,1) for ra disk 0, hp(2,1) for massbuss disk 2\n"); + + return (-errors); +} + diff --git a/sys/arch/vax/boot/data.h b/sys/arch/vax/boot/data.h new file mode 100644 index 00000000000..d63b5496fbc --- /dev/null +++ b/sys/arch/vax/boot/data.h @@ -0,0 +1,74 @@ +/* $NetBSD: data.h,v 1.4 1995/09/16 15:58:57 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + + +extern unsigned *bootregs; + +/* + * rpb->iovec gives pointer to this structure. + * + * bqo->unit_init() is used to initialize the controller, + * bqo->qio() is used to read from boot-device + */ + +struct bqo { + long qio; /* 4 QIO entry */ + long map; /* 4 Mapping entry */ + long select; /* 4 Selection entry */ + long drivrname; /* 4 Offset to driver name */ + short version; /* 2 Version number of VMB */ + short vercheck; /* 2 Check field */ + /* offset: 20 */ + long reselect; /* 4 Reselection entry */ + long move; /* 4 Move driver entry */ + long unit_init; /* 4 Unit initialization entry */ + long auxdrname; /* 4 Offset to auxiliary driver name */ + long umr_dis; /* 4 UNIBUS Map Registers to disable */ + /* offset: 40 */ + long ucode; /* 4 Absolute address of booting microcode */ + long unit_disc; /* 4 Unit disconnecting entry */ + long devname; /* 4 Offset to boot device name */ + long umr_tmpl; /* 4 UNIBUS map register template */ + /* offset: 60 */ + /* + * the rest is unknown / unneccessary ... + */ + long xxx[6]; /* 24 -- total: 84 bytes */ +}; + +extern struct bqo *bqo; diff --git a/sys/arch/vax/boot/devopen.c b/sys/arch/vax/boot/devopen.c new file mode 100644 index 00000000000..6200f477f49 --- /dev/null +++ b/sys/arch/vax/boot/devopen.c @@ -0,0 +1,212 @@ +/* $NetBSD: devopen.c,v 1.3 1995/09/16 13:18:29 ragge Exp $ */ +/*- + * Copyright (c) 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/reboot.h> + +#include "lib/libsa/stand.h" +/* #include "samachdep.h" */ + +u_int opendev; + +#define ispart(c) ((c) >= 'a' && (c) <= 'h') + +int +atoi(cp) + char *cp; +{ + int val = 0; + while(isdigit(*cp)) + val = val * 10 + (*cp++ - '0'); + return(val); +} + +usage() +{ + printf("\ + Usage: device(adaptor, controller, drive, partition)file\n\ + <device><unit><partitonletter>:file\n\ + "); +} + +devlookup(d,len) + char *d; + int len; +{ + struct devsw *dp = devsw; + int i; + + for (i = 0; i < ndevs; i++, dp++) + if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) + return(i); + + printf("No such device - Configured devices are:\n"); + for (dp = devsw, i = 0; i < ndevs; i++, dp++) + if (dp->dv_name) + printf(" %s", dp->dv_name); + printf("\n"); + errno = ENODEV; + return(-1); +} + +/* + * Parse a device spec in one of two forms. + * + * dev(adapt, ctlr, unit, part)file + * [A-Za-z]*[0-9]*[A-Za-z]:file + * dev unit part + */ +devparse(fname, dev, adapt, ctlr, unit, part, file) + char *fname; + int *dev, *adapt, *ctlr, *unit, *part; + char **file; +{ + int *argp, i; + char *s, *args[4]; + + /* get device name and make lower case */ + for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++) + if(isupper(*s)) + *s = tolower(*s); + + /* first form */ + if(*s == '('){ + /* lookup device and get index */ + if ((*dev = devlookup(fname, s - fname)) < 0) + goto baddev; + + /* tokenize device ident */ + args[0] = ++s; + for (args[0] = s, i = 1; *s && *s != ')'; s++) + if (*s == ',') + args[i++] = ++s; + + + switch(i) { + case 4: + *adapt = atoi(args[0]); + *ctlr = atoi(args[1]); + *unit = atoi(args[2]); + *part = atoi(args[3]); + break; + case 3: + *ctlr = atoi(args[0]); + *unit = atoi(args[1]); + *part = atoi(args[2]); + break; + case 2: + *unit = atoi(args[0]); + *part = atoi(args[1]); + break; + case 1: + *part = atoi(args[0]); + break; + case 0: + break; + } + *file = ++s; + + /* second form */ + } else if (*s == ':') { + + /* isolate device */ + for(s = fname; *s != ':' && !isdigit(*s); s++) + ; + + /* lookup device and get index */ + if ((*dev = devlookup(fname, s - fname)) < 0) + goto baddev; + + /* isolate unit */ + if ((*unit = atoi(s)) > sizeof(char)) + goto bad; + for (; isdigit(*s); s++) + ; + + /* translate partition */ + if(!ispart(*s)) + goto bad; + + *part = *s++ - 'a'; + if(*s != ':') + goto bad; + *file = ++s; + + /* no device present */ + } else + *file = fname; + + /* return the remaining unparsed part as the file to boot */ + return(0); + +bad: + usage(); + + baddev: + return(-1); +} + +extern int bootdev; + +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + int n, error; + int dev, ctlr, unit, part; + int adapt = 0; /* XXX not used on HP */ + struct devsw *dp = &devsw[0]; + + dev = B_TYPE(bootdev); + ctlr = B_CONTROLLER(bootdev); + unit = B_UNIT(bootdev); + part = B_PARTITION(bootdev); + + if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) + return(error); + + dp = &devsw[dev]; + + if (!dp->dv_open) + return(ENODEV); + + opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part); + + f->f_dev = dp; + + if ((error = (*dp->dv_open)(f, adapt, ctlr, unit, part)) == 0) + return(0); + + printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name, + adapt, ctlr, unit, part, strerror(error)); + + return(error); +} diff --git a/sys/arch/vax/boot/edlabel.c b/sys/arch/vax/boot/edlabel.c new file mode 100644 index 00000000000..09844183bef --- /dev/null +++ b/sys/arch/vax/boot/edlabel.c @@ -0,0 +1,222 @@ +/* $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 at Ludd, University of + * Lule}, Sweden and its contributors. + * 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. + */ + +#define DKTYPENAMES + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "ufs/ffs/fs.h" + +struct disklabel dlabel; +char bootblock[8192]; + +void +showlabel() +{ + struct disklabel *lp; + struct partition *pp; + int i, j; + + lp = &dlabel; + + printf("\n\ndisk type %d (%s), %s: %s%s%s\n", lp->d_type, lp->d_type + <DKMAXTYPES?dktypenames[lp->d_type]:dktypenames[0], lp->d_typename, + lp->d_flags & D_REMOVABLE?" removable":"", lp->d_flags & D_ECC? + " ecc":"", lp->d_flags & D_BADSECT?" badsect":""); + + printf("interleave %d, rpm %d, trackskew %d, cylinderskew %d\n", + lp->d_interleave, lp->d_rpm, lp->d_trackskew, lp->d_cylskew); + printf("headswitch %d, track-to-track %d, drivedata: %d %d %d %d %d\n", + lp->d_headswitch, lp->d_trkseek, lp->d_drivedata[0], + lp->d_drivedata[1], lp->d_drivedata[2], lp->d_drivedata[3], + lp->d_drivedata[4]); + + printf("\nbytes/sector: %d\n", lp->d_secsize); + printf("sectors/track: %d\n", lp->d_nsectors); + printf("tracks/cylinder: %d\n", lp->d_ntracks); + printf("sectors/cylinder: %d\n", lp->d_secpercyl); + printf("cylinders: %d\n", lp->d_ncylinders); + + printf("\n%d partitions:\n", lp->d_npartitions); + printf(" size offset\n"); + pp = lp->d_partitions; + for (i = 0; i < lp->d_npartitions; i++) { + printf("%c: %d, %d\n", 97 + i, lp->d_partitions[i].p_size, + lp->d_partitions[i].p_offset); + } + printf("\n"); +} + +setdefaultlabel() +{ + printf("Sorry, not implemented yet. Later...\n\n"); +} + +#define GETNUM(out, num) printf(out, num);gets(store); \ + if (*store) num = atoi(store); +#define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \ + if (*store) num = atoi(store); +#define GETSTR(out, str) printf(out, str);gets(store); \ + if (*store) strcpy(str, store); +#define FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \ + if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \ + else lp->d_flags &= ~flag; + +editlabel() +{ + struct disklabel *lp; + char store[256]; + int i; + + lp = &dlabel; + printf("\nFirst set disk type. Valid types are:\n"); + for (i = 0; i < DKMAXTYPES; i++) + printf("%d %s\n", i, dktypenames[i]); + + GETNUM("\nNumeric disk type? [%d] ", lp->d_type); + GETSTR("Disk name? [%s] ", lp->d_typename); + FLAGS("badsectoring? [%c] ", D_BADSECT); + FLAGS("ecc? [%c] ", D_ECC); + FLAGS("removable? [%c] ", D_REMOVABLE); + + GETNUM("Interleave? [%d] ", lp->d_interleave); + GETNUM("rpm? [%d] ", lp->d_rpm); + GETNUM("trackskew? [%d] ", lp->d_trackskew); + GETNUM("cylinderskew? [%d] ", lp->d_cylskew); + GETNUM("headswitch? [%d] ", lp->d_headswitch); + GETNUM("track-to-track? [%d] ", lp->d_trkseek); + GETNUM("drivedata 0? [%d] ", lp->d_drivedata[0]); + GETNUM("drivedata 1? [%d] ", lp->d_drivedata[1]); + GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]); + GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]); + GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]); + GETNUM("\nbytes/sector? [%d] ", lp->d_secsize); + GETNUM("sectors/track? [%d] ", lp->d_nsectors); + GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks); + GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl); + GETNUM("cylinders? [%d] ", lp->d_ncylinders); + lp->d_npartitions = MAXPARTITIONS; + for (i = 0; i < 8; i++) { + GETNUM2("%c partition: offset? [%d] ", 97 + i, + lp->d_partitions[i].p_offset); + GETNUM(" size? [%d] ", lp->d_partitions[i].p_size); + } +} + +int bootdev; + +void +main() +{ + register bdev asm("r10"); + + struct open_file file; + char diskname[64], *msg, *filename, indata[64]; + int i, rsize; + + bootdev = bdev; + printf("With this program you can modify everything in the on-disk\n"); + printf("disklabel. To do something useful you must know the exact\n"); + printf("geometry of your disk, and have ideas about how you want\n"); + printf("your partitions to be placed on disk. Some hints:\n"); + printf("The a partition should be at least ~20000 blocks, the\n"); + printf("b (swap) is depending on your use of the machine but it\n"); + printf("should almost never be less than ~32000 blocks.\n\n"); + printf("Disk geometry for most DEC disks can be found in the disktab"); + printf("\nfile, and disknames is listed in the installation notes.\n"); + printf("\nRemember that disk names is given as disk(adapt, ctrl, "); + printf("disk, part)\nwhen using the installation tools.\n\n"); + + autoconf(); +igen: + printf("Label which disk? "); + gets(diskname); + if (*diskname == 0) goto igen; + if (devopen(&file, diskname, &filename)) { + printf("cannot open %s\n", diskname); + goto igen; + } + if ((*file.f_dev->dv_strategy)(file.f_devdata, F_READ, + (daddr_t)0, 8192, bootblock, &rsize)) { + printf("cannot read label block\n"); + goto igen; + } + if (msg = (char *) getdisklabel(LABELOFFSET + bootblock, &dlabel)) + printf("%s: %s\n", diskname, msg); + + do { + printf("(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : "); + gets(indata); + switch (*indata) { + case ('e'): + case ('E'): + editlabel(); + break; + case ('s'): + case ('S'): + showlabel(); + break; + case ('d'): + case ('D'): + setdefaultlabel(); + break; + case ('w'): + case ('W'): + dlabel.d_magic = DISKMAGIC; + dlabel.d_magic2 = DISKMAGIC; + dlabel.d_bbsize = BBSIZE; + dlabel.d_sbsize = SBSIZE; + dlabel.d_checksum = 0; + dlabel.d_checksum = dkcksum(&dlabel); + bcopy(&dlabel, LABELOFFSET + bootblock, + sizeof(struct disklabel)); + if ((*file.f_dev->dv_strategy)(file.f_devdata, F_WRITE, + (daddr_t)0, 8192, bootblock, &rsize)) { + printf("cannot write label sectors.\n"); + break; + } + printf("\nThis program does not (yet) write"); + printf(" bootblocks, only disklabel.\n"); + printf("Remember to write the bootblocks from the "); + printf("miniroot later with the\ncommand "); + printf("\"disklabel -B <diskname>\".\n\n"); + break; + case ('q'): + case ('Q'): + default: + break; + } + } while (*indata != 'q' && *indata != 'Q'); + goto igen; +} diff --git a/sys/arch/vax/boot/hp.c b/sys/arch/vax/boot/hp.c new file mode 100644 index 00000000000..c7019a3527d --- /dev/null +++ b/sys/arch/vax/boot/hp.c @@ -0,0 +1,165 @@ +/* $NetBSD: hp.c,v 1.4 1995/09/16 15:43:25 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../mba/mbareg.h" +#include "../mba/hpreg.h" + +#include "../include/pte.h" +#include "../include/macros.h" + +#include "vaxstand.h" + +/* + * These routines for HP disk standalone boot is wery simple, + * assuming a lots of thing like that we only working at one hp disk + * a time, no separate routines for mba driver etc.. + * But it works :) + */ + +struct hp_softc { + int adapt; + int ctlr; + int unit; + int part; +}; + +struct disklabel hplabel; +struct hp_softc hp_softc; +char io_buf[MAXBSIZE]; +daddr_t part_offset; + +hpopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + struct disklabel *lp; + struct hp_softc *hs; + volatile struct mba_regs *mr; + volatile struct hp_drv *hd; + char *msg; + int i,err; + + lp = &hplabel; + hs = &hp_softc; + mr = (void *)mbaaddr[ctlr]; + hd = (void *)&mr->mba_md[unit]; + + if (adapt > nsbi) return(EADAPT); + if (ctlr > nmba) return(ECTLR); + if (unit > MAXMBAU) return(EUNIT); + + bzero(lp, sizeof(struct disklabel)); + + lp->d_secpercyl = 32; + lp->d_nsectors = 32; + hs->adapt = adapt; + hs->ctlr = ctlr; + hs->unit = unit; + hs->part = part; + + /* Set volume valid and 16 bit format; only done once */ + mr->mba_cr = MBACR_INIT; + hd->hp_cs1 = HPCS_PA; + hd->hp_of = HPOF_FMT; + + err = hpstrategy(hs, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n", strerror(err)); + return 0; + } + + msg = getdisklabel(io_buf + LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + + f->f_devdata = (void *)hs; + return 0; +} + +hpstrategy(hs, func, dblk, size, buf, rsize) + struct hp_softc *hs; + daddr_t dblk; + u_int size, *rsize; + char *buf; + int func; +{ + volatile struct mba_regs *mr; + volatile struct hp_drv *hd; + struct disklabel *lp; + unsigned int i, pfnum, mapnr, nsize, bn, cn, sn, tn; + + mr = (void *)mbaaddr[hs->ctlr]; + hd = (void *)&mr->mba_md[hs->unit]; + lp = &hplabel; + + pfnum = (u_int)buf >> PGSHIFT; + + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + mr->mba_map[mapnr++] = PG_V | pfnum++; + + mr->mba_var = ((u_int)buf & PGOFSET); + mr->mba_bc = (~size) + 1; + bn = dblk + lp->d_partitions[hs->part].p_offset; + + if (bn) { + cn = bn / lp->d_secpercyl; + sn = bn % lp->d_secpercyl; + tn = sn / lp->d_nsectors; + sn = sn % lp->d_nsectors; + } else + cn = sn = tn = 0; + + hd->hp_dc = cn; + hd->hp_da = (tn << 8) | sn; + if (func == F_WRITE) + hd->hp_cs1 = HPCS_WRITE; + else + hd->hp_cs1 = HPCS_READ; + + while (mr->mba_sr & MBASR_DTBUSY) + ; + + if (mr->mba_sr & MBACR_ABORT) + return 1; + + *rsize = size; + + return 0; +} diff --git a/sys/arch/vax/boot/init.c b/sys/arch/vax/boot/init.c new file mode 100644 index 00000000000..94c7ad6276a --- /dev/null +++ b/sys/arch/vax/boot/init.c @@ -0,0 +1,82 @@ +/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * 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}, Sweden and its contributors. 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 */ + + + +#include "lib/libsa/stand.h" + +#include "../include/mtpr.h" /* mfpr(), mtpr() */ +#include "../include/sid.h" /* cpu_type, cpu_number */ + +#define NRSP 0 /* Kludge, must be done before udareg.h */ +#define NCMD 0 /* includes */ + +#include "../uba/udareg.h" /* struct udadevice */ + +#include "data.h" /* bootregs[], rpb, bqo */ + +struct rpb *rpb; +struct bqo *bqo; + +int is_750 = 0, is_mvax = 0; + +/* + * initdata() sets up data gotten from start routines, mostly for uVAX. + */ +int +initdata() +{ + int i, *tmp; + + cpu_type = mfpr(PR_SID); + cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; + + switch (cpunumber) { + + case VAX_78032: + case VAX_650: + { + int cpu_sie; /* sid-extension */ + + is_mvax = 1; + cpu_sie = *((int *) 0x20040004) >> 24; + cpu_type |= cpu_sie; + + break; + } + case VAX_750: + is_750 = 1; + break; + } + return 0; +} diff --git a/sys/arch/vax/boot/ra.c b/sys/arch/vax/boot/ra.c new file mode 100644 index 00000000000..a0ecefc1a1b --- /dev/null +++ b/sys/arch/vax/boot/ra.c @@ -0,0 +1,186 @@ +/* $NetBSD: ra.c,v 1.3 1995/09/16 13:34:22 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../include/pte.h" +#include "../include/macros.h" +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "vaxstand.h" + +static command(int); + +/* + * These routines for RA disk standalone boot is wery simple, + * assuming a lots of thing like that we only working at one ra disk + * a time, no separate routines for uba driver etc.. + * This code is foolish and should need a cleanup. + * But it works :) + */ + +struct ra_softc { + int udaddr; + int ubaddr; + int part; + int unit; +}; + +volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; + +volatile struct uda *ubauda; +volatile struct udadevice *udacsr; +struct disklabel ralabel; +struct ra_softc ra_softc; +char io_buf[MAXBSIZE]; + +raopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp=&ralabel; + volatile struct ra_softc *ra=&ra_softc; + volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + volatile u_int *nisse; + unsigned short johan; + int i,err; + + if(adapt>nuba) return(EADAPT); + if(ctlr>nuda) return(ECTLR); + bzero(lp, sizeof(struct disklabel)); + ra->udaddr=uioaddr[adapt]+udaaddr[ctlr]; + ra->ubaddr=(int)mr; + ra->unit=unit; + ra->part = part; + udacsr=(void*)ra->udaddr; + nisse=&mr->uba_map[0]; + nisse[494]=PG_V|(((u_int)&uda)>>9); + nisse[495]=nisse[494]+1; + ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + /* Init of this uda */ + udacsr->udaip=0; /* Start init */ + while((udacsr->udasa&UDA_STEP1) == 0); + udacsr->udasa=0x8000; + while((udacsr->udasa&UDA_STEP2) == 0); + johan=(((u_int)ubauda)&0xffff)+8; + udacsr->udasa=johan; + while((udacsr->udasa&UDA_STEP3) == 0); + udacsr->udasa=3; + while((udacsr->udasa&UDA_STEP4) == 0); + udacsr->udasa=0x0001; + uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + command(M_OP_SETCTLRC); + uda.uda_cmd.mscp_unit=ra->unit; + command(M_OP_ONLINE); + + err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if(err){ + printf("reading disklabel: %s\n",strerror(err)); + return 0; + } + + msg=getdisklabel(io_buf+LABELOFFSET, lp); + if(msg) { + printf("getdisklabel: %s\n",msg); + } + f->f_devdata=(void *)ra; + return(0); +} + +static +command(cmd) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode=cmd; + uda.uda_cmd.mscp_msglen=MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen=MSCP_MSGLEN; + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej=udacsr->udaip; + while(uda.uda_ca.ca_rspdsc<0); + +} + +rastrategy(ra, func, dblk, size, buf, rsize) + struct ra_softc *ra; + int func; + daddr_t dblk; + char *buf; + u_int size, *rsize; +{ + volatile struct uba_regs *ur; + volatile struct udadevice *udadev; + volatile u_int *ptmapp; + struct disklabel *lp; + u_int i, j, pfnum, mapnr, nsize; + volatile int hej; + + + ur = (void *)ra->ubaddr; + udadev = (void*)ra->udaddr; + ptmapp = &ur->uba_map[0]; + lp = &ralabel; + + pfnum = (u_int)buf >> PGSHIFT; + + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + ptmapp[mapnr++] = PG_V | pfnum++; + + uda.uda_cmd.mscp_seq.seq_lbn = + dblk + lp->d_partitions[ra->part].p_offset; + uda.uda_cmd.mscp_seq.seq_bytecount = size; + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; + uda.uda_cmd.mscp_unit = ra->unit; + if (func == F_WRITE) + command(M_OP_WRITE); + else + command(M_OP_READ); + + *rsize = size; + return 0; +} diff --git a/sys/arch/vax/boot/romread.s b/sys/arch/vax/boot/romread.s new file mode 100644 index 00000000000..966280792fb --- /dev/null +++ b/sys/arch/vax/boot/romread.s @@ -0,0 +1,89 @@ +/* $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + + +#include "../include/asm.h" + +/* + * read630 (int block, int *regs) + */ +ENTRY(read630, 0xFFE) + pushl $0 # base of rpb + pushl $0 # virtual-flag + pushl $33 # read-logical-block + pushl 12(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 4(ap) # buffer-address + calls $6, (r6) # call the qio-routine + halt + ret # r0 holds the result + +/* + * read750 (int block, int *regs) + */ +ENTRY(read750, 0xFFE) + movl 8(ap), r8 + movl 4(r8), r1 + movl 8(r8), r2 + movl 12(r8), r3 + movl 24(r8), r6 + clrl r5 + movl 4(ap), r8 + pushl $0 + movl $0, 4(sp) + movl fp, 0xf0000 # ragge ??? + jsb (r6) + movl 0xf0000, fp + ret + +/* + * bulkread630 (int lbn, int size, void *buf, int *regs) + */ +ENTRY(bulkread630, 0xFFE) + movl 16(ap), r11 # array of bootregs + movl 44(r11), r11 # restore boot-contents of r11 (rpb) + movl 52(r11), r7 # load iovec/bqo into r7 + addl3 (r7), r7, r6 # load qio into r6 + pushl r11 # base of rpb + pushl $0 # virtual-flag + pushl $33 # read-logical-block + pushl 4(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 12(ap) # buffer-address + calls $6, (r6) # call the qio-routine + ret # r0 holds the result diff --git a/sys/arch/vax/boot/srt0.s b/sys/arch/vax/boot/srt0.s new file mode 100644 index 00000000000..a85d02538ba --- /dev/null +++ b/sys/arch/vax/boot/srt0.s @@ -0,0 +1,70 @@ +/* $NetBSD: srt0.s,v 1.4 1995/09/16 16:20:20 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +/* + * Auto-moving startup code for standalone programs. Can be loaded + * (almost) anywhere in memory but moves itself to the position + * it is linked for. Must be started at first position, recommended + * is phys addr 0 (boot loads programs at 0, but starts them at the + * position set in a.out header. + */ + +nisse: .set nisse,0 # pass -e nisse to ld gives OK start addr + .globl nisse + +_start: .globl _start + nop;nop; # If we get called by calls, or something + movl $_start, sp # Probably safe place for stack + subl2 $52, sp # do not overwrite saved boot-registers + + subl3 $_start, $_end, r0 + moval _start, r1 + movl $_start, r2 + movc3 r0, (r1), (r2) # should use movc5 instead, to clear bss. + + jsb 1f +1: movl $relocated, (sp) # return-address on top of stack + rsb # can be replaced with new address +relocated: # now relocation is done !!! + calls $0,_main # Were here! + halt # no return + + + .globl _hoppabort +_hoppabort: .word 0x0 + movl 4(ap), r6 + movl 8(ap), r11 + movl 0xc(ap), r10 + movl 16(ap), r9 + calls $0,(r6) diff --git a/sys/arch/vax/boot/start.s b/sys/arch/vax/boot/start.s new file mode 100644 index 00000000000..45a9c56169d --- /dev/null +++ b/sys/arch/vax/boot/start.s @@ -0,0 +1,188 @@ +/* $NetBSD: start.s,v 1.4 1995/09/16 16:20:21 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + +#define LOCORE +#include "sys/disklabel.h" +#undef LOCORE + +#define ASSEMBLER +#include "../include/mtpr.h" +#include "../include/asm.h" +#include "bootdefs.h" + +_start: .globl _start # this is the symbolic name for the start + # of code to be relocated. We can use this + # to get the actual/real adress (pc-rel) + # or to get the relocated address (abs). + +.org 0x00 # uVAX booted from TK50 starts here + brb from_0x00 # continue behind dispatch-block + +.org 0x02 # information used by uVAX-ROM + .byte (LABELOFFSET + d_end_)/2 # offset in words to identification area + .byte 1 # this byte must be 1 + .word 0 # logical block number (word swapped) + .word 0 # of the secondary image + +.org 0x08 # + brb from_0x08 # skip ... + +.org 0x0A # uVAX booted from disk starts here + brb from_0x0A # skip ... + +.org 0x0C # 11/750 & 8200 starts here + brw cont_750 + + +from_0x00: # uVAX from TK50 +from_0x0A: # uVAX from disk + brw start_uvax # all(?) uVAXen continue there + +from_0x08: # What comes here??? + halt + +.org LABELOFFSET - 6 +regmask: .word 0x0fff # using a variable saves 3 bytes !!! +bootinfo: .long 0x0 # another 3 bytes if within byte-offset + +# the complete area reserved for label +# must be empty (i.e. filled with zeroes). +# disklabel(8) checks that before installing +# the bootblocks over existing label. + +/* + * Parameter block for uVAX boot. + */ +#define VOLINFO 0 /* 1=single-sided 81=double-sided volumes */ +#define SISIZE 16 /* size in blocks of secondary image */ +#define SILOAD 0 /* load offset (usually 0) from the default */ +#define SIOFF 0x0A /* byte offset into secondary image */ + +.org LABELOFFSET + d_end_ + .byte 0x18 # must be 0x18 + .byte 0x00 # must be 0x00 (MBZ) + .byte 0x00 # any value + .byte 0xFF - (0x18 + 0x00 + 0x00) + /* 4th byte holds 1s' complement of sum of previous 3 bytes */ + + .byte 0x00 # must be 0x00 (MBZ) + .byte VOLINFO + .byte 0x00 # any value + .byte 0x00 # any value + + .long SISIZE # size in blocks of secondary image + .long SILOAD # load offset (usually 0) + .long SIOFF # byte offset into secondary image + .long (SISIZE + SILOAD + SIOFF) # sum of previous 3 + +/* + * After bootblock (LBN0) has been loaded into the first page + * of good memory by 11/750's ROM-code (transfer address + * of bootblock-code is: base of good memory + 0x0C) registers + * are initialized as: + * R0: type of boot-device + * 0: Massbus device + * 1: RK06/RK07 + * 2: RL02 + * 17: UDA50 + * 35: TK50 + * 64: TU58 + * R1: (UBA) address of UNIBUS I/O-page + * (MBA) address of boot device's adapter + * R2: (UBA) address of the boot device's CSR + * (MBA) controller number of boot device + * R6: address of driver subroutine in ROM + * + * cont_750 reads in LBN1-15 for further execution. + */ + .align 2 +cont_750: + movl r0,r10 + movl r5, ap # ap not used here + clrl r5 + clrl r4 + movl $_start,sp +1: incl r4 + movl r4,r8 + addl2 $0x200,r5 + cmpl $16,r4 + beql 2f + pushl r5 + jsb (r6) + blbs r0,1b +2: movl r10, r0 + movl r11, r5 + brw start_all + + +start_uvax: + mtpr $0, $PR_MAPEN # Turn off MM, please. + movl $_start, sp + movl 48(r11), ap + brb start_all + +/* + * start_all: stack already at RELOC, we save registers, move ourself + * to RELOC and loads boot. + */ +start_all: + pushr $0xfff # save all regs, used later. + + subl3 $_start, $_edata, r0 # get size of text+data (w/o bss) + moval _start, r1 # get actual base-address of code + subl3 $_start, $_end, r2 # get complete size (incl. bss) + movl $_start, r3 # get relocated base-address of code + movc5 r0, (r1), $0, r2, (r3) # copy code to new location + + movl $relocated, -(sp) # return-address on top of stack + rsb # can be replaced with new address +relocated: # now relocation is done !!! + movl sp, _bootregs + movl ap, _boothowto + calls $0, _main # call main() which is + halt # not intended to return ... + +/* + * hoppabort() is called when jumping to the newly loaded program. + */ +ENTRY(hoppabort, 0) + movl 4(ap),r6 + movl 8(ap),r11 + movl 0xc(ap),r10 + calls $0,(r6) + halt diff --git a/sys/arch/vax/boot/tmscp.c b/sys/arch/vax/boot/tmscp.c new file mode 100644 index 00000000000..eb143e61426 --- /dev/null +++ b/sys/arch/vax/boot/tmscp.c @@ -0,0 +1,202 @@ +/* $NetBSD: tmscp.c,v 1.1 1995/09/16 12:57:35 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../include/pte.h" +#include "../include/macros.h" +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "vaxstand.h" + +static command(int,int); + +/* + * These routines for TMSCP tape standalone boot is very simple, + * assuming a lots of thing like that we only working at one tape at + * a time, no separate routines for uba driver etc.. + * This code is directly copied from ra disk driver. + */ + +struct ra_softc { + int udaddr; + int ubaddr; + int unit; +}; + +static volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; + +static volatile struct uda *ubauda; +static volatile struct udadevice *udacsr; +static struct ra_softc ra_softc; +static char io_buf[MAXBSIZE]; + +tmscpopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + extern u_int tmsaddr; + volatile struct ra_softc *ra=&ra_softc; + volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + volatile u_int *nisse; + unsigned short johan; + int i,err; + + if(adapt>nuba) return(EADAPT); + if(ctlr>nuda) return(ECTLR); + ra->udaddr=uioaddr[adapt]+tmsaddr; + ra->ubaddr=(int)mr; + ra->unit=unit; + udacsr=(void*)ra->udaddr; + nisse=&mr->uba_map[0]; + nisse[494]=PG_V|(((u_int)&uda)>>9); + nisse[495]=nisse[494]+1; + ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + + /* + * Init of this tmscp ctlr. + */ + udacsr->udaip=0; /* Start init */ + while((udacsr->udasa&UDA_STEP1) == 0); + udacsr->udasa=0x8000; + while((udacsr->udasa&UDA_STEP2) == 0); + johan=(((u_int)ubauda)&0xffff)+8; + udacsr->udasa=johan; + while((udacsr->udasa&UDA_STEP3) == 0); + udacsr->udasa=3; + while((udacsr->udasa&UDA_STEP4) == 0); + udacsr->udasa=0x0001; + + uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + uda.uda_cmd.mscp_un.un_seq.seq_addr = &uda.uda_ca.ca_cmddsc; + uda.uda_rsp.mscp_un.un_seq.seq_addr = &uda.uda_ca.ca_rspdsc; + uda.uda_cmd.mscp_vcid = 1; + uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0; + + command(M_OP_SETCTLRC, 0); + uda.uda_cmd.mscp_unit=ra->unit; + command(M_OP_ONLINE, 0); + + if (part) { + uda.uda_cmd.mscp_un.un_seq.seq_buffer = part; + command(M_OP_POS, 0); + uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0; + } + + f->f_devdata=(void *)ra; + return(0); +} + +static +command(cmd, arg) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_modifier = arg; + + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; + + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej = udacsr->udaip; + while (uda.uda_ca.ca_rspdsc < 0) { + if (uda.uda_ca.ca_cmdint) + uda.uda_ca.ca_cmdint = 0; + } + +} + +static int curblock = 0; + +tmscpstrategy(ra, func, dblk, size, buf, rsize) + struct ra_softc *ra; + int func; + daddr_t dblk; + char *buf; + u_int size, *rsize; +{ + u_int i,j,pfnum, mapnr, nsize, bn, cn, sn, tn; + volatile struct uba_regs *ur=(void *)ra->ubaddr; + volatile struct udadevice *udadev=(void*)ra->udaddr; + volatile u_int *ptmapp=&ur->uba_map[0]; + volatile int hej; + + pfnum=(u_int)buf>>PGSHIFT; + + for(mapnr=0, nsize=size;(nsize+NBPG)>0;nsize-=NBPG) + ptmapp[mapnr++]=PG_V|pfnum++; + + /* + * First position tape. Remember where we are. + */ + if (dblk < curblock) { + uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; + command(M_OP_POS, 12); /* 12 == step block backward */ + } else { + uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock; + command(M_OP_POS, 4); /* 4 == step block forward */ + } + curblock = size/512 + dblk; + + /* + * Read in the number of blocks we need. + * Why doesn't read of multiple blocks work????? + */ + for (i = 0 ; i < size/512 ; i++) { + uda.uda_cmd.mscp_seq.seq_lbn = 1; + uda.uda_cmd.mscp_seq.seq_bytecount = 512; + uda.uda_cmd.mscp_seq.seq_buffer = + (((u_int)buf) & 0x1ff) + i * 512; + uda.uda_cmd.mscp_unit = ra->unit; + command(M_OP_READ, 0); + } + + *rsize=size; + return 0; +} diff --git a/sys/arch/vax/boot/vaxstand.h b/sys/arch/vax/boot/vaxstand.h new file mode 100644 index 00000000000..17ec1cbcd03 --- /dev/null +++ b/sys/arch/vax/boot/vaxstand.h @@ -0,0 +1,52 @@ +/* $NetBSD: vaxstand.h,v 1.3 1995/04/25 14:14:34 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#define MAXNMBA 8 /* Massbussadapters */ +#define MAXNUBA 8 /* Unibusadapters */ +#define MAXNBI 4 /* Bi-bussadapters */ +#define MAXMBAU 8 /* Units on an mba */ +#define MAXBIN 16 /* Bi-nodes */ + +/* Variables used in autoconf */ +extern int nmba, nuba, nbi, nsbi, nuda; +extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; + +/* devsw type definitions, used in bootxx and conf */ +#define SADEV(name,strategy,open,close,ioctl) \ + { name, \ + (int(*)(void *, int ,daddr_t , u_int , char *, u_int *))strategy, \ + (int(*)(struct open_file *, ...))open, \ + (int(*)(struct open_file *))close, \ + (int(*)(struct open_file *,u_long, void *))ioctl} + diff --git a/sys/arch/vax/compile/.keep_me b/sys/arch/vax/compile/.keep_me new file mode 100644 index 00000000000..e018447add3 --- /dev/null +++ b/sys/arch/vax/compile/.keep_me @@ -0,0 +1,3 @@ +$NetBSD: .keep_me,v 1.3 1994/10/26 08:06:10 cgd Exp $ + +This normally empty directory needs to be kept in the distribution. diff --git a/sys/arch/vax/conf/EVERYTHING b/sys/arch/vax/conf/EVERYTHING new file mode 100644 index 00000000000..97703691c5c --- /dev/null +++ b/sys/arch/vax/conf/EVERYTHING @@ -0,0 +1,92 @@ +# $NetBSD: EVERYTHING,v 1.1 1995/03/29 22:54:02 ragge Exp $ +# +# This file contains everything that is known to be compiled +# without errors. Some things may not be tested, like NETISO. +# + +include "std.vax" + +# Here are all different supported CPU types listed. +options "VAX750" +options "VAX630" + +# Kernel identification +options EVERYTHING + +# Max users on system; this is just a hint +maxusers 16 + +# Paging system, we always have them all. +options SWAPPAGER, DEVPAGER, VNODEPAGER + +# Kernel compiled-in symbolic debugger +#options DDB + +# System V shared memory +options SYSVMSG # Message passing +options SYSVSEM # Semaphores +options SYSVSHM # Shared memory +options SHMMAXPGS=1024 + +# Network support +options INET # Internet protocol, (almost) mandatory +options ETHER # Ethernet, probably needed +options NS # Xerox Network system, untested +options ISO,TPIP # ISO network, untested +options EON +options CCITT,LLC,HDLC + +# All supported filesystem types +options FFS,QUOTA # Normal fast filesystem, mandatory +options LFS # Log-structured file system +options MFS # Memory filesystem +options NFSCLIENT # Network filesystem client +options NFSSERVER # Network filesystem server +options CD9660 # CDRom filesystem +options FDESC # Filedescriptors, /dev/fd +options FIFO +options KERNFS # Kernel info filesystems +options NULLFS +options PORTAL +options PROCFS # Process filesystem +options UMAPFS +options UNION + +# Old compat stuff; needed to run 4.3BSD Reno programs +options COMPAT_43 +options COMPAT_09 +options COMPAT_10 +options COMPAT_RENO +options TCP_COMPAT_42 # Bug compat with 4.2BSD systems (like NDIX) + +# loadable kernel modules. +options LKM + + +# Kernel(s) to compile +config vmunix root on hp0 swap on hp0 + +# All supported CPU:s +cpu0 at backplane0 + +# Main buses at backplane +sbi* at backplane0 + +# Devices connected at sbi +mem* at sbi? tr? # Memory subsystems +uba0 at sbi? tr? # Unibus adapters + +# Disk controllers at Unibus +uda0 at uba? csr 0172150 # UDA50/KDA50/RQDX3 +ra0 at uda0 drive 0 # RA??/RD?? + +# Ethernet cards +de0 at uba? csr 0174510 # DEUNA/DELUA +qe0 at uba? csr 0174440 # DEQNA/DELQA + +# Tape drivers +tmscp0 at uba? csr 0174500 +tms0 at tmscp0 drive ? # TK50/TU81 + +pseudo-device loop +pseudo-device pty 48 diff --git a/sys/arch/vax/conf/GENERIC b/sys/arch/vax/conf/GENERIC new file mode 100644 index 00000000000..b187a85c1e8 --- /dev/null +++ b/sys/arch/vax/conf/GENERIC @@ -0,0 +1,103 @@ +# $NetBSD: GENERIC,v 1.7.2.1 1995/10/15 13:52:58 ragge Exp $ +# +# GENERIC VAX, currently only supports 11/750 anyway. +# + +include "std.vax" + +# Here are all different supported CPU types listed. +options "VAX750" +options "VAX630" + +# Kernel identification +options GENERIC + +# Max users on system; this is just a hint +maxusers 16 + +# Paging system, we always have them all. +options SWAPPAGER, DEVPAGER, VNODEPAGER + +# Kernel compiled-in symbolic debugger & system call tracer +#options DDB +options KTRACE + +# Network support +#options GATEWAY +options INET +options ETHER + +# All supported filesystem types +options FFS,QUOTA +options LFS +options MFS +options NFSSERVER +options NFSCLIENT +options FDESC +options FIFO +options KERNFS +options NULLFS +options PROCFS +options UMAPFS +options UNION + +# System V shared memory & semaphores support. +options SYSVMSG +options SYSVSEM +options SYSVSHM + +# Old compat stuff; needed to run 4.3BSD Reno programs +options COMPAT_43 +options COMPAT_09 +options COMPAT_10 +options COMPAT_RENO +options TCP_COMPAT_42 + +options LKM + + +# Kernel(s) to compile +config netbsd swap generic + +# All supported CPU:s +cpu0 at backplane0 + +# Main buses at backplane +sbi* at backplane0 + +# Devices connected at sbi +mem* at sbi? tr? # Memory subsystems +uba0 at sbi? tr? # Unibus adapters +uba1 at sbi? tr? # Unibus adapters +uba2 at sbi? tr? # Unibus adapters +uba3 at sbi? tr? # Unibus adapters + +# Disk controllers at Unibus +uda0 at uba? csr 0172150 +ra0 at uda0 drive 0 +ra1 at uda0 drive 1 +ra2 at uda0 drive 2 +ra3 at uda0 drive 3 + +uda1 at uba? csr 0160334 +ra4 at uda1 drive 0 +ra5 at uda1 drive 1 +ra6 at uda1 drive 2 +ra7 at uda1 drive 3 + +# Ethernet cards +de0 at uba? csr 0174510 +qe0 at uba? csr 0174440 + +# Tape drivers +tmscp0 at uba? csr 0174500 +tms0 at tmscp0 drive ? + +pseudo-device loop 1 +pseudo-device pty 48 +pseudo-device bpfilter 8 +pseudo-device sl 2 +pseudo-device ppp 2 +pseudo-device tun 2 +pseudo-device tb 1 +pseudo-device vnd 4 diff --git a/sys/arch/vax/conf/Makefile.vax b/sys/arch/vax/conf/Makefile.vax new file mode 100644 index 00000000000..ba04c06ccb5 --- /dev/null +++ b/sys/arch/vax/conf/Makefile.vax @@ -0,0 +1,125 @@ +# $NetBSD: Makefile.vax,v 1.12 1995/09/19 23:57:55 thorpej Exp $ + +# @(#)Makefile.vax 7.18 (Berkeley) 12/16/90 +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/vax/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/conf/Makefile.``machinetype'' +# after which config should be rerun for all machines of that type. +# +# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE +# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING +# +# -DTRACE compile in kernel tracing hooks +# -DQUOTA compile in file system quotas +# -DUUDMA compile in unibus tu58 pseudo-dma code +# +CC= cc +CPP= cpp +LD= /usr/bin/ld +AWK= awk + +S= ../../../.. +VAX= ../.. + +INCLUDES= -I. -I$S/arch -I$S -I$S/sys +COPTS= ${INCLUDES} ${IDENT} -D_KERNEL -D_VAX_INLINE_ +AOPTS= ${COPTS} -DASSEMBLER +CFLAGS= -Werror -fno-builtin ${COPTS} +LOAD_ADDRESS=80000000 + +### find out what to use for libkern +.include "$S/lib/libkern/Makefile.inc" +.ifndef PROF +LIBKERN= ${KERNLIB} +.else +LIBKERN= ${KERNLIB_PROF} +.endif + +### find out what to use for libcompat +.include "$S/compat/common/Makefile.inc" +.ifndef PROF +LIBCOMPAT= ${COMPATLIB} +.else +LIBCOMPAT= ${COMPATLIB_PROF} +.endif + +NORMAL_C= ${CC} -O -c ${CFLAGS} ${PROF} $< +NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +NORMAL_S= ${CC} -x assembler-with-cpp -E -I. -DLOCORE ${COPTS} $< | \ + ${AS} ${ASFLAGS} -o $*.o +DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< +DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +SYSTEM_ASMS=intvec.o subr.o +SYSTEM_OBJS=${SYSTEM_ASMS} lim.o vnode_if.o ${OBJS} param.o ioconf.o \ + ${LIBKERN} ${LIBCOMPAT} +#SYSTEM_DEP=${SYSTEM_ASMS} lovm.o pmap.o +SYSTEM_DEP=${SYSTEM_ASMS} ${SYSTEM_OBJS} +SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ +SYSTEM_LD= ${LD} -Z -e _start -T ${LOAD_ADDRESS} -o $@ ${SYSTEM_OBJS} vers.o +#SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; ${DBSYM} -f +SYSTEM_LD_TAIL=@echo Nu {r k{rnan klar!!!! + + +%OBJS + +%CFILES + +%LOAD + +clean:: + rm -f eddep *vmunix tags *.o subr.i [a-tv-z]*.s \ + Errs errs linterrs makelinks vnode_if.* genassym + +lint: /tmp param.c + @lint -hbxn -DGENERIC ${COPTS} ${PARAM} \ + ${VAX}/vax/Locore.c ${CFILES} ioconf.c param.c | \ + grep -v 'struct/union .* never defined' | \ + grep -v 'possible pointer alignment problem' + +symbols.sort: ${VAX}/vax/symbols.raw + grep -v '^#' ${VAX}/vax/symbols.raw \ + | sed 's/^ //' | sort -u > symbols.sort + +intvec.o: ${VAX}/vax/intvec.s + ${CC} -x assembler-with-cpp -E ${AOPTS} ${VAX}/vax/intvec.s| as -o intvec.o + +subr.o: ${VAX}/vax/subr.s + ${CC} -x assembler-with-cpp -E ${AOPTS} ${VAX}/vax/subr.s| as -o subr.o + + +depend: ${CFILES} + mkdep ${COPTS} ${.ALLSRC:M*.c} ioconf.c + mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} + +ioconf.o: + ${CC} -c ${CFLAGS} ${PARAM} ioconf.c + +lim.o: Makefile + ../../conf/mkoldconf.awk < ioconf.c > lim.c + ${CC} -O -c ${CFLAGS} ${PARAM} lim.c + +param.c: $S/conf/param.c + rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${CC} -O -c ${CFLAGS} ${PARAM} param.c + +conf.o: ${VAX}/vax/conf.c + ${CC} -O -c ${CFLAGS} ${PARAM} ${VAX}/vax/conf.c + +newvers: + sh $S/conf/newvers.sh + ${CC} ${CFLAGS} -c vers.c + +vnode_if.c vnode_if.h : $S/kern/vnode_if.sh $S/kern/vnode_if.src + AWK="${AWK}" sh $S/kern/vnode_if.sh $S/kern/vnode_if.src + + +%RULES diff --git a/sys/arch/vax/conf/files.vax b/sys/arch/vax/conf/files.vax new file mode 100644 index 00000000000..52c4ac00ac3 --- /dev/null +++ b/sys/arch/vax/conf/files.vax @@ -0,0 +1,252 @@ +# $NetBSD: files.vax,v 1.13 1995/07/24 18:58:36 ragge Exp $ +# +# new style config file for vax architecture +# + +# maxpartitions must be first item in files.${ARCH}.newconf +maxpartitions 8 + +maxusers 8 32 64 + +device backplane at root { } +device sbi at backplane { tr=-1 } +device bi at backplane { node=-1 } + +device cpu at backplane, bi, sbi +device mem at backplane, bi, sbi + +file arch/vax/vax/sbi.c sbi needs-flag +file arch/vax/vax/bi.c bi needs-flag + +device mba at sbi { drive = -1 } +file arch/vax/mba/mba.c mba needs-flag + +device hp at mba +file arch/vax/mba/hp.c hp needs-flag +major {hp = 0} + +device ht at mba +file arch/vax/mba/ht.c ht needs-flag + +device uba at sbi, bi { csr } +file arch/vax/uba/uba.c uba needs-count + +device uda at uba { drive=-1 } +file arch/vax/uba/uda.c uda needs-count + +device de at uba:ifnet, ether +file arch/vax/if/if_de.c de needs-count + +device ra at uda +file arch/vax/vax/mscp.c ra needs-count +major {ra = 9} + +# TK50/TU81 at UBA +device tmscp at uba {drive = -1} +device tms at tmscp +file arch/vax/uba/tmscp.c tmscp needs-count + +# DEQNA/DELQA used on Qbus +device qe at uba:ifnet, ether +file arch/vax/if/if_qe.c qe needs-count + +# These devices aren't tested (or even compiled!) +# They are just included here to make some files happy ;) +# + +# Ikonas framebuffer +device ik at uba +file arch/vax/uba/ik.c ik needs-count + +device vs at uba +file arch/vax/uba/vs.c vs needs-count + +# TU58 on 750/730 +device tu at root +file arch/vax/vax/tu.c tu needs-count + +# RK06/07 on UBA +device rk at uba +file arch/vax/uba/rk.c rk needs-count + +# TM11/TE10 at UBA +device te at uba +file arch/vax/uba/tm.c te needs-count + +# TS11 at UBA +device ts at uba +file arch/vax/uba/ts.c ts needs-count + +# TU78 at MBA +device mu at mba +file arch/vax/mba/mt.c mu needs-count + +# KDB50 on BI +device kdb at bi { drive=-1 } +file arch/vax/bi/kdb.c kdb needs-count + + +# DMF32 on UBA +device dmf at uba +file arch/vax/uba/dmf.c dmf needs-count +file arch/vax/uba/dmz.c dmf needs-count + +# DMZ32 on UBA +device dmz at uba +file arch/vax/uba/dmx.c dmz needs-count + +# DN-11 on UBA +device dn at uba +file arch/vax/uba/dn.c dn needs-count + +# DZ11 at UBA +device dz at uba +file arch/vax/uba/dz.c dz needs-count + +# IDC (RB730) on UBA (VAX 11/730) +device idc at uba { drive=-1 } +device rb at idc +file arch/vax/uba/idc.c rb needs-count + +# LP-11 at UBA +device lp at uba +file arch/vax/uba/lp.c lp needs-count + +# ???? at UBA +device lpa at uba +file arch/vax/uba/lpa.c lpa needs-count + +# PS2 at UBA +device ps at uba +file arch/vax/uba/ps.c ps needs-count + +# RL02/RL11 at UBA +device hl at uba { drive=-1 } +device rl at hl +file arch/vax/uba/rl.c rl needs-count + +# RX211/RX02 at UBA +device fx at uba { drive=-1 } +device rx at fx +file arch/vax/uba/rx.c rx needs-count + +# SC-21/SC-31 at UBA +device sc at uba { drive=-1 } +device up at sc +file arch/vax/uba/up.c up needs-count + +# TU45 at UBA +device ut at uba { drive=-1} +device tj at ut +file arch/vax/uba/ut.c tj needs-count + +# TU58/DECtape II +device uu at uba +file arch/vax/uba/uu.c uu needs-count + +# Benson-Varian plotter at UBA +device va at uba { drive=-1} +device vz at va +file arch/vax/uba/va.c va needs-count + +# Versatec plotter at UBA +device vp at uba +file arch/vax/uba/vp.c vp needs-count + +# QVSS at UBA +device qv at uba +file arch/vax/uba/qv.c qv needs-count +file arch/vax/uba/qfont.c qv needs-count + +# QDSS at UBA +device qd at uba +file arch/vax/uba/qd.c qd needs-count + +# Interlan NP100 at UBA +device np at uba +file arch/vax/if/if_ix.c np needs-count +file arch/vax/uba/np.c np needs-count + +# ACC LH/DH IMP on UBA +device acc at uba +file arch/vax/if/if_acc.c acc needs-count + +# DR11C at UBA +device ct at uba +file arch/vax/uba/ct.c ct needs-count + +# A/D-converter on UBA +device ad at uba +file arch/vax/uba/ad.c ad needs-count + +# DH-11/DM-11 on UBA +device dh at uba +file arch/vax/uba/dh.c dh needs-count + +# DHU-11 at UBA +device dhu at uba +file arch/vax/uba/dhu.c dhu needs-count + +# These are general files needed for compilation. +file dev/cons.c +file dev/cninit.c +file arch/vax/vax/locore.c +file arch/vax/vax/mem.c +file arch/vax/vax/clock.c +file arch/vax/vax/gencons.c +file arch/vax/vax/pmap.c +file arch/vax/vax/machdep.c +file arch/vax/vax/ka750.c vax750 +file arch/vax/vax/uvaxII.c vax630 +file arch/vax/vax/emulate.s vax630 +file arch/vax/vax/conf.c +file arch/vax/vax/urem.s +file arch/vax/vax/udiv.s +file arch/vax/vax/rootfil.c +file arch/vax/vax/trap.c + +file arch/vax/vax/vm_machdep.c +file arch/vax/vax/autoconf.c +#file arch/vax/vax/cpu_machdep.c +#file arch/vax/vax/in_cksum.c inet +file netinet/in_cksum.c inet +file arch/vax/vax/random.s inet +file arch/vax/vax/disksubr.c ffs +file arch/vax/if/if_uba.c de qe +file arch/vax/vax/db_machdep.c ddb +file arch/vax/vax/db_disasm.c ddb + +# Dom h{ra f}r vara kvar s} l{nge f}r vi se vilka vi beh|ver... +#arch/vax/vax/crl.c standard +#arch/vax/vax/dkbad.c standard +#arch/vax/vax/flp.c standard +#arch/vax/vax/ka650.c standard +#arch/vax/vax/ka630.c standard +#arch/vax/vax/ka730.c standard +#arch/vax/vax/ka750.c standard +#arch/vax/vax/ka780.c standard +#arch/vax/vax/ka820.c standard +#arch/vax/vax/ka860.c standard +#arch/vax/vax/kdb_machdep.c optional kadb +#arch/vax/vax/kdb_opset.c optional kadb +#arch/vax/vax/ns_cksum.c optional ns +#arch/vax/vax/rx50.c standard +#arch/vax/vax/sys_machdep.c standard +#arch/vax/vax/iidr.o optional ii +#arch/vax/vax/iidrsys.o optional ii +#arch/vax/vax/iidr_glob.o optional ii +#arch/vax/if/if_css.c optional css imp device-driver +#arch/vax/if/if_dp.c optional dp device-driver +#arch/vax/if/if_ddn.c optional ddn device-driver +#arch/vax/if/if_dmc.c optional dmc device-driver +#arch/vax/if/if_dmv.c optional dmv device-driver +#arch/vax/if/if_ec.c optional ec device-driver +#arch/vax/if/if_en.c optional en device-driver +#arch/vax/if/if_ex.c optional ex device-driver +#arch/vax/if/if_hdh.c optional hdh device-driver +#arch/vax/if/if_hy.c optional hy device-driver +#arch/vax/if/if_il.c optional il device-driver +#arch/vax/if/if_pcl.c optional pcl device-driver +##arch/vax/if/if_uba.c optional ns device-driver +#arch/vax/if/if_vv.c optional vv device-driver +#arch/vax/if/raw_hy.c optional hy device-driver diff --git a/sys/arch/vax/conf/mkoldconf.awk b/sys/arch/vax/conf/mkoldconf.awk new file mode 100644 index 00000000000..2212b4e2103 --- /dev/null +++ b/sys/arch/vax/conf/mkoldconf.awk @@ -0,0 +1,155 @@ +#!/usr/bin/awk -f +# +# $NetBSD: mkoldconf.awk,v 1.3 1995/03/29 22:50:51 ragge Exp $ +# + +/tmscd/{ + tmsplats[ntms]=$2; + tmsaddr[ntms]=$5; + ntms++; +} + +/racd/{ + raplats[nra]=$2; + raaddr[nra]=$5; + nra++; +} + +/decd/{ + deplats[nde]=$2; + deaddr[nde]=$5; + nde++; +} + +/qecd/{ + qeplats[nqe]=$2; + qeaddr[nqe]=$5; + nqe++; +} + +{ + if(savenext==1){ + l=sprintf("%d",$2) + udanummer[l-1]=nuda-1 + savenext=0; + } +} + + +{ + if(tmssavenext==1){ + l=sprintf("%d",$2) + tmsnummer[l-1]=ntmscp-1 + tmssavenext=0; + } +} + +/tmscpcd/{ + tmscpplats[ntmscp]=$2; + tmscpaddr[ntmscp]=$5; + ntmscp++; + tmssavenext=1; +} + +/udacd/{ + udaplats[nuda]=$2; + udaddr[nuda]=$5; + nuda++; + savenext=1; +} + + +/};/{ + k=0; + m=0; +} + +{ + if (k==1){ + for(i=1;i<NF+1;i++){ + loc[loccnt+i]=$i; + } + loccnt+=NF; + } +} + +/static int loc/{ + k=1; + loccnt=0; +} + +{ + if(m==1){ + for(i=1;i<NF+1;i++){ + pv[i]=$i; + } + } +} + +/static short pv/{ + m=1; +} + +END{ + +printf "#include \"sys/param.h\"\n" +printf "#include \"machine/pte.h\"\n" +printf "#include \"sys/buf.h\"\n" +printf "#include \"sys/map.h\"\n" + +printf "#include \"vax/uba/ubavar.h\"\n" + +printf "int antal_ra=%d;\n",nra-1 +printf "int antal_de=%d;\n",nde-1 +printf "int antal_uda=%d;\n",nuda-1 +printf "int antal_tms=%d;\n",ntms-1 +printf "int antal_tmscp=%d;\n",ntmscp-1 + +printf "extern struct uba_driver udadriver;\n" +printf "extern struct uba_driver dedriver;\n" +printf "extern struct uba_driver qedriver;\n" +if(ntms) printf "extern struct uba_driver tmscpdriver;\n" +if(ntms) printf "int tmscpintr();\n" +printf "int deintr();\n" +printf "int qeintr();\n" +printf "int udaintr();\n" +printf "int udacd=0, racd=0, tmscpcd=0, tmscd=0;\n" +printf "#define C (caddr_t)\n" + +printf "struct uba_ctlr ubminit[]={\n" +for(i=1;i<nuda;i++){ + k=sprintf("%d",udaddr[i]) + printf " { &udadriver, %d,0,0,udaintr,C %s},\n", + udaplats[i],loc[k+1] +} +for(i=1;i<ntmscp;i++){ + k=sprintf("%d",tmscpaddr[i]) +if(ntms)printf " { &tmscpdriver, %d,'?',0,tmscpintr,C %s},\n", + tmscpplats[i],loc[k+1] +} +printf "0};\n" + +printf "struct uba_device ubdinit[]={\n" +for(i=1;i<nra;i++){ + k=sprintf("%d",raaddr[i]) + printf " { &udadriver,%d,%d,0,%d,0,0,1,0},\n",raplats[i], + rr++/4,loc[k+1] +} +for(i=1;i<nde;i++){ + k=sprintf("%d",deaddr[i]) + printf " {&dedriver,%d,-1,0,-1,deintr,C %s0,0},\n",deplats[i], + loc[k+1] +} +for(i=1;i<nqe;i++){ + k=sprintf("%d",qeaddr[i]) + printf " {&qedriver,%d,-1,0,-1,qeintr,C %s0,0},\n",qeplats[i], + loc[k+1] +} +for(i=1;i<ntms;i++){ + k=sprintf("%d",tmsaddr[i]) + printf " {&tmscpdriver,%d,0,'?',0,0,C 0,1,0},\n",tmsplats[i] +} +printf "0};\n" + +} + diff --git a/sys/arch/vax/conf/std.vax b/sys/arch/vax/conf/std.vax new file mode 100644 index 00000000000..ba605d9b4c6 --- /dev/null +++ b/sys/arch/vax/conf/std.vax @@ -0,0 +1,10 @@ +# $NetBSD: std.vax,v 1.3 1995/02/13 00:41:59 ragge Exp $ +# +# Std vaxfiles +# +machine vax + +backplane0 at root + +options MAXFDESCS=2048 +options TIMEZONE=-60, DST=1 diff --git a/sys/arch/vax/if/if_de.c b/sys/arch/vax/if/if_de.c new file mode 100644 index 00000000000..18f01217787 --- /dev/null +++ b/sys/arch/vax/if/if_de.c @@ -0,0 +1,723 @@ +/* $NetBSD: if_de.c,v 1.7.2.1 1995/10/15 13:56:24 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_de.c 7.12 (Berkeley) 12/16/90 + */ + +#include "de.h" +#if NDE > 0 + +/* + * DEC DEUNA interface + * + * Lou Salkind + * New York University + * + * TODO: + * timeout routine (get statistics) + */ + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/mbuf.h" +#include "sys/buf.h" +#include "sys/protosw.h" +#include "sys/socket.h" +/* #include "sys/vmmac.h" */ +#include "sys/ioctl.h" +#include "sys/errno.h" +#include "sys/syslog.h" +#include "sys/device.h" + +#include "vax/include/pte.h" +#include "vax/include/sid.h" + +#include "net/if.h" +#include "net/netisr.h" +#include "net/route.h" + +#ifdef INET +#include "netinet/in.h" +#include "netinet/in_systm.h" +#include "netinet/in_var.h" +#include "netinet/ip.h" +#include "netinet/if_ether.h" +#endif + +#ifdef NS +#include "netns/ns.h" +#include "netns/ns_if.h" +#endif + +#ifdef ISO +#include "netiso/iso.h" +#include "netiso/iso_var.h" +extern char all_es_snpa[], all_is_snpa[]; +#endif + +#include "../include/cpu.h" +#include "../include/mtpr.h" +#include "if_dereg.h" +#include "if_uba.h" +#include "../uba/ubareg.h" +#include "../uba/ubavar.h" + +#define NXMT 3 /* number of transmit buffers */ +#define NRCV 7 /* number of receive buffers (must be > 1) */ + +int dedebug = 0; + + +int deprobe(), deattach(), deintr(); +struct uba_device *deinfo[NDE]; +u_short destd[] = { 0 }; +struct uba_driver dedriver = + { deprobe, 0, deattach, 0, destd, "de", deinfo }; +int deinit(),deioctl(),dereset(); +void destart(); + + +/* + * Ethernet software status per interface. + * + * Each interface is referenced by a network interface structure, + * ds_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + * We also have, for each interface, a UBA interface structure, which + * contains information about the UNIBUS resources held by the interface: + * map registers, buffered data paths, etc. Information is cached in this + * structure for use by the if_uba.c routines in running the interface + * efficiently. + */ +struct de_softc { + struct arpcom ds_ac; /* Ethernet common part */ +#define ds_if ds_ac.ac_if /* network-visible interface */ +#define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ + int ds_flags; +#define DSF_RUNNING 2 /* board is enabled */ +#define DSF_SETADDR 4 /* physical address is changed */ + int ds_ubaddr; /* map info for incore structs */ + struct ifubinfo ds_deuba; /* unibus resource structure */ + struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ + struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ + /* the following structures are always mapped in */ + struct de_pcbb ds_pcbb; /* port control block */ + struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ + struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ + struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ + /* end mapped area */ +#define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) +#define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) +#define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) +#define PCBB_OFFSET RVAL_OFF(ds_pcbb) +#define XRENT_OFFSET LVAL_OFF(ds_xrent) +#define RRENT_OFFSET LVAL_OFF(ds_rrent) +#define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) +#define INCORE_SIZE RVAL_OFF(ds_xindex) + int ds_xindex; /* UNA index into transmit chain */ + int ds_rindex; /* UNA index into receive chain */ + int ds_xfree; /* index for next transmit buffer */ + int ds_nxmit; /* # of transmits in progress */ +} de_softc[NDE]; + +deprobe(reg) + caddr_t reg; +{ + register int br, cvec; /* r11, r10 value-result */ + volatile struct dedevice *addr = (struct dedevice *)reg; + register i; + +#ifdef lint + br = 0; cvec = br; br = cvec; + i = 0; derint(i); deintr(i); +#endif + + /* + * Make sure self-test is finished before we screw with the board. + * Self-test on a DELUA can take 15 seconds (argh). + */ + for (i = 0; + i < 160 && + (addr->pcsr0 & PCSR0_FATI) == 0 && + (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; + ++i) + waitabit(10); + if ((addr->pcsr0 & PCSR0_FATI) != 0 || + (addr->pcsr1 & PCSR1_STMASK) != STAT_READY && + (addr->pcsr1 & PCSR1_STMASK) != STAT_RUN) + return(0); + + addr->pcsr0 = 0; + waitabit(1); + addr->pcsr0 = PCSR0_RSET; + while ((addr->pcsr0 & PCSR0_INTR) == 0) + ; + /* make board interrupt by executing a GETPCBB command */ + addr->pcsr0 = PCSR0_INTE; + addr->pcsr2 = 0; + addr->pcsr3 = 0; + addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; + waitabit(10); + return(1); +} + +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. We get the ethernet address here. + */ +deattach(ui) + struct uba_device *ui; +{ + register struct de_softc *ds = &de_softc[ui->ui_unit]; + register struct ifnet *ifp = &ds->ds_if; + volatile struct dedevice *addr = (struct dedevice *)ui->ui_addr; + int csr1; + + ifp->if_unit = ui->ui_unit; + ifp->if_name = "de"; + ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; + + /* + * What kind of a board is this? + * The error bits 4-6 in pcsr1 are a device id as long as + * the high byte is zero. + */ + csr1 = addr->pcsr1; + if (csr1 & 0xff60) + printf("de%d: broken\n", ui->ui_unit); + else if (csr1 & 0x10) + printf("de%d: delua\n", ui->ui_unit); + else + printf("de%d: deuna\n", ui->ui_unit); + + /* + * Reset the board and temporarily map + * the pcbb buffer onto the Unibus. + */ + addr->pcsr0 = 0; /* reset INTE */ + waitabit(1); + addr->pcsr0 = PCSR0_RSET; + (void)dewait(ui, "reset"); + + ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, + sizeof (struct de_pcbb), 0); + addr->pcsr2 = ds->ds_ubaddr & 0xffff; + addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; + addr->pclow = CMD_GETPCBB; + (void)dewait(ui, "pcbb"); + + ds->ds_pcbb.pcbb0 = FC_RDPHYAD; + addr->pclow = CMD_GETCMD; + (void)dewait(ui, "read addr "); + + ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); + bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, + sizeof (ds->ds_addr)); + printf("de%d: hardware address %s\n", ui->ui_unit, + ether_sprintf(ds->ds_addr)); + ifp->if_ioctl = deioctl; + ifp->if_reset = dereset; + ifp->if_start = destart; + ds->ds_deuba.iff_flags = UBA_CANTWAIT; +#ifdef notdef + /* CAN WE USE BDP's ??? */ + ds->ds_deuba.iff_flags |= UBA_NEEDBDP; +#endif + if_attach(ifp); + ether_ifattach(ifp); +} + +/* + * Reset of interface after UNIBUS reset. + * If interface is on specified uba, reset its state. + */ +dereset(unit, uban) + int unit, uban; +{ + register struct uba_device *ui; + + if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || + ui->ui_ubanum != uban) + return; + printf(" de%d", unit); + de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + de_softc[unit].ds_flags &= ~DSF_RUNNING; + ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; + (void)dewait(ui, "reset"); + deinit(unit); +} + +/* + * Initialization of interface; clear recorded pending + * operations, and reinitialize UNIBUS usage. + */ +deinit(unit) + int unit; +{ + struct de_softc *ds; + struct uba_device *ui; + volatile struct dedevice *addr; + struct ifrw *ifrw; + struct ifxmt *ifxp; + struct ifnet *ifp; + struct de_ring *rp; + int s,incaddr; + + ds = &de_softc[unit]; + ui = deinfo[unit]; + ifp = &ds->ds_if; + + /* not yet, if address still unknown */ + if (ifp->if_addrlist.tqh_first == (struct ifaddr *)0) + return; + + if (ds->ds_flags & DSF_RUNNING) + return; + if ((ifp->if_flags & IFF_RUNNING) == 0) { + if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, + sizeof (struct ether_header), (int)btoc(ETHERMTU), + ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { + printf("de%d: can't initialize\n", unit); + ds->ds_if.if_flags &= ~IFF_UP; + return; + } + ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), + INCORE_SIZE, 0); + } + addr = (struct dedevice *)ui->ui_addr; + + /* set the pcbb block address */ + incaddr = ds->ds_ubaddr + PCBB_OFFSET; + addr->pcsr2 = incaddr & 0xffff; + addr->pcsr3 = (incaddr >> 16) & 0x3; + addr->pclow = 0; /* reset INTE */ + waitabit(1); + addr->pclow = CMD_GETPCBB; + (void)dewait(ui, "pcbb"); + + /* set the transmit and receive ring header addresses */ + incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; + ds->ds_pcbb.pcbb0 = FC_WTRING; + ds->ds_pcbb.pcbb2 = incaddr & 0xffff; + ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; + + incaddr = ds->ds_ubaddr + XRENT_OFFSET; + ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; + ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; + ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); + ds->ds_udbbuf.b_trlen = NXMT; + incaddr = ds->ds_ubaddr + RRENT_OFFSET; + ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; + ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; + ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); + ds->ds_udbbuf.b_rrlen = NRCV; + + addr->pclow = CMD_GETCMD; + (void)dewait(ui, "wtring"); + + /* initialize the mode - enable hardware padding */ + ds->ds_pcbb.pcbb0 = FC_WTMODE; + /* let hardware do padding - set MTCH bit on broadcast */ + ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; + addr->pclow = CMD_GETCMD; + (void)dewait(ui, "wtmode"); + + /* set up the receive and transmit ring entries */ + ifxp = &ds->ds_ifw[0]; + for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { + rp->r_segbl = ifxp->ifw_info & 0xffff; + rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; + rp->r_flags = 0; + ifxp++; + } + ifrw = &ds->ds_ifr[0]; + for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { + rp->r_slen = sizeof (struct de_buf); + rp->r_segbl = ifrw->ifrw_info & 0xffff; + rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; + rp->r_flags = RFLG_OWN; /* hang receive */ + ifrw++; + } + + /* start up the board (rah rah) */ + s = splimp(); + ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; + ds->ds_if.if_flags |= IFF_RUNNING; + addr->pclow = PCSR0_INTE; /* avoid interlock */ + destart(&ds->ds_if); /* queue output packets */ + ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ + if (ds->ds_flags & DSF_SETADDR) + de_setaddr(ds->ds_addr, unit); + addr->pclow = CMD_START | PCSR0_INTE; + splx(s); +} + +/* + * Setup output on interface. + * Get another datagram to send off of the interface queue, + * and map it to the interface before starting the output. + * Must be called from ipl >= our interrupt level. + */ +void +destart(ifp) + struct ifnet *ifp; +{ + int len; + int unit = ifp->if_unit; + struct uba_device *ui = deinfo[unit]; + volatile struct dedevice *addr = (struct dedevice *)ui->ui_addr; + register struct de_softc *ds = &de_softc[unit]; + register struct de_ring *rp; + struct mbuf *m; + register int nxmit; + + /* + * the following test is necessary, since + * the code is not reentrant and we have + * multiple transmission buffers. + */ + if (ds->ds_if.if_flags & IFF_OACTIVE) + return; + for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { + IF_DEQUEUE(&ds->ds_if.if_snd, m); + if (m == 0) + break; + rp = &ds->ds_xrent[ds->ds_xfree]; + if (rp->r_flags & XFLG_OWN) + panic("deuna xmit in progress"); + len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); + if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) + UBAPURGE(ds->ds_deuba.iff_uba, + ds->ds_ifw[ds->ds_xfree].ifw_bdp); + rp->r_slen = len; + rp->r_tdrerr = 0; + rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; + + ds->ds_xfree++; + if (ds->ds_xfree == NXMT) + ds->ds_xfree = 0; + } + if (ds->ds_nxmit != nxmit) { + ds->ds_nxmit = nxmit; + if (ds->ds_flags & DSF_RUNNING) + addr->pclow = PCSR0_INTE|CMD_PDMD; + } +} + +/* + * Command done interrupt. + */ +deintr(uba,vector,level,unit) +{ + struct uba_device *ui; + volatile struct dedevice *addr; + register struct de_softc *ds; + register struct de_ring *rp; + register struct ifxmt *ifxp; + short csr0; + + ui = deinfo[unit]; + addr = (struct dedevice *)ui->ui_addr; + ds = &de_softc[unit]; + + + /* save flags right away - clear out interrupt bits */ + csr0 = addr->pcsr0; + addr->pchigh = csr0 >> 8; + + + ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ + /* + * if receive, put receive buffer on mbuf + * and hang the request again + */ + derecv(unit); + + /* + * Poll transmit ring and check status. + * Be careful about loopback requests. + * Then free buffer space and check for + * more transmit requests. + */ + for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { + rp = &ds->ds_xrent[ds->ds_xindex]; + if (rp->r_flags & XFLG_OWN) + break; + ds->ds_if.if_opackets++; + ifxp = &ds->ds_ifw[ds->ds_xindex]; + /* check for unusual conditions */ + if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { + if (rp->r_flags & XFLG_ERRS) { + /* output error */ + ds->ds_if.if_oerrors++; + if (dedebug) + printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", + unit, rp->r_flags, XFLG_BITS, + rp->r_tdrerr, XERR_BITS, rp->r_slen); + } else if (rp->r_flags & XFLG_ONE) { + /* one collision */ + ds->ds_if.if_collisions++; + } else if (rp->r_flags & XFLG_MORE) { + /* more than one collision */ + ds->ds_if.if_collisions += 2; /* guess */ + } else if (rp->r_flags & XFLG_MTCH) { + /* received our own packet */ + ds->ds_if.if_ipackets++; + deread(ds, &ifxp->ifrw, + rp->r_slen - sizeof (struct ether_header)); + } + } + if (ifxp->ifw_xtofree) { + m_freem(ifxp->ifw_xtofree); + ifxp->ifw_xtofree = 0; + } + /* check if next transmit buffer also finished */ + ds->ds_xindex++; + if (ds->ds_xindex == NXMT) + ds->ds_xindex = 0; + } + ds->ds_if.if_flags &= ~IFF_OACTIVE; + destart(&ds->ds_if); + + if (csr0 & PCSR0_RCBI) { + if (dedebug) + log(LOG_WARNING, "de%d: buffer unavailable\n", unit); + addr->pclow = PCSR0_INTE|CMD_PDMD; + } +} + +/* + * Ethernet interface receiver interface. + * If input error just drop packet. + * Otherwise purge input buffered data path and examine + * packet to determine type. If can't determine length + * from type, then have to drop packet. Othewise decapsulate + * packet based on type and pass to type specific higher-level + * input routine. + */ +derecv(unit) + int unit; +{ + register struct de_softc *ds = &de_softc[unit]; + register struct de_ring *rp; + int len; + + rp = &ds->ds_rrent[ds->ds_rindex]; + while ((rp->r_flags & RFLG_OWN) == 0) { + ds->ds_if.if_ipackets++; + if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) + UBAPURGE(ds->ds_deuba.iff_uba, + ds->ds_ifr[ds->ds_rindex].ifrw_bdp); + len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) + - 4; /* don't forget checksum! */ + /* check for errors */ + if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || + (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || + (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || + len < ETHERMIN || len > ETHERMTU) { + ds->ds_if.if_ierrors++; + if (dedebug) + printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", + unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, + RERR_BITS, len); + } else + deread(ds, &ds->ds_ifr[ds->ds_rindex], len); + + /* hang the receive buffer again */ + rp->r_lenerr = 0; + rp->r_flags = RFLG_OWN; + + /* check next receive buffer */ + ds->ds_rindex++; + if (ds->ds_rindex == NRCV) + ds->ds_rindex = 0; + rp = &ds->ds_rrent[ds->ds_rindex]; + } +} + +/* + * Pass a packet to the higher levels. + * We deal with the trailer protocol here. + */ +deread(ds, ifrw, len) + register struct de_softc *ds; + struct ifrw *ifrw; + int len; +{ + struct ether_header *eh; + struct mbuf *m; + int s; + register struct ifqueue *inq; + + /* + * Deal with trailer protocol: if type is trailer type + * get true type from first 16-bit word past data. + * Remember that type was trailer by setting off. + */ + eh = (struct ether_header *)ifrw->ifrw_addr; +/* eh->ether_type = ntohs((u_short)eh->ether_type); */ + if (len == 0) + return; + + /* + * Pull packet off interface. Off is nonzero if packet + * has trailing header; if_ubaget will then force this header + * information to be at the front. + */ + m = if_ubaget(&ds->ds_deuba, ifrw, len, &ds->ds_if); + if (m) + ether_input(&ds->ds_if, eh, m); +} +/* + * Process an ioctl request. + */ +deioctl(ifp, cmd, data) + register struct ifnet *ifp; + int cmd; + caddr_t data; +{ + register struct ifaddr *ifa = (struct ifaddr *)data; + register struct de_softc *ds = &de_softc[ifp->if_unit]; + int s = splimp(), error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + deinit(ifp->if_unit); + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + arp_ifinit(&ds->ds_ac, ifa); + break; +#endif +#ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *)(ds->ds_addr); + else + de_setaddr(ina->x_host.c_host,ifp->if_unit); + break; + } +#endif + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + ds->ds_flags & DSF_RUNNING) { + ((struct dedevice *) + (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; + waitabit(1); + ((struct dedevice *) + (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; + ds->ds_flags &= ~DSF_RUNNING; + ds->ds_if.if_flags &= ~IFF_OACTIVE; + } else if (ifp->if_flags & IFF_UP && + (ds->ds_flags & DSF_RUNNING) == 0) + deinit(ifp->if_unit); + break; + + default: + error = EINVAL; + } + splx(s); + return (error); +} + +/* + * set ethernet address for unit + */ +de_setaddr(physaddr, unit) + u_char *physaddr; + int unit; +{ + register struct de_softc *ds = &de_softc[unit]; + struct uba_device *ui = deinfo[unit]; + volatile struct dedevice *addr= (struct dedevice *)ui->ui_addr; + + if (! (ds->ds_flags & DSF_RUNNING)) + return; + + bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); + ds->ds_pcbb.pcbb0 = FC_WTPHYAD; + addr->pclow = PCSR0_INTE|CMD_GETCMD; + if (dewait(ui, "address change") == 0) { + ds->ds_flags |= DSF_SETADDR; + bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); + } +} + +/* + * Await completion of the named function + * and check for errors. + */ +dewait(ui, fn) + register struct uba_device *ui; + char *fn; +{ + volatile struct dedevice *addr = (struct dedevice *)ui->ui_addr; + register csr0; + + while ((addr->pcsr0 & PCSR0_INTR) == 0) + ; + csr0 = addr->pcsr0; + addr->pchigh = csr0 >> 8; + if (csr0 & PCSR0_PCEI) + printf("de%d: %s failed, csr0=%b csr1=%b\n", + ui->ui_unit, fn, csr0, PCSR0_BITS, + addr->pcsr1, PCSR1_BITS); + return (csr0 & PCSR0_PCEI); +} + +de_match(){ + printf("de_match\n"); + return 0; +} + +void +de_attach(){ + printf("de_attach\n"); +} + +struct cfdriver decd = + { NULL,"de",de_match, de_attach, DV_IFNET, sizeof(struct uba_driver) }; + + +#endif diff --git a/sys/arch/vax/if/if_dereg.h b/sys/arch/vax/if/if_dereg.h new file mode 100644 index 00000000000..2f2b48c9796 --- /dev/null +++ b/sys/arch/vax/if/if_dereg.h @@ -0,0 +1,220 @@ +/* $NetBSD: if_dereg.h,v 1.2 1994/10/26 08:01:51 cgd Exp $ */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_dereg.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * DEC DEUNA interface + */ +struct dedevice { + union { + short p0_w; + char p0_b[2]; + } u_p0; +#define pcsr0 u_p0.p0_w +#define pclow u_p0.p0_b[0] +#define pchigh u_p0.p0_b[1] + short pcsr1; + short pcsr2; + short pcsr3; +}; + +/* + * PCSR 0 bit descriptions + */ +#define PCSR0_SERI 0x8000 /* Status error interrupt */ +#define PCSR0_PCEI 0x4000 /* Port command error interrupt */ +#define PCSR0_RXI 0x2000 /* Receive done interrupt */ +#define PCSR0_TXI 0x1000 /* Transmit done interrupt */ +#define PCSR0_DNI 0x0800 /* Done interrupt */ +#define PCSR0_RCBI 0x0400 /* Receive buffer unavail intrpt */ +#define PCSR0_FATI 0x0100 /* Fatal error interrupt */ +#define PCSR0_INTR 0x0080 /* Interrupt summary */ +#define PCSR0_INTE 0x0040 /* Interrupt enable */ +#define PCSR0_RSET 0x0020 /* DEUNA reset */ +#define PCSR0_CMASK 0x000f /* command mask */ + +#define PCSR0_BITS "\20\20SERI\17PCEI\16RXI\15TXI\14DNI\13RCBI\11FATI\10INTR\7INTE\6RSET" + +/* bits 0-3 are for the PORT_COMMAND */ +#define CMD_NOOP 0x0 +#define CMD_GETPCBB 0x1 /* Get PCB Block */ +#define CMD_GETCMD 0x2 /* Execute command in PCB */ +#define CMD_STEST 0x3 /* Self test mode */ +#define CMD_START 0x4 /* Reset xmit and receive ring ptrs */ +#define CMD_BOOT 0x5 /* Boot DEUNA */ +#define CMD_PDMD 0x8 /* Polling demand */ +#define CMD_TMRO 0x9 /* Sanity timer on */ +#define CMD_TMRF 0xa /* Sanity timer off */ +#define CMD_RSTT 0xb /* Reset sanity timer */ +#define CMD_STOP 0xf /* Suspend operation */ + +/* + * PCSR 1 bit descriptions + */ +#define PCSR1_XPWR 0x8000 /* Transceiver power BAD */ +#define PCSR1_ICAB 0x4000 /* Interconnect cabling BAD */ +#define PCSR1_STCODE 0x3f00 /* Self test error code */ +#define PCSR1_PCTO 0x0080 /* Port command timed out */ +#define PCSR1_ILLINT 0x0040 /* Illegal interrupt */ +#define PCSR1_TIMEOUT 0x0020 /* Timeout */ +#define PCSR1_POWER 0x0010 /* Power fail */ +#define PCSR1_RMTC 0x0008 /* Remote console reserved */ +#define PCSR1_STMASK 0x0007 /* State */ + +/* bit 0-3 are for STATE */ +#define STAT_RESET 0x0 +#define STAT_PRIMLD 0x1 /* Primary load */ +#define STAT_READY 0x2 +#define STAT_RUN 0x3 +#define STAT_UHALT 0x5 /* UNIBUS halted */ +#define STAT_NIHALT 0x6 /* NI halted */ +#define STAT_NIUHALT 0x7 /* NI and UNIBUS Halted */ + +#define PCSR1_BITS "\20\20XPWR\17ICAB\10PCTO\7ILLINT\6TIMEOUT\5POWER\4RMTC" + +/* + * Port Control Block Base + */ +struct de_pcbb { + short pcbb0; /* function */ + short pcbb2; /* command specific */ + short pcbb4; + short pcbb6; +}; + +/* PCBB function codes */ +#define FC_NOOP 0x00 /* NO-OP */ +#define FC_LSUADDR 0x01 /* Load and start microaddress */ +#define FC_RDDEFAULT 0x02 /* Read default physical address */ +#define FC_RDPHYAD 0x04 /* Read physical address */ +#define FC_WTPHYAD 0x05 /* Write physical address */ +#define FC_RDMULTI 0x06 /* Read multicast address list */ +#define FC_WTMULTI 0x07 /* Read multicast address list */ +#define FC_RDRING 0x08 /* Read ring format */ +#define FC_WTRING 0x09 /* Write ring format */ +#define FC_RDCNTS 0x0a /* Read counters */ +#define FC_RCCNTS 0x0b /* Read and clear counters */ +#define FC_RDMODE 0x0c /* Read mode */ +#define FC_WTMODE 0x0d /* Write mode */ +#define FC_RDSTATUS 0x0e /* Read port status */ +#define FC_RCSTATUS 0x0f /* Read and clear port status */ +#define FC_DUMPMEM 0x10 /* Dump internal memory */ +#define FC_LOADMEM 0x11 /* Load internal memory */ +#define FC_RDSYSID 0x12 /* Read system ID parameters */ +#define FC_WTSYSID 0x13 /* Write system ID parameters */ +#define FC_RDSERAD 0x14 /* Read load server address */ +#define FC_WTSERAD 0x15 /* Write load server address */ + +/* + * Unibus Data Block Base (UDBB) for ring buffers + */ +struct de_udbbuf { + short b_tdrbl; /* Transmit desc ring base low 16 bits */ + char b_tdrbh; /* Transmit desc ring base high 2 bits */ + char b_telen; /* Length of each transmit entry */ + short b_trlen; /* Number of entries in the XMIT desc ring */ + short b_rdrbl; /* Receive desc ring base low 16 bits */ + char b_rdrbh; /* Receive desc ring base high 2 bits */ + char b_relen; /* Length of each receive entry */ + short b_rrlen; /* Number of entries in the RECV desc ring */ +}; + +/* + * Transmit/Receive Ring Entry + */ +struct de_ring { + short r_slen; /* Segment length */ + short r_segbl; /* Segment address (low 16 bits) */ + char r_segbh; /* Segment address (hi 2 bits) */ + u_char r_flags; /* Status flags */ + u_short r_tdrerr; /* Errors */ +#define r_lenerr r_tdrerr + short r_rid; /* Request ID */ +}; + +#define XFLG_OWN 0x80 /* If 0 then owned by driver */ +#define XFLG_ERRS 0x40 /* Error summary */ +#define XFLG_MTCH 0x20 /* Address match on xmit request */ +#define XFLG_MORE 0x10 /* More than one entry required */ +#define XFLG_ONE 0x08 /* One collision encountered */ +#define XFLG_DEF 0x04 /* Transmit deferred */ +#define XFLG_STP 0x02 /* Start of packet */ +#define XFLG_ENP 0x01 /* End of packet */ + +#define XFLG_BITS "\10\10OWN\7ERRS\6MTCH\5MORE\4ONE\3DEF\2STP\1ENP" + +#define XERR_BUFL 0x8000 /* Buffer length error */ +#define XERR_UBTO 0x4000 /* UNIBUS tiemout +#define XERR_LCOL 0x1000 /* Late collision */ +#define XERR_LCAR 0x0800 /* Loss of carrier */ +#define XERR_RTRY 0x0400 /* Failed after 16 retries */ +#define XERR_TDR 0x03ff /* TDR value */ + +#define XERR_BITS "\20\20BUFL\17UBTO\15LCOL\14LCAR\13RTRY" + +#define RFLG_OWN 0x80 /* If 0 then owned by driver */ +#define RFLG_ERRS 0x40 /* Error summary */ +#define RFLG_FRAM 0x20 /* Framing error */ +#define RFLG_OFLO 0x10 /* Message overflow */ +#define RFLG_CRC 0x08 /* CRC error */ +#define RFLG_STP 0x02 /* Start of packet */ +#define RFLG_ENP 0x01 /* End of packet */ + +#define RFLG_BITS "\10\10OWN\7ERRS\6FRAM\5OFLO\4CRC\2STP\1ENP" + +#define RERR_BUFL 0x8000 /* Buffer length error */ +#define RERR_UBTO 0x4000 /* UNIBUS tiemout */ +#define RERR_NCHN 0x2000 /* No data chaining */ +#define RERR_MLEN 0x0fff /* Message length */ + +#define RERR_BITS "\20\20BUFL\17UBTO\16NCHN" + +/* mode description bits */ +#define MOD_HDX 0x0001 /* Half duplex mode */ +#define MOD_LOOP 0x0004 /* Enable internal loopback */ +#define MOD_DTCR 0x0008 /* Disables CRC generation */ +#define MOD_DMNT 0x0200 /* Disable maintenance features */ +#define MOD_ECT 0x0400 /* Enable collision test */ +#define MOD_TPAD 0x1000 /* Transmit message pad enable */ +#define MOD_DRDC 0x2000 /* Disable data chaining */ +#define MOD_ENAL 0x4000 /* Enable all multicast */ +#define MOD_PROM 0x8000 /* Enable promiscuous mode */ + +struct de_buf { + struct ether_header db_head; /* header */ + char db_data[ETHERMTU]; /* packet data */ + int db_crc; /* CRC - on receive only */ +}; diff --git a/sys/arch/vax/if/if_qe.c b/sys/arch/vax/if/if_qe.c new file mode 100644 index 00000000000..fbf584fd09e --- /dev/null +++ b/sys/arch/vax/if/if_qe.c @@ -0,0 +1,975 @@ +/* $NetBSD: if_qe.c,v 1.4.2.1 1995/10/15 13:56:26 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Digital Equipment Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_qe.c 7.20 (Berkeley) 3/28/91 + */ + +/* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 */ + +/**************************************************************** + * * + * Licensed from Digital Equipment Corporation * + * Copyright (c) * + * Digital Equipment Corporation * + * Maynard, Massachusetts * + * 1985, 1986 * + * All rights reserved. * + * * + * The Information in this software is subject to change * + * without notice and should not be construed as a commitment * + * by Digital Equipment Corporation. Digital makes no * + * representations about the suitability of this software for * + * any purpose. It is supplied "As Is" without expressed or * + * implied warranty. * + * * + * If the Regents of the University of California or its * + * licensees modify the software in a manner creating * + * derivative copyright rights, appropriate copyright * + * legends may be placed on the derivative work in addition * + * to that set forth above. * + * * + ****************************************************************/ +/* --------------------------------------------------------------------- + * Modification History + * + * 15-Apr-86 -- afd + * Rename "unused_multi" to "qunused_multi" for extending Generic + * kernel to MicroVAXen. + * + * 18-mar-86 -- jaw br/cvec changed to NOT use registers. + * + * 12 March 86 -- Jeff Chase + * Modified to handle the new MCLGET macro + * Changed if_qe_data.c to use more receive buffers + * Added a flag to poke with adb to log qe_restarts on console + * + * 19 Oct 85 -- rjl + * Changed the watch dog timer from 30 seconds to 3. VMS is using + * less than 1 second in their's. Also turned the printf into an + * mprintf. + * + * 09/16/85 -- Larry Cohen + * Add 43bsd alpha tape changes for subnet routing + * + * 1 Aug 85 -- rjl + * Panic on a non-existent memory interrupt and the case where a packet + * was chained. The first should never happen because non-existant + * memory interrupts cause a bus reset. The second should never happen + * because we hang 2k input buffers on the device. + * + * 1 Aug 85 -- rich + * Fixed the broadcast loopback code to handle Clusters without + * wedging the system. + * + * 27 Feb. 85 -- ejf + * Return default hardware address on ioctl request. + * + * 12 Feb. 85 -- ejf + * Added internal extended loopback capability. + * + * 27 Dec. 84 -- rjl + * Fixed bug that caused every other transmit descriptor to be used + * instead of every descriptor. + * + * 21 Dec. 84 -- rjl + * Added watchdog timer to mask hardware bug that causes device lockup. + * + * 18 Dec. 84 -- rjl + * Reworked driver to use q-bus mapping routines. MicroVAX-I now does + * copying instead of m-buf shuffleing. + * A number of deficencies in the hardware/firmware were compensated + * for. See comments in qestart and qerint. + * + * 14 Nov. 84 -- jf + * Added usage counts for multicast addresses. + * Updated general protocol support to allow access to the Ethernet + * header. + * + * 04 Oct. 84 -- jf + * Added support for new ioctls to add and delete multicast addresses + * and set the physical address. + * Add support for general protocols. + * + * 14 Aug. 84 -- rjl + * Integrated Shannon changes. (allow arp above 1024 and ? ) + * + * 13 Feb. 84 -- rjl + * + * Initial version of driver. derived from IL driver. + * + * --------------------------------------------------------------------- + */ + +#include "qe.h" +#if NQE > 0 +/* + * Digital Q-BUS to NI Adapter + */ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/mbuf.h" +#include "sys/buf.h" +#include "sys/protosw.h" +#include "sys/socket.h" +#include "sys/ioctl.h" +#include "sys/errno.h" +#include "sys/syslog.h" +#include "sys/device.h" +#include "sys/time.h" +#include "sys/kernel.h" + +#include "net/if.h" +#include "net/netisr.h" +#include "net/route.h" + +#ifdef INET +#include "netinet/in.h" +#include "netinet/in_systm.h" +#include "netinet/in_var.h" +#include "netinet/ip.h" +#include "netinet/if_ether.h" +#endif + +#ifdef NS +#include "netns/ns.h" +#include "netns/ns_if.h" +#endif + +#ifdef ISO +#include "netiso/iso.h" +#include "netiso/iso_var.h" +extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[]; +#endif + +#include "vax/include/pte.h" +#include "vax/include/cpu.h" +#include "vax/include/mtpr.h" +#include "if_qereg.h" +#include "if_uba.h" +#include "vax/uba/ubareg.h" +#include "vax/uba/ubavar.h" + +#if NQE == 1 && !defined(QNIVERT) +#define NRCV 15 /* Receive descriptors */ +#else +#define NRCV 10 /* Receive descriptors */ +#endif +#define NXMT 5 /* Transmit descriptors */ +#define NTOT (NXMT + NRCV) + +#define QETIMEOUT 2 /* transmit timeout, must be > 1 */ +#define QESLOWTIMEOUT 40 /* timeout when no xmits in progress */ + +#define MINDATA 60 + +void qetimeout(int); + +/* + * Ethernet software status per interface. + * + * Each interface is referenced by a network interface structure, + * qe_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + */ +struct qe_softc { + struct arpcom qe_ac; /* Ethernet common part */ +#define qe_if qe_ac.ac_if /* network-visible interface */ +#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */ + struct ifubinfo qe_uba; /* Q-bus resources */ + volatile struct ifrw qe_ifr[NRCV]; /* for receive buffers; */ + volatile struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */ + int qe_flags; /* software state */ +#define QEF_RUNNING 0x01 +#define QEF_SETADDR 0x02 +#define QEF_FASTTIMEO 0x04 + int setupaddr; /* mapping info for setup pkts */ + int ipl; /* interrupt priority */ + struct qe_ring *rringaddr; /* mapping info for rings */ + struct qe_ring *tringaddr; /* "" */ + volatile struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */ + volatile struct qe_ring tring[NXMT+1]; /* Xmit ring descriptors */ + u_char setup_pkt[16][8]; /* Setup packet */ + int rindex; /* Receive index */ + int tindex; /* Transmit index */ + int otindex; /* Old transmit index */ + int qe_intvec; /* Interrupt vector */ + volatile struct qedevice *addr; /* device addr */ + int setupqueued; /* setup packet queued */ + int nxmit; /* Transmits in progress */ + int qe_restarts; /* timeouts */ +} qe_softc[NQE]; + +struct uba_device *qeinfo[NQE]; + +extern struct timeval time; + +int qeprobe(), qeattach(), qeintr(); +int qeinit(), qeioctl(), qereset(); +void qestart(); + +u_short qestd[] = { 0 }; +struct uba_driver qedriver = + { qeprobe, 0, qeattach, 0, qestd, "qe", qeinfo }; + +#define QEUNIT(x) minor(x) +/* + * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) + * but will actually take in up to 2048 bytes. To guard against the receiver + * chaining buffers (which we aren't prepared to handle) we allocate 2kb + * size buffers. + */ +#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */ +/* + * Probe the QNA to see if it's there + */ +qeprobe(reg, ui) + caddr_t reg; + struct uba_device *ui; +{ + /* register int br, cvec; r11, r10 value-result */ + register volatile struct qedevice *addr = (struct qedevice *)reg; + register volatile struct qe_ring *rp; + register struct qe_ring *prp; /* physical rp */ + register int i; + register volatile struct qe_softc *sc = &qe_softc[ui->ui_unit]; + +#ifdef lint + br = 0; cvec = br; br = cvec; + qeintr(0); +#endif + + /* + * The QNA interrupts on i/o operations. To do an I/O operation + * we have to setup the interface by transmitting a setup packet. + */ + addr->qe_csr = QE_RESET; + addr->qe_csr &= ~QE_RESET; + addr->qe_vector = (uba_hd[numuba].uh_lastiv -= 4); + + /* + * Map the communications area and the setup packet. + */ + sc->setupaddr = + uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0); + sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring, + sizeof(struct qe_ring) * (NTOT+2), 0); + prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr); + + /* + * The QNA will loop the setup packet back to the receive ring + * for verification, therefore we initialize the first + * receive & transmit ring descriptors and link the setup packet + * to them. + */ + qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr), + sizeof(sc->setup_pkt)); + qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr), + sizeof(sc->setup_pkt)); + + rp = (struct qe_ring *)sc->tring; + rp->qe_setup = 1; + rp->qe_eomsg = 1; + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_valid = 1; + + rp = (struct qe_ring *)sc->rring; + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_valid = 1; + + /* + * Get the addr off of the interface and place it into the setup + * packet. This code looks strange due to the fact that the address + * is placed in the setup packet in col. major order. + */ + for( i = 0 ; i < 6 ; i++ ) + sc->setup_pkt[i][1] = addr->qe_sta_addr[i]; + + qesetup( sc ); + /* + * Start the interface and wait for the packet. + */ + addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT; + addr->qe_rcvlist_lo = (short)((int)prp); + addr->qe_rcvlist_hi = (short)((int)prp >> 16); + prp += NRCV+1; + addr->qe_xmtlist_lo = (short)((int)prp); + addr->qe_xmtlist_hi = (short)((int)prp >> 16); + DELAY(10000); + /* + * All done with the bus resources. + */ + ubarelse(0, &sc->setupaddr); + ubarelse(0, (int *)&sc->rringaddr); + sc->ipl = 0x15; + return( sizeof(struct qedevice) ); +} + +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. + */ +qeattach(ui) + struct uba_device *ui; +{ + struct qe_softc *sc = &qe_softc[ui->ui_unit]; + struct ifnet *ifp = (struct ifnet *)&sc->qe_if; + volatile struct qedevice *addr=(struct qedevice *)ui->ui_addr; + int i; + + ifp->if_unit = ui->ui_unit; + ifp->if_name = "qe"; + /* + * The Deqna is cable of transmitting broadcasts, but + * doesn't listen to its own. + */ + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; + + /* + * Read the address from the prom and save it. + */ + for( i=0 ; i<6 ; i++ ) + sc->setup_pkt[i][1] = sc->qe_addr[i] = addr->qe_sta_addr[i] & 0xff; + addr->qe_vector |= 1; + printf("qe%d: %s, hardware address %s\n", ui->ui_unit, + addr->qe_vector&01 ? "delqa":"deqna", + ether_sprintf(sc->qe_addr)); + addr->qe_vector &= ~1; + + /* + * Save the vector for initialization at reset time. + */ + sc->qe_intvec = addr->qe_vector; + + ifp->if_start = qestart; + ifp->if_ioctl = qeioctl; + ifp->if_reset = qereset; + ifp->if_watchdog = qetimeout; + sc->qe_uba.iff_flags = UBA_CANTWAIT; + if_attach(ifp); + ether_ifattach(ifp); +} + +/* + * Reset of interface after UNIBUS reset. + * If interface is on specified uba, reset its state. + */ +qereset(unit, uban) + int unit, uban; +{ + register struct uba_device *ui; + + if (unit >= NQE || (ui = qeinfo[unit]) == 0 || ui->ui_alive == 0 || + ui->ui_ubanum != uban) + return; + printf(" qe%d", unit); + qe_softc[unit].qe_if.if_flags &= ~IFF_RUNNING; + qeinit(unit); +} + +/* + * Initialization of interface. + */ +qeinit(unit) + int unit; +{ + volatile struct qe_softc *sc = &qe_softc[unit]; + struct uba_device *ui = qeinfo[unit]; + volatile struct qedevice *addr=(struct qedevice *)ui->ui_addr; + struct ifnet *ifp = (struct ifnet *)&sc->qe_if; + int i; + int s; + + /* address not known */ + if (ifp->if_addrlist.tqh_first == (struct ifaddr *)0) + return; + if (sc->qe_flags & QEF_RUNNING) + return; + + if ((ifp->if_flags & IFF_RUNNING) == 0) { + /* + * map the communications area onto the device + */ + i = uballoc(0, (caddr_t)sc->rring, + sizeof(struct qe_ring) * (NTOT+2), 0); + if (i == 0) + goto fail; + sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i); + sc->tringaddr = sc->rringaddr + NRCV + 1; + i = uballoc(0, (caddr_t)sc->setup_pkt, + sizeof(sc->setup_pkt), 0); + if (i == 0) + goto fail; + sc->setupaddr = UBAI_ADDR(i); + /* + * init buffers and maps + */ + if (if_ubaminit(&sc->qe_uba, ui->ui_ubanum, + sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), + sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) { + fail: + printf("qe%d: can't allocate uba resources\n", unit); + sc->qe_if.if_flags &= ~IFF_UP; + return; + } + } + /* + * Init the buffer descriptors and indexes for each of the lists and + * loop them back to form a ring. + */ + for (i = 0; i < NRCV; i++) { + qeinitdesc( &sc->rring[i], + (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE); + sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; + sc->rring[i].qe_valid = 1; + } + qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0); + + sc->rring[i].qe_addr_lo = (short)((int)sc->rringaddr); + sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16); + sc->rring[i].qe_chain = 1; + sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET; + sc->rring[i].qe_valid = 1; + + for( i = 0 ; i <= NXMT ; i++ ) + qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0); + i--; + + sc->tring[i].qe_addr_lo = (short)((int)sc->tringaddr); + sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16); + sc->tring[i].qe_chain = 1; + sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET; + sc->tring[i].qe_valid = 1; + + sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; + + /* + * Take the interface out of reset, program the vector, + * enable interrupts, and tell the world we are up. + */ + s = splimp(); + addr->qe_vector = sc->qe_intvec; + sc->addr = addr; + addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | + QE_RCV_INT | QE_ILOOP; + addr->qe_rcvlist_lo = (short)((int)sc->rringaddr); + addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); + ifp->if_flags |= IFF_UP | IFF_RUNNING; + sc->qe_flags |= QEF_RUNNING; + qesetup( sc ); + qestart( ifp ); + sc->qe_if.if_timer = QESLOWTIMEOUT; /* Start watchdog */ + splx( s ); +} + +/* + * Start output on interface. + * + */ +void +qestart(ifp) + struct ifnet *ifp; +{ + int unit = ifp->if_unit; + struct uba_device *ui = qeinfo[unit]; + register volatile struct qe_softc *sc = &qe_softc[unit]; + register volatile struct qedevice *addr; + register volatile struct qe_ring *rp; + register index; + struct mbuf *m; + int buf_addr, len, s; + + + s = splimp(); + addr = (struct qedevice *)ui->ui_addr; + /* + * The deqna doesn't look at anything but the valid bit + * to determine if it should transmit this packet. If you have + * a ring and fill it the device will loop indefinately on the + * packet and continue to flood the net with packets until you + * break the ring. For this reason we never queue more than n-1 + * packets in the transmit ring. + * + * The microcoders should have obeyed their own defination of the + * flag and status words, but instead we have to compensate. + */ + for( index = sc->tindex; + sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ; + sc->tindex = index = ++index % NXMT){ + rp = &sc->tring[index]; + if( sc->setupqueued ) { + buf_addr = sc->setupaddr; + len = 128; + rp->qe_setup = 1; + sc->setupqueued = 0; + } else { + IF_DEQUEUE(&sc->qe_if.if_snd, m); + if( m == 0 ){ + splx(s); + return; + } + buf_addr = sc->qe_ifw[index].ifw_info; + len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m); + } + if( len < MINDATA ) + len = MINDATA; + /* + * Does buffer end on odd byte ? + */ + if( len & 1 ) { + len++; + rp->qe_odd_end = 1; + } + rp->qe_buf_len = -(len/2); + buf_addr = UBAI_ADDR(buf_addr); + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_addr_lo = (short)buf_addr; + rp->qe_addr_hi = (short)(buf_addr >> 16); + rp->qe_eomsg = 1; + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_valid = 1; + if (sc->nxmit++ == 0) { + sc->qe_flags |= QEF_FASTTIMEO; + sc->qe_if.if_timer = QETIMEOUT; + } + + /* + * See if the xmit list is invalid. + */ + if( addr->qe_csr & QE_XL_INVALID ) { + buf_addr = (int)(sc->tringaddr+index); + addr->qe_xmtlist_lo = (short)buf_addr; + addr->qe_xmtlist_hi = (short)(buf_addr >> 16); + } + } + splx(s); + return; +} + +/* + * Ethernet interface interrupt processor + */ +qeintr(uba, vector, level, unit) +{ + register volatile struct qe_softc *sc = &qe_softc[unit]; + volatile struct qedevice *addr = + (struct qedevice *)qeinfo[unit]->ui_addr; + int buf_addr, csr; + + splx(sc->ipl); + if (!(sc->qe_flags & QEF_FASTTIMEO)) + sc->qe_if.if_timer = QESLOWTIMEOUT; /* Restart timer clock */ + csr = addr->qe_csr; + addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; + if( csr & QE_RCV_INT ) + qerint( unit ); + if( csr & QE_XMIT_INT ) + qetint( unit ); + if( csr & QE_NEX_MEM_INT ) + printf("qe%d: Nonexistent memory interrupt\n", unit); + + if( addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == QE_NOTYET ) { + buf_addr = (int)&sc->rringaddr[sc->rindex]; + addr->qe_rcvlist_lo = (short)buf_addr; + addr->qe_rcvlist_hi = (short)(buf_addr >> 16); + } +} + +/* + * Ethernet interface transmit interrupt. + */ + +qetint(unit) + int unit; +{ + register volatile struct qe_softc *sc = &qe_softc[unit]; + register volatile struct qe_ring *rp; + register volatile struct ifxmt *ifxp; + int status1, setupflag; + short len; + + + while( sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 != QE_NOTYET && sc->nxmit > 0 ) { + /* + * Save the status words from the descriptor so that it can + * be released. + */ + rp = &sc->tring[sc->otindex]; + status1 = rp->qe_status1; + setupflag = rp->qe_setup; + len = (-rp->qe_buf_len) * 2; + if( rp->qe_odd_end ) + len++; + /* + * Init the buffer descriptor + */ + bzero((caddr_t)rp, sizeof(struct qe_ring)); + if( --sc->nxmit == 0 ) { + sc->qe_flags &= ~QEF_FASTTIMEO; + sc->qe_if.if_timer = QESLOWTIMEOUT; + } + if( !setupflag ) { + /* + * Do some statistics. + */ + sc->qe_if.if_opackets++; + sc->qe_if.if_collisions += ( status1 & QE_CCNT ) >> 4; + if (status1 & QE_ERROR) + sc->qe_if.if_oerrors++; + ifxp = &sc->qe_ifw[sc->otindex]; + if (ifxp->ifw_xtofree) { + m_freem(ifxp->ifw_xtofree); + ifxp->ifw_xtofree = 0; + } + } + sc->otindex = ++sc->otindex % NXMT; + } + qestart( &sc->qe_if ); +} + +/* + * Ethernet interface receiver interrupt. + * If can't determine length from type, then have to drop packet. + * Othewise decapsulate packet based on type and pass to type specific + * higher-level input routine. + */ +qerint(unit) + int unit; +{ + register volatile struct qe_softc *sc = &qe_softc[unit]; + register volatile struct qe_ring *rp; + register int nrcv = 0; + int len, status1, status2; + int bufaddr; + + /* + * Traverse the receive ring looking for packets to pass back. + * The search is complete when we find a descriptor not in use. + * + * As in the transmit case the deqna doesn't honor it's own protocols + * so there exists the possibility that the device can beat us around + * the ring. The proper way to guard against this is to insure that + * there is always at least one invalid descriptor. We chose instead + * to make the ring large enough to minimize the problem. With a ring + * size of 4 we haven't been able to see the problem. To be safe we + * doubled that to 8. + * + */ + while (sc->rring[sc->rindex].qe_status1 == QE_NOTYET && nrcv < NRCV) { + /* + * We got an interrupt but did not find an input packet + * where we expected one to be, probably because the ring + * was overrun. + * We search forward to find a valid packet and start + * processing from there. If no valid packet is found it + * means we processed all the packets during a previous + * interrupt and that the QE_RCV_INT bit was set while + * we were processing one of these earlier packets. In + * this case we can safely ignore the interrupt (by dropping + * through the code below). + */ + sc->rindex = (sc->rindex + 1) % NRCV; + nrcv++; + } + if (nrcv && nrcv < NRCV) + log(LOG_ERR, "qe%d: ring overrun, resync'd by skipping %d\n", + unit, nrcv); + + for( ; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ; sc->rindex = ++sc->rindex % NRCV ){ + rp = &sc->rring[sc->rindex]; + status1 = rp->qe_status1; + status2 = rp->qe_status2; + bzero((caddr_t)rp, sizeof(struct qe_ring)); + if( (status1 & QE_MASK) == QE_MASK ) + panic("qe: chained packet"); + len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60; + sc->qe_if.if_ipackets++; + + if (status1 & QE_ERROR) { + if ((status1 & QE_RUNT) == 0) + sc->qe_if.if_ierrors++; + } else { + /* + * We don't process setup packets. + */ + if( !(status1 & QE_ESETUP) ) + qeread(sc, &sc->qe_ifr[sc->rindex], + len - sizeof(struct ether_header)); + } + /* + * Return the buffer to the ring + */ + bufaddr = (int)UBAI_ADDR(sc->qe_ifr[sc->rindex].ifrw_info); + rp->qe_buf_len = -((MAXPACKETSIZE)/2); + rp->qe_addr_lo = (short)bufaddr; + rp->qe_addr_hi = (short)((int)bufaddr >> 16); + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_valid = 1; + } +} + +/* + * Process an ioctl request. + */ +qeioctl(ifp, cmd, data) + register struct ifnet *ifp; + int cmd; + caddr_t data; +{ + struct qe_softc *sc = &qe_softc[ifp->if_unit]; + struct ifaddr *ifa = (struct ifaddr *)data; + int s = splimp(), error = 0; + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + qeinit(ifp->if_unit); + switch(ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + arp_ifinit(&sc->qe_ac, ifa); + break; +#endif +#ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *)(sc->qe_addr); + else + qe_setaddr(ina->x_host.c_host, ifp->if_unit); + break; + } +#endif + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + sc->qe_flags & QEF_RUNNING) { + ((volatile struct qedevice *) + (qeinfo[ifp->if_unit]->ui_addr))->qe_csr = QE_RESET; + sc->qe_flags &= ~QEF_RUNNING; + } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == + IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0) + qerestart(sc); + break; + + default: + error = EINVAL; + + } + splx(s); + return (error); +} + +/* + * set ethernet address for unit + */ +qe_setaddr(physaddr, unit) + u_char *physaddr; + int unit; +{ + register volatile struct qe_softc *sc = &qe_softc[unit]; + register int i; + + for (i = 0; i < 6; i++) + sc->setup_pkt[i][1] = sc->qe_addr[i] = physaddr[i]; + sc->qe_flags |= QEF_SETADDR; + if (sc->qe_if.if_flags & IFF_RUNNING) + qesetup(sc); + qeinit(unit); +} + + +/* + * Initialize a ring descriptor with mbuf allocation side effects + */ +qeinitdesc(rp, addr, len) + register volatile struct qe_ring *rp; + caddr_t addr; /* mapped address */ + int len; +{ + /* + * clear the entire descriptor + */ + bzero((caddr_t)rp, sizeof(struct qe_ring)); + + if( len ) { + rp->qe_buf_len = -(len/2); + rp->qe_addr_lo = (short)((int)addr); + rp->qe_addr_hi = (short)((int)addr >> 16); + } +} +/* + * Build a setup packet - the physical address will already be present + * in first column. + */ +qesetup( sc ) + volatile struct qe_softc *sc; +{ + register i, j; + + /* + * Copy the target address to the rest of the entries in this row. + */ + for ( j = 0; j < 6 ; j++ ) + for ( i = 2 ; i < 8 ; i++ ) + sc->setup_pkt[j][i] = sc->setup_pkt[j][1]; + /* + * Duplicate the first half. + */ + bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64); + /* + * Fill in the broadcast (and ISO multicast) address(es). + */ + for ( i = 0; i < 6 ; i++ ) { + sc->setup_pkt[i][2] = 0xff; +#ifdef ISO + sc->setup_pkt[i][3] = all_es_snpa[i]; + sc->setup_pkt[i][4] = all_is_snpa[i]; + sc->setup_pkt[i][5] = all_l1is_snpa[i]; + sc->setup_pkt[i][6] = all_l2is_snpa[i]; +#endif + } + sc->setupqueued++; +} + +/* + * Pass a packet to the higher levels. + * We deal with the trailer protocol here. + */ +qeread(sc, ifrw, len) + register volatile struct qe_softc *sc; + volatile struct ifrw *ifrw; + int len; +{ + struct ether_header *eh; + struct mbuf *m; + int s; + struct ifqueue *inq; + + /* + * Deal with trailer protocol: if type is INET trailer + * get true type from first 16-bit word past data. + * Remember that type was trailer by setting off. + */ + + eh = (struct ether_header *)ifrw->ifrw_addr; + if (len == 0) + return; + + /* + * Pull packet off interface. Off is nonzero if packet + * has trailing header; qeget will then force this header + * information to be at the front, but we still have to drop + * the type and length which are at the front of any trailer data. + */ + m = if_ubaget(&sc->qe_uba, ifrw, len, &sc->qe_if); +#ifdef notdef +if (m) { +*(((u_long *)m->m_data)+0), +*(((u_long *)m->m_data)+1), +*(((u_long *)m->m_data)+2), +*(((u_long *)m->m_data)+3) +); } +#endif + + if (m) + ether_input((struct ifnet *)&sc->qe_if, eh, m); +} + +/* + * Watchdog timeout routine. There is a condition in the hardware that + * causes the board to lock up under heavy load. This routine detects + * the hang up and restarts the device. + */ +void +qetimeout(unit) + int unit; +{ + register volatile struct qe_softc *sc; + + sc = &qe_softc[unit]; +#ifdef notdef + log(LOG_ERR, "qe%d: transmit timeout, restarted %d\n", + unit, sc->qe_restarts++); +#endif + qerestart(sc); +} +/* + * Restart for board lockup problem. + */ +qerestart(sc) + register volatile struct qe_softc *sc; +{ + register struct ifnet *ifp = (struct ifnet *)&sc->qe_if; + register volatile struct qedevice *addr = sc->addr; + register volatile struct qe_ring *rp; + register i; + + addr->qe_csr = QE_RESET; + addr->qe_csr &= ~QE_RESET; + qesetup( sc ); + for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) { + rp->qe_flag = rp->qe_status1 = QE_NOTYET; + rp->qe_valid = 0; + } + sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; + addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | + QE_RCV_INT | QE_ILOOP; + addr->qe_rcvlist_lo = (short)((int)sc->rringaddr); + addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); + sc->qe_flags |= QEF_RUNNING; + qestart(ifp); +} + +qe_match(){ + printf("qe_match\n"); + return 0; +} + +void +qe_attach(){ + printf("qe_attach\n"); +} + +struct cfdriver qecd = + { 0,"qe",qe_match, qe_attach, DV_IFNET, sizeof(struct uba_driver) }; + +#endif diff --git a/sys/arch/vax/if/if_qereg.h b/sys/arch/vax/if/if_qereg.h new file mode 100644 index 00000000000..fe608daa42a --- /dev/null +++ b/sys/arch/vax/if/if_qereg.h @@ -0,0 +1,172 @@ +/* $NetBSD: if_qereg.h,v 1.1 1995/03/30 20:26:41 ragge Exp $ */ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Digital Equipment Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_qereg.h 7.3 (Berkeley) 6/28/90 + */ + +/* @(#)if_qereg.h 1.2 (ULTRIX) 1/3/85 */ + +/**************************************************************** + * * + * Licensed from Digital Equipment Corporation * + * Copyright (c) * + * Digital Equipment Corporation * + * Maynard, Massachusetts * + * 1985, 1986 * + * All rights reserved. * + * * + * The Information in this software is subject to change * + * without notice and should not be construed as a commitment * + * by Digital Equipment Corporation. Digital makes no * + * representations about the suitability of this software for * + * any purpose. It is supplied "As Is" without expressed or * + * implied warranty. * + * * + * If the Regents of the University of California or its * + * licensees modify the software in a manner creating * + * diriviative copyright rights, appropriate copyright * + * legends may be placed on the drivative work in addition * + * to that set forth above. * + * * + ****************************************************************/ +/* --------------------------------------------------------------------- + * Modification History + * + * 13 Feb. 84 -- rjl + * + * Initial version of driver. derived from IL driver. + * + * --------------------------------------------------------------------- + */ + +/* + * Digital Q-BUS to NI Adapter + */ +struct qedevice { + u_short qe_sta_addr[2]; /* Station address (actually 6 */ + u_short qe_rcvlist_lo; /* Receive list lo address */ + u_short qe_rcvlist_hi; /* Receive list hi address */ + u_short qe_xmtlist_lo; /* Transmit list lo address */ + u_short qe_xmtlist_hi; /* Transmit list hi address */ + u_short qe_vector; /* Interrupt vector */ + u_short qe_csr; /* Command and Status Register */ +}; + +/* + * Command and status bits (csr) + */ +#define QE_RCV_ENABLE 0x0001 /* Receiver enable */ +#define QE_RESET 0x0002 /* Software reset */ +#define QE_NEX_MEM_INT 0x0004 /* Non existant mem interrupt */ +#define QE_LOAD_ROM 0x0008 /* Load boot/diag from rom */ +#define QE_XL_INVALID 0x0010 /* Transmit list invalid */ +#define QE_RL_INVALID 0x0020 /* Receive list invalid */ +#define QE_INT_ENABLE 0x0040 /* Interrupt enable */ +#define QE_XMIT_INT 0x0080 /* Transmit interrupt */ +#define QE_ILOOP 0x0100 /* Internal loopback */ +#define QE_ELOOP 0x0200 /* External loopback */ +#define QE_STIM_ENABLE 0x0400 /* Sanity timer enable */ +#define QE_POWERUP 0x1000 /* Tranceiver power on */ +#define QE_CARRIER 0x2000 /* Carrier detect */ +#define QE_RCV_INT 0x8000 /* Receiver interrupt */ + +/* + * Transmit and receive ring discriptor --------------------------- + * + * The QNA uses the flag, status1 and the valid bit as a handshake/semiphore + * mechinism. + * + * The flag word is written on ( bits 15,15 set to 1 ) when it reads the + * descriptor. If the valid bit is set it considers the address to be valid. + * When it uses the buffer pointed to by the valid address it sets status word + * one. + */ +struct qe_ring { + u_short qe_flag; /* Buffer utilization flags */ + u_short qe_addr_hi:6, /* Hi order bits of buffer addr */ + qe_odd_begin:1, /* Odd byte begin and end (xmit)*/ + qe_odd_end:1, + qe_fill1:4, + qe_setup:1, /* Setup packet */ + qe_eomsg:1, /* End of message flag */ + qe_chain:1, /* Chain address instead of buf */ + qe_valid:1; /* Address field is valid */ + u_short qe_addr_lo; /* Low order bits of address */ + short qe_buf_len; /* Negative buffer length */ + u_short qe_status1; /* Status word one */ + u_short qe_status2; /* Status word two */ +}; + +/* + * Status word definations (receive) + * word1 + */ +#define QE_OVF 0x0001 /* Receiver overflow */ +#define QE_CRCERR 0x0002 /* CRC error */ +#define QE_FRAME 0x0004 /* Framing alignment error */ +#define QE_SHORT 0x0008 /* Packet size < 10 bytes */ +#define QE_RBL_HI 0x0700 /* Hi bits of receive len */ +#define QE_RUNT 0x0800 /* Runt packet */ +#define QE_DISCARD 0x1000 /* Discard the packet */ +#define QE_ESETUP 0x2000 /* Looped back setup or eloop */ +#define QE_ERROR 0x4000 /* Receiver error */ +#define QE_LASTNOT 0x8000 /* Not the last in the packet */ +/* word2 */ +#define QE_RBL_LO 0x00ff /* Low bits of receive len */ + +/* + * Status word definations (transmit) + * word1 + */ +#define QE_CCNT 0x00f0 /* Collision count this packet */ +#define QE_FAIL 0x0100 /* Heart beat check failure */ +#define QE_ABORT 0x0200 /* Transmission abort */ +#define QE_STE16 0x0400 /* Sanity timer default on */ +#define QE_NOCAR 0x0800 /* No carrier */ +#define QE_LOSS 0x1000 /* Loss of carrier while xmit */ +/* word2 */ +#define QE_TDR 0x3fff /* Time domain reflectometry */ + +/* + * General constant definations + */ +#define QEALLOC 0 /* Allocate an mbuf */ +#define QENOALLOC 1 /* No mbuf allocation */ +#define QEDEALLOC 2 /* Release an mbuf chain */ + +#define QE_NOTYET 0x8000 /* Descriptor not in use yet */ +#define QE_INUSE 0x4000 /* Descriptor being used by QNA */ +#define QE_MASK 0xc000 /* Lastnot/error/used mask */ diff --git a/sys/arch/vax/if/if_uba.c b/sys/arch/vax/if/if_uba.c new file mode 100644 index 00000000000..1ef5b3f8179 --- /dev/null +++ b/sys/arch/vax/if/if_uba.c @@ -0,0 +1,390 @@ +/* $NetBSD: if_uba.c,v 1.6 1995/04/11 06:19:09 mycroft Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_uba.c 7.16 (Berkeley) 12/16/90 + */ + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/malloc.h" +#include "sys/mbuf.h" +#include "sys/map.h" +#include "sys/buf.h" +#include "sys/socket.h" +#include "sys/syslog.h" + +#include "net/if.h" + +#include "vax/include/pte.h" +#include "vax/include/mtpr.h" +#include "if_uba.h" +#include "vax/include/vmparam.h" +#include "vax/uba/ubareg.h" +#include "vax/uba/ubavar.h" +#include "machine/macros.h" + +static if_ubaalloc(struct ifubinfo *, struct ifrw *, int); +static rcv_xmtbuf(struct ifxmt *); +static restor_xmtbuf(struct ifxmt *); + +/* + * Routines supporting UNIBUS network interfaces. + * + * TODO: + * Support interfaces using only one BDP statically. + */ + +/* + * Init UNIBUS for interface on uban whose headers of size hlen are to + * end on a page boundary. We allocate a UNIBUS map register for the page + * with the header, and nmr more UNIBUS map registers for i/o on the adapter, + * doing this once for each read and once for each write buffer. We also + * allocate page frames in the mbuffer pool for these pages. + */ +if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw) + register struct ifubinfo *ifu; + int uban, hlen, nmr, nr, nw; + register struct ifrw *ifr; + register struct ifxmt *ifw; +{ + register caddr_t p; + caddr_t cp; + int i, nclbytes, off; + + if (hlen) + off = MCLBYTES - hlen; + else + off = 0; + nclbytes = roundup(nmr * NBPG, MCLBYTES); + if (hlen) + nclbytes += MCLBYTES; + if (ifr[0].ifrw_addr) + cp = ifr[0].ifrw_addr - off; + else { + cp = (caddr_t)malloc((u_long)((nr + nw) * nclbytes), M_DEVBUF, + M_NOWAIT); + if (cp == 0) + return (0); + p = cp; + for (i = 0; i < nr; i++) { + ifr[i].ifrw_addr = p + off; + p += nclbytes; + } + for (i = 0; i < nw; i++) { + ifw[i].ifw_base = p; + ifw[i].ifw_addr = p + off; + p += nclbytes; + } + ifu->iff_hlen = hlen; + ifu->iff_uban = uban; + ifu->iff_uba = uba_hd[uban].uh_uba; + ifu->iff_ubamr = uba_hd[uban].uh_mr; + } + for (i = 0; i < nr; i++) + if (if_ubaalloc(ifu, &ifr[i], nmr) == 0) { + nr = i; + nw = 0; + goto bad; + } + for (i = 0; i < nw; i++) + if (if_ubaalloc(ifu, &ifw[i].ifrw, nmr) == 0) { + nw = i; + goto bad; + } + while (--nw >= 0) { + for (i = 0; i < nmr; i++) + ifw[nw].ifw_wmap[i] = ifw[nw].ifw_mr[i]; + ifw[nw].ifw_xswapd = 0; + ifw[nw].ifw_flags = IFRW_W; + ifw[nw].ifw_nmr = nmr; + } + return (1); +bad: + while (--nw >= 0) + ubarelse(ifu->iff_uban, &ifw[nw].ifw_info); + while (--nr >= 0) + ubarelse(ifu->iff_uban, &ifr[nr].ifrw_info); + free(cp, M_DEVBUF); + ifr[0].ifrw_addr = 0; + return (0); +} + +/* + * Setup an ifrw structure by allocating UNIBUS map registers, + * possibly a buffered data path, and initializing the fields of + * the ifrw structure to minimize run-time overhead. + */ +static +if_ubaalloc(ifu, ifrw, nmr) + struct ifubinfo *ifu; + register struct ifrw *ifrw; + int nmr; +{ + register int info; + + info = + uballoc(ifu->iff_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen, + ifu->iff_flags); + if (info == 0) + return (0); + ifrw->ifrw_info = info; + ifrw->ifrw_bdp = UBAI_BDP(info); + ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT); + ifrw->ifrw_mr = &ifu->iff_ubamr[UBAI_MR(info) + (ifu->iff_hlen? 1 : 0)]; + return (1); +} + +/* + * Pull read data off a interface. + * Totlen is length of data, with local net header stripped. + * When full cluster sized units are present + * on the interface on cluster boundaries we can get them more + * easily by remapping, and take advantage of this here. + * Save a pointer to the interface structure and the total length, + * so that protocols can determine where incoming packets arrived. + * Note: we may be called to receive from a transmit buffer by some + * devices. In that case, we must force normal mapping of the buffer, + * so that the correct data will appear (only unibus maps are + * changed when remapping the transmit buffers). + */ +struct mbuf * +if_ubaget(ifu, ifr, totlen, ifp) + struct ifubinfo *ifu; + register struct ifrw *ifr; + register int totlen; + struct ifnet *ifp; +{ + struct mbuf *top, **mp; + register struct mbuf *m; + register caddr_t cp = ifr->ifrw_addr + ifu->iff_hlen, pp; + register int len; + top = 0; + mp = ⊤ + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0){ + return ((struct mbuf *)NULL); + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; + + if (ifr->ifrw_flags & IFRW_W){ + rcv_xmtbuf((struct ifxmt *)ifr); + } + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + top = 0; + goto out; + } + m->m_len = MLEN; + } + len = totlen; + if (len >= MINCLSIZE) { + struct pte *cpte, *ppte; + int x, *ip, i; + + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0){ + goto nopage; + } + len = min(len, MCLBYTES); + m->m_len = len; + if (!claligned(cp)){ + goto copy; + } + /* + * Switch pages mapped to UNIBUS with new page pp, + * as quick form of copy. Remap UNIBUS and invalidate. + */ + pp = mtod(m, char *); + cpte = (struct pte *)kvtopte(cp); + ppte = (struct pte *)kvtopte(pp); + x = vax_btop(cp - ifr->ifrw_addr); + ip = (int *)&ifr->ifrw_mr[x]; + for (i = 0; i < MCLBYTES/NBPG; i++) { + struct pte t; + t = *ppte; *ppte++ = *cpte; *cpte = t; + *ip++ = cpte++->pg_pfn|ifr->ifrw_proto; + mtpr(cp,PR_TBIS); + cp += NBPG; + mtpr((caddr_t)pp,PR_TBIS); + pp += NBPG; + } + goto nocopy; + } +nopage: + if (len < m->m_len) { + /* + * Place initial small packet/header at end of mbuf. + */ + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; +copy: + bcopy(cp, mtod(m, caddr_t), (unsigned)len); + cp += len; +nocopy: + *mp = m; + mp = &m->m_next; + totlen -= len; + } +out: + if (ifr->ifrw_flags & IFRW_W){ + restor_xmtbuf((struct ifxmt *)ifr); + } + return (top); +} + +/* + * Change the mapping on a transmit buffer so that if_ubaget may + * receive from that buffer. Copy data from any pages mapped to Unibus + * into the pages mapped to normal kernel virtual memory, so that + * they can be accessed and swapped as usual. We take advantage + * of the fact that clusters are placed on the xtofree list + * in inverse order, finding the last one. + */ +static +rcv_xmtbuf(ifw) + register struct ifxmt *ifw; +{ + register struct mbuf *m; + struct mbuf **mprev; + register i; + char *cp; + + while (i = ffs((long)ifw->ifw_xswapd)) { + cp = ifw->ifw_base + i * MCLBYTES; + i--; + ifw->ifw_xswapd &= ~(1<<i); + mprev = &ifw->ifw_xtofree; + for (m = ifw->ifw_xtofree; m && m->m_next; m = m->m_next) + mprev = &m->m_next; + if (m == NULL) + break; + bcopy(mtod(m, caddr_t), cp, MCLBYTES); + (void) m_free(m); + *mprev = NULL; + } + ifw->ifw_xswapd = 0; + for (i = 0; i < ifw->ifw_nmr; i++) + ifw->ifw_mr[i] = ifw->ifw_wmap[i]; +} + +/* + * Put a transmit buffer back together after doing an if_ubaget on it, + * which may have swapped pages. + */ +static +restor_xmtbuf(ifw) + register struct ifxmt *ifw; +{ + register i; + + for (i = 0; i < ifw->ifw_nmr; i++) + ifw->ifw_wmap[i] = ifw->ifw_mr[i]; +} + +/* + * Map a chain of mbufs onto a network interface + * in preparation for an i/o operation. + * The argument chain of mbufs includes the local network + * header which is copied to be in the mapped, aligned + * i/o space. + */ +if_ubaput(ifu, ifw, m) + struct ifubinfo *ifu; + register struct ifxmt *ifw; + register struct mbuf *m; +{ + register struct mbuf *mp; + register caddr_t cp, dp; + register int i; + int xswapd = 0; + int x, cc, t; + + cp = ifw->ifw_addr; + while (m) { + dp = mtod(m, char *); + if (claligned(cp) && claligned(dp) && + (m->m_len == MCLBYTES || m->m_next == (struct mbuf *)0)) { + struct pte *pte; + int *ip; + + pte = (struct pte *)kvtopte(dp); + x = vax_btop(cp - ifw->ifw_addr); + ip = (int *)&ifw->ifw_mr[x]; + for (i = 0; i < MCLBYTES/NBPG; i++) + *ip++ = ifw->ifw_proto | pte++->pg_pfn; + xswapd |= 1 << (x>>(MCLSHIFT-PGSHIFT)); + mp = m->m_next; + m->m_next = ifw->ifw_xtofree; + ifw->ifw_xtofree = m; + cp += m->m_len; + } else { + bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); + cp += m->m_len; + MFREE(m, mp); + } + m = mp; + } + + /* + * Xswapd is the set of clusters we just mapped out. Ifu->iff_xswapd + * is the set of clusters mapped out from before. We compute + * the number of clusters involved in this operation in x. + * Clusters mapped out before and involved in this operation + * should be unmapped so original pages will be accessed by the device. + */ + cc = cp - ifw->ifw_addr; + x = ((cc - ifu->iff_hlen) + MCLBYTES - 1) >> MCLSHIFT; + ifw->ifw_xswapd &= ~xswapd; + while (i = ffs((long)ifw->ifw_xswapd)) { + i--; + if (i >= x) + break; + ifw->ifw_xswapd &= ~(1<<i); + i *= MCLBYTES/NBPG; + for (t = 0; t < MCLBYTES/NBPG; t++) { + ifw->ifw_mr[i] = ifw->ifw_wmap[i]; + i++; + } + } + ifw->ifw_xswapd |= xswapd; + return (cc); +} diff --git a/sys/arch/vax/if/if_uba.h b/sys/arch/vax/if/if_uba.h new file mode 100644 index 00000000000..b1d6a2a203f --- /dev/null +++ b/sys/arch/vax/if/if_uba.h @@ -0,0 +1,136 @@ +/* $NetBSD: if_uba.h,v 1.3 1995/05/11 16:53:12 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_uba.h 7.4 (Berkeley) 6/28/90 + */ + +/* + * Structure and routine definitions + * for UNIBUS network interfaces. + */ + +#define IF_MAXNUBAMR 10 +/* + * Each interface has structures giving information + * about UNIBUS resources held by the interface + * for each send and receive buffer. + * + * We hold IF_NUBAMR map registers for datagram data, starting + * at ifr_mr. Map register ifr_mr[-1] maps the local network header + * ending on the page boundary. Bdp's are reserved for read and for + * write, given by ifr_bdp. The prototype of the map register for + * read and for write is saved in ifr_proto. + * + * When write transfers are not full pages on page boundaries we just + * copy the data into the pages mapped on the UNIBUS and start the + * transfer. If a write transfer is of a (1024 byte) page on a page + * boundary, we swap in UNIBUS pte's to reference the pages, and then + * remap the initial pages (from ifu_wmap) when the transfer completes. + * + * When read transfers give whole pages of data to be input, we + * allocate page frames from a network page list and trade them + * with the pages already containing the data, mapping the allocated + * pages to replace the input pages for the next UNIBUS data input. + */ + +/* + * Information per interface. + */ +struct ifubinfo { + short iff_uban; /* uba number */ + short iff_hlen; /* local net header length */ + struct uba_regs *iff_uba; /* uba adaptor regs, in vm */ + struct pte *iff_ubamr; /* uba map regs, in vm */ + short iff_flags; /* used during uballoc's */ +}; + +/* + * Information per buffer. + */ +struct ifrw { + caddr_t ifrw_addr; /* virt addr of header */ + short ifrw_bdp; /* unibus bdp */ + short ifrw_flags; /* type, etc. */ +#define IFRW_W 0x01 /* is a transmit buffer */ + int ifrw_info; /* value from ubaalloc */ + int ifrw_proto; /* map register prototype */ + struct pte *ifrw_mr; /* base of map registers */ +}; + +/* + * Information per transmit buffer, including the above. + */ +struct ifxmt { + struct ifrw ifrw; + caddr_t ifw_base; /* virt addr of buffer */ + struct pte ifw_wmap[IF_MAXNUBAMR]; /* base pages for output */ + struct mbuf *ifw_xtofree; /* pages being dma'd out */ + short ifw_xswapd; /* mask of clusters swapped */ + short ifw_nmr; /* number of entries in wmap */ +}; +#define ifw_addr ifrw.ifrw_addr +#define ifw_bdp ifrw.ifrw_bdp +#define ifw_flags ifrw.ifrw_flags +#define ifw_info ifrw.ifrw_info +#define ifw_proto ifrw.ifrw_proto +#define ifw_mr ifrw.ifrw_mr + +/* + * Most interfaces have a single receive and a single transmit buffer, + * and use struct ifuba to store all of the unibus information. + */ +struct ifuba { + struct ifubinfo ifu_info; + struct ifrw ifu_r; + struct ifxmt ifu_xmt; +}; + +#define ifu_uban ifu_info.iff_uban +#define ifu_hlen ifu_info.iff_hlen +#define ifu_uba ifu_info.iff_uba +#define ifu_ubamr ifu_info.iff_ubamr +#define ifu_flags ifu_info.iff_flags +#define ifu_w ifu_xmt.ifrw +#define ifu_xtofree ifu_xmt.ifw_xtofree + +#ifdef _KERNEL +#define if_ubainit(ifuba, uban, hlen, nmr) \ + if_ubaminit(&(ifuba)->ifu_info, uban, hlen, nmr, \ + &(ifuba)->ifu_r, 1, &(ifuba)->ifu_xmt, 1) +#define if_rubaget(ifu, totlen, off0, ifp) \ + if_ubaget(&(ifu)->ifu_info, &(ifu)->ifu_r, totlen, off0, ifp) +#define if_wubaput(ifu, m) \ + if_ubaput(&(ifu)->ifu_info, &(ifu)->ifu_xmt, m) +struct mbuf *if_ubaget(); +#endif diff --git a/sys/arch/vax/include/ansi.h b/sys/arch/vax/include/ansi.h new file mode 100644 index 00000000000..5af1f55f91a --- /dev/null +++ b/sys/arch/vax/include/ansi.h @@ -0,0 +1,60 @@ +/* $NetBSD: ansi.h,v 1.3 1994/10/26 08:01:59 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 7.1 (Berkeley) 3/9/91 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _SIZE_T_ + * typedef _SIZE_T_ size_t; + * #undef _SIZE_T_ + * #endif + * + * Thanks, ANSI! + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */ +#define _BSD_SIZE_T_ unsigned int /* sizeof() */ +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_TIME_T_ long /* time() */ +#define _BSD_VA_LIST_ char * /* va_list */ +#define _BSD_WCHAR_T_ int /* wchar_t */ + +#endif /* _ANSI_H_ */ diff --git a/sys/arch/vax/include/asm.h b/sys/arch/vax/include/asm.h new file mode 100644 index 00000000000..e175b77bdc2 --- /dev/null +++ b/sys/arch/vax/include/asm.h @@ -0,0 +1,76 @@ +/* $NetBSD: asm.h,v 1.3 1995/05/03 19:53:40 ragge Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + * @(#)DEFS.h 5.3 (Berkeley) 6/1/90 + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#define R0 0x001 +#define R1 0x002 +#define R2 0x004 +#define R3 0x008 +#define R4 0x010 +#define R5 0x020 +#define R6 0x040 +#define R7 0x080 +#define R8 0x100 +#define R9 0x200 +#define R10 0x400 +#define R11 0x800 + +#ifdef __STDC__ +# define _FUNC(x) _ ## x ## : +# define _GLOB(x) .globl _ ## x +#else +# define _FUNC(x) _/**/x: +# define _GLOB(x) .globl _/**/x +#endif + +#ifdef PROF +#define ENTRY(x,regs) \ + _GLOB(x);.align 2;_FUNC(x);.word regs;jsb mcount; +#else +#define ENTRY(x,regs) \ + _GLOB(x);.align 2;_FUNC(x);.word regs; +#endif + +#define ASMSTR .asciz + +#endif /* !_MACHINE_ASM_H_ */ diff --git a/sys/arch/vax/include/cdefs.h b/sys/arch/vax/include/cdefs.h new file mode 100644 index 00000000000..0468cc9e196 --- /dev/null +++ b/sys/arch/vax/include/cdefs.h @@ -0,0 +1,35 @@ +/* $NetBSD: cdefs.h,v 1.2 1995/03/23 20:10:53 jtc Exp $ */ + +/* + * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#ifdef __STDC__ +#define _C_LABEL(x) _STRING(_ ## x) +#else +#define _C_LABEL(x) _STRING(_/**/x) +#endif + +#ifdef __GNUC__ +#ifdef __STDC__ +#define __indr_reference(sym,alias) \ + __asm__(".stabs \"_" #alias "\",11,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs \"" msg "\",30,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#else +#define __indr_reference(sym,alias) \ + __asm__(".stabs \"_/**/alias\",11,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs msg,30,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#endif +#endif + +#endif /* !_MACHINE_CDEFS_H_ */ diff --git a/sys/arch/vax/include/cpu.h b/sys/arch/vax/include/cpu.h new file mode 100644 index 00000000000..b7cdd1855a1 --- /dev/null +++ b/sys/arch/vax/include/cpu.h @@ -0,0 +1,88 @@ +/* $NetBSD: cpu.h,v 1.12 1995/06/05 17:17:57 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden + * 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 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 */ + +#include "sys/cdefs.h" +#include "machine/mtpr.h" +#include "machine/pcb.h" + +#define enablertclock() +#define cpu_wait(p) +#define cpu_swapout(p) + + +extern volatile int cpunumber; +extern struct cpu_dep cpu_calls[]; + +struct cpu_dep { + int (*cpu_loinit)(); /* Locore init before everything else */ + int (*cpu_clock)(); /* CPU dependent clock handling */ + int (*cpu_mchk)(); /* Machine check handling */ + int (*cpu_memerr)(); /* Memory subsystem errors */ + int (*cpu_conf)(); /* Autoconfiguration */ +}; + +struct clockframe { + int pc; + int ps; +}; + +#define setsoftnet() mtpr(12,PR_SIRR) +#define setsoftclock() mtpr(8,PR_SIRR) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ + +#define need_resched(){ \ + want_resched++; \ + mtpr(AST_OK,PR_ASTLVL); \ + } + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#define signotify(p) mtpr(AST_OK,PR_ASTLVL); + +extern int want_resched; /* resched() was called */ + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the hp300, request an ast to send us + * through trap, marking the proc as needing a profiling tick. + */ +#define need_proftick(p) {(p)->p_flag |= P_OWEUPC; mtpr(AST_OK,PR_ASTLVL); } + diff --git a/sys/arch/vax/include/db_machdep.h b/sys/arch/vax/include/db_machdep.h new file mode 100644 index 00000000000..b2a9fd68642 --- /dev/null +++ b/sys/arch/vax/include/db_machdep.h @@ -0,0 +1,73 @@ +/* $NetBSD: db_machdep.h,v 1.1 1995/06/16 15:17:27 ragge Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _VAX_DB_MACHDEP_H_ +#define _VAX_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + * Modified for vax out of i386 code. + */ + +#include <sys/param.h> +#include <vm/vm.h> +#include <machine/trap.h> + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef int db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((db_addr_t)(regs)->pc) + +#define BKPT_INST 0x03 /* breakpoint instruction */ +#define BKPT_SIZE (1) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define FIXUP_PC_AFTER_BREAK ddb_regs.pc -= BKPT_SIZE; + +#define db_clear_single_step(regs) ((regs)->psl &= ~PSL_T) +#define db_set_single_step(regs) ((regs)->psl |= PSL_T) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP) + +#define I_CALL 0xfb +#define I_RET 0x04 +#define I_IRET 0x02 + +#define inst_trap_return(ins) (((ins)&0xff) == I_IRET) +#define inst_return(ins) (((ins)&0xff) == I_RET) +#define inst_call(ins) (((ins)&0xff) == I_CALL) + +#define inst_load(ins) 0 +#define inst_store(ins) 0 + +#endif /* _VAX_DB_MACHDEP_H_ */ diff --git a/sys/arch/vax/include/disklabel.h b/sys/arch/vax/include/disklabel.h new file mode 100644 index 00000000000..e1505c58f6c --- /dev/null +++ b/sys/arch/vax/include/disklabel.h @@ -0,0 +1,47 @@ +/* $NetBSD: disklabel.h,v 1.2 1995/05/03 19:53:44 ragge Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * 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 Christopher G. Demetriou. + * 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. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 0 /* sector containing label */ +#define LABELOFFSET 64 /* offset of label in sector */ +#define MAXPARTITIONS 8 /* number of partitions */ +#define RAW_PART 3 /* raw partition: xx?c (XXX) */ + +/* Just a dummy */ +#ifndef LOCORE +struct cpu_disklabel { + int cd_dummy; /* must have one element. */ +}; +#endif +#endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/vax/include/endian.h b/sys/arch/vax/include/endian.h new file mode 100644 index 00000000000..05e1526909c --- /dev/null +++ b/sys/arch/vax/include/endian.h @@ -0,0 +1,112 @@ +/* $NetBSD: endian.h,v 1.6 1995/08/21 16:36:32 ragge Exp $ */ + +/* + * Copyright (c) 1987, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)endian.h 7.8 (Berkeley) 4/3/91 + */ + +#ifndef _VAX_ENDIAN_H_ +#define _VAX_ENDIAN_H_ + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + +#ifndef _POSIX_SOURCE + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define BYTE_ORDER LITTLE_ENDIAN + +#include <sys/cdefs.h> + +__BEGIN_DECLS +unsigned long htonl __P((unsigned long)); +unsigned short htons __P((unsigned short)); +unsigned long ntohl __P((unsigned long)); +unsigned short ntohs __P((unsigned short)); +__END_DECLS + +#ifdef __GNUC__ + +#define __byte_swap_long_variable(x) \ +({ register unsigned long __y, __x = (x); \ + \ + __asm ("rotl $-8, %1, %0; \ + insv %0, $16, $8, %0; \ + rotl $8, %1, r1; \ + movb r1, %0" \ + : "&=r" (__y) \ + : "r" (__x) \ + : "r1", "cc" ); \ + __y; }) + +#define __byte_swap_word_variable(x) \ +({ register unsigned short __y, __x = (x); \ + \ + __asm ("rotl $8, %1, %0; \ + rotl $-8, %1, r1; \ + movb r1, %0; \ + movzwl %0, %0" \ + : "&=r" (__y) \ + : "r" (__x) \ + : "r1", "cc" ); \ + __y; }) + + +#define __byte_swap_long(x) __byte_swap_long_variable(x) +#define __byte_swap_word(x) __byte_swap_word_variable(x) + +#define ntohl(x) __byte_swap_long(x) +#define ntohs(x) __byte_swap_word(x) +#define htonl(x) __byte_swap_long(x) +#define htons(x) __byte_swap_word(x) + +#endif /* __GNUC__ */ + +/* + * Macros for network/external number representation conversion. + */ +#define NTOHL(x) (x) = ntohl((unsigned long)(x)) +#define NTOHS(x) (x) = ntohs((unsigned long)(x)) +#define HTONL(x) (x) = htonl((unsigned long)(x)) +#define HTONS(x) (x) = htons((unsigned long)(x)) + +#endif /* _POSIX_SOURCE */ + +#endif /* _VAX_ENDIAN_H_ */ diff --git a/sys/arch/vax/include/exec.h b/sys/arch/vax/include/exec.h new file mode 100644 index 00000000000..3493e317afa --- /dev/null +++ b/sys/arch/vax/include/exec.h @@ -0,0 +1,49 @@ +/* $NetBSD: exec.h,v 1.4 1995/09/23 14:57:40 ragge Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VAX_EXEC_H_ +#define _VAX_EXEC_H_ + +#define __LDPGSZ 1024 + +/* Relocation format. */ +struct relocation_info_vax { + int r_address; /* offset in text or data segment */ + unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ + r_pcrel : 1, /* 1 if value should be pc-relative */ + r_length : 2, /* log base 2 of value's width */ + r_extern : 1, /* 1 if need to add symbol to value */ + r_baserel : 1, /* linkage table relative */ + r_jmptable : 1, /* relocate to jump table */ + r_relative : 1, /* load address relative */ + r_copy : 1; /* run time copy */ +}; +#define relocation_info relocation_info_vax + +#endif /* _VAX_EXEC_H_ */ diff --git a/sys/arch/vax/include/float.h b/sys/arch/vax/include/float.h new file mode 100644 index 00000000000..4ec3fa86baf --- /dev/null +++ b/sys/arch/vax/include/float.h @@ -0,0 +1,69 @@ +/* $NetBSD: float.h,v 1.2 1994/10/26 08:02:08 cgd Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)float.h 7.2 (Berkeley) 6/28/90 + */ + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS 1 /* FP addition rounds to nearest */ + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP -127 /* emin */ +#define FLT_MIN 2.93873588E-39F /* b**(emin-1) */ +#define FLT_MIN_10_EXP -38 /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 127 /* emax */ +#define FLT_MAX 1.70141173E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG 56 +#define DBL_EPSILON 2.775557561562891351E-17 +#define DBL_DIG 16 +#define DBL_MIN_EXP -127 +#define DBL_MIN 2.938735877055718770E-39 +#define DBL_MIN_10_EXP -38 +#define DBL_MAX_EXP 127 +#define DBL_MAX 1.701411834604692294E+38 +#define DBL_MAX_10_EXP 38 + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP diff --git a/sys/arch/vax/include/ioa.h b/sys/arch/vax/include/ioa.h new file mode 100644 index 00000000000..b09da95056f --- /dev/null +++ b/sys/arch/vax/include/ioa.h @@ -0,0 +1,36 @@ +/* $NetBSD: ioa.h,v 1.2 1994/10/26 08:02:09 cgd Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + diff --git a/sys/arch/vax/include/ka750.h b/sys/arch/vax/include/ka750.h new file mode 100644 index 00000000000..c6c0b494fa4 --- /dev/null +++ b/sys/arch/vax/include/ka750.h @@ -0,0 +1,41 @@ +/* $NetBSD: ka750.h,v 1.2 1994/10/26 08:02:10 cgd Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +/* ka750.h - definitioner enbart f|r VAX 750 940328/ragge */ + +#define V750UCODE(x) ((x>>8)&255) +#define V750HARDW(x) (x&255) + diff --git a/sys/arch/vax/include/kg.h b/sys/arch/vax/include/kg.h new file mode 100644 index 00000000000..e37e6f94c2c --- /dev/null +++ b/sys/arch/vax/include/kg.h @@ -0,0 +1,36 @@ +/* $NetBSD: kg.h,v 1.2 1994/10/26 08:02:11 cgd Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + diff --git a/sys/arch/vax/include/limits.h b/sys/arch/vax/include/limits.h new file mode 100644 index 00000000000..06d3f52e852 --- /dev/null +++ b/sys/arch/vax/include/limits.h @@ -0,0 +1,85 @@ +/* $NetBSD: limits.h,v 1.5 1995/05/28 18:38:30 ragge Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#define CHAR_BIT 8 /* number of bits in a char */ +/* #define CLK_TCK 60 /* ticks per second */ +#define MB_LEN_MAX 1 /* no multibyte characters */ + +#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */ +#define SCHAR_MAX 0x7f /* max value for a signed char */ + +#define UCHAR_MAX 0xff /* max value for an unsigned char */ +#define CHAR_MAX 0x7f /* max value for a char */ +#define CHAR_MIN (-0x7f-1) /* min value for a char */ + +#define USHRT_MAX 0xffff /* max value for an unsigned short */ +#define SHRT_MAX 0x7fff /* max value for a short */ +#define SHRT_MIN (-0x7fff-1) /* min value for a short */ + +#define UINT_MAX 0xffffffffU /* max value for an unsigned int */ +#define INT_MAX 0x7fffffff /* max value for an int */ +#define INT_MIN (-0x7fffffff-1) /* min value for an int */ + +#define ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +#define LONG_MAX 0x7fffffffL /* max value for a long */ +#define LONG_MIN (-0x7fffffffL-1)/* min value for a long */ + +#if !defined(_ANSI_SOURCE) +#define SSIZE_MAX INT_MAX /* max value for a ssize_t */ + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#define SIZE_T_MAX UINT_MAX /* max value for a size_t */ + +#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* !_POSIX_SOURCE && !_XOPEN_SOURCE */ +#endif /* !_ANSI_SOURCE */ + +#if (!defined(_ANSI_SOURCE)&&!defined(_POSIX_SOURCE)) || defined(_XOPEN_SOURCE) +#define LONG_BIT 32 +#define WORD_BIT 32 + +#define DBL_DIG 16 +#define DBL_MAX 1.701411834604692294E+38 +#define DBL_MIN 2.938735877055718770E-39 + +#define FLT_DIG 6 +#define FLT_MAX 1.70141173E+38F +#define FLT_MIN 2.93873588E-39F +#endif diff --git a/sys/arch/vax/include/loconf.h b/sys/arch/vax/include/loconf.h new file mode 100644 index 00000000000..62fb2f2b802 --- /dev/null +++ b/sys/arch/vax/include/loconf.h @@ -0,0 +1,57 @@ +/* $NetBSD: loconf.h,v 1.2 1994/10/26 08:02:13 cgd Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + + + +#define ISTACK_SIZE 4*NBPG + +/* XXX If kernel never crashes with kernel stack overflow trap + * kstack can be removed altogether. (Was 4*NBPG) + */ + +#define PROC_PAGES 0 + +#define MAX_UCODE 1024*1024*6 +#define MAX_UDATA 1024*1024*32 +#define MAX_USTCK 1024*1024*8 + +#define MAX_PROCESSES 32 + +#define PROCOFFSET (MAX_UCODE+MAX_UDATA+MAX_USTCK)/16384 + +/* Add 1 to USERPAGES if (MAX_PROCESSES mod 8) != 0 */ + +#define USERPAGES (MAX_UCODE+MAX_UDATA+MAX_USTCK)*MAX_PROCESSES/(512*128*128) diff --git a/sys/arch/vax/include/macros.h b/sys/arch/vax/include/macros.h new file mode 100644 index 00000000000..eb2dc2b9fd1 --- /dev/null +++ b/sys/arch/vax/include/macros.h @@ -0,0 +1,220 @@ +/* $NetBSD: macros.h,v 1.4 1995/07/05 08:22:21 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#if !defined(_VAX_MACROS_H_)&&!defined(ASSEMBLER)&&defined(_VAX_INLINE_) +#define _VAX_MACROS_H_ + +/* Here general macros are supposed to be stored */ + +static __inline__ int ffs(int reg){ + register int val; + + asm __volatile ("ffs $0,$32,%1,%0 + bneq 1f + mnegl $1,%0 + 1: incl %0" + : "&=r" (val) + : "r" (reg) ); + return val; +} + +static __inline__ void _remque(void*p){ + asm __volatile ("remque (%0),%0;clrl 4(%0)" + : + : "r" (p) + : "memory" ); +} + +static __inline__ void _insque(void*p, void*q) { + asm __volatile ("insque (%0), (%1)" + : + : "r" (p),"r" (q) + : "memory" ); +} + +#define bitset(bitnr,var) \ +({ asm __volatile ("bbss %0,%1,1f;1:;" \ + : \ + : "g" (bitnr), "g" (var)); \ +}) + +#define bitclear(bitnr,var) \ +({ asm __volatile ("bbsc %0,%1,1f;1:;" \ + : \ + : "g" (bitnr), "g" (var)); \ +}) + +#define bitisset(bitnr,var) \ +({ \ + register int val; \ + asm __volatile ("clrl %0;bbc %1,%2,1f;incl %0;1:;" \ + : "=g" (val) \ + : "g" (bitnr), "g" (var)); \ + val; \ +}) + +#define bitisclear(bitnr,var) \ +({ \ + register int val; \ + asm __volatile ("clrl %0;bbs %1,%2,1f;incl %0;1:;" \ + : "=g" (val) \ + : "g" (bitnr), "g" (var)); \ + val; \ +}) +static __inline__ void bcopy(const void*from, void*toe, u_int len) { + asm __volatile ("movc3 %0,(%1),(%2)" + : + : "r" (len),"r" (from),"r"(toe) + :"r0","r1","r2","r3","r4","r5"); +} + +static __inline__ void bzero(void*block, u_int len){ + asm __volatile ("movc5 $0,(%0),$0,%1,(%0)" + : + : "r" (block), "r" (len) + :"r0","r1","r2","r3","r4","r5"); +} + +static __inline__ int bcmp(const void *b1, const void *b2, size_t len){ + register ret; + + asm __volatile("cmpc3 %3,(%1),(%2);movl r0,%0" + : "=r" (ret) + : "r" (b1), "r" (b2), "r" (len) + : "r0","r1","r2","r3" ); + return ret; +} + +static __inline__ int locc(int mask, char *cp,u_int size){ + register ret; + + asm __volatile("locc %1,%2,(%3);movl r0,%0" + : "=r" (ret) + : "r" (mask),"r"(size),"r"(cp) + : "r0","r1" ); + return ret; +} + +static __inline__ int scanc(u_int size, u_char *cp,u_char *table, int mask){ + register ret; + + asm __volatile("scanc %1,(%2),(%3),%4;movl r0,%0" + : "=g"(ret) + : "r"(size),"r"(cp),"r"(table),"r"(mask) + : "r0","r1","r2","r3" ); + return ret; +} + +static __inline__ int skpc(int mask, int size, char *cp){ + register ret; + + asm __volatile("skpc %1,%2,(%3);movl r0,%0" + : "=g"(ret) + : "r"(mask),"r"(size),"r"(cp) + : "r0","r1" ); + return ret; +} +#if 0 +static __inline__ int imin(int a, int b){ + asm __volatile("cmpl %0,%2;bleq 1f;movl %2,%0;1:" + : "=r"(a) + : "r"(a),"r"(b) ); + return a; +} + +static __inline__ int imax(int a, int b){ + asm __volatile("cmpl %0,%2;bgeq 1f;movl %2,%0;1:" + : "=r"(a) + : "r"(a),"r"(b) ); + return a; +} + +static __inline__ int min(int a, int b){ + asm __volatile("cmpl %0,%2;bleq 1f;movl %2,%0;1:" + : "=r"(a) + : "r"(a),"r"(b) ); + return a; +} + +static __inline__ int max(int a, int b){ + asm __volatile("cmpl %0,%2;bgeq 1f;movl %2,%0;1:" + : "=r"(a) + : "r"(a),"r"(b) ); + return a; +} +#endif + +#define waitabit(tid) \ +({ \ + asm __volatile ("mfpr $27,r0;addl2 %0,r0;1:;mfpr $27,r1; \ + cmpl r0,r1;bneq 1b;" \ + : \ + : "g"(tid) \ + : "r0","r1"); \ +}) + +static __inline__ void blkcpy(const void*from, void*to, u_int len) { + asm __volatile(" + movl %0,r1 + movl %1,r3 + movl %2,r6 + jbr 2f + 1: subl2 r0,r6 + movc3 r0,(r1),(r3) + 2: movzwl $65535,r0 + cmpl r6,r0 + jgtr 1b + movc3 r6,(r1),(r3)" + : + : "g" (from), "g" (to), "g" (len) + : "r0","r1","r2","r3","r4","r5", "r6" ); +} + +static __inline__ void blkclr(void *blk, int len) { + asm __volatile(" + movl %0, r3 + movl %1, r6 + jbr 2f + 1: subl2 r0, r6 + movc5 $0,(r3),$0,r0,(r3) + 2: movzwl $65535,r0 + cmpl r6, r0 + jgtr 1b + movc5 $0,(r3),$0,r6,(r3)" + : + : "g" (blk), "g" (len) + : "r0","r1","r2","r3","r4","r5", "r6" ); +} + +#endif /* _VAX_MACROS_H_ */ diff --git a/sys/arch/vax/include/mtpr.h b/sys/arch/vax/include/mtpr.h new file mode 100644 index 00000000000..6da155b2f69 --- /dev/null +++ b/sys/arch/vax/include/mtpr.h @@ -0,0 +1,129 @@ +/* $NetBSD: mtpr.h,v 1.5 1995/05/03 19:53:45 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#ifndef _VAX_MTPR_H_ +#define _VAX_MTPR_H_ + +#include "machine/macros.h" + +/****************************************************************************** + + Processor register numbers in the VAX /IC + +******************************************************************************/ + + +#define PR_KSP 0 /* Kernel Stack Pointer */ +#define PR_ESP 1 /* Executive Stack Pointer */ +#define PR_SSP 2 /* Supervisor Stack Pointer */ +#define PR_USP 3 /* User Stack Pointer */ +#define PR_ISP 4 /* Interrupt Stack Pointer */ + +#define PR_P0BR 8 /* P0 Base Register */ +#define PR_P0LR 9 /* P0 Length Register */ +#define PR_P1BR 10 /* P1 Base Register */ +#define PR_P1LR 11 /* P1 Length Register */ +#define PR_SBR 12 /* System Base Register */ +#define PR_SLR 13 /* System Limit Register */ +#define PR_PCBB 16 /* Process Control Block Base */ +#define PR_SCBB 17 /* System Control Block Base */ +#define PR_IPL 18 /* Interrupt Priority Level */ +#define PR_ASTLVL 19 /* AST Level */ +#define PR_SIRR 20 /* Software Interrupt Request */ +#define PR_SISR 21 /* Software Interrupt Summary */ +#define PR_IPIR 22 /* KA820 Interprocessor register */ +#define PR_MCSR 23 /* Machine Check Status Register 11/750 */ +#define PR_ICCS 24 /* Interval Clock Control */ +#define PR_NICR 25 /* Next Interval Count */ +#define PR_ICR 26 /* Interval Count */ +#define PR_TODR 27 /* Time Of Year (optional) */ +#define PR_CSRS 28 /* Console Storage R/S */ +#define PR_CSRD 29 /* Console Storage R/D */ +#define PR_CSTS 30 /* Console Storage T/S */ +#define PR_CSTD 31 /* Console Storage T/D */ +#define PR_RXCS 32 /* Console Receiver C/S */ +#define PR_RXDB 33 /* Console Receiver D/B */ +#define PR_TXCS 34 /* Console Transmit C/S */ +#define PR_TXDB 35 /* Console Transmit D/B */ +#define PR_TBDR 36 /* Translation Buffer Group Disable Register 11/750 */ +#define PR_CADR 37 /* Cache Disable Register 11/750 */ +#define PR_MCESR 38 /* Machiune Check Error Summary Register 11/750 */ +#define PR_CAER 39 /* Cache Error Register 11/750 */ +#define PR_ACCS 40 /* Accelerator control register */ +#define PR_SAVISP 41 /* Console Saved ISP */ +#define PR_SAVPC 42 /* Console Saved PC */ +#define PR_SAVPSL 43 /* Console Saved PSL */ +#define PR_WCSA 44 /* WCS Address */ +#define PR_WCSB 45 /* WCS Data */ +#define PR_SBIFS 48 /* SBI Fault/Status */ +#define PR_SBIS 49 /* SBI Silo */ +#define PR_SBISC 50 /* SBI Silo Comparator */ +#define PR_SBIMT 51 /* SBI Silo Maintenance */ +#define PR_SBIER 52 /* SBI Error Register */ +#define PR_SBITA 53 /* SBI Timeout Address Register */ +#define PR_SBIQC 54 /* SBI Quadword Clear */ +#define PR_IUR 55 /* Initialize Unibus Register 11/750 */ +#define PR_MAPEN 56 /* Memory Management Enable */ +#define PR_TBIA 57 /* Trans. Buf. Invalidate All */ +#define PR_TBIS 58 /* Trans. Buf. Invalidate Single */ +#define PR_TBDATA 59 /* Translation Buffer Data */ +#define PR_MBRK 60 /* Microprogram Break */ +#define PR_PMR 61 /* Performance Monnitor Enable */ +#define PR_SID 62 /* System ID Register */ +#define PR_TBCHK 63 /* Translation Buffer Check */ + +/* Definitions for AST */ +#define AST_NO 4 +#define AST_OK 3 + +#ifndef ASSEMBLER + +#define mtpr(val,reg) \ +{ \ + asm __volatile ("mtpr %0,%1" \ + : /* No output */ \ + : "g" (val), "g" (reg)); \ +} + +#define mfpr(reg) \ +({ \ + register int val; \ + asm __volatile ("mfpr %1,%0" \ + : "=g" (val) \ + : "g" (reg)); \ + val; \ +}) +#endif /* ASSEMBLER */ + +#endif /* _VAX_MTPR_H_ */ diff --git a/sys/arch/vax/include/nexus.h b/sys/arch/vax/include/nexus.h new file mode 100644 index 00000000000..a4c9a8ce678 --- /dev/null +++ b/sys/arch/vax/include/nexus.h @@ -0,0 +1,179 @@ +/* $NetBSD: nexus.h,v 1.4 1995/02/23 17:51:42 ragge Exp $ */ + +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nexus.h 7.3 (Berkeley) 5/9/91 + */ + +/* + * Information about nexus's. + * + * Each machine has an address of backplane slots (nexi). + * Each nexus is some type of adapter, whose code is the low + * byte of the first word of the adapter address space. + * At boot time the system looks through the array of available + * slots and finds the interconnects for the machine. + */ +#define IO_CMI750 2 +#define MAXNMCR 1 + +#define NNEXSBI 16 +#if VAX8600 +#define NNEX8600 NNEXSBI +#define NEXA8600 ((struct nexus *)(0x20000000)) +#define NEXB8600 ((struct nexus *)(0x22000000)) +#endif +#if VAX780 +#define NNEX780 NNEXSBI +#define NEX780 ((struct nexus *)0x20000000) +#endif +#if VAX750 +#define NNEX750 NNEXSBI +#ifndef ASSEMBLER +#define NEX750 ((struct nexus*)0xf20000) +#else +#define NEX750 (0xF20000) +#endif +#endif +#if VAX730 +#define NNEX730 NNEXSBI +#define NEX730 ((struct nexus *)0xf20000) +#endif +#if VAX630 +#define NNEX630 1 +#define NEX630 ((struct nexus *)0x20088000) +#endif +#define NEXSIZE 0x2000 + +#if VAX8600 +#define MAXNNEXUS (2 * NNEXSBI) +#else +#define MAXNNEXUS NNEXSBI +#endif + +#ifndef ASSEMBLER + +#include "sys/types.h" + +struct nexus { + union nexcsr { + long nex_csr; + u_char nex_type; + } nexcsr; + long nex_pad[NEXSIZE / sizeof (long) - 1]; +}; + +struct sbi_attach_args { + u_int nexnum; + u_int type; + void *nexaddr; +}; + +struct iobus { + int io_type; + int io_addr; + int io_size; + int io_details; +}; + +struct nexusconnect { + int psb_nnexus; + struct nexus *psb_nexbase; + int psb_ubatype; + int psb_nubabdp; + caddr_t *psb_umaddr; + int *psb_nextype; +}; + +extern caddr_t *nex_vec; +#define nex_vec_num(ipl, nexnum) nex_vec[(ipl-14)*16+nexnum] + +#endif + +/* + * Bits in high word of nexus's. + */ +#define SBI_PARFLT (1<<31) /* sbi parity fault */ +#define SBI_WSQFLT (1<<30) /* write sequence fault */ +#define SBI_URDFLT (1<<29) /* unexpected read data fault */ +#define SBI_ISQFLT (1<<28) /* interlock sequence fault */ +#define SBI_MXTFLT (1<<27) /* multiple transmitter fault */ +#define SBI_XMTFLT (1<<26) /* transmit fault */ + +#define NEX_CFGFLT (0xfc000000) + +#ifndef LOCORE +#if defined(VAX780) || defined(VAX8600) +#define NEXFLT_BITS \ +"\20\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT" +#endif +#endif + +#define NEX_APD (1<<23) /* adaptor power down */ +#define NEX_APU (1<<22) /* adaptor power up */ + +#define MBA_OT (1<<21) /* overtemperature */ + +#define UBA_UBINIT (1<<18) /* unibus init */ +#define UBA_UBPDN (1<<17) /* unibus power down */ +#define UBA_UBIC (1<<16) /* unibus initialization complete */ + +/* + * Types for nex_type. + */ +#define NEX_ANY 0 /* pseudo for handling 11/750 */ +#define NEX_MEM4 0x08 /* 4K chips, non-interleaved mem */ +#define NEX_MEM4I 0x09 /* 4K chips, interleaved mem */ +#define NEX_MEM16 0x10 /* 16K chips, non-interleaved mem */ +#define NEX_MEM16I 0x11 /* 16K chips, interleaved mem */ +#define NEX_MBA 0x20 /* Massbus adaptor */ +#define NEX_UBA0 0x28 /* Unibus adaptor */ +#define NEX_UBA1 0x29 /* 4 flavours for 4 addr spaces */ +#define NEX_UBA2 0x2a +#define NEX_UBA3 0x2b +#define NEX_DR32 0x30 /* DR32 user i'face to SBI */ +#define NEX_CI 0x38 /* CI adaptor */ +#define NEX_MPM0 0x40 /* Multi-port mem */ +#define NEX_MPM1 0x41 /* Who knows why 4 different ones ? */ +#define NEX_MPM2 0x42 +#define NEX_MPM3 0x43 +#define NEX_MEM64L 0x68 /* 64K chips, non-interleaved, lower */ +#define NEX_MEM64LI 0x69 /* 64K chips, ext-interleaved, lower */ +#define NEX_MEM64U 0x6a /* 64K chips, non-interleaved, upper */ +#define NEX_MEM64UI 0x6b /* 64K chips, ext-interleaved, upper */ +#define NEX_MEM64I 0x6c /* 64K chips, interleaved */ +#define NEX_MEM256L 0x70 /* 256K chips, non-interleaved, lower */ +#define NEX_MEM256LI 0x71 /* 256K chips, ext-interleaved, lower */ +#define NEX_MEM256U 0x72 /* 256K chips, non-interleaved, upper */ +#define NEX_MEM256UI 0x73 /* 256K chips, ext-interleaved, upper */ +#define NEX_MEM256I 0x74 /* 256K chips, interleaved */ diff --git a/sys/arch/vax/include/param.h b/sys/arch/vax/include/param.h new file mode 100644 index 00000000000..208a254711a --- /dev/null +++ b/sys/arch/vax/include/param.h @@ -0,0 +1,195 @@ +/* $NetBSD: param.h,v 1.12 1995/08/13 00:45:21 mycroft Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Modified for VAX 940213/Ragge + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)param.h 5.8 (Berkeley) 6/28/91 + */ + +#ifndef _VAX_PARAM_H_ +#define _VAX_PARAM_H_ + +#include "machine/macros.h" +#include "psl.h" + +/* + * Machine dependent constants for VAX. + */ + +#define MACHINE "vax" +#define MID_MACHINE MID_VAX +#define UNIX "vmunix" + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is u_int and + * must be cast to any desired pointer type. + */ + +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES) + +#define PGSHIFT 9 /* LOG2(NBPG) */ +#define NBPG (1<<PGSHIFT) /* (1 << PGSHIFT) bytes/page */ +#define PGOFSET (NBPG-1) /* byte offset into page */ +#define NPTEPG (NBPG/(sizeof (struct pte))) + +#define KERNBASE 0x80000000 /* start of kernel virtual */ +#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT) + +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define DEV_BSIZE (1 << DEV_BSHIFT) + +#define BLKDEV_IOSIZE 2048 +#define MAXPHYS (63 * 1024) /* max raw I/O transfer size */ + +#define CLSIZELOG2 1 +#define CLSIZE 2 + +/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */ +#define SSIZE 4 /* initial stack size/NBPG */ +#define SINCR 4 /* increment of stack/NBPG */ + +#define UPAGES 16 /* pages of u-area */ +#define USPACE (NBPG*UPAGES) + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than CLBYTES (the software page size), and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ + +#ifndef MSIZE +#define MSIZE 128 /* size of an mbuf */ +#endif /* MSIZE */ + +#ifndef MCLSHIFT +#define MCLSHIFT 10 /* convert bytes to m_buf clusters */ +#endif /* MCLSHIFT */ +#define MCLBYTES (1 << MCLSHIFT) /* size of an m_buf cluster */ +#define MCLOFSET (MCLBYTES - 1) /* offset within an m_buf cluster */ + +#ifndef NMBCLUSTERS +#ifdef GATEWAY +#define NMBCLUSTERS 512 /* map size, max cluster allocation */ +#else +#define NMBCLUSTERS 256 /* map size, max cluster allocation */ +#endif /* GATEWAY */ +#endif /* NMBCLUSTERS */ + +/* + * Size of kernel malloc arena in CLBYTES-sized logical pages + */ + +#ifndef NKMEMCLUSTERS +#define NKMEMCLUSTERS (2048*1024/CLBYTES) +#endif + +/* + * Some macros for units conversion + */ + +/* pages ("clicks") to disk blocks */ +#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT)) + +/* clicks to bytes */ +#define ctob(x) ((x) << PGSHIFT) +#define btoc(x) (((x) + PGOFSET) >> PGSHIFT) + +/* bytes to disk blocks */ +#define btodb(x) ((x) >> DEV_BSHIFT) +#define dbtob(x) ((x) << DEV_BSHIFT) + +/* + * Map a ``block device block'' to a file system block. + * This should be device dependent, and will be if we + * add an entry to cdevsw/bdevsw for that purpose. + * For now though just use DEV_BSIZE. + */ + +#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE)) + +/* + * Mach derived conversion macros + */ + +#define vax_round_pdr(x) ((((unsigned)(x)) + NBPDR - 1) & ~(NBPDR-1)) +#define vax_trunc_pdr(x) ((unsigned)(x) & ~(NBPDR-1)) +#define vax_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1)) +#define vax_trunc_page(x) ((unsigned)(x) & ~(NBPG-1)) +#define vax_btod(x) ((unsigned)(x) >> PDRSHIFT) +#define vax_dtob(x) ((unsigned)(x) << PDRSHIFT) +#define vax_btop(x) ((unsigned)(x) >> PGSHIFT) +#define vax_ptob(x) ((unsigned)(x) << PGSHIFT) + +#define splx(reg) \ +({ \ + register int val; \ + asm __volatile ("mfpr $0x12,%0;mtpr %1,$0x12" \ + : "=g" (val) \ + : "g" (reg)); \ + val; \ +}) + + +#define spl0() splx(0) /* IPL0 */ +#define splsoftclock() splx(8) /* IPL08 */ +#define splsoftnet() splx(0xc) /* IPL0C */ +#define splddb() splx(0xf) /* IPL0F */ +#define spl4() splx(0x14) /* IPL14 */ +#define splbio() splx(0x15) /* IPL15 */ +#define splnet() splx(0x15) /* IPL15 */ +#define spltty() splx(0x15) /* IPL15 */ +#define splimp() splx(0x16) /* IPL16 */ +#define splclock() splx(0x18) /* IPL18 */ +#define splhigh() splx(0x1f) /* IPL1F */ +#define splstatclock() splclock() + +#define ovbcopy(x,y,z) bcopy(x,y,z) /* This should work i hope... */ + +#define vmapbuf(p,q) +#define vunmapbuf(p,q) + +#if !defined(VAX630) && !defined(VAX410) +#define todr() mfpr(PR_TODR) +#endif +#define DELAY(x) {int N=todr()+(x/1000)+1;while(todr()!=N);} + +#endif /* _VAX_PARAM_H_ */ diff --git a/sys/arch/vax/include/pcb.h b/sys/arch/vax/include/pcb.h new file mode 100644 index 00000000000..a92831c81e4 --- /dev/null +++ b/sys/arch/vax/include/pcb.h @@ -0,0 +1,72 @@ +/* $NetBSD: pcb.h,v 1.8 1995/05/07 16:43:34 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#ifndef _VAX_PCB_H_ +#define _VAX_PCB_H_ + +#include "machine/trap.h" + +struct pcb { + + /* Hardware registers, based on VAX special instructions */ + + long KSP; /* Kernel Stack Pointer */ + long ESP; /* Executive Stack Pointer */ + long SSP; /* Supervisor Stack Pointer */ + long USP; /* User Stack Pointer */ + long R[12]; /* Register 0-11 */ + long AP; /* Argument Pointer */ + long FP; /* Frame Pointer */ + long PC; /* Program Counter */ + long PSL; /* Program Status Longword */ + void *P0BR; /* Page 0 Base Register */ + long P0LR; /* Page 0 Length Register */ + void *P1BR; /* Page 1 Base Register */ + long P1LR; /* Page 1 Length Register */ + + /* Software registers, only used by kernel software */ + void *framep; /* Pointer to syscall frame */ + void *iftrap; /* Tells whether fault copy */ +}; + +#define AST_MASK 0x07000000 +#define AST_PCB 0x04000000 + +/* machine-specific core dump; save trapframe */ +struct md_coredump { + struct trapframe md_tf; +}; + +#endif /* _VAX_PCB_H_ */ + diff --git a/sys/arch/vax/include/pmap.h b/sys/arch/vax/include/pmap.h new file mode 100644 index 00000000000..a753c873e51 --- /dev/null +++ b/sys/arch/vax/include/pmap.h @@ -0,0 +1,107 @@ +/* $NetBSD: pmap.h,v 1.10 1995/05/11 16:53:14 jtc Exp $ */ + +/* + * Copyright (c) 1987 Carnegie-Mellon University + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Changed for the VAX port. /IC + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmap.h 7.6 (Berkeley) 5/10/91 + */ + + +#ifndef PMAP_H +#define PMAP_H + +#include "machine/mtpr.h" + + +#define VAX_PAGE_SIZE NBPG +#define VAX_SEG_SIZE NBSEG + +/* + * Pmap structure + * + * p0br == PR_P0BR in user struct, p0br is also == SBR in pmap_kernel() + * p1br is the same for stack space, stack is base of alloced pte mem + */ + +typedef struct pmap { + vm_offset_t pm_stack; /* Base of alloced p1 pte space */ + struct pcb *pm_pcb; /* Pointer to PCB for this pmap */ + int ref_count; /* reference count */ + struct pmap_statistics stats; /* statistics */ + simple_lock_data_t lock; /* lock on pmap */ +} *pmap_t; + +/* + * For each vm_page_t, there is a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry_t, the list is pv_table. + */ + +typedef struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + struct pmap *pv_pmap;/* if not NULL, pmap where mapping lies */ + vm_offset_t pv_va; /* virtual address for mapping */ + int pv_flags; /* flags */ +} *pv_entry_t; + +#define PV_REF 0x00000001 /* Simulated phys ref bit */ + +#define PHYS_TO_PV(phys_page) (&pv_table[((phys_page)>>PAGE_SHIFT)]) + +#ifdef _KERNEL +pv_entry_t pv_table; /* array of entries, + one per LOGICAL page */ +struct pmap kernel_pmap_store; + +#define pa_index(pa) atop(pa) +#define pa_to_pvh(pa) (&pv_table[atop(pa)]) + +#define pmap_kernel() (&kernel_pmap_store) + +#endif /* _KERNEL */ + +/* Routines that are best to define as macros */ +#define pmap_copy(a,b,c,d,e) /* Dont do anything */ +#define pmap_update() mtpr(0,PR_TBIA) /* Update buffes */ +#define pmap_pageable(a,b,c,d) /* Dont do anything */ +#define pmap_collect(pmap) /* No need so far */ +#define pmap_reference(pmap) if(pmap) (pmap)->ref_count++ +#define pmap_pinit(pmap) (pmap)->ref_count=1; +#define pmap_phys_address(phys) ((u_int)(phys)<<PAGE_SIZE) + +#endif PMAP_H diff --git a/sys/arch/vax/include/proc.h b/sys/arch/vax/include/proc.h new file mode 100644 index 00000000000..07559a36d24 --- /dev/null +++ b/sys/arch/vax/include/proc.h @@ -0,0 +1,49 @@ +/* $NetBSD: proc.h,v 1.2 1994/10/26 08:02:21 cgd Exp $ */ + +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 7.1 (Berkeley) 5/15/91 + */ + +/* + * Machine-dependent part of the proc structure for hp300. + */ +struct mdproc { + int md_flags; /* machine-dependent flags */ +#if 0 + int *md_regs; /* registers on current frame */ +#endif +}; + +/* md_flags */ +#define MDP_AST 0x0001 /* async trap pending */ diff --git a/sys/arch/vax/include/profile.h b/sys/arch/vax/include/profile.h new file mode 100644 index 00000000000..2bb0ab25d14 --- /dev/null +++ b/sys/arch/vax/include/profile.h @@ -0,0 +1,49 @@ +/* $NetBSD: profile.h,v 1.4 1995/05/11 16:53:15 jtc Exp $ */ +/* + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)profile.h 7.1 (Berkeley) 7/16/92 + */ + +#define _MCOUNT_DECL static inline void _mcount + +#define MCOUNT \ +asm(".text; .globl mcount; mcount: pushl 16(fp); calls $1,__mcount; rsb"); + +#ifdef _KERNEL +/* + * Note that we assume splhigh() and splx() cannot call mcount() + * recursively. + */ +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif /* _KERNEL */ diff --git a/sys/arch/vax/include/psl.h b/sys/arch/vax/include/psl.h new file mode 100644 index 00000000000..6ebc47683ee --- /dev/null +++ b/sys/arch/vax/include/psl.h @@ -0,0 +1,113 @@ +/* $NetBSD: psl.h,v 1.4 1994/11/25 19:08:58 ragge Exp $ */ + +/* + * Rewritten for the VAX port. Based on Berkeley code. /IC + * + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)psl.h 7.2 (Berkeley) 5/4/91 + */ + +#ifndef PSL_C + +/* + * VAX program status longword + */ + +#define PSL_C 0x00000001 /* carry bit */ +#define PSL_V 0x00000002 /* overflow bit */ +#define PSL_Z 0x00000004 /* zero bit */ +#define PSL_N 0x00000008 /* negative bit */ +/* #define PSL_ALLCC 0x0000000F /* all cc bits - unlikely */ +#define PSL_T 0x00000010 /* trace enable bit */ +#define PSL_IPL00 0x00000000 /* interrupt priority level 0 */ +#define PSL_IPL01 0x00010000 /* interrupt priority level 1 */ +#define PSL_IPL02 0x00020000 /* interrupt priority level 2 */ +#define PSL_IPL03 0x00030000 /* interrupt priority level 3 */ +#define PSL_IPL04 0x00040000 /* interrupt priority level 4 */ +#define PSL_IPL05 0x00050000 /* interrupt priority level 5 */ +#define PSL_IPL06 0x00060000 /* interrupt priority level 6 */ +#define PSL_IPL07 0x00070000 /* interrupt priority level 7 */ +#define PSL_IPL08 0x00080000 /* interrupt priority level 8 */ +#define PSL_IPL09 0x00090000 /* interrupt priority level 9 */ +#define PSL_IPL0A 0x000a0000 /* interrupt priority level 10 */ +#define PSL_IPL0B 0x000b0000 /* interrupt priority level 11 */ +#define PSL_IPL0C 0x000c0000 /* interrupt priority level 12 */ +#define PSL_IPL0D 0x000d0000 /* interrupt priority level 13 */ +#define PSL_IPL0E 0x000e0000 /* interrupt priority level 14 */ +#define PSL_IPL0F 0x000f0000 /* interrupt priority level 15 */ +#define PSL_IPL10 0x00100000 /* interrupt priority level 16 */ +#define PSL_IPL11 0x00110000 /* interrupt priority level 17 */ +#define PSL_IPL12 0x00120000 /* interrupt priority level 18 */ +#define PSL_IPL13 0x00130000 /* interrupt priority level 19 */ +#define PSL_IPL14 0x00140000 /* interrupt priority level 20 */ +#define PSL_IPL15 0x00150000 /* interrupt priority level 21 */ +#define PSL_IPL16 0x00160000 /* interrupt priority level 22 */ +#define PSL_IPL17 0x00170000 /* interrupt priority level 23 */ +#define PSL_IPL18 0x00180000 /* interrupt priority level 24 */ +#define PSL_IPL19 0x00190000 /* interrupt priority level 25 */ +#define PSL_IPL1A 0x001a0000 /* interrupt priority level 26 */ +#define PSL_IPL1B 0x001b0000 /* interrupt priority level 27 */ +#define PSL_IPL1C 0x001c0000 /* interrupt priority level 28 */ +#define PSL_IPL1D 0x001d0000 /* interrupt priority level 29 */ +#define PSL_IPL1E 0x001e0000 /* interrupt priority level 30 */ +#define PSL_IPL1F 0x001f0000 /* interrupt priority level 31 */ +#define PSL_PREVU 0x00c00000 /* Previous user mode */ +#define PSL_K 0x00000000 /* kernel mode */ +#define PSL_E 0x01000000 /* executive mode */ +#define PSL_S 0x02000000 /* executive mode */ +#define PSL_U 0x03000000 /* user mode */ +#define PSL_IS 0x04000000 /* interrupt stack select */ +#define PSL_FPD 0x04000000 /* first part done flag */ +#define PSL_TP 0x40000000 /* trace pending */ +#define PSL_CM 0x80000000 /* compatibility mode */ + +#define PSL_LOWIPL (PSL_K) +#define PSL_HIGHIPL (PSL_K | PSL_IPL1F) +#define PSL_IPL (PSL_IPL1F) +#define PSL_USER (0) + +#define PSL_MBZ 0x3020ff00 /* must be zero bits */ + +#define PSL_USERSET (0) +#define PSL_USERCLR (PSL_S | PSL_IPL1F | PSL_MBZ) + +/* + * Macros to decode processor status word. + */ +#define CLKF_USERMODE(framep) ((((framep)->ps) & (PSL_U)) == PSL_U) +#define CLKF_BASEPRI(framep) ((((framep)->ps) & (PSL_IPL1F)) == 0) +#define CLKF_PC(framep) ((framep)->pc) +#define CLKF_INTR(framep) 0 +#define PSL2IPL(ps) ((ps) >> 16) + +#endif diff --git a/sys/arch/vax/include/pte.h b/sys/arch/vax/include/pte.h new file mode 100644 index 00000000000..f99839e1931 --- /dev/null +++ b/sys/arch/vax/include/pte.h @@ -0,0 +1,95 @@ +/* $NetBSD: pte.h,v 1.5 1995/08/21 03:28:50 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#include "vax/include/param.h" + +#ifndef ASSEMBLER + +/* + * VAX page table entries + */ +struct pte { + unsigned int pg_pfn:21; /* Page Frame Number or 0 */ + unsigned int pg_u:1; /* Uniform bit, does WHAT?? XXX */ + unsigned int pg_w:1; /* Wired bit */ + unsigned int pg_sref:1; /* Help for ref simulation */ + unsigned int pg_ref:1; /* Simulated reference bit */ + unsigned int pg_z:1; /* Zero DIGITAL = 0 */ + unsigned int pg_m:1; /* Modify DIGITAL */ + unsigned int pg_prot:4; /* reserved at zero */ + unsigned int pg_v:1; /* valid bit */ +}; + + +typedef unsigned int pt_entry_t; /* Mach page table entry */ + +#endif ASSEMBLER + +#define PT_ENTRY_NULL ((pt_entry_t *) 0) + +#define PG_V 0x80000000 +#define PG_NV 0x00000000 +#define PG_PROT 0x78000000 +#define PG_RW 0x20000000 +#define PG_KW 0x10000000 +#define PG_KR 0x18000000 +#define PG_URKW 0x70000000 +#define PG_RO 0x78000000 +#define PG_NONE 0x00000000 +#define PG_M 0x04000000 +#define PG_REF 0x01000000 +#define PG_SREF 0x00800000 +#define PG_W 0x00400000 +#define PG_U 0x00200000 +#define PG_FRAME 0x001fffff +#define PG_SHIFT 9 +#define PG_PFNUM(x) ((x) >> PG_SHIFT) + + +#define VAX_MAX_KPTSIZE VM_KERNEL_PT_PAGES + +#ifndef ASSEMBLER +extern pt_entry_t *Sysmap; +/* + * Kernel virtual address to page table entry and to physical address. + */ +#endif + +#define kvtopte(va) \ + (&Sysmap[((unsigned)(va) - KERNBASE) >> PGSHIFT]) +#define ptetokv(pt) \ + ((((pt_entry_t *)(pt) - Sysmap) << PGSHIFT) + 0x80000000) +#define kvtophys(va) \ + ((kvtopte(va)->pg_pfnum << PGSHIFT) | ((int)(va) & PGOFSET)) diff --git a/sys/arch/vax/include/ptrace.h b/sys/arch/vax/include/ptrace.h new file mode 100644 index 00000000000..d62d017d036 --- /dev/null +++ b/sys/arch/vax/include/ptrace.h @@ -0,0 +1,39 @@ +/* $NetBSD: ptrace.h,v 1.3 1995/04/12 15:26:49 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) + diff --git a/sys/arch/vax/include/reg.h b/sys/arch/vax/include/reg.h new file mode 100644 index 00000000000..9555794d510 --- /dev/null +++ b/sys/arch/vax/include/reg.h @@ -0,0 +1,55 @@ +/* $NetBSD: reg.h,v 1.3 1995/04/12 15:26:52 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +struct reg { + int r0; /* General registers saved upon trap/syscall */ + int r1; + int r2; + int r3; + int r4; + int r5; + int r6; + int r7; + int r8; + int r9; + int r10; + int r11; + int ap; /* Argument pointer on user stack */ + int fp; /* Stack frame pointer */ + int sp; + int pc; /* User pc */ + int psl; /* User psl */ +}; + diff --git a/sys/arch/vax/include/rpb.h b/sys/arch/vax/include/rpb.h new file mode 100644 index 00000000000..de7aec72007 --- /dev/null +++ b/sys/arch/vax/include/rpb.h @@ -0,0 +1,100 @@ +/* $NetBSD: rpb.h,v 1.1 1995/06/05 17:17:59 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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. + */ + +/* + * Look at "VAX/VMS Internals and Data Structures" around page 907 + * to get more info about RPB. + */ + +struct rpb { /* size description */ + struct rpb *rpb_base; /* 4 physical base address of block */ + void (*rpb_restart)();/* 4 physical address of restart routine */ + long rpb_chksum;/* 4 checksum of first 31 longwords of restart */ + long rpb_rstflg; /* 4 Restart in progress flag */ + long rpb_haltpc; /* 4 PC at HALT/restart */ + /* offset: 20 */ + long rpb_haltpsl;/* 4 PSL at HALT/restart */ + long rpb_haltcode;/* 4 reason for restart */ + long rpb_bootr0;/* 24 Saved bootstrap parameters (R0 through R5) */ + long rpb_bootr1; + long rpb_bootr2; + long rpb_bootr3; + long rpb_bootr4; + long rpb_bootr5; + long iovec; /* 4 Address of bootstrap driver */ + long iovecsz;/* 4 Size (in bytes) of bootstrap driver */ + /* offset: 60 */ + long fillbn; /* 4 LBN of seconday bootstrap file */ + long filsiz; /* 4 Size (in blocks) of seconday bootstrap file */ + long pfnmap[2]; /* 8 Descriptor of PFN bitmap */ + long pfncnt; /* 4 Count of physical pages */ + /* offset: 80 */ + long svaspt; /* 4 system virtual address of system page table */ + long csrphy; /* 4 Physical Address of UBA device CSR */ + long csrvir; /* 4 Virtual Address of UBA device CSR */ + long adpphy; /* 4 Physical Address of adapter configurate reg. */ + long adpvir; /* 4 Virtual Address of adapter configurate reg. */ + /* offset: 100 */ + short unit; /* 2 Bootstrap device unit number */ + u_char devtyp; /* 1 Bootstrap device type code */ + u_char slave; /* 1 Bootstrap device slave unit number */ + char file[40]; /* 40 Secondary bootstrap file name */ + u_char confreg[16]; /* 16 Byte array of adapter types */ + /* offset: 160 */ +#if 0 + u_char hdrpgcnt; /* 1 Count of header pages in 2nd bootstrap image */ + short bootndt;/* 2 Type of boot adapter */ + u_char flags; /* 1 Miscellaneous flag bits */ +#else + long align; /* if the compiler doesnt proper alignment */ +#endif + long max_pfn;/* 4 Absolute highest PFN */ + long sptep; /* 4 System space PTE prototype register */ + long sbr; /* 4 Saved system base register */ + long cpudbvec;/* 4 Physical address of per-CPU database vector */ + /* offset: 180 */ + long cca_addr; /* 4 Physical address of CCA */ + long slr; /* 4 Saved system length register */ + long memdesc[16]; /* 64 Longword array of memory descriptors */ + long smp_pc; /* 4 SMP boot page physical address */ + long wait; /* 4 Bugcheck loop code for attached processor */ + /* offset: 260 */ + long badpgs; /* 4 Number of bad pages found in memory scan */ + u_char ctrlltr;/* 1 Controller letter designation */ + u_char scbpagct; /* 1 SCB page count */ + u_char reserved[6]; /* 6 -- */ + long vmb_revision; /* 4 VMB revision label */ +}; + +extern struct rpb rpb; diff --git a/sys/arch/vax/include/scb.h b/sys/arch/vax/include/scb.h new file mode 100644 index 00000000000..f5663183149 --- /dev/null +++ b/sys/arch/vax/include/scb.h @@ -0,0 +1,39 @@ +/* $NetBSD: scb.h,v 1.2 1994/10/26 08:02:26 cgd Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +struct scb { +}; + diff --git a/sys/arch/vax/include/setjmp.h b/sys/arch/vax/include/setjmp.h new file mode 100644 index 00000000000..251569b9c05 --- /dev/null +++ b/sys/arch/vax/include/setjmp.h @@ -0,0 +1,7 @@ +/* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:18 cgd Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 10 /* size, in longs, of a jmp_buf */ diff --git a/sys/arch/vax/include/sid.h b/sys/arch/vax/include/sid.h new file mode 100644 index 00000000000..91f89399156 --- /dev/null +++ b/sys/arch/vax/include/sid.h @@ -0,0 +1,63 @@ +/* $NetBSD: sid.h,v 1.5 1995/02/23 17:51:44 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#define VAX_780 1 +#define VAX_750 2 +#define VAX_730 3 +#define VAX_8600 4 +#define VAX_8200 5 +#define VAX_8800 6 +#define VAX_610 7 +#define VAX_78032 8 +#define VAX_650 10 +#define VAX_MAX 10 + +#define MACHID(x) ((x>>24)&255) + +#define V750UCODE(x) ((x>>8)&255) +#define V750HARDW(x) (cpu_type&255) + +/* + * The MicroVAXII CPU chip (78032) is used on more than one type of system + * that are differentiated by the low order 8 bits of cpu_type. (Filled in + * from the System Identification Extension Register.) To test for the cpu + * chip, compare cpunumber == VAX_78032, but to test for a Qbus MicroVAXII + * compare cpu_type == VAX_630. + */ +#define VAX_630 0x8000001 +#define VAX_410 0x8000002 + +extern int cpu_type, cpunumber; diff --git a/sys/arch/vax/include/signal.h b/sys/arch/vax/include/signal.h new file mode 100644 index 00000000000..5c4fa439947 --- /dev/null +++ b/sys/arch/vax/include/signal.h @@ -0,0 +1,64 @@ +/* $NetBSD: signal.h,v 1.4 1995/01/10 19:01:52 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 7.16 (Berkeley) 3/17/91 + */ + + /* All bugs are subject to removal without further notice */ + +#ifndef _VAX_SIGNAL_H_ +#define _VAX_SIGNAL_H_ + +typedef int sig_atomic_t; + +#ifndef _ANSI_SOURCE +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + int sc_onstack; /* sigstack state to restore */ + int sc_mask; /* signal mask to restore */ + int sc_sp; /* sp to restore */ + int sc_fp; /* fp to restore */ + int sc_ap; /* ap to restore */ + int sc_pc; /* pc to restore */ + int sc_ps; /* psl to restore */ +}; + +#endif /* !_ANSI_SOURCE */ +#endif /* !_VAX_SIGNAL_H_ */ diff --git a/sys/arch/vax/include/stdarg.h b/sys/arch/vax/include/stdarg.h new file mode 100644 index 00000000000..a6cb75347bb --- /dev/null +++ b/sys/arch/vax/include/stdarg.h @@ -0,0 +1,62 @@ +/* $NetBSD: stdarg.h,v 1.5 1995/03/28 18:21:25 jtc Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 7.2 (Berkeley) 5/4/91 + */ + +#ifndef _VAX_STDARG_H_ +#define _VAX_STDARG_H_ + +#include <machine/ansi.h> + +typedef _BSD_VA_LIST_ va_list; + +#define __va_promote(type) \ + (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) + +#define va_start(ap, last) \ + (ap = ((char *)&(last) + __va_promote(last))) + +#ifdef _KERNEL +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type)))[-1] +#else +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type) < sizeof(int) ? \ + (abort(), 0) : sizeof(type)))[-1] +#endif + +#define va_end(ap) ((void) 0) + +#endif /* !_VAX_STDARG_H_ */ diff --git a/sys/arch/vax/include/trap.h b/sys/arch/vax/include/trap.h new file mode 100644 index 00000000000..b1cafc13785 --- /dev/null +++ b/sys/arch/vax/include/trap.h @@ -0,0 +1,109 @@ +/* $NetBSD: trap.h,v 1.8 1995/06/16 15:17:40 ragge Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 5.4 (Berkeley) 5/9/91 + */ + +/* + * Trap type values + * also known in trap.c for name strings + */ +#ifndef _VAX_TRAP_H_ +#define _VAX_TRAP_H_ + +#define T_RESADFLT 0 /* reserved addressing */ +#define T_PRIVINFLT 1 /* privileged instruction */ +#define T_RESOPFLT 2 /* reserved operand */ +#define T_BPTFLT 3 /* breakpoint instruction */ +#define T_SYSCALL 5 /* system call (kcall) */ +#define T_ARITHFLT 6 /* arithmetic trap */ +#define T_ASTFLT 7 /* system forced exception */ +#define T_PTELEN 8 /* Page table length exceeded */ +#define T_TRANSFLT 9 /* translation fault */ +#define T_TRCTRAP 10 /* trace trap */ +/* #define T_COMPAT 11 /* compatibility mode fault on VAX */ +#define T_ACCFLT 12 /* Access violation fault */ +/* #define T_TABLEFLT 13 /* page table fault */ +/* #define T_ALIGNFLT 14 /* alignment fault */ +#define T_KSPNOTVAL 15 /* kernel stack pointer not valid */ +/* #define T_BUSERR 16 /* bus error */ +#define T_KDBTRAP 17 /* kernel debugger trap */ + +/* #define T_DIVIDE 18 /* integer divide fault */ +/* #define T_NMI 19 /* non-maskable trap */ +/* #define T_OFLOW 20 /* overflow trap */ +/* #define T_BOUND 21 /* bound instruction fault */ +/* #define T_DNA 22 /* device not available fault */ +/* #define T_DOUBLEFLT 23 /* double fault */ +/* #define T_FPOPFLT 24 /* fp coprocessor operand fetch fault */ +/* #define T_TSSFLT 25 /* invalid tss fault */ +/* #define T_SEGNPFLT 26 /* segment not present fault */ +/* #define T_STKFLT 27 /* stack fault */ +/* #define T_RESERVED 28 /* reserved fault base */ + +/* These gets ORed with the word for page handling routines */ +#define T_WRITE 0x80 +#define T_PTEFETCH 0x40 + +/* Trap's coming from user mode */ +#define T_USER 0x100 + +#ifndef ASSEMBLER +/* If we want to alter USP in some syscall, we do it with mtpr */ +struct trapframe { + int fp; /* Stack frame pointer */ + int ap; /* Argument pointer on user stack */ + int r0; /* General registers saved upon trap/syscall */ + int r1; + int r2; + int r3; + int r4; + int r5; + int r6; + int r7; + int r8; + int r9; + int r10; + int r11; + int trap; /* Type of trap */ + u_int code; /* Trap specific code */ + u_int pc; /* User pc */ + u_int psl; /* User psl */ +}; +#endif /* ASSEMBLER */ + +#endif _VAX_TRAP_H_ diff --git a/sys/arch/vax/include/types.h b/sys/arch/vax/include/types.h new file mode 100644 index 00000000000..dbf36014062 --- /dev/null +++ b/sys/arch/vax/include/types.h @@ -0,0 +1,77 @@ +/* $NetBSD: types.h,v 1.5 1995/07/06 03:39:45 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 7.5 (Berkeley) 3/9/91 + */ + +#ifndef _MACHTYPES_H_ +#define _MACHTYPES_H_ + +#include <sys/cdefs.h> + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +#if 0 +typedef struct _physadr { + int r[1]; +} *physadr; + + +typedef struct label_t { + int val[6]; +} label_t; +#endif /* 0 */ +#endif + +typedef unsigned long vm_offset_t; +typedef unsigned long vm_size_t; + +/* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +#define __BIT_TYPES_DEFINED__ +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 long long int64_t; +typedef unsigned long long u_int64_t; + +typedef int32_t register_t; + +#define __BDEVSW_DUMP_OLD_TYPE + +#endif /* _MACHTYPES_H_ */ diff --git a/sys/arch/vax/include/uvaxII.h b/sys/arch/vax/include/uvaxII.h new file mode 100644 index 00000000000..c5376d0ee80 --- /dev/null +++ b/sys/arch/vax/include/uvaxII.h @@ -0,0 +1,125 @@ +/* $NetBSD: uvaxII.h,v 1.1 1995/02/23 17:51:45 ragge Exp $ */ +/*- + * Copyright (c) 1986, 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uvaxII.h 7.4 (Berkeley) 5/9/91 + */ + +#if VAX630 || VAX410 +#define UVAXIISID ((u_long *)0x20040004) +#define UVAXIICPU ((struct uvaxIIcpu *)0x20080000) + +struct uvaxIIcpu { + u_short uvaxII_bdr; + u_short uvaxII_xxx; + u_long uvaxII_mser; + u_long uvaxII_cear; + u_long uvaxII_dear; +}; + +/* Memory system err reg. */ +#define UVAXIIMSER_CD 0x00000300 +#define UVAXIIMSER_NXM 0x00000080 +#define UVAXIIMSER_LPE 0x00000040 +#define UVAXIIMSER_QPE 0x00000020 +#define UVAXIIMSER_MERR 0x000000f0 +#define UVAXIIMSER_CPUE 0x00000060 +#define UVAXIIMSER_DQPE 0x00000010 +#define UVAXIIMSER_LEB 0x00000008 +#define UVAXIIMSER_WRWP 0x00000002 +#define UVAXIIMSER_PEN 0x00000001 + +/* Mem. error address regs. */ +#define UVAXIICEAR_PG 0x00007fff +#define UVAXIIDEAR_PG 0x00007fff + +u_long uvaxII_gettodr(); +void uvaxII_settodr(); +#endif + +/* + * Definitions specific to the ka630 MicroVAXII Q22 bus cpu card. Includes the + * tod clock chip and the cpu registers. + */ +#if VAX630 +#define KA630CLK ((struct ka630clock *)0x200b8000) + +/* Bdr register bits */ +#define KA630BDR_PWROK 0x8000 +#define KA630BDR_HLTENB 0x4000 +#define KA630BDR_CPU 0x0c00 +#define KA630BDR_BDG 0x0300 +#define KA630BDR_DSPL 0x000f + +/* Clock registers and constants */ +#define MINSEC 60 +#define HRSEC 3600 +#define DAYSEC (HRSEC * 24) +#define YEARSEC (DAYSEC * 365) + +#define KA630CLK_VRT 0200 +#define KA630CLK_UIP 0200 +#define KA630CLK_RATE 040 +#define KA630CLK_ENABLE 06 +#define KA630CLK_SET 0206 +/* cpmbx bits */ +#define KA630CLK_HLTACT 03 +/* halt action values */ +#define KA630CLK_RESTRT 01 +#define KA630CLK_REBOOT 02 +#define KA630CLK_HALT 03 +/* in progress flags */ +#define KA630CLK_BOOT 04 +#define KA630CLK_RSTRT 010 +#define KA630CLK_LANG 0360 + +#ifndef LOCORE +struct ka630clock { + u_short sec; + u_short secalrm; + u_short min; + u_short minalrm; + u_short hr; + u_short hralrm; + u_short dayofwk; + u_short day; + u_short mon; + u_short yr; + u_short csr0; + u_short csr1; + u_short csr2; + u_short csr3; + u_short cpmbx; /* CPMBX is used by the boot rom. see ka630-ug-3.3.3 */ +}; + +#endif +#endif diff --git a/sys/arch/vax/include/varargs.h b/sys/arch/vax/include/varargs.h new file mode 100644 index 00000000000..ec7a9e31b50 --- /dev/null +++ b/sys/arch/vax/include/varargs.h @@ -0,0 +1,61 @@ +/* $NetBSD: varargs.h,v 1.5 1995/03/28 18:21:27 jtc Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)varargs.h 5.3 (Berkeley) 4/3/91 + */ + +#ifndef _VAX_VARARGS_H_ +#define _VAX_VARARGS_H_ + +#include <machine/ansi.h> + +typedef _BSD_VA_LIST_ va_list; + +#define va_dcl int va_alist; + +#define va_start(ap) \ + ap = (char *)&va_alist + +#ifdef _KERNEL +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type)))[-1] +#else +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type) < sizeof(int) ? \ + (abort(), 0) : sizeof(type)))[-1] +#endif + +#define va_end(ap) ((void) 0) + +#endif /* !_VAX_VARARGS_H_ */ diff --git a/sys/arch/vax/include/vmparam.h b/sys/arch/vax/include/vmparam.h new file mode 100644 index 00000000000..41b7e2d30d7 --- /dev/null +++ b/sys/arch/vax/include/vmparam.h @@ -0,0 +1,188 @@ +/* $NetBSD: vmparam.h,v 1.9 1995/08/22 04:28:20 ragge Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Slightly modified for the VAX port /IC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + */ +#ifndef ASSEMBLER +#include <vm/vm_param.h> +#endif + +/* + * Machine dependent constants for VAX. + */ + +/* + * Virtual address space arrangement. On 386, both user and kernel + * share the address space, not unlike the vax. + * USRTEXT is the start of the user text/data space, while USRSTACK + * is the top (end) of the user stack. Immediately above the user stack + * resides the user structure, which is UPAGES long and contains the + * kernel stack. + * + */ + +#define USRTEXT 0x400 +#define USRSTACK 0x7fffe000 /* XXX */ + +/* + * Virtual memory related constants, all in bytes + */ + +#ifndef MAXTSIZ +#define MAXTSIZ (6*1024*1024) /* max text size */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (16*1024*1024) /* max data size */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (16*1024*1024) /* max stack size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (6*1024*1024) /* initial data size limit */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (512*1024) /* initial stack size limit */ +#endif + +/* + * Default sizes of swap allocation chunks (see dmap.h). + * The actual values may be changed in vminit() based on MAXDSIZ. + * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024. + */ + +#define DMMIN 32 /* smallest swap allocation */ +#define DMMAX 4096 /* largest potential swap allocation */ +#define DMTEXT 1024 /* swap allocation for text */ + +/* + * Size of shared memory map + */ + +#ifndef SHMMAXPGS +#define SHMMAXPGS 64 /* XXXX should be 1024 */ +#endif + +/* + * Sizes of the system and user portions of the system page table. + * USRPTSIZE is maximum possible user virtual memory to be used. + * KALLOCMEM is kernel malloc area size. How much needed for each process? + * SYSPTSIZE is total size of statically allocated pte. (in physmem) + * Ptsizes are in PTEs. + */ + +#define USRPTSIZE ((MAXDSIZ >> PG_SHIFT) * maxproc) +#define KALLOCMEM (((1*1024*1024*maxproc)>>PG_SHIFT)/4) +#define SYSPTSIZE (((USRPTSIZE * 4) >> PG_SHIFT) + UPAGES * maxproc + \ + KALLOCMEM) + +/* + * The time for a process to be blocked before being very swappable. + * This is a number of seconds which the system takes as being a non-trivial + * amount of real time. You probably shouldn't change this; + * it is used in subtle ways (fractions and multiples of it are, that is, like + * half of a ``long time'', almost a long time, etc.) + * It is related to human patience and other factors which don't really + * change over time. + */ + +#define MAXSLP 20 + +/* + * A swapped in process is given a small amount of core without being bothered + * by the page replacement algorithm. Basically this says that if you are + * swapped in you deserve some resources. We protect the last SAFERSS + * pages against paging and will just swap you out rather than paging you. + * Note that each process has at least UPAGES+CLSIZE pages which are not + * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this + * number just means a swapped in process is given around 25k bytes. + * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81), + * so we loan each swapped in process memory worth 100$, or just admit + * that we don't consider it worthwhile and swap it out to disk which costs + * $30/mb or about $0.75. + */ + +#define SAFERSS 8 /* nominal ``small'' resident set size + protected against replacement */ + +/* + * There are two clock hands, initially separated by HANDSPREAD bytes + * (but at most all of user memory). The amount of time to reclaim + * a page once the pageout process examines it increases with this + * distance and decreases as the scan rate rises. + */ + +#define HANDSPREAD (2 * 1024 * 1024) + +/* + * The number of times per second to recompute the desired paging rate + * and poke the pagedaemon. + */ + +#define RATETOSCHEDPAGING 4 + +/* + * Believed threshold (in megabytes) for which interleaved + * swapping area is desirable. + */ + +#define LOTSOFMEM 2 + +#define mapin(pte, v, pfnum, prot) \ + {(*(int *)(pte) = ((pfnum)<<PGSHIFT) | (prot)) ; } + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vm_offset_t)0) +#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x7FFFE000) +#define VM_MAX_ADDRESS ((vm_offset_t)0xC0000000) +#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0x80000000) +#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)(VM_MIN_KERNEL_ADDRESS+\ + (VM_KERNEL_PT_PAGES*0x10000))) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) +#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES) +#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES) + +/* pcb base */ +#define pcbb(p) ((u_int)(p)->p_addr) + diff --git a/sys/arch/vax/mba/hp.c b/sys/arch/vax/mba/hp.c new file mode 100644 index 00000000000..4220d547acb --- /dev/null +++ b/sys/arch/vax/mba/hp.c @@ -0,0 +1,366 @@ +/* $NetBSD: hp.c,v 1.1 1995/02/13 00:43:59 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +/* hp.c - drivrutiner f|r massbussdiskar 940325/ragge */ + +#include "param.h" +#include "types.h" +#include "fcntl.h" +#include "syslog.h" +#include "disklabel.h" +#include "buf.h" +#include "vax/mba/mbareg.h" +#include "vax/mba/mbavar.h" +#include "vax/mba/hpdefs.h" +#include "hp.h" + +struct mba_device *hpinfo[NHP]; +struct hp_info hp_info[NHP]; +struct disklabel hplabel[NHP]; +int hpslave(), hpattach(); + +char hptypes[]={ + 0x22,0 +}; + +struct mba_driver hpdriver={ + hpslave, 0, "hp", hptypes, hpattach, hpinfo +}; + +hpslave(){ + printf("Hpslave.\n"); + asm("halt"); +}; + +hpopen(){ + printf("hpopen"); + asm("halt"); +}; + +hpclose(){ + printf("hpclose\n"); + asm("halt"); +}; + +hpioctl(){ + printf("hpioctl\n"); + asm("halt"); +} + +hpdump(){ + printf("hpdump\n"); + asm("halt"); +}; + +hpsize(){ + printf("hpsize"); + asm("halt"); +}; + + + +hpattach(mi) + struct mba_device *mi; +{ + struct mba_drv *md; + +/* + * We check status of the drive first; to see if there is any idea + * to try to read the label. + */ + md=&(mi->mi_mba->mba_drv[mi->drive]); + if(!md->rmcs1&HPCS1_DVA){ + printf(": Drive not available"); + return; + } + if(!md->rmds&HPDS_MOL){ + printf(": Drive offline"); + return; + } + if (hpinit(mi, 0)) + printf(": offline"); +/* else if (ra_info[unit].ra_state == OPEN) { + printf(": %s, size = %d sectors", + udalabel[unit].d_typename, ra_info[unit].ra_dsize); +*/ + printf("rmcs1: %x, rmds: %x, rmdt: %x rmsn: %x\n", + md->rmcs1, md->rmds, md->rmdt, md->rmsn); + + +/* asm("halt"); */ +/* + if (MSCP_MID_ECH(1, ra_info[unit].ra_mediaid) == 'X' - '@') { + printf(": floppy"); + return; + } + if (ui->ui_dk >= 0) + dk_wpms[ui->ui_dk] = (60 * 31 * 256); + udaip[ui->ui_ctlr][ui->ui_slave] = ui; + + if (uda_rainit(ui, 0)) + printf(": offline"); + else if (ra_info[unit].ra_state == OPEN) { + printf(": %s, size = %d sectors", + udalabel[unit].d_typename, ra_info[unit].ra_dsize); + }*/ +} + + +/* + * Initialise a drive. If it is not already, bring it on line, + * and set a timeout on it in case it fails to respond. + * When on line, read in the pack label. + */ +hpinit(mi, flags) + struct mba_device *mi; +{ +/* struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; */ + struct disklabel *lp; + struct hp_info *hp; +/* struct mscp *mp; */ + int unit = mi->unit; + char *msg, *readdisklabel(); + int s, i, hpstrategy(); + extern int cold; + + hp = &hp_info[unit]; +/* + if ((ui->ui_flags & UNIT_ONLINE) == 0) { + mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); + mp->mscp_opcode = M_OP_ONLINE; + mp->mscp_unit = ui->ui_slave; + mp->mscp_cmdref = (long)&ui->ui_flags; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + ra->ra_state = WANTOPEN; + if (!cold) + s = spl5(); + i = ((struct udadevice *)ui->ui_addr)->udaip; + + if (cold) { + i = todr() + 1000; + while ((ui->ui_flags & UNIT_ONLINE) == 0) + if (todr() > i) + break; + } else { + timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); + sleep((caddr_t)&ui->ui_flags, PSWP + 1); + splx(s); + untimeout(wakeup, (caddr_t)&ui->ui_flags); + } + if (ra->ra_state != OPENRAW) { + ra->ra_state = CLOSED; + wakeup((caddr_t)ra); + return (EIO); + } + } +*/ + lp = &hplabel[unit]; + lp->d_secsize = DEV_BSIZE; + + lp->d_secsize = DEV_BSIZE; + lp->d_secperunit = 15 /*ra->ra_dsize*/; + + if (flags & O_NDELAY) + return (0); + hp->hp_state = RDLABEL; + /* + * Set up default sizes until we have the label, or longer + * if there is none. Set secpercyl, as readdisklabel wants + * to compute b_cylin (although we do not need it), and set + * nsectors in case diskerr is called. + */ + lp->d_secpercyl = 1; + lp->d_npartitions = 1; + lp->d_secsize = 512; +/* lp->d_secperunit = ra->ra_dsize; */ + lp->d_nsectors = 15 /*ra->ra_geom.rg_nsectors*/; + lp->d_partitions[0].p_size = lp->d_secperunit; + lp->d_partitions[0].p_offset = 0; + + /* + * Read pack label. + */ + if ((msg = readdisklabel(hpminor(unit, 0), hpstrategy, lp)) != NULL) { + if (cold) + printf(": %s", msg); + else + log(LOG_ERR, "hp%d: %s", unit, msg); +/* ra->ra_state = OPENRAW; */ +/* uda_makefakelabel(ra, lp); */ + } else +/* ra->ra_state = OPEN; */ +/* wakeup((caddr_t)hp); */ + return (0); +} + +/* + * Queue a transfer request, and if possible, hand it to the controller. + * + * This routine is broken into two so that the internal version + * udastrat1() can be called by the (nonexistent, as yet) bad block + * revectoring routine. + */ +hpstrategy(bp) + register struct buf *bp; +{ + register int unit; + register struct uba_device *ui; + register struct hp_info *hp; + struct partition *pp; + int p; + daddr_t sz, maxsz; + + /* + * Make sure this is a reasonable drive to use. + */ +/* bp->b_error = ENXIO; + goto bad; +*/ + unit = hpunit(bp->b_dev); + + /* + * If drive is open `raw' or reading label, let it at it. + */ + + if (hp->hp_state < OPEN) { + hpstrat1(bp); + return; + } + + +/* if ((unit = udaunit(bp->b_dev)) >= NRA || + (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || + (ra = &ra_info[unit])->ra_state == CLOSED) { + bp->b_error = ENXIO; + goto bad; + } +*/ + /* + * If drive is open `raw' or reading label, let it at it. + */ +/* + if (ra->ra_state < OPEN) { + udastrat1(bp); + return; + } + p = udapart(bp->b_dev); + if ((ra->ra_openpart & (1 << p)) == 0) { + bp->b_error = ENODEV; + goto bad; + } +*/ + /* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. + */ +/* + pp = &udalabel[unit].d_partitions[p]; + maxsz = pp->p_size; + if (pp->p_offset + pp->p_size > ra->ra_dsize) + maxsz = ra->ra_dsize - pp->p_offset; + sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + if (bp->b_blkno + pp->p_offset <= LABELSECTOR && +#if LABELSECTOR != 0 + bp->b_blkno + pp->p_offset + sz > LABELSECTOR && +#endif + (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } + if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ +/* + if (bp->b_blkno == maxsz) { + bp->b_resid = bp->b_bcount; + biodone(bp); + return; + } + /* or truncate if part of it fits */ +/* + sz = maxsz - bp->b_blkno; + if (sz <= 0) { + bp->b_error = EINVAL; /* or hang it up */ +/* + goto bad; + } + bp->b_bcount = sz << DEV_BSHIFT; + } + udastrat1(bp); + return; +*/ +bad: + bp->b_flags |= B_ERROR; + biodone(bp); +} + +/* + * Work routine for udastrategy. + */ +hpstrat1(bp) + register struct buf *bp; +{ + register int unit = hpunit(bp->b_dev); + register struct hp_ctlr *um; + register struct buf *dp; + struct hp_device *ui; +/* int s = spl5(); */ + + asm("halt"); + /* + * Append the buffer to the drive queue, and if it is not + * already there, the drive to the controller queue. (However, + * if the drive queue is marked to be requeued, we must be + * awaiting an on line or get unit status command; in this + * case, leave it off the controller queue.) + */ +/* + um = (ui = udadinfo[unit])->ui_mi; + dp = &udautab[unit]; + APPEND(bp, dp, av_forw); + if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { + APPEND(dp, &um->um_tab, b_forw); + dp->b_active++; + } + + /* + * Start activity on the controller. Note that unlike other + * Unibus drivers, we must always do this, not just when the + * controller is not active. + */ +/* + udastart(um); + splx(s); +*/ +} diff --git a/sys/arch/vax/mba/hpdefs.h b/sys/arch/vax/mba/hpdefs.h new file mode 100644 index 00000000000..251ce2b7923 --- /dev/null +++ b/sys/arch/vax/mba/hpdefs.h @@ -0,0 +1,81 @@ +/* $NetBSD: hpdefs.h,v 1.1 1995/02/13 00:44:00 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +/* hpdefs.h - 940325/ragge */ + +#define HPCS1_DVA 0x800 /* Drive avail, in dual-port config */ +#define HPDS_VV 0x40 /* Volume valid, not changed */ +#define HPDS_DRY 0x80 /* Drive ready to accept commands */ +#define HPDS_DPR 0x100 /* Drive present */ +#define HPDS_PGM 0x200 /* Programmable in dual-port config */ +#define HPDS_WRL 0x800 /* Write locked media */ +#define HPDS_MOL 0x1000 /* Medium on-line */ +#define HPDT_DRQ 0x800 /* Dual-port disk */ + +/* + * Drive status, per drive + */ +struct hp_info { + daddr_t hp_dsize; /* size in sectors */ +/* u_long hp_type; /* drive type */ + u_long hp_mediaid; /* media id */ + int hp_state; /* open/closed state */ + struct hp_geom { /* geometry information */ + u_short rg_nsectors; /* sectors/track */ + u_short rg_ngroups; /* track groups */ + u_short rg_ngpc; /* groups/cylinder */ + u_short rg_ntracks; /* ngroups*ngpc */ + u_short rg_ncyl; /* ra_dsize/ntracks/nsectors */ +#ifdef notyet + u_short rg_rctsize; /* size of rct */ + u_short rg_rbns; /* replacement blocks per track */ + u_short rg_nrct; /* number of rct copies */ +#endif + } hp_geom; + int hp_wlabel; /* label sector is currently writable */ + u_long hp_openpart; /* partitions open */ + u_long hp_bopenpart; /* block partitions open */ + u_long hp_copenpart; /* character partitions open */ +}; + +/* + * Device to unit number and partition and back + */ +#define UNITSHIFT 3 +#define UNITMASK 7 +#define hpunit(dev) (minor(dev) >> UNITSHIFT) +#define hppart(dev) (minor(dev) & UNITMASK) +#define hpminor(u, p) (((u) << UNITSHIFT) | (p)) + diff --git a/sys/arch/vax/mba/hpreg.h b/sys/arch/vax/mba/hpreg.h new file mode 100644 index 00000000000..ddf2ed2eed3 --- /dev/null +++ b/sys/arch/vax/mba/hpreg.h @@ -0,0 +1,86 @@ +/* $NetBSD: hpreg.h,v 1.2 1995/06/16 15:20:11 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +struct hp_regs { + int hp_cs1; + int hp_ds; + int hp_er1; + int hp_mr1; + int hp_as; + int hp_da; + int hp_dt; + int hp_la; + int hp_sn; + int hp_of; + int hp_dc; + int hp_hr; + int hp_mr2; + int hp_er2; + int hp_ec1; + int hp_ec2; + int utrymme[16]; +}; + +#define hp_drv hp_regs + +#define HPCS_PA 0x13 /* Pack acknowledge */ +#define HPCS_SEEK 0x5 +#define HPCS_READ 0x39 +#define HPCS_DVA 0x800 /* Drive avail, in dual-port config */ + +#define HPDS_VV 0x40 /* Volume valid, not changed */ +#define HPDS_DRY 0x80 /* Drive ready to accept commands */ +#define HPDS_DPR 0x100 /* Drive present */ +#define HPDS_PGM 0x200 /* Programmable in dual-port config */ +#define HPDS_WRL 0x800 /* Write locked media */ +#define HPDS_MOL 0x1000 /* Medium on-line */ + +#define HPDT_DRQ 0x800 /* Dual-port disk */ + +#define HPOF_FMT 0x1000 /* 16/18 bit data */ + +#if 0 +#define HPCS_ +#define HPCS_ +#define HPCS_ +#define HPCS_ +#define HPCS_ +#define HPCS_ +#define HPCS_ +#define HPCS_ +#endif + + + diff --git a/sys/arch/vax/mba/mba.c b/sys/arch/vax/mba/mba.c new file mode 100644 index 00000000000..4b2d13f7864 --- /dev/null +++ b/sys/arch/vax/mba/mba.c @@ -0,0 +1,99 @@ + +/* $NetBSD: mba.c,v 1.1 1995/02/13 00:44:02 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +/* mba.c - main mba routines, 930312/ragge */ + +#include "mba.h" +#include "nexus.h" +#include "vax/mba/mbavar.h" +#include "vax/mba/mbareg.h" + +struct mba_ctrl mba_ctrl[NMBA]; + +extern mba_0(), mba_1(), mba_2(), mba_3(); +int (*mbaintv[4])() = { mba_0, mba_1, mba_2, mba_3 }; +#if NMBA > 4 + Need to expand the table for more than 4 massbus adaptors +#endif + +mbainterrupt(mba){ + + if(mba_hd[mba].mh_mba->mba_sr&MBA_NED){ + printf("Adresserat icke existerande massbussenhet.\n"); + mba_hd[mba].mh_mba->mba_sr=MBA_NED+MBA_MCPE; + return; + } + printf("Interrupt fr}n massbussadapter %d\n",mba); + printf("mba_hd[mba]->mba_sr: %x\n",mba_hd[mba].mh_mba->mba_sr); +} + +/* + * mbafind() set up interrupt vectors for each found mba and calls + * config routines for hp disks, tu and mt tapes (currently only hp). + */ + +mbafind(nexnum,nexaddr){ + struct mba_regs *mbr; + struct mba_device *mi; + + mba_ctrl[nmba].mba_regs= (struct mba_regs *)nexaddr; + mbr=&(mba_ctrl[nmba].mba_regs); +/* + * Set up interruptvectors and enable interrupt + */ + nex_vec_num(14,nexnum)=nex_vec_num(15,nexnum)= + nex_vec_num(16,nexnum)=nex_vec_num(17,nexnum)= + (caddr_t)mbaintv[nmba]; + mbr->mba_cr=MBCR_INIT; + mbr->mba_cr=MBCR_IE; +/* + * Loop thru all massbuss devices and check for existance + */ + + for(i=0;i<8;i++){ + if(!mbr->mba_drv[i].rmds&MBDS_DPR) continue; +/* + * Device found; check if generated + */ + for(mi = mbdinit; mi->driver; mi++) { + if(mi->alive) continue; /* Already config'd */ + } + } + + +} + + diff --git a/sys/arch/vax/mba/mbareg.h b/sys/arch/vax/mba/mbareg.h new file mode 100644 index 00000000000..79e1acc4eba --- /dev/null +++ b/sys/arch/vax/mba/mbareg.h @@ -0,0 +1,80 @@ +/* $NetBSD: mbareg.h,v 1.1 1995/02/13 00:44:03 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden + * 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 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. + */ + +/* mbareg.h - 940320/ragge */ +#include "vax/mba/hpreg.h" + +struct mba_regs { + u_int mba_csr; + u_int mba_cr; + u_int mba_sr; + u_int mba_var; + u_int mba_bc; + u_int mba_dr; + u_int mba_smr; + u_int mba_car; + u_int utrymme[248]; + struct hp_drv hp_drv[8]; + u_int mba_map[256]; +}; + +/* + * Different states which can be on massbus. + */ +/* Write to mba_cr */ +#define MBACR_IBC 0x10 +#define MBACR_MMM 0x8 +#define MBACR_IE 0x4 +#define MBACR_ABORT 0x2 +#define MBACR_INIT 0x1 + +/* Read from mba_sr: */ +#define MBASR_DTBUSY 0x80000000 +#define MBASR_CRD 0x20000000 +#define MBASR_CBHUNG 0x800000 +#define MBASR_PGE 0x80000 +#define MBASR_NED 0x40000 /* NonExistent Drive */ +#define MBASR_MCPE 0x20000 /* Massbuss Control Parity Error */ +#define MBASR_ATTN 0x10000 /* Attention from Massbus */ +#define MBASR_SPE 0x4000 /* Silo Parity Error */ +#define MBASR_DTCMP 0x2000 /* Data Transfer CoMPleted */ +#define MBASR_DTABT 0x1000 /* Data Transfer ABorTed */ +#define MBASR_DLT 0x800 /* Data LaTe */ +#define MBASR_WCKUE 0x400 /* Write check upper error */ +#define MBASR_WCKLE 0x200 /* Write check lower error */ +#define MBASR_MXE 0x100 /* Miss transfer error */ +#define MBASR_MBEXC 0x80 /* Massbuss exception */ +#define MBASR_MDPE 0x40 /* Massbuss data parity error */ +#define MBASR_MAPPE 0x20 /* Page frame map parity error */ +#define MBASR_INVMAP 0x10 /* Invalid map */ +#define MBASR_ERR_STAT 0x8 /* Error status */ +#define MBASR_NRSTAT 0x2 /* No Response status */ + diff --git a/sys/arch/vax/mba/mbavar.h b/sys/arch/vax/mba/mbavar.h new file mode 100644 index 00000000000..b020564bee6 --- /dev/null +++ b/sys/arch/vax/mba/mbavar.h @@ -0,0 +1,94 @@ +/* $NetBSD: mbavar.h,v 1.1 1995/02/13 00:44:04 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden + * 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 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 */ + +/* Mba n}nting... ragge 940311 */ + +#define MBCR_INIT 1 +#define MBCR_IE (1<<2) +#define MBDS_DPR (1<<8) +#define MBSR_NED (1<<18) +#define MBDT_MOH (1<<13) +#define MBDT_TYPE 511 +#define MBDT_TAP (1<<14) + +#define CLOSED 0 +#define WANTOPEN 1 +#define RDLABEL 2 +#define OPEN 3 +#define OPENRAW 4 + +struct mba_ctrl { + struct mba_regs *mba_regs; + struct mba_device *mba_device[8]; +}; + +struct mba_device { + struct mba_driver *driver; + int unit; + int mbanum; + int drive; + int dk; + int alive; + int type; + struct mba_regs *mi_mba; + struct mba_hd *hd; + int drv; + int device; +}; + +struct mba_slave { + struct mba_driver *driver; + int ctlr; + int unit; + int slave; + int alive; +}; + +struct mba_driver { + int (*slave)(); + char *sname; + char *dname; + short *type; + int (*attach)(); + struct mba_device **info; +}; + +struct mba_hd { + struct mba_device *device[8]; /* XXX - Var tidigare mh_mbip */ + int ndrive; + int mh_active; + struct mba_regs *mh_mba; + struct mba_regs *mh_physmba; + struct mba_device *mh_actf; + struct mba_device *mh_actl; +}; diff --git a/sys/arch/vax/stand/Makefile b/sys/arch/vax/stand/Makefile new file mode 100644 index 00000000000..b54fa987f1f --- /dev/null +++ b/sys/arch/vax/stand/Makefile @@ -0,0 +1,103 @@ +# $NetBSD: Makefile,v 1.4 1995/09/16 13:18:27 ragge Exp $ +# + +INCPATH=-I. -I../../.. -I../.. -I../../../lib/libsa + +CC= cc +AS= as + +S= ../../.. +RELOC= 100000 +CFLAGS+=-O ${INCPATH} -DSTANDALONE -DRELOC=0x${RELOC} -D_VAX_INLINE_ + +DEVS= autoconf.o hp.o ra.o tmscp.o + +.include "$S/lib/libkern/Makefile.inc" +LIBKERN= ${KERNLIB} + +.include "$S/lib/libsa/Makefile.inc" +LIBSA= ${SA_LIB} + +all: xxboot boot copy edlabel + +libsvax.a: consio.o urem.o udiv.o + ar crv $@ $? + ranlib $@ + +urem.o: ../vax/urem.s + ${CC} -x assembler-with-cpp -E ../vax/urem.s | as -o urem.o + +udiv.o: ../vax/udiv.s + ${CC} -x assembler-with-cpp -E ../vax/udiv.s | as -o udiv.o + +# startups + +start.o: start.s + ${CC} -x assembler-with-cpp -E start.s | as -o start.o + +srt0.o: srt0.s + ${CC} -x assembler-with-cpp -E srt0.s | as -o srt0.o + +# + +xxboot: start.o bootxx.o romread.o ${LIBSA} ${LIBKERN} libsvax.a + ld -N -Ttext ${RELOC} -o a.out start.o bootxx.o romread.o \ + ${LIBSA} ${LIBKERN} libsvax.a + @strip a.out + @size a.out + @dd if=a.out of=xxboot bs=32 skip=1 + @rm -f a.out + +boot: boot.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o boot.o \ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip boot + @size boot + +edlabel: edlabel.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o edlabel.o\ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip edlabel + @size edlabel + +copy: copy.o srt0.o devopen.o conf.o ${DEVS} ${LIBKERN} ${LIBSA} libsvax.a + ld -N -Ttext ${RELOC} -e nisse -o $@ srt0.o devopen.o copy.o \ + conf.o ${DEVS} ${LIBSA} ${LIBKERN} libsvax.a + @strip copy + @size copy + +# + +hp.o: hp.c + ${CC} -c ${CFLAGS} $*.c + +ra.o: ra.c + ${CC} -c ${CFLAGS} $*.c + +autoconf.o: autoconf.c + ${CC} -c ${CFLAGS} $*.c + +conf.o: conf.c + ${CC} -c ${CFLAGS} $*.c + +boot.o: boot.c + ${CC} -c ${CFLAGS} $*.c + +copy.o: copy.c + ${CC} -c ${CFLAGS} $*.c + +romread.o: romread.s + ${CC} -x assembler-with-cpp -E romread.s | as -o romread.o + +init.o: init.c + ${CC} -c ${CFLAGS} $*.c + +bootxx.o: bootxx.c + ${CC} -c ${CFLAGS} $*.c + +clean:: + rm -f start.o romread.o bootxx.o init.o xxboot boot racopy \ + libsvax.a udiv.o urem.o consio.o ${DEVS} edlabel edlabel.o + rm -f conf.o boot.o rom.o racopy.o srt0.o devopen.o rootcopy.o \ + copy copy.o + diff --git a/sys/arch/vax/stand/autoconf.c b/sys/arch/vax/stand/autoconf.c new file mode 100644 index 00000000000..654d6a68680 --- /dev/null +++ b/sys/arch/vax/stand/autoconf.c @@ -0,0 +1,92 @@ +/* $NetBSD: autoconf.c,v 1.3 1995/09/16 13:34:20 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" +#include "../include/mtpr.h" +#include "../include/sid.h" +#include "vaxstand.h" + +int nmba=0, nuba=0, nbi=0,nsbi=0,nuda=0; +int *mbaaddr, *ubaaddr; +int *udaaddr, *uioaddr, tmsaddr; + +static int mba750[]={0xf28000,0xf2a000,0xf2c000}; +static int uba750[]={0xf30000,0xf32000}; +static int uio750[]={0xfc0000,0xf80000}; +static int uda750[]={0772150}; + +static int uba630[]={0x20087800}; +static int uio630[]={0x30000000}; +#define qbdev(csr) (((csr) & 017777)-0x10000000) +static int uda630[]={qbdev(0772150),qbdev(0760334)}; +/* + * Autoconf routine is really stupid; but it actually don't + * need any intelligence. We just assume that all possible + * devices exists on each cpu. Fast & easy. + */ + +autoconf() +{ + int i = MACHID(mfpr(PR_SID)); + + switch (i) { + + default: + printf("CPU type %d not supported by boot\n",i); + asm("halt"); + + case VAX_750: + nmba = 3; + nuba = 2; + nuda = 1; + mbaaddr = mba750; + ubaaddr = uba750; + udaaddr = uda750; + uioaddr = uio750; + tmsaddr = 0774500; + break; + + case VAX_650: /* the same for uvaxIII */ + case VAX_78032: + nuba = 1; + nuda = 2; + ubaaddr = uba630; + udaaddr = uda630; + uioaddr = uio630; + tmsaddr = qbdev(0774500); + break; + } +} + diff --git a/sys/arch/vax/stand/boot.c b/sys/arch/vax/stand/boot.c new file mode 100644 index 00000000000..d85ddabdf5d --- /dev/null +++ b/sys/arch/vax/stand/boot.c @@ -0,0 +1,249 @@ +/* $NetBSD: boot.c,v 1.4 1995/09/16 15:54:20 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "lib/libsa/stand.h" + +#include <a.out.h> + +/* + * Boot program... arguments passed in r10 and r11 determine + * whether boot stops to ask for system name and which device + * boot comes from. + */ + +char line[100]; +volatile u_int devtype, bootdev; +extern unsigned opendev; + +main() +{ + register howto asm("r11"); + register bdev asm("r10"); + int io, retry, type; + + io=0; + bootdev=bdev; + autoconf(); + + if ((howto & RB_ASKNAME) == 0) { + type = (devtype >> B_TYPESHIFT) & B_TYPEMASK; + if ((unsigned)type < ndevs && devsw[type].dv_name) + strcpy(line, "/netbsd"); + else + howto |= RB_SINGLE|RB_ASKNAME; + } + + for (retry = 0;;) { + if (io >= 0) + printf("\nNboot\n"); + if (howto & RB_ASKNAME) { + printf(": "); + gets(line); + if (line[0] == 0) { + strcpy(line, "/netbsd"); + printf(": %s\n", line); + } + } else + printf(": %s\n", line); + io = open(line, 0); + if (io >= 0) { + loadpcs(); + copyunix(howto, opendev, io); + close(io); + howto |= RB_SINGLE|RB_ASKNAME; + } else { + printf("%s\n",strerror(errno)); + } + if (++retry > 2) + howto |= RB_SINGLE|RB_ASKNAME; + } +} + +/*ARGSUSED*/ +copyunix(howto, devtype, aio) + register howto, devtype; /* howto=r11, devtype=r10 */ + int aio; +{ + register int esym; /* must be r9 */ + struct exec x; + register int io = aio, i; + char *addr; + + if (read(io, (char *)&x, sizeof(x)) != sizeof(x) || N_BADMAG(x)) { + printf("Bad format\n"); + return; + } + printf("%d", x.a_text); + if (N_GETMAGIC(x) == ZMAGIC && lseek(io, 0x400, SEEK_SET) == -1) + goto shread; + if (read(io, (char *)0, x.a_text) != x.a_text) + goto shread; + addr = (char *)x.a_text; + if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) + while ((int)addr & CLOFSET) + *addr++ = 0; + printf("+%d", x.a_data); + if (read(io, addr, x.a_data) != x.a_data) + goto shread; + addr += x.a_data; + printf("+%d", x.a_bss); + for (i = 0; i < x.a_bss; i++) + *addr++ = 0; + if (howto & RB_KDB && x.a_syms) { + *(int *)addr = x.a_syms; /* symbol table size */ + addr += sizeof (int); + printf("[+%d", x.a_syms); + if (read(io, addr, x.a_syms) != x.a_syms) + goto shread; + addr += x.a_syms; + if (read(io, addr, sizeof (int)) != sizeof (int)) + goto shread; + i = *(int *)addr - sizeof (int); /* string table size */ + addr += sizeof (int); + printf("+%d]", i); + if (read(io, addr, i) != i) + goto shread; + addr += i; + esym = roundup((int)addr, sizeof (int)); + x.a_bss = 0; + } else + howto &= ~RB_KDB; + for (i = 0; i < 128*512; i++) /* slop */ + *addr++ = 0; + printf(" start 0x%x\n", (x.a_entry&0x7fffffff)); + hoppabort((x.a_entry&0x7fffffff),howto, devtype, esym); + return; +shread: + printf("Short read\n"); + return; +} + +/* 750 Patchable Control Store magic */ + +#include "../include/mtpr.h" +#include "../include/cpu.h" +#include "../include/sid.h" +#define PCS_BITCNT 0x2000 /* number of patchbits */ +#define PCS_MICRONUM 0x400 /* number of ucode locs */ +#define PCS_PATCHADDR 0xf00000 /* start addr of patchbits */ +#define PCS_PCSADDR (PCS_PATCHADDR+0x8000) /* start addr of pcs */ +#define PCS_PATCHBIT (PCS_PATCHADDR+0xc000) /* patchbits enable reg */ +#define PCS_ENABLE 0xfff00000 /* enable bits for pcs */ + +#define extzv(one, two, three,four) \ +({ \ + asm __volatile (" extzv %0,%3,(%1),(%2)+" \ + : \ + : "g"(one),"g"(two),"g"(three),"g"(four)); \ +}) + + +loadpcs() +{ + register int *ip; /* known to be r11 below */ + register int i; /* known to be r10 below */ + register int *jp; /* known to be r9 below */ + register int j; + static int pcsdone = 0; + int mid = mfpr(PR_SID); + char pcs[100]; + char *cp; + + if ((mid >> 24) != VAX_750 || ((mid >> 8) & 255) < 95 || pcsdone) + return; + printf("Updating 11/750 microcode: "); + for (cp = line; *cp; cp++) + if (*cp == ')' || *cp == ':') + break; + if (*cp) { + strncpy(pcs, line, 99); + pcs[99] = 0; + i = cp - line + 1; + } else + i = 0; + strcpy(pcs + i, "pcs750.bin"); + i = open(pcs, 0); + if (i < 0) { + printf("bad luck - missing pcs750.bin :-(\n"); + return; + } + /* + * We ask for more than we need to be sure we get only what we expect. + * After read: + * locs 0 - 1023 packed patchbits + * 1024 - 11264 packed microcode + */ + if (read(i, (char *)0, 23*512) != 22*512) { + printf("Error reading %s\n", pcs); + close(i); + return; + } + close(i); + + /* + * Enable patchbit loading and load the bits one at a time. + */ + *((int *)PCS_PATCHBIT) = 1; + ip = (int *)PCS_PATCHADDR; + jp = (int *)0; + for (i=0; i < PCS_BITCNT; i++) { + extzv(i,jp,ip,1); + } + *((int *)PCS_PATCHBIT) = 0; + + /* + * Load PCS microcode 20 bits at a time. + */ + ip = (int *)PCS_PCSADDR; + jp = (int *)1024; + for (i=j=0; j < PCS_MICRONUM * 4; i+=20, j++) { + extzv(i,jp,ip,20); + } + + /* + * Enable PCS. + */ + i = *jp; /* get 1st 20 bits of microcode again */ + i &= 0xfffff; + i |= PCS_ENABLE; /* reload these bits with PCS enable set */ + *((int *)PCS_PCSADDR) = i; + + mid = mfpr(PR_SID); + printf("new rev level=%d\n", V750UCODE(mid)); + pcsdone = 1; +} diff --git a/sys/arch/vax/stand/bootxx.c b/sys/arch/vax/stand/bootxx.c new file mode 100644 index 00000000000..b2f01417c95 --- /dev/null +++ b/sys/arch/vax/stand/bootxx.c @@ -0,0 +1,399 @@ +/* $NetBSD: bootxx.c,v 1.3 1995/09/16 13:01:06 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "../mba/mbareg.h" +#include "../mba/hpreg.h" + +#include "../include/pte.h" +#include "../include/sid.h" +#include "../include/mtpr.h" +#include "../include/reg.h" + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "data.h" +#include "vaxstand.h" + +#include <a.out.h> + +int romstrategy(), romopen(); +int command(int, int); + +/* + * Boot program... argume passed in r10 and r11 determine whether boot + * stops to ask for system name and which device boot comes from. + */ + +volatile u_int devtype, bootdev; +unsigned opendev, boothowto, bootset; +int cpu_type, cpunumber; +unsigned *bootregs; +int is_750 = 0, is_mvax = 0, is_tmscp = 0; +struct rpb *rpb; + +main() +{ + int io; + char *hej = "/boot"; + + cpu_type = mfpr(PR_SID); + cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; + + switch (cpunumber) { + + case VAX_78032: + case VAX_650: + { + int cpu_sie; /* sid-extension */ + + is_mvax = 1; + cpu_sie = *((int *) 0x20040004) >> 24; + cpu_type |= cpu_sie; + rpb = bootregs[11]; + bootdev = rpb->devtyp; + + break; + } + case VAX_750: + is_750 = 1; + bootdev = bootregs[10]; + + break; + } + + bootset = getbootdev(); + + printf("\nhowto 0x%x, bdev 0x%x, booting...\n", boothowto, bootdev); + io = open(hej, 0); + + if (io >= 0 && io < SOPEN_MAX) { + copyunix(io); + } else { + printf("Boot failed. errno %d (%s)\n", errno, strerror(errno)); + } +} + +/* ARGSUSED */ +copyunix(aio) +{ + struct exec x; + register int io = aio, i; + char *addr; + + i = read(io, (char *) &x, sizeof(x)); + if (i != sizeof(x) || N_BADMAG(x)) { + printf("Bad format: errno %s\n", strerror(errno)); + return; + } + printf("%d", x.a_text); + if (N_GETMAGIC(x) == ZMAGIC && lseek(io, N_TXTADDR(x), SEEK_SET) == -1) + goto shread; + if (read(io, (char *) 0x10000, x.a_text) != x.a_text) + goto shread; + addr = (char *) x.a_text; + if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) + while ((int) addr & CLOFSET) + *addr++ = 0; + printf("+%d", x.a_data); + if (read(io, addr + 0x10000, x.a_data) != x.a_data) + goto shread; + addr += x.a_data; + bcopy((void *) 0x10000, 0, (int) addr); + printf("+%d", x.a_bss); + for (i = 0; i < x.a_bss; i++) + *addr++ = 0; + for (i = 0; i < 128 * 512; i++) /* slop */ + *addr++ = 0; + printf(" start 0x%x\n", x.a_entry); + hoppabort(x.a_entry, boothowto, bootset); + (*((int (*) ()) x.a_entry)) (); + return; +shread: + printf("Short read\n"); + return; +} + +getbootdev() +{ + int i, major, adaptor, controller, unit, partition; + + + switch (cpunumber) { + case VAX_78032: + case VAX_650: + adaptor = 0; + controller = ((rpb->csrphy & 017777) == 0xDC)?1:0; + unit = rpb->unit; /* DUC, DUD? */ + + break; + + case VAX_750: + controller = 0; /* XXX Actually massbuss can be on 3 ctlr's */ + unit = bootregs[3]; + break; + } + + partition = 0; + + switch (bootdev) { + case 0: /* massbuss boot */ + major = 0; /* hp / ... */ + adaptor = (bootregs[1] & 0x6000) >> 17; + break; + + case 17: /* UDA50 boot */ + major = 9; /* ra / mscp */ + if (is_750) + adaptor = (bootregs[1] & 0x40000 ? 0 : 1); + break; + + case 18: /* TK50 boot */ + major = 15; /* tms / tmscp */ + is_tmscp = 1; /* use tape spec in mscp routines */ + break; + + default: + printf("Unsupported boot device %d, trying anyway.\n", bootdev); + boothowto |= (RB_SINGLE | RB_ASKNAME); + } + return MAKEBOOTDEV(major, adaptor, controller, unit, partition); +} + +struct devsw devsw[] = { + SADEV("rom", romstrategy,nullsys,nullsys, noioctl), +}; + +int ndevs = (sizeof(devsw) / sizeof(devsw[0])); + +struct fs_ops file_system[] = { + {ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat} +}; + +int nfsys = (sizeof(file_system) / sizeof(struct fs_ops)); + +struct disklabel lp; +int part_off = 0; /* offset into partition holding /boot */ +char io_buf[MAXBSIZE]; +volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; +volatile struct udadevice *csr; + +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + char *msg; + int i, err, off; + char line[64]; + + f->f_dev = &devsw[0]; + *file = fname; + + /* + * On uVAX we need to init [T]MSCP ctlr to be able to use it. + */ + if (is_mvax) { + switch (bootdev) { + case 17: /* MSCP */ + case 18: /* TMSCP */ + csr = (struct udadevice *)rpb->csrphy; + + csr->udaip = 0; /* Start init */ + while((csr->udasa & UDA_STEP1) == 0); + csr->udasa = 0x8000; + while((csr->udasa & UDA_STEP2) == 0); + csr->udasa = (short)(((u_int)&uda)&0xffff) + 8; + while((csr->udasa & UDA_STEP3) == 0); + csr->udasa = 0x10; + while((csr->udasa & UDA_STEP4) == 0); + csr->udasa = 0x0001; + + uda.uda_ca.ca_rspdsc = + (int) &uda.uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc = + (int) &uda.uda_cmd.mscp_cmdref; + if (is_tmscp) + uda.uda_cmd.mscp_vcid = 1; + command(M_OP_SETCTLRC, 0); + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_ONLINE, 0); + } + } + + /* + * the disklabel _shall_ be at address LABELOFFSET + RELOC in + * phys memory now, no need at all to reread it again. + * Actually disklabel is only needed when using hp disks, + * but it doesn't hurt to always get it. + */ + if (!is_tmscp) { + msg = getdisklabel(LABELOFFSET + RELOC, &lp); + if (msg) { + printf("getdisklabel: %s\n", msg); + } + } + return 0; +} + +command(cmd, arg) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_modifier = arg; + + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej = csr->udaip; + while (uda.uda_ca.ca_rspdsc < 0); + +} + +int curblock = 0; + +romstrategy(sc, func, dblk, size, buf, rsize) + void *sc; + int func; + daddr_t dblk; + char *buf; + int size, *rsize; +{ + int i; + int block = dblk; + int nsize = size; + + switch (cpunumber) { + + case VAX_650: + case VAX_78032: + switch (bootdev) { + + case 17: /* MSCP */ + uda.uda_cmd.mscp_seq.seq_lbn = dblk; + uda.uda_cmd.mscp_seq.seq_bytecount = size; + uda.uda_cmd.mscp_seq.seq_buffer = buf; + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_READ, 0); + break; + + case 18: /* TMSCP */ + if (dblk < curblock) { + uda.uda_cmd.mscp_seq.seq_bytecount = + curblock - dblk; + command(M_OP_POS, 12); + } else { + uda.uda_cmd.mscp_seq.seq_bytecount = + dblk - curblock; + command(M_OP_POS, 4); + } + curblock = size/512 + dblk; + for (i = 0 ; i < size/512 ; i++) { + uda.uda_cmd.mscp_seq.seq_lbn = 1; + uda.uda_cmd.mscp_seq.seq_bytecount = 512; + uda.uda_cmd.mscp_seq.seq_buffer = buf + i * 512; + uda.uda_cmd.mscp_unit = rpb->unit; + command(M_OP_READ, 0); + } + break; + + } + break; + + case VAX_750: + if (bootdev) { + while (size > 0) { + if ((read750(block, bootregs) & 0x01) == 0) + return 1; + + bcopy(0, buf, 512); + size -= 512; + buf += 512; + block++; + } + } else + hpread(block, size, buf); + break; + } + + *rsize = nsize; + return 0; +} + +hpread(block, size, buf) + char *buf; +{ + volatile struct mba_regs *mr = (void *) bootregs[1]; + volatile struct hp_drv *hd = (void*)&mr->mba_md[bootregs[3]]; + struct disklabel *dp = &lp; + u_int pfnum, nsize, mapnr, bn, cn, sn, tn; + + pfnum = (u_int) buf >> PGSHIFT; + + for (mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + mr->mba_map[mapnr++] = PG_V | pfnum++; + mr->mba_var = ((u_int) buf & PGOFSET); + mr->mba_bc = (~size) + 1; + bn = block; + cn = bn / dp->d_secpercyl; + sn = bn % dp->d_secpercyl; + tn = sn / dp->d_nsectors; + sn = sn % dp->d_nsectors; + hd->hp_dc = cn; + hd->hp_da = (tn << 8) | sn; + hd->hp_cs1 = HPCS_READ; + while (mr->mba_sr & MBASR_DTBUSY); + if (mr->mba_sr & MBACR_ABORT){ + return 1; + } + return 0; +} diff --git a/sys/arch/vax/stand/conf.c b/sys/arch/vax/stand/conf.c new file mode 100644 index 00000000000..15236d763df --- /dev/null +++ b/sys/arch/vax/stand/conf.c @@ -0,0 +1,72 @@ +/* $NetBSD: conf.c,v 1.4 1995/09/16 13:18:28 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#include "sys/param.h" + +#include "lib/libsa/stand.h" +#include "lib/libsa/ufs.h" + +#include "vaxstand.h" + +int raopen(), rastrategy(); +int hpopen(), hpstrategy(); +int tmscpopen(), tmscpstrategy(); + +struct devsw devsw[]={ + SADEV("hp",hpstrategy, hpopen, nullsys, noioctl), + SADEV("ht",nullsys, nodev, nullsys, noioctl), + SADEV("up",nullsys, nodev, nullsys, noioctl), + SADEV("hk",nullsys, nodev, nullsys, noioctl), + SADEV( 0 ,nullsys, nodev, nullsys, noioctl), + SADEV("tm",nullsys, nodev, nullsys, noioctl), + SADEV("ts",nullsys, nodev, nullsys, noioctl), + SADEV("mt",nullsys, nodev, nullsys, noioctl), + SADEV("tu",nullsys, nodev, nullsys, noioctl), + SADEV("ra",rastrategy, raopen, nullsys, noioctl), + SADEV("ut",nullsys, nodev, nullsys, noioctl), + SADEV("id",nullsys, nodev, nullsys, noioctl), + SADEV("rx",nullsys, nodev, nullsys, noioctl), + SADEV("uu",nullsys, nodev, nullsys, noioctl), + SADEV("rl",nullsys, nodev, nullsys, noioctl), + SADEV("tms",tmscpstrategy, tmscpopen, nullsys, noioctl), + SADEV("kra",nullsys, nodev, nullsys, noioctl), +}; + +int ndevs = (sizeof(devsw)/sizeof(devsw[0])); + +struct fs_ops file_system[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat } +}; + +int nfsys = (sizeof(file_system) / sizeof(struct fs_ops)); + diff --git a/sys/arch/vax/stand/consio.c b/sys/arch/vax/stand/consio.c new file mode 100644 index 00000000000..39402cc1d44 --- /dev/null +++ b/sys/arch/vax/stand/consio.c @@ -0,0 +1,61 @@ +/* $NetBSD: consio.c,v 1.3 1995/09/16 15:48:49 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" + +#include "../vax/gencons.h" + +#include "../include/mtpr.h" + +putchar(ch) + int ch; +{ + while ((mfpr(PR_TXCS) & GC_RDY) == 0); /* Wait until xmit ready */ + mtpr(ch, PR_TXDB); /* xmit character */ + if (ch == 10) + putchar(13); /* CR/LF */ + +} + +getchar() +{ + int ch; + + do { + while ((mfpr(PR_RXCS) & GC_DON) == 0); /* wait for char */ + ch = mfpr(PR_RXDB); /* now get it */ + } while (ch == 17 || ch == 19); + return ch; +} diff --git a/sys/arch/vax/stand/copy.c b/sys/arch/vax/stand/copy.c new file mode 100644 index 00000000000..a67721d7458 --- /dev/null +++ b/sys/arch/vax/stand/copy.c @@ -0,0 +1,243 @@ +/* $NetBSD: copy.c,v 1.2 1995/09/29 16:35:00 ragge Exp $ */ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 7.15 (Berkeley) 5/4/91 + */ + +#include "sys/param.h" +#include "sys/reboot.h" +#include "lib/libsa/stand.h" + +#include <a.out.h> + +char line[100]; +volatile u_int devtype, bootdev; +extern unsigned opendev; + +static char *progname = "copy"; +static char *iobuf = NULL; +static char *bufp = NULL; +static int bufsize = 0; +static int partlist[8]; + +int fill_buffer (void); +int write_disk (void); + +main() +{ + int adapt, ctlr, unit, part; + int res, i, loops; + char line[64]; + + autoconf (); + + printf ("\n"); + printf ("%s: \n", progname); + printf ("This program will read miniroot from tape/floppy/disk \n"); + printf ("and install this miniroot onto disk.\n"); + printf ("\n"); + + res = fill_buffer (); + if (res < 0) { + printf ("errors occured during read. Continue at your own risk.\n"); + printf ("Do you want to continue ? [y/n] "); + gets (line); + if (*line != 'y' && *line != 'Y') { + printf ("bye.\n"); + return (-1); + } + } + + printf ("\n"); + res = write_disk (); + + printf ("\n"); + printf ("Halt/Reboot the machine NOW.\n"); + for (;;) + ; + /* NOTREACHED */ +} + +int +fill_buffer (void) +{ + char devname[64]; + int numblocks; + int blocksize = 512; + int bpv = 0; /* blocks per volume */ + int bpt = 8; /* blocks per transfer */ + struct open_file file; + char *filename; + int i, loops; + int size, rsize; + int res, errors = 0; + +again: + printf("\n"); + printf("Specify the device to read from as xx(N,?), where\n"); + printf("xx is the device-name, ? is file/partition number\n"); + printf("and N is the unit-number, e.g.\n"); + printf("\"tms(0,1)\" for the first TMSCP-tape (TK50),\n"); + printf("\"ra(2,0)\" for the third MSCP-disk/floppy (RX33/RX50)\n"); + printf("\n"); + printf("device to read from ? "); + gets(devname); + + printf("\n"); + printf("Specify number of blocks to transfer. Usually this is\n"); + printf("sizeof(miniroot) / 512.\n"); + printf("It's safe to transfer more blocks than just the miniroot.\n"); + printf("\n"); + while (1) { + printf ("number of blocks ? "); + gets (line); + if (atoi(line) > 0) { + if (iobuf && bufsize) + free (iobuf, bufsize); + numblocks = atoi (line); + bufsize = 512 * numblocks; + iobuf = alloc (bufsize); + bufp = iobuf; + if (iobuf == NULL) { + printf ("cannot allocate this much memory.\n"); + continue; + } + break; + } + printf ("invalid number %d.\n", atoi(line)); + } + + printf ("\n"); + printf ("If your miniroot is split into volumes, then you must\n"); + printf ("specify the number of blocks per volume.\n"); + printf ("(e.g. 800 blocks per RX50, 2400 blocks per RX33)\n"); + printf ("\n"); + while (1) { + printf ("number of blocks per volume ? [%d] ", numblocks); + gets (line); + if (!*line || atoi(line) > 0) { + bpv = (atoi(line) > 0 ? atoi(line) : numblocks); + break; + } + printf ("invalid number %d.\n", atoi(line)); + } + + printf ("\n"); + do { + printf ("Make sure unit %s is online and holds the proper volume.\n", devname); + printf ("Then type \'g\' to Go or \'a\' to Abort.\n"); + printf ("\n"); + printf ("OK to go on ? [g/a] "); + gets (line); + if (*line == 'g' || *line == 'G') { + printf ("Reading ... "); + if (devopen (&file, devname, &filename)) { + printf ("cannot open unit %s.\n", devname); + goto again; + } + loops = bpv / bpt + (bpv % bpt != 0); + for (i=0; i<loops; i++) { + twiddle (); + size = 512 * min (bpt, bpv - (i*bpt)); + res = (*file.f_dev->dv_strategy) + (file.f_devdata, F_READ, + (daddr_t)i*bpt, size, bufp, &rsize); + if (res != 0) { + printf ("error %d in read.\n", res); + errors++; + /* continue ? halt ??? */ + } + bufp += size; + } + numblocks -= bpv; + } + if (numblocks > 0) { + int vn = ((bufp - iobuf) / 512) / bpv; + printf ("\n"); + printf ("volume #%d done. Now insert volume #%d\n", + vn - 1, vn); + } + } while (numblocks > 0); + printf ("Reading of miniroot done. (%d blocks read)\n", + (bufp - iobuf) / 512); + + return (-errors); +} + +int +write_disk (void) +{ + char line[64]; + char devname[64]; + struct open_file file; + char *fname; + int rsize, res; + int i, errors = 0; + + printf ("\n"); + printf ("Now specify the device to write miniroot to as xx(N,1)\n"); + printf ("where xx is the drive type and N is the drive number.\n"); + printf ("For example: ra(0,1) refers to MSCP drive #0, b partition\n"); + printf ("\n"); + do { + printf ("Root disk ? : "); + gets (devname); + } while (devopen (&file, devname, &fname)); + + /* + * next: initialize the partition + */ + printf ("Initializing partition ... "); + bufp = iobuf + (16 * 512); + for (i=16; i<bufsize/512; i++) { + twiddle (); + res = (*file.f_dev->dv_strategy) (file.f_devdata, F_WRITE, + (daddr_t)i, 512, bufp, &rsize); + if (res != 0) { + errors++; + printf ("error writing block %d.\n"); + printf ("trying to continue ...\n"); + } + bufp += 512; + } + printf ("done.\n"); + printf ("(%d blocks written.)\n", bufsize/512); + + printf ("\n"); + printf ("Halt the machine and reboot from distribution media,\n"); + printf ("giving second partition as part to mount as root. Ex:\n"); + printf (": ra(0,1) for ra disk 0, hp(2,1) for massbuss disk 2\n"); + + return (-errors); +} + diff --git a/sys/arch/vax/stand/data.h b/sys/arch/vax/stand/data.h new file mode 100644 index 00000000000..d63b5496fbc --- /dev/null +++ b/sys/arch/vax/stand/data.h @@ -0,0 +1,74 @@ +/* $NetBSD: data.h,v 1.4 1995/09/16 15:58:57 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + + +extern unsigned *bootregs; + +/* + * rpb->iovec gives pointer to this structure. + * + * bqo->unit_init() is used to initialize the controller, + * bqo->qio() is used to read from boot-device + */ + +struct bqo { + long qio; /* 4 QIO entry */ + long map; /* 4 Mapping entry */ + long select; /* 4 Selection entry */ + long drivrname; /* 4 Offset to driver name */ + short version; /* 2 Version number of VMB */ + short vercheck; /* 2 Check field */ + /* offset: 20 */ + long reselect; /* 4 Reselection entry */ + long move; /* 4 Move driver entry */ + long unit_init; /* 4 Unit initialization entry */ + long auxdrname; /* 4 Offset to auxiliary driver name */ + long umr_dis; /* 4 UNIBUS Map Registers to disable */ + /* offset: 40 */ + long ucode; /* 4 Absolute address of booting microcode */ + long unit_disc; /* 4 Unit disconnecting entry */ + long devname; /* 4 Offset to boot device name */ + long umr_tmpl; /* 4 UNIBUS map register template */ + /* offset: 60 */ + /* + * the rest is unknown / unneccessary ... + */ + long xxx[6]; /* 24 -- total: 84 bytes */ +}; + +extern struct bqo *bqo; diff --git a/sys/arch/vax/stand/devopen.c b/sys/arch/vax/stand/devopen.c new file mode 100644 index 00000000000..6200f477f49 --- /dev/null +++ b/sys/arch/vax/stand/devopen.c @@ -0,0 +1,212 @@ +/* $NetBSD: devopen.c,v 1.3 1995/09/16 13:18:29 ragge Exp $ */ +/*- + * Copyright (c) 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/reboot.h> + +#include "lib/libsa/stand.h" +/* #include "samachdep.h" */ + +u_int opendev; + +#define ispart(c) ((c) >= 'a' && (c) <= 'h') + +int +atoi(cp) + char *cp; +{ + int val = 0; + while(isdigit(*cp)) + val = val * 10 + (*cp++ - '0'); + return(val); +} + +usage() +{ + printf("\ + Usage: device(adaptor, controller, drive, partition)file\n\ + <device><unit><partitonletter>:file\n\ + "); +} + +devlookup(d,len) + char *d; + int len; +{ + struct devsw *dp = devsw; + int i; + + for (i = 0; i < ndevs; i++, dp++) + if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) + return(i); + + printf("No such device - Configured devices are:\n"); + for (dp = devsw, i = 0; i < ndevs; i++, dp++) + if (dp->dv_name) + printf(" %s", dp->dv_name); + printf("\n"); + errno = ENODEV; + return(-1); +} + +/* + * Parse a device spec in one of two forms. + * + * dev(adapt, ctlr, unit, part)file + * [A-Za-z]*[0-9]*[A-Za-z]:file + * dev unit part + */ +devparse(fname, dev, adapt, ctlr, unit, part, file) + char *fname; + int *dev, *adapt, *ctlr, *unit, *part; + char **file; +{ + int *argp, i; + char *s, *args[4]; + + /* get device name and make lower case */ + for(s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++) + if(isupper(*s)) + *s = tolower(*s); + + /* first form */ + if(*s == '('){ + /* lookup device and get index */ + if ((*dev = devlookup(fname, s - fname)) < 0) + goto baddev; + + /* tokenize device ident */ + args[0] = ++s; + for (args[0] = s, i = 1; *s && *s != ')'; s++) + if (*s == ',') + args[i++] = ++s; + + + switch(i) { + case 4: + *adapt = atoi(args[0]); + *ctlr = atoi(args[1]); + *unit = atoi(args[2]); + *part = atoi(args[3]); + break; + case 3: + *ctlr = atoi(args[0]); + *unit = atoi(args[1]); + *part = atoi(args[2]); + break; + case 2: + *unit = atoi(args[0]); + *part = atoi(args[1]); + break; + case 1: + *part = atoi(args[0]); + break; + case 0: + break; + } + *file = ++s; + + /* second form */ + } else if (*s == ':') { + + /* isolate device */ + for(s = fname; *s != ':' && !isdigit(*s); s++) + ; + + /* lookup device and get index */ + if ((*dev = devlookup(fname, s - fname)) < 0) + goto baddev; + + /* isolate unit */ + if ((*unit = atoi(s)) > sizeof(char)) + goto bad; + for (; isdigit(*s); s++) + ; + + /* translate partition */ + if(!ispart(*s)) + goto bad; + + *part = *s++ - 'a'; + if(*s != ':') + goto bad; + *file = ++s; + + /* no device present */ + } else + *file = fname; + + /* return the remaining unparsed part as the file to boot */ + return(0); + +bad: + usage(); + + baddev: + return(-1); +} + +extern int bootdev; + +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + int n, error; + int dev, ctlr, unit, part; + int adapt = 0; /* XXX not used on HP */ + struct devsw *dp = &devsw[0]; + + dev = B_TYPE(bootdev); + ctlr = B_CONTROLLER(bootdev); + unit = B_UNIT(bootdev); + part = B_PARTITION(bootdev); + + if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file)) + return(error); + + dp = &devsw[dev]; + + if (!dp->dv_open) + return(ENODEV); + + opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part); + + f->f_dev = dp; + + if ((error = (*dp->dv_open)(f, adapt, ctlr, unit, part)) == 0) + return(0); + + printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name, + adapt, ctlr, unit, part, strerror(error)); + + return(error); +} diff --git a/sys/arch/vax/stand/edlabel.c b/sys/arch/vax/stand/edlabel.c new file mode 100644 index 00000000000..09844183bef --- /dev/null +++ b/sys/arch/vax/stand/edlabel.c @@ -0,0 +1,222 @@ +/* $NetBSD: edlabel.c,v 1.1 1995/09/16 12:56:03 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 at Ludd, University of + * Lule}, Sweden and its contributors. + * 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. + */ + +#define DKTYPENAMES + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" +#include "ufs/ffs/fs.h" + +struct disklabel dlabel; +char bootblock[8192]; + +void +showlabel() +{ + struct disklabel *lp; + struct partition *pp; + int i, j; + + lp = &dlabel; + + printf("\n\ndisk type %d (%s), %s: %s%s%s\n", lp->d_type, lp->d_type + <DKMAXTYPES?dktypenames[lp->d_type]:dktypenames[0], lp->d_typename, + lp->d_flags & D_REMOVABLE?" removable":"", lp->d_flags & D_ECC? + " ecc":"", lp->d_flags & D_BADSECT?" badsect":""); + + printf("interleave %d, rpm %d, trackskew %d, cylinderskew %d\n", + lp->d_interleave, lp->d_rpm, lp->d_trackskew, lp->d_cylskew); + printf("headswitch %d, track-to-track %d, drivedata: %d %d %d %d %d\n", + lp->d_headswitch, lp->d_trkseek, lp->d_drivedata[0], + lp->d_drivedata[1], lp->d_drivedata[2], lp->d_drivedata[3], + lp->d_drivedata[4]); + + printf("\nbytes/sector: %d\n", lp->d_secsize); + printf("sectors/track: %d\n", lp->d_nsectors); + printf("tracks/cylinder: %d\n", lp->d_ntracks); + printf("sectors/cylinder: %d\n", lp->d_secpercyl); + printf("cylinders: %d\n", lp->d_ncylinders); + + printf("\n%d partitions:\n", lp->d_npartitions); + printf(" size offset\n"); + pp = lp->d_partitions; + for (i = 0; i < lp->d_npartitions; i++) { + printf("%c: %d, %d\n", 97 + i, lp->d_partitions[i].p_size, + lp->d_partitions[i].p_offset); + } + printf("\n"); +} + +setdefaultlabel() +{ + printf("Sorry, not implemented yet. Later...\n\n"); +} + +#define GETNUM(out, num) printf(out, num);gets(store); \ + if (*store) num = atoi(store); +#define GETNUM2(out, num1, num) printf(out, num1, num);gets(store); \ + if (*store) num = atoi(store); +#define GETSTR(out, str) printf(out, str);gets(store); \ + if (*store) strcpy(str, store); +#define FLAGS(out, flag) printf(out, lp->d_flags & flag?'y':'n');gets(store); \ + if (*store == 'y' || *store == 'Y') lp->d_flags |= flag; \ + else lp->d_flags &= ~flag; + +editlabel() +{ + struct disklabel *lp; + char store[256]; + int i; + + lp = &dlabel; + printf("\nFirst set disk type. Valid types are:\n"); + for (i = 0; i < DKMAXTYPES; i++) + printf("%d %s\n", i, dktypenames[i]); + + GETNUM("\nNumeric disk type? [%d] ", lp->d_type); + GETSTR("Disk name? [%s] ", lp->d_typename); + FLAGS("badsectoring? [%c] ", D_BADSECT); + FLAGS("ecc? [%c] ", D_ECC); + FLAGS("removable? [%c] ", D_REMOVABLE); + + GETNUM("Interleave? [%d] ", lp->d_interleave); + GETNUM("rpm? [%d] ", lp->d_rpm); + GETNUM("trackskew? [%d] ", lp->d_trackskew); + GETNUM("cylinderskew? [%d] ", lp->d_cylskew); + GETNUM("headswitch? [%d] ", lp->d_headswitch); + GETNUM("track-to-track? [%d] ", lp->d_trkseek); + GETNUM("drivedata 0? [%d] ", lp->d_drivedata[0]); + GETNUM("drivedata 1? [%d] ", lp->d_drivedata[1]); + GETNUM("drivedata 2? [%d] ", lp->d_drivedata[2]); + GETNUM("drivedata 3? [%d] ", lp->d_drivedata[3]); + GETNUM("drivedata 4? [%d] ", lp->d_drivedata[4]); + GETNUM("\nbytes/sector? [%d] ", lp->d_secsize); + GETNUM("sectors/track? [%d] ", lp->d_nsectors); + GETNUM("tracks/cylinder? [%d] ", lp->d_ntracks); + GETNUM("sectors/cylinder? [%d] ", lp->d_secpercyl); + GETNUM("cylinders? [%d] ", lp->d_ncylinders); + lp->d_npartitions = MAXPARTITIONS; + for (i = 0; i < 8; i++) { + GETNUM2("%c partition: offset? [%d] ", 97 + i, + lp->d_partitions[i].p_offset); + GETNUM(" size? [%d] ", lp->d_partitions[i].p_size); + } +} + +int bootdev; + +void +main() +{ + register bdev asm("r10"); + + struct open_file file; + char diskname[64], *msg, *filename, indata[64]; + int i, rsize; + + bootdev = bdev; + printf("With this program you can modify everything in the on-disk\n"); + printf("disklabel. To do something useful you must know the exact\n"); + printf("geometry of your disk, and have ideas about how you want\n"); + printf("your partitions to be placed on disk. Some hints:\n"); + printf("The a partition should be at least ~20000 blocks, the\n"); + printf("b (swap) is depending on your use of the machine but it\n"); + printf("should almost never be less than ~32000 blocks.\n\n"); + printf("Disk geometry for most DEC disks can be found in the disktab"); + printf("\nfile, and disknames is listed in the installation notes.\n"); + printf("\nRemember that disk names is given as disk(adapt, ctrl, "); + printf("disk, part)\nwhen using the installation tools.\n\n"); + + autoconf(); +igen: + printf("Label which disk? "); + gets(diskname); + if (*diskname == 0) goto igen; + if (devopen(&file, diskname, &filename)) { + printf("cannot open %s\n", diskname); + goto igen; + } + if ((*file.f_dev->dv_strategy)(file.f_devdata, F_READ, + (daddr_t)0, 8192, bootblock, &rsize)) { + printf("cannot read label block\n"); + goto igen; + } + if (msg = (char *) getdisklabel(LABELOFFSET + bootblock, &dlabel)) + printf("%s: %s\n", diskname, msg); + + do { + printf("(E)dit, (S)how, (D)efaults, (W)rite, (Q)uit) : "); + gets(indata); + switch (*indata) { + case ('e'): + case ('E'): + editlabel(); + break; + case ('s'): + case ('S'): + showlabel(); + break; + case ('d'): + case ('D'): + setdefaultlabel(); + break; + case ('w'): + case ('W'): + dlabel.d_magic = DISKMAGIC; + dlabel.d_magic2 = DISKMAGIC; + dlabel.d_bbsize = BBSIZE; + dlabel.d_sbsize = SBSIZE; + dlabel.d_checksum = 0; + dlabel.d_checksum = dkcksum(&dlabel); + bcopy(&dlabel, LABELOFFSET + bootblock, + sizeof(struct disklabel)); + if ((*file.f_dev->dv_strategy)(file.f_devdata, F_WRITE, + (daddr_t)0, 8192, bootblock, &rsize)) { + printf("cannot write label sectors.\n"); + break; + } + printf("\nThis program does not (yet) write"); + printf(" bootblocks, only disklabel.\n"); + printf("Remember to write the bootblocks from the "); + printf("miniroot later with the\ncommand "); + printf("\"disklabel -B <diskname>\".\n\n"); + break; + case ('q'): + case ('Q'): + default: + break; + } + } while (*indata != 'q' && *indata != 'Q'); + goto igen; +} diff --git a/sys/arch/vax/stand/hp.c b/sys/arch/vax/stand/hp.c new file mode 100644 index 00000000000..c7019a3527d --- /dev/null +++ b/sys/arch/vax/stand/hp.c @@ -0,0 +1,165 @@ +/* $NetBSD: hp.c,v 1.4 1995/09/16 15:43:25 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../mba/mbareg.h" +#include "../mba/hpreg.h" + +#include "../include/pte.h" +#include "../include/macros.h" + +#include "vaxstand.h" + +/* + * These routines for HP disk standalone boot is wery simple, + * assuming a lots of thing like that we only working at one hp disk + * a time, no separate routines for mba driver etc.. + * But it works :) + */ + +struct hp_softc { + int adapt; + int ctlr; + int unit; + int part; +}; + +struct disklabel hplabel; +struct hp_softc hp_softc; +char io_buf[MAXBSIZE]; +daddr_t part_offset; + +hpopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + struct disklabel *lp; + struct hp_softc *hs; + volatile struct mba_regs *mr; + volatile struct hp_drv *hd; + char *msg; + int i,err; + + lp = &hplabel; + hs = &hp_softc; + mr = (void *)mbaaddr[ctlr]; + hd = (void *)&mr->mba_md[unit]; + + if (adapt > nsbi) return(EADAPT); + if (ctlr > nmba) return(ECTLR); + if (unit > MAXMBAU) return(EUNIT); + + bzero(lp, sizeof(struct disklabel)); + + lp->d_secpercyl = 32; + lp->d_nsectors = 32; + hs->adapt = adapt; + hs->ctlr = ctlr; + hs->unit = unit; + hs->part = part; + + /* Set volume valid and 16 bit format; only done once */ + mr->mba_cr = MBACR_INIT; + hd->hp_cs1 = HPCS_PA; + hd->hp_of = HPOF_FMT; + + err = hpstrategy(hs, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if (err) { + printf("reading disklabel: %s\n", strerror(err)); + return 0; + } + + msg = getdisklabel(io_buf + LABELOFFSET, lp); + if (msg) + printf("getdisklabel: %s\n", msg); + + f->f_devdata = (void *)hs; + return 0; +} + +hpstrategy(hs, func, dblk, size, buf, rsize) + struct hp_softc *hs; + daddr_t dblk; + u_int size, *rsize; + char *buf; + int func; +{ + volatile struct mba_regs *mr; + volatile struct hp_drv *hd; + struct disklabel *lp; + unsigned int i, pfnum, mapnr, nsize, bn, cn, sn, tn; + + mr = (void *)mbaaddr[hs->ctlr]; + hd = (void *)&mr->mba_md[hs->unit]; + lp = &hplabel; + + pfnum = (u_int)buf >> PGSHIFT; + + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + mr->mba_map[mapnr++] = PG_V | pfnum++; + + mr->mba_var = ((u_int)buf & PGOFSET); + mr->mba_bc = (~size) + 1; + bn = dblk + lp->d_partitions[hs->part].p_offset; + + if (bn) { + cn = bn / lp->d_secpercyl; + sn = bn % lp->d_secpercyl; + tn = sn / lp->d_nsectors; + sn = sn % lp->d_nsectors; + } else + cn = sn = tn = 0; + + hd->hp_dc = cn; + hd->hp_da = (tn << 8) | sn; + if (func == F_WRITE) + hd->hp_cs1 = HPCS_WRITE; + else + hd->hp_cs1 = HPCS_READ; + + while (mr->mba_sr & MBASR_DTBUSY) + ; + + if (mr->mba_sr & MBACR_ABORT) + return 1; + + *rsize = size; + + return 0; +} diff --git a/sys/arch/vax/stand/init.c b/sys/arch/vax/stand/init.c new file mode 100644 index 00000000000..94c7ad6276a --- /dev/null +++ b/sys/arch/vax/stand/init.c @@ -0,0 +1,82 @@ +/* $NetBSD: init.c,v 1.3 1995/09/16 13:34:21 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. All rights reserved. + * + * This code is derived from software contributed to Ludd by Bertram Barth. + * + * 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}, Sweden and its contributors. 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 */ + + + +#include "lib/libsa/stand.h" + +#include "../include/mtpr.h" /* mfpr(), mtpr() */ +#include "../include/sid.h" /* cpu_type, cpu_number */ + +#define NRSP 0 /* Kludge, must be done before udareg.h */ +#define NCMD 0 /* includes */ + +#include "../uba/udareg.h" /* struct udadevice */ + +#include "data.h" /* bootregs[], rpb, bqo */ + +struct rpb *rpb; +struct bqo *bqo; + +int is_750 = 0, is_mvax = 0; + +/* + * initdata() sets up data gotten from start routines, mostly for uVAX. + */ +int +initdata() +{ + int i, *tmp; + + cpu_type = mfpr(PR_SID); + cpunumber = (mfpr(PR_SID) >> 24) & 0xFF; + + switch (cpunumber) { + + case VAX_78032: + case VAX_650: + { + int cpu_sie; /* sid-extension */ + + is_mvax = 1; + cpu_sie = *((int *) 0x20040004) >> 24; + cpu_type |= cpu_sie; + + break; + } + case VAX_750: + is_750 = 1; + break; + } + return 0; +} diff --git a/sys/arch/vax/stand/ra.c b/sys/arch/vax/stand/ra.c new file mode 100644 index 00000000000..a0ecefc1a1b --- /dev/null +++ b/sys/arch/vax/stand/ra.c @@ -0,0 +1,186 @@ +/* $NetBSD: ra.c,v 1.3 1995/09/16 13:34:22 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../include/pte.h" +#include "../include/macros.h" +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "vaxstand.h" + +static command(int); + +/* + * These routines for RA disk standalone boot is wery simple, + * assuming a lots of thing like that we only working at one ra disk + * a time, no separate routines for uba driver etc.. + * This code is foolish and should need a cleanup. + * But it works :) + */ + +struct ra_softc { + int udaddr; + int ubaddr; + int part; + int unit; +}; + +volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; + +volatile struct uda *ubauda; +volatile struct udadevice *udacsr; +struct disklabel ralabel; +struct ra_softc ra_softc; +char io_buf[MAXBSIZE]; + +raopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + struct disklabel *lp=&ralabel; + volatile struct ra_softc *ra=&ra_softc; + volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + volatile u_int *nisse; + unsigned short johan; + int i,err; + + if(adapt>nuba) return(EADAPT); + if(ctlr>nuda) return(ECTLR); + bzero(lp, sizeof(struct disklabel)); + ra->udaddr=uioaddr[adapt]+udaaddr[ctlr]; + ra->ubaddr=(int)mr; + ra->unit=unit; + ra->part = part; + udacsr=(void*)ra->udaddr; + nisse=&mr->uba_map[0]; + nisse[494]=PG_V|(((u_int)&uda)>>9); + nisse[495]=nisse[494]+1; + ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + /* Init of this uda */ + udacsr->udaip=0; /* Start init */ + while((udacsr->udasa&UDA_STEP1) == 0); + udacsr->udasa=0x8000; + while((udacsr->udasa&UDA_STEP2) == 0); + johan=(((u_int)ubauda)&0xffff)+8; + udacsr->udasa=johan; + while((udacsr->udasa&UDA_STEP3) == 0); + udacsr->udasa=3; + while((udacsr->udasa&UDA_STEP4) == 0); + udacsr->udasa=0x0001; + uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + command(M_OP_SETCTLRC); + uda.uda_cmd.mscp_unit=ra->unit; + command(M_OP_ONLINE); + + err=rastrategy(ra,F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); + if(err){ + printf("reading disklabel: %s\n",strerror(err)); + return 0; + } + + msg=getdisklabel(io_buf+LABELOFFSET, lp); + if(msg) { + printf("getdisklabel: %s\n",msg); + } + f->f_devdata=(void *)ra; + return(0); +} + +static +command(cmd) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode=cmd; + uda.uda_cmd.mscp_msglen=MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen=MSCP_MSGLEN; + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej=udacsr->udaip; + while(uda.uda_ca.ca_rspdsc<0); + +} + +rastrategy(ra, func, dblk, size, buf, rsize) + struct ra_softc *ra; + int func; + daddr_t dblk; + char *buf; + u_int size, *rsize; +{ + volatile struct uba_regs *ur; + volatile struct udadevice *udadev; + volatile u_int *ptmapp; + struct disklabel *lp; + u_int i, j, pfnum, mapnr, nsize; + volatile int hej; + + + ur = (void *)ra->ubaddr; + udadev = (void*)ra->udaddr; + ptmapp = &ur->uba_map[0]; + lp = &ralabel; + + pfnum = (u_int)buf >> PGSHIFT; + + for(mapnr = 0, nsize = size; (nsize + NBPG) > 0; nsize -= NBPG) + ptmapp[mapnr++] = PG_V | pfnum++; + + uda.uda_cmd.mscp_seq.seq_lbn = + dblk + lp->d_partitions[ra->part].p_offset; + uda.uda_cmd.mscp_seq.seq_bytecount = size; + uda.uda_cmd.mscp_seq.seq_buffer = ((u_int)buf) & 0x1ff; + uda.uda_cmd.mscp_unit = ra->unit; + if (func == F_WRITE) + command(M_OP_WRITE); + else + command(M_OP_READ); + + *rsize = size; + return 0; +} diff --git a/sys/arch/vax/stand/romread.s b/sys/arch/vax/stand/romread.s new file mode 100644 index 00000000000..966280792fb --- /dev/null +++ b/sys/arch/vax/stand/romread.s @@ -0,0 +1,89 @@ +/* $NetBSD: romread.s,v 1.3 1995/09/16 16:20:18 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + + +#include "../include/asm.h" + +/* + * read630 (int block, int *regs) + */ +ENTRY(read630, 0xFFE) + pushl $0 # base of rpb + pushl $0 # virtual-flag + pushl $33 # read-logical-block + pushl 12(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 4(ap) # buffer-address + calls $6, (r6) # call the qio-routine + halt + ret # r0 holds the result + +/* + * read750 (int block, int *regs) + */ +ENTRY(read750, 0xFFE) + movl 8(ap), r8 + movl 4(r8), r1 + movl 8(r8), r2 + movl 12(r8), r3 + movl 24(r8), r6 + clrl r5 + movl 4(ap), r8 + pushl $0 + movl $0, 4(sp) + movl fp, 0xf0000 # ragge ??? + jsb (r6) + movl 0xf0000, fp + ret + +/* + * bulkread630 (int lbn, int size, void *buf, int *regs) + */ +ENTRY(bulkread630, 0xFFE) + movl 16(ap), r11 # array of bootregs + movl 44(r11), r11 # restore boot-contents of r11 (rpb) + movl 52(r11), r7 # load iovec/bqo into r7 + addl3 (r7), r7, r6 # load qio into r6 + pushl r11 # base of rpb + pushl $0 # virtual-flag + pushl $33 # read-logical-block + pushl 4(ap) # lbn to start reading + pushl 8(ap) # number of bytes to read + pushl 12(ap) # buffer-address + calls $6, (r6) # call the qio-routine + ret # r0 holds the result diff --git a/sys/arch/vax/stand/srt0.s b/sys/arch/vax/stand/srt0.s new file mode 100644 index 00000000000..a85d02538ba --- /dev/null +++ b/sys/arch/vax/stand/srt0.s @@ -0,0 +1,70 @@ +/* $NetBSD: srt0.s,v 1.4 1995/09/16 16:20:20 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +/* + * Auto-moving startup code for standalone programs. Can be loaded + * (almost) anywhere in memory but moves itself to the position + * it is linked for. Must be started at first position, recommended + * is phys addr 0 (boot loads programs at 0, but starts them at the + * position set in a.out header. + */ + +nisse: .set nisse,0 # pass -e nisse to ld gives OK start addr + .globl nisse + +_start: .globl _start + nop;nop; # If we get called by calls, or something + movl $_start, sp # Probably safe place for stack + subl2 $52, sp # do not overwrite saved boot-registers + + subl3 $_start, $_end, r0 + moval _start, r1 + movl $_start, r2 + movc3 r0, (r1), (r2) # should use movc5 instead, to clear bss. + + jsb 1f +1: movl $relocated, (sp) # return-address on top of stack + rsb # can be replaced with new address +relocated: # now relocation is done !!! + calls $0,_main # Were here! + halt # no return + + + .globl _hoppabort +_hoppabort: .word 0x0 + movl 4(ap), r6 + movl 8(ap), r11 + movl 0xc(ap), r10 + movl 16(ap), r9 + calls $0,(r6) diff --git a/sys/arch/vax/stand/start.s b/sys/arch/vax/stand/start.s new file mode 100644 index 00000000000..45a9c56169d --- /dev/null +++ b/sys/arch/vax/stand/start.s @@ -0,0 +1,188 @@ +/* $NetBSD: start.s,v 1.4 1995/09/16 16:20:21 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Ludd by + * Bertram Barth. + * + * 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}, Sweden and its contributors. + * 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 */ + + +#define LOCORE +#include "sys/disklabel.h" +#undef LOCORE + +#define ASSEMBLER +#include "../include/mtpr.h" +#include "../include/asm.h" +#include "bootdefs.h" + +_start: .globl _start # this is the symbolic name for the start + # of code to be relocated. We can use this + # to get the actual/real adress (pc-rel) + # or to get the relocated address (abs). + +.org 0x00 # uVAX booted from TK50 starts here + brb from_0x00 # continue behind dispatch-block + +.org 0x02 # information used by uVAX-ROM + .byte (LABELOFFSET + d_end_)/2 # offset in words to identification area + .byte 1 # this byte must be 1 + .word 0 # logical block number (word swapped) + .word 0 # of the secondary image + +.org 0x08 # + brb from_0x08 # skip ... + +.org 0x0A # uVAX booted from disk starts here + brb from_0x0A # skip ... + +.org 0x0C # 11/750 & 8200 starts here + brw cont_750 + + +from_0x00: # uVAX from TK50 +from_0x0A: # uVAX from disk + brw start_uvax # all(?) uVAXen continue there + +from_0x08: # What comes here??? + halt + +.org LABELOFFSET - 6 +regmask: .word 0x0fff # using a variable saves 3 bytes !!! +bootinfo: .long 0x0 # another 3 bytes if within byte-offset + +# the complete area reserved for label +# must be empty (i.e. filled with zeroes). +# disklabel(8) checks that before installing +# the bootblocks over existing label. + +/* + * Parameter block for uVAX boot. + */ +#define VOLINFO 0 /* 1=single-sided 81=double-sided volumes */ +#define SISIZE 16 /* size in blocks of secondary image */ +#define SILOAD 0 /* load offset (usually 0) from the default */ +#define SIOFF 0x0A /* byte offset into secondary image */ + +.org LABELOFFSET + d_end_ + .byte 0x18 # must be 0x18 + .byte 0x00 # must be 0x00 (MBZ) + .byte 0x00 # any value + .byte 0xFF - (0x18 + 0x00 + 0x00) + /* 4th byte holds 1s' complement of sum of previous 3 bytes */ + + .byte 0x00 # must be 0x00 (MBZ) + .byte VOLINFO + .byte 0x00 # any value + .byte 0x00 # any value + + .long SISIZE # size in blocks of secondary image + .long SILOAD # load offset (usually 0) + .long SIOFF # byte offset into secondary image + .long (SISIZE + SILOAD + SIOFF) # sum of previous 3 + +/* + * After bootblock (LBN0) has been loaded into the first page + * of good memory by 11/750's ROM-code (transfer address + * of bootblock-code is: base of good memory + 0x0C) registers + * are initialized as: + * R0: type of boot-device + * 0: Massbus device + * 1: RK06/RK07 + * 2: RL02 + * 17: UDA50 + * 35: TK50 + * 64: TU58 + * R1: (UBA) address of UNIBUS I/O-page + * (MBA) address of boot device's adapter + * R2: (UBA) address of the boot device's CSR + * (MBA) controller number of boot device + * R6: address of driver subroutine in ROM + * + * cont_750 reads in LBN1-15 for further execution. + */ + .align 2 +cont_750: + movl r0,r10 + movl r5, ap # ap not used here + clrl r5 + clrl r4 + movl $_start,sp +1: incl r4 + movl r4,r8 + addl2 $0x200,r5 + cmpl $16,r4 + beql 2f + pushl r5 + jsb (r6) + blbs r0,1b +2: movl r10, r0 + movl r11, r5 + brw start_all + + +start_uvax: + mtpr $0, $PR_MAPEN # Turn off MM, please. + movl $_start, sp + movl 48(r11), ap + brb start_all + +/* + * start_all: stack already at RELOC, we save registers, move ourself + * to RELOC and loads boot. + */ +start_all: + pushr $0xfff # save all regs, used later. + + subl3 $_start, $_edata, r0 # get size of text+data (w/o bss) + moval _start, r1 # get actual base-address of code + subl3 $_start, $_end, r2 # get complete size (incl. bss) + movl $_start, r3 # get relocated base-address of code + movc5 r0, (r1), $0, r2, (r3) # copy code to new location + + movl $relocated, -(sp) # return-address on top of stack + rsb # can be replaced with new address +relocated: # now relocation is done !!! + movl sp, _bootregs + movl ap, _boothowto + calls $0, _main # call main() which is + halt # not intended to return ... + +/* + * hoppabort() is called when jumping to the newly loaded program. + */ +ENTRY(hoppabort, 0) + movl 4(ap),r6 + movl 8(ap),r11 + movl 0xc(ap),r10 + calls $0,(r6) + halt diff --git a/sys/arch/vax/stand/tmscp.c b/sys/arch/vax/stand/tmscp.c new file mode 100644 index 00000000000..eb143e61426 --- /dev/null +++ b/sys/arch/vax/stand/tmscp.c @@ -0,0 +1,202 @@ +/* $NetBSD: tmscp.c,v 1.1 1995/09/16 12:57:35 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#define NRSP 0 /* Kludge */ +#define NCMD 0 /* Kludge */ + +#include "sys/param.h" +#include "sys/disklabel.h" + +#include "lib/libsa/stand.h" + +#include "../include/pte.h" +#include "../include/macros.h" +#include "../uba/ubareg.h" +#include "../uba/udareg.h" +#include "../vax/mscp.h" + +#include "vaxstand.h" + +static command(int,int); + +/* + * These routines for TMSCP tape standalone boot is very simple, + * assuming a lots of thing like that we only working at one tape at + * a time, no separate routines for uba driver etc.. + * This code is directly copied from ra disk driver. + */ + +struct ra_softc { + int udaddr; + int ubaddr; + int unit; +}; + +static volatile struct uda { + struct uda1ca uda_ca; /* communications area */ + struct mscp uda_rsp; /* response packets */ + struct mscp uda_cmd; /* command packets */ +} uda; + +static volatile struct uda *ubauda; +static volatile struct udadevice *udacsr; +static struct ra_softc ra_softc; +static char io_buf[MAXBSIZE]; + +tmscpopen(f, adapt, ctlr, unit, part) + struct open_file *f; + int ctlr, unit, part; +{ + char *msg; + extern u_int tmsaddr; + volatile struct ra_softc *ra=&ra_softc; + volatile struct uba_regs *mr=(void *)ubaaddr[adapt]; + volatile u_int *nisse; + unsigned short johan; + int i,err; + + if(adapt>nuba) return(EADAPT); + if(ctlr>nuda) return(ECTLR); + ra->udaddr=uioaddr[adapt]+tmsaddr; + ra->ubaddr=(int)mr; + ra->unit=unit; + udacsr=(void*)ra->udaddr; + nisse=&mr->uba_map[0]; + nisse[494]=PG_V|(((u_int)&uda)>>9); + nisse[495]=nisse[494]+1; + ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); + + /* + * Init of this tmscp ctlr. + */ + udacsr->udaip=0; /* Start init */ + while((udacsr->udasa&UDA_STEP1) == 0); + udacsr->udasa=0x8000; + while((udacsr->udasa&UDA_STEP2) == 0); + johan=(((u_int)ubauda)&0xffff)+8; + udacsr->udasa=johan; + while((udacsr->udasa&UDA_STEP3) == 0); + udacsr->udasa=3; + while((udacsr->udasa&UDA_STEP4) == 0); + udacsr->udasa=0x0001; + + uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; + uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; + uda.uda_cmd.mscp_un.un_seq.seq_addr = &uda.uda_ca.ca_cmddsc; + uda.uda_rsp.mscp_un.un_seq.seq_addr = &uda.uda_ca.ca_rspdsc; + uda.uda_cmd.mscp_vcid = 1; + uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0; + + command(M_OP_SETCTLRC, 0); + uda.uda_cmd.mscp_unit=ra->unit; + command(M_OP_ONLINE, 0); + + if (part) { + uda.uda_cmd.mscp_un.un_seq.seq_buffer = part; + command(M_OP_POS, 0); + uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0; + } + + f->f_devdata=(void *)ra; + return(0); +} + +static +command(cmd, arg) +{ + volatile int hej; + + uda.uda_cmd.mscp_opcode = cmd; + uda.uda_cmd.mscp_modifier = arg; + + uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; + uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; + + uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; + uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; + hej = udacsr->udaip; + while (uda.uda_ca.ca_rspdsc < 0) { + if (uda.uda_ca.ca_cmdint) + uda.uda_ca.ca_cmdint = 0; + } + +} + +static int curblock = 0; + +tmscpstrategy(ra, func, dblk, size, buf, rsize) + struct ra_softc *ra; + int func; + daddr_t dblk; + char *buf; + u_int size, *rsize; +{ + u_int i,j,pfnum, mapnr, nsize, bn, cn, sn, tn; + volatile struct uba_regs *ur=(void *)ra->ubaddr; + volatile struct udadevice *udadev=(void*)ra->udaddr; + volatile u_int *ptmapp=&ur->uba_map[0]; + volatile int hej; + + pfnum=(u_int)buf>>PGSHIFT; + + for(mapnr=0, nsize=size;(nsize+NBPG)>0;nsize-=NBPG) + ptmapp[mapnr++]=PG_V|pfnum++; + + /* + * First position tape. Remember where we are. + */ + if (dblk < curblock) { + uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; + command(M_OP_POS, 12); /* 12 == step block backward */ + } else { + uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock; + command(M_OP_POS, 4); /* 4 == step block forward */ + } + curblock = size/512 + dblk; + + /* + * Read in the number of blocks we need. + * Why doesn't read of multiple blocks work????? + */ + for (i = 0 ; i < size/512 ; i++) { + uda.uda_cmd.mscp_seq.seq_lbn = 1; + uda.uda_cmd.mscp_seq.seq_bytecount = 512; + uda.uda_cmd.mscp_seq.seq_buffer = + (((u_int)buf) & 0x1ff) + i * 512; + uda.uda_cmd.mscp_unit = ra->unit; + command(M_OP_READ, 0); + } + + *rsize=size; + return 0; +} diff --git a/sys/arch/vax/stand/vaxstand.h b/sys/arch/vax/stand/vaxstand.h new file mode 100644 index 00000000000..17ec1cbcd03 --- /dev/null +++ b/sys/arch/vax/stand/vaxstand.h @@ -0,0 +1,52 @@ +/* $NetBSD: vaxstand.h,v 1.3 1995/04/25 14:14:34 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#define MAXNMBA 8 /* Massbussadapters */ +#define MAXNUBA 8 /* Unibusadapters */ +#define MAXNBI 4 /* Bi-bussadapters */ +#define MAXMBAU 8 /* Units on an mba */ +#define MAXBIN 16 /* Bi-nodes */ + +/* Variables used in autoconf */ +extern int nmba, nuba, nbi, nsbi, nuda; +extern int *ubaaddr, *mbaaddr, *udaaddr, *uioaddr; + +/* devsw type definitions, used in bootxx and conf */ +#define SADEV(name,strategy,open,close,ioctl) \ + { name, \ + (int(*)(void *, int ,daddr_t , u_int , char *, u_int *))strategy, \ + (int(*)(struct open_file *, ...))open, \ + (int(*)(struct open_file *))close, \ + (int(*)(struct open_file *,u_long, void *))ioctl} + diff --git a/sys/arch/vax/uba/tmscp.c b/sys/arch/vax/uba/tmscp.c new file mode 100644 index 00000000000..5a7cbb47d99 --- /dev/null +++ b/sys/arch/vax/uba/tmscp.c @@ -0,0 +1,2136 @@ +/* $NetBSD: tmscp.c,v 1.4.2.1 1995/10/15 13:57:40 ragge Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tmscp.c 7.16 (Berkeley) 5/9/91 + */ + +/* + * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; + */ + +/************************************************************************ + * * + * Licensed from Digital Equipment Corporation * + * Copyright (c) * + * Digital Equipment Corporation * + * Maynard, Massachusetts * + * 1985, 1986 * + * All rights reserved. * + * * + * The Information in this software is subject to change * + * without notice and should not be construed as a commitment * + * by Digital Equipment Corporation. Digital makes no * + * representations about the suitability of this software for * + * any purpose. It is supplied "As Is" without expressed or * + * implied warranty. * + * * + * If the Regents of the University of California or its * + * licensees modify the software in a manner creating * + * diriviative copyright rights, appropriate copyright * + * legends may be placed on the drivative work in addition * + * to that set forth above. * + * * + ************************************************************************ + * + * tmscp.c - TMSCP (TK50/TU81) tape device driver + * + * Modification History: + * + * 06-Jan-86 - afd + * Changed the probe routine to use DELAY (not TODR). This now + * works for MicroVAXen as well. This eliminates the busy-wait + * for MicroVAXen so a dead TK50 controller will not hang autoconf. + * + * 06-Dec-85 - afd + * Fixed a bug in density selection. The "set unit characteristics" + * command to select density, was clearing the "unit flags" field + * where the CACHE bit was for TU81-E. Now the unit's "format" and + * "unitflgs" are saved in tms_info struct. And are used on STUNT + * commands. + * + * 19-Oct-85 - afd + * Added support to the open routine to allow drives to be opened + * for low density (800 or 1600 bpi) use. When the slave routine + * initiates a "get-unit-char" cmd, the format menu for the unit + * is saved in the tms_info structure. The format menu is used in the + * start routine to select the proper low density. + * + * 02-Oct-85 - afd + * When a tmscp-type controller is initializing, it is possible for + * the sa reg to become 0 between states. Thus the init code in + * the interrupt routine had to be modified to reflect this. + * + * 21-Sep-85 - afd + * The TK50 declares a serious exception when a tape mark is encountered. + * This causes problems to dd (& other UN*X utilities). So a flag + * is set in the rsp() routine when a tape mark is encountered. If + * this flag is set, the start() routine appends the Clear Serious + * Exception modifier to the next command. + * + * 03-Sep-85 -- jaw + * messed up previous edit.. + * + * 29-Aug-85 - jaw + * fixed bugs in 8200 and 750 buffered datapath handling. + * + * 06-Aug-85 - afd + * 1. When repositioning records or files, the count of items skipped + * does NOT HAVE to be returned by controllers (& the TU81 doesn't). + * So tmscprsp() had to be modified to stop reporting + * residual count errors on reposition commands. + * + * 2. Fixed bug in the open routine which allowed multiple opens. + * + * 18-Jul-85 - afd + * 1. Need to return status when mt status (or corresponding ioctl) is done. + * Save resid, flags, endcode & status in tmscprsp() routine (except on + * clear serious exception no-op). Return these fields when status + * ioctl is done (in tmscpcommand()). How they are returned: + * mt_resid = resid + * mt_dsreg = flags|endcode + * mt_erreg = status + * + * 2. Added latent support for enabling/disabling caching. This is + * handled along with all other ioctl commands. + * + * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since + * we have already commited to issuing a command at that point. + * + * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); + * We need to: Unlink the buffer from the I/O wait queue, + * and signal iodone, so the higher level command can exit! + * Just as if it were a valid command. + * + * 11-jul-85 -- jaw + * fix bua/bda map registers. + * + * 19-Jun-85 -- jaw + * VAX8200 name change. + * + * 06-Jun-85 - jaw + * fixes for 8200. + * + * 9-Apr-85 - afd + * Added timeout code to the probe routine, so if the controller + * fails to init in 10 seconds we return failed status. + * + * 13-Mar-85 -jaw + * Changes for support of the VAX8200 were merged in. + * + * 27-Feb-85 -tresvik + * Changes for support of the VAX8600 were merged in. + * + */ + +#define NTMS 2 /* XXX - This is _wery_ kludgy! /ragge */ + +#include "tmscp.h" +#if NTMSCP > 0 + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/buf.h" +#include "sys/conf.h" +#include "sys/errno.h" +#include "sys/file.h" +#include "sys/map.h" +#include "sys/ioctl.h" +#include "sys/syslog.h" +#include "sys/mtio.h" +/* #include "sys/cmap.h" */ +#include "sys/uio.h" +#include "sys/proc.h" +#include "sys/tprintf.h" + +#include "vax/include/pte.h" +#include "vax/include/cpu.h" +#include "vax/include/mtpr.h" +#include "vax/include/sid.h" +#include "vax/uba/ubareg.h" +#include "vax/uba/ubavar.h" + +#define TENSEC (1000) +#define TMS_PRI LOG_INFO + +#define NRSPL2 3 /* log2 number of response packets */ +#define NCMDL2 3 /* log2 number of command packets */ +#define NRSP (1<<NRSPL2) +#define NCMD (1<<NCMDL2) + +#include "tmscpreg.h" +#include "vax/vax/tmscpinf.h" +#include "vax/vax/mscpvar.h" + +/* Software state per controller */ + +struct tmscp_softc { + short sc_state; /* state of controller */ + short sc_mapped; /* Unibus map allocated for tmscp struct? */ + int sc_ubainfo; /* Unibus mapping info */ + struct tmscp *sc_tmscp; /* Unibus address of tmscp struct */ + int sc_ivec; /* interrupt vector address */ + short sc_credits; /* transfer credits */ + short sc_lastcmd; /* pointer into command ring */ + short sc_lastrsp; /* pointer into response ring */ + short sc_ipl; /* interrupt priority (Q-bus) */ +} tmscp_softc[NTMSCP]; + +struct tmscp { + struct tmscpca tmscp_ca; /* communications area */ + struct mscp tmscp_rsp[NRSP]; /* response packets */ + struct mscp tmscp_cmd[NCMD]; /* command packets */ +} tmscp[NTMSCP]; + +void tmscpstrategy(struct buf *); + +/* + * Per drive-unit info + */ +struct tms_info { + daddr_t tms_dsize; /* Max user size from online pkt */ + unsigned tms_type; /* Drive type int field */ + int tms_resid; /* residual from last xfer */ + u_char tms_endcode; /* last command endcode */ + u_char tms_flags; /* last command end flags */ + unsigned tms_status; /* Command status from last command */ + char tms_openf; /* lock against multiple opens */ + char tms_lastiow; /* last op was a write */ + char tms_serex; /* set when serious exception occurs */ + char tms_clserex; /* set when serex being cleared by no-op */ + short tms_fmtmenu; /* the unit's format (density) menu */ + short tms_unitflgs; /* unit flag parameters */ + short tms_format; /* the unit's current format (density) */ + tpr_t tms_tpr; /* tprintf handle */ +} tms_info[NTMS]; +struct uba_ctlr *tmscpminfo[NTMSCP]; +struct uba_device *tmsdinfo[NTMS]; +/* + * ifdef other tmscp devices here if they allow more than 1 unit/controller + */ +struct uba_device *tmscpip[NTMSCP][1]; +struct buf ctmscpbuf[NTMSCP]; /* internal cmd buffer (for ioctls) */ +struct buf tmsutab[NTMS]; /* Drive queue */ +struct buf tmscpwtab[NTMSCP]; /* I/O wait queue, per controller */ +int tmscpmicro[NTMSCP]; /* to store microcode level */ +short utoctlr[NTMS]; /* Slave unit to controller mapping */ + /* filled in by the slave routine */ + +/* Bits in minor device */ +#define TMSUNIT(dev) (minor(dev)&03) +#define T_HIDENSITY 010 + +/* Slave unit to controller mapping */ +#define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) + +/* + * Internal (ioctl) command codes (these must also be declared in the + * tmscpioctl routine). These correspond to ioctls in mtio.h + */ +#define TMS_WRITM 0 /* write tape mark */ +#define TMS_FSF 1 /* forward space file */ +#define TMS_BSF 2 /* backward space file */ +#define TMS_FSR 3 /* forward space record */ +#define TMS_BSR 4 /* backward space record */ +#define TMS_REW 5 /* rewind tape */ +#define TMS_OFFL 6 /* rewind tape & mark unit offline */ +#define TMS_SENSE 7 /* noop - do a get unit status */ +#define TMS_CACHE 8 /* enable cache */ +#define TMS_NOCACHE 9 /* disable cache */ +/* These go last: after all real mt cmds, just bump the numbers up */ +#define TMS_CSE 10 /* clear serious exception */ +#define TMS_LOWDENSITY 11 /* set unit to low density */ +#define TMS_HIDENSITY 12 /* set unit to high density */ + +/* + * Controller states + */ +#define S_IDLE 0 /* hasn't been initialized */ +#define S_STEP1 1 /* doing step 1 init */ +#define S_STEP2 2 /* doing step 2 init */ +#define S_STEP3 3 /* doing step 3 init */ +#define S_SCHAR 4 /* doing "set controller characteristics" */ +#define S_RUN 5 /* running */ + +int tmscperror = 0; /* causes hex dump of packets */ +int tmscp_cp_wait = 0; /* Something to wait on for command */ + /* packets and or credits. */ +void wakeup(); +extern int hz; /* Should find the right include */ + +#ifdef DEBUG +#define printd if (tmscpdebug) printf +int tmscpdebug = 1; +#define printd10 if(tmscpdebug >= 10) printf +#endif + +int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); +struct mscp *tmscpgetcp(); + +#define DRVNAME "tms" +#define CTRLNAME "tmscp" + +u_short tmscpstd[] = { 0174500, 0 }; +struct uba_driver tmscpdriver = +{ tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME +, tmscpminfo, 0}; + +#define b_qsize b_resid /* queue size per drive, in tmsutab */ +#define b_ubinfo b_resid /* Unibus mapping info, per buffer */ + + +/*************************************************************************/ + +#define DELAYTEN 1000 + + +/* + * Unfortunately qbgetpri can't be used because the TK50 doesn't flip the + * TMSCP_STEP2 flag in the tmscpsa register until after the pending interrupt + * has been acknowledged by the cpu. If you are at spl6(), the TMSCP_STEP2 + * flag never gets set and you return (0). + */ +tmscpprobe(reg, ctlr, um) + caddr_t reg; /* address of the IP register */ + int ctlr; /* index of controller in the tmscp_softc array */ + struct uba_ctlr *um; +{ + /* register int br, cvec; MUST be 1st (r11 & r10): IPL and intr vec */ + register struct tmscp_softc *sc = &tmscp_softc[ctlr]; + /* ptr to software controller structure */ + volatile struct tmscpdevice *tmscpaddr; + int count; /* for probe delay time out */ + +# ifdef lint + br = 0; cvec = br; br = cvec; reg = reg; + tmscpreset(0); tmscpintr(0); +# endif + + tmscpminfo[ctlr] = um; + tmscpaddr = (struct tmscpdevice *) reg; + /* + * Set host-settable interrupt vector. + * Assign 0 to the ip register to start the tmscp-device initialization. + * The device is not really initialized at this point, this is just to + * find out if the device exists. + */ + sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); + tmscpaddr->tmscpip = 0; + + count=0; + while(count < DELAYTEN) + { /* wait for at most 10 secs */ + if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) + break; + DELAY(10000); + count=count+1; + } + if (count == DELAYTEN) + return(0); + + tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); + + count=0; + while(count < DELAYTEN) + { + if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) + break; + DELAY(10000); + count = count+1; + } + if (count == DELAYTEN) + return(0); + +#ifdef QBA + sc->sc_ipl = 0x15; +#endif + return(sizeof (struct tmscpdevice)); +} + +/* + * Try to find a slave (a drive) on the controller. + * If the controller is not in the run state, call init to initialize it. + */ +tmscpslave (ui, reg) + struct uba_device *ui; /* ptr to the uba device structure */ + caddr_t reg; /* addr of the device controller */ +{ + register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; + register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; + register struct tms_info *tms = &tms_info[ui->ui_unit]; + volatile struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ + volatile struct mscp *mp; + volatile int i; /* Something to write into to start */ + /* the tmscp polling */ + +# ifdef lint + reg = reg; +# endif + tmscpaddr = (struct tmscpdevice *)um->um_addr; + /* + * If its not in the run state, start the initialization process + * (tmscpintr will complete it); if the initialization doesn't start; + * then return. + */ + if(sc->sc_state != S_RUN) + { +# ifdef DEBUG + printd("tmscpslave: ctlr not running: calling init \n"); +# endif + if(!tmscpinit(ui->ui_ctlr)) + return(0); + } + /* + * Wait for the controller to come into the run state or go idle. + * If it goes idle return. + */ +# ifdef DEBUG + i=1; +# endif + while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) +# ifdef DEBUG + if (tmscpaddr->tmscpsa & TMSCP_ERR && i) + { + printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff); + i=0; + } +# endif + ; /* wait */ + if(sc->sc_state == S_IDLE) + { /* The tmscp device failed to initialize */ + printf("tmscp controller failed to init\n"); + return(0); + } + /* The controller is up so see if the drive is there */ + if(0 == (mp = tmscpgetcp(um))) + { + printf("tmscp can't get command packet\n"); + return(0); + } + /* Need to determine the drive type for generic driver */ + mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type */ + mp->mscp_unit = ui->ui_slave; + mp->mscp_cmdref = (long) ui->ui_slave; + tms->tms_status = 0; /* set to zero */ + tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; + *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/ + i = tmscpaddr->tmscpip; +#ifdef lint + i = i; +#endif + while(!tms->tms_status) + ; /* Wait for some status */ +# ifdef DEBUG + printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK); +# endif + tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; + if(!tms->tms_type) /* packet from a GTUNT */ + return(0); /* Failed No such drive */ + else + return(1); /* Got it and it is there */ +} + + +/* + * Set ui flags to zero to show device is not online & set tmscpip. + * Unit to Controller mapping is set up here. + * Open routine will issue the online command, later. + */ +tmscpattach (ui) + register struct uba_device *ui; /* ptr to unibus dev struct */ +{ + + ui->ui_flags = 0; + tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; +# ifdef DEBUG + /* + * Check to see if the drive is available. + * If not then just print debug. + */ + if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) + printd("tmscpattach: unavailable \n"); +# endif + utoctlr[ui->ui_unit] = ui->ui_ctlr; +} + + +/* + * TMSCP interrupt routine. + */ +tmscpintr(uba,vector,level,d) +{ + volatile struct uba_ctlr *um = tmscpminfo[d]; + volatile struct tmscpdevice *tmscpaddr = + (struct tmscpdevice *)um->um_addr; + struct buf *bp; + volatile int i; + volatile struct tmscp_softc *sc = &tmscp_softc[d]; + struct tmscp *tm = &tmscp[d]; + struct tmscp *ttm; + volatile struct mscp *mp; + +# ifdef DEBUG + printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); +# endif + +#ifdef QBA + if (cpunumber == VAX_78032) + splx(sc->sc_ipl); +#endif + /* + * How the interrupt is handled depends on the state of the controller. + */ + switch (sc->sc_state) { + + case S_IDLE: + printf("tmscp%d: random interrupt ignored\n", d); + return; + + /* Controller was in step 1 last, see if its gone to step 2 */ + case S_STEP1: +# define STEP1MASK 0174377 +# define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) + for (i = 0; i < 150; i++) + { + if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) + { /* still in step 1 (wait 1/100 sec) */ + DELAY(10000); +# ifdef DEBUG + printd("still in step 1, delaying\n"); +# endif DEBUG + } + else + break; + } + if (i > 149) + { + sc->sc_state = S_IDLE; + printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa); + wakeup((caddr_t)um); + return; + } + tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) + | ((cpunumber == VAX_780 || cpunumber == VAX_8600) ? + TMSCP_PI : 0); + sc->sc_state = S_STEP2; + return; + + /* Controller was in step 2 last, see if its gone to step 3 */ + case S_STEP2: +# define STEP2MASK 0174377 +# define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) + for (i = 0; i < 150; i++) + { + if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) + { /* still in step 2 (wait 1/100 sec) */ + DELAY(10000); +# ifdef DEBUG + printd("still in step 2, delaying\n"); +# endif DEBUG + } + else + break; + } + if (i > 149) + { + sc->sc_state = S_IDLE; + printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa); + wakeup((caddr_t)um); + return; + } + tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16; + sc->sc_state = S_STEP3; + return; + + /* Controller was in step 3 last, see if its gone to step 4 */ + case S_STEP3: +# define STEP3MASK 0174000 +# define STEP3GOOD TMSCP_STEP4 + for (i = 0; i < 150; i++) + { + if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) + { /* still in step 3 (wait 1/100 sec) */ + DELAY(10000); +# ifdef DEBUG + printd("still in step 3, delaying\n"); +# endif DEBUG + } + else + break; + } + if (i > 149) + { + sc->sc_state = S_IDLE; + printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa); + wakeup((caddr_t)um); + return; + } + /* + * Get microcode version and model number of controller; + * Signal initialization complete (_GO) (to the controller); + * ask for Last Fail response if tmscperror is set; + * Set state to "set controller characteristics". + */ + tmscpmicro[d] = tmscpaddr->tmscpsa; + tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); + sc->sc_state = S_SCHAR; +# ifdef DEBUG + printd("tmscpintr: completed state %d \n", sc->sc_state); + printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, + (tmscpmicro[d]>>4) & 0xF); +# endif + + /* + * Initialize the data structures (response and command queues). + */ + ttm = sc->sc_tmscp; + for (i = 0; i < NRSP; i++) + { + tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | + (long)&ttm->tmscp_rsp[i].mscp_cmdref; + tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; + tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; + } + for (i = 0; i < NCMD; i++) + { + tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | + (long)&ttm->tmscp_cmd[i].mscp_cmdref; + tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; + tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; + tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; + } + bp = &tmscpwtab[d]; + bp->b_actf = NULL; + sc->sc_lastcmd = 1; + sc->sc_lastrsp = 0; + mp = &tmscp[d].tmscp_cmd[0]; + mp->mscp_unit = mp->mscp_modifier = 0; + mp->mscp_flags = 0; + mp->mscp_version = 0; + mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; + /* + * A host time out value of 0 means that the controller will not + * time out. This is ok for the TK50. + */ + mp->mscp_hsttmo = 0; + mp->mscp_time = 0; + mp->mscp_cntdep = 0; + mp->mscp_opcode = M_OP_STCON; + *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; + i = tmscpaddr->tmscpip; /* initiate polling */ + return; + + case S_SCHAR: + case S_RUN: + break; + + default: + printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state); + return; + } /* end switch */ + + /* + * The controller state is S_SCHAR or S_RUN + */ + + /* + * If the error bit is set in the SA register then print an error + * message and reinitialize the controller. + */ + if (tmscpaddr->tmscpsa&TMSCP_ERR) + { + printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff); + tmscpaddr->tmscpip = 0; + wakeup((caddr_t)um); + } + /* + * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) + */ + if (tm->tmscp_ca.ca_bdp) + { + UBAPURGE(um->um_hd->uh_uba, tm->tmscp_ca.ca_bdp); + tm->tmscp_ca.ca_bdp = 0; + tmscpaddr->tmscpsa = 0; /* signal purge complete */ + } + + /* + * Check for response ring transition. + */ + if (tm->tmscp_ca.ca_rspint) + { + tm->tmscp_ca.ca_rspint = 0; + for (i = sc->sc_lastrsp;; i++) + { + i %= NRSP; + if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) + break; + tmscprsp(um, tm, sc, i); + tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; + } + sc->sc_lastrsp = i; + } + + /* + * Check for command ring transition. + */ + if (tm->tmscp_ca.ca_cmdint) + { +# ifdef DEBUG + printd("tmscpintr: command ring transition\n"); +# endif + tm->tmscp_ca.ca_cmdint = 0; + } + if(tmscp_cp_wait) + wakeup((caddr_t)&tmscp_cp_wait); + (void) tmscpstart(um); +} + + +/* + * Open a tmscp device and set the unit online. If the controller is not + * in the run state, call init to initialize the tmscp controller first. + */ + +/* ARGSUSED */ +tmscpopen(dev, flag) + dev_t dev; + int flag; +{ + register int unit; + register struct uba_device *ui; + register struct tmscp_softc *sc; + register struct tms_info *tms; + register volatile struct mscp *mp; + register struct uba_ctlr *um; + volatile struct tmscpdevice *tmscpaddr; + volatile int i; + int s; + + unit = TMSUNIT(dev); +# ifdef DEBUG + printd("tmscpopen unit %d\n",unit); + if(tmscpdebug)DELAY(10000); +# endif + if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0) + return (ENXIO); + tms = &tms_info[ui->ui_unit]; + if (tms->tms_openf) + return (EBUSY); + sc = &tmscp_softc[ui->ui_ctlr]; + tms->tms_openf = 1; + tms->tms_tpr = tprintf_open(curproc); + s = splbio(); + if (sc->sc_state != S_RUN) + { + if (sc->sc_state == S_IDLE) + if(!tmscpinit(ui->ui_ctlr)) + { + printf("tmscp controller failed to init\n"); + (void) splx(s); + tms->tms_openf = 0; + return(ENXIO); + } + /* + * Wait for initialization to complete + */ + timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ + sleep((caddr_t)ui->ui_mi, 0); + if (sc->sc_state != S_RUN) + { + (void) splx(s); + tms->tms_openf = 0; + return (EIO); + } + } + /* + * Check to see if the device is really there. + * this code was taken from Fred Canters 11 driver + */ + um = ui->ui_mi; + tmscpaddr = (struct tmscpdevice *) um->um_addr; + (void) splx(s); + if(ui->ui_flags == 0) + { + s = splbio(); + while(0 ==(mp = tmscpgetcp(um))) + { + tmscp_cp_wait++; + sleep((caddr_t)&tmscp_cp_wait,PSWP+1); + tmscp_cp_wait--; + } + (void) splx(s); + mp->mscp_opcode = M_OP_ONLIN; + mp->mscp_unit = ui->ui_slave; + mp->mscp_cmdref = (long) & tms->tms_type; + /* need to sleep on something */ +# ifdef DEBUG + printd("tmscpopen: bring unit %d online\n",ui->ui_unit); +# endif + *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; + i = tmscpaddr->tmscpip; +#ifdef lint + i = i; +#endif + /* + * To make sure we wake up, timeout in 240 seconds. + * Wakeup in tmscprsp routine. + * 240 seconds (4 minutes) is necessary since a rewind + * can take a few minutes. + */ + timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); + sleep((caddr_t) mp->mscp_cmdref,PSWP+1); + } + if(ui->ui_flags == 0) { + tms->tms_openf = 0; + return(ENXIO); /* Didn't go online */ + } + tms->tms_lastiow = 0; + /* + * If the high density device is not specified, set unit to low + * density. This is done as an "internal" ioctl command so + * that the command setup and response handling + * is done thru "regular" command routines. + */ + if ((minor(dev) & T_HIDENSITY) == 0) + tmscpcommand(dev, TMS_LOWDENSITY, 1); + else + tmscpcommand(dev, TMS_HIDENSITY, 1); + return (0); +} + + +/* + * Close tape device. + * + * If tape was open for writing or last operation was + * a write, then write two EOF's and backspace over the last one. + * Unless this is a non-rewinding special file, rewind the tape. + * + * NOTE: + * We want to be sure that any serious exception is cleared on the + * close. A Clear Serious Exception (CSE) modifier is always done on + * the rewind command. For the non-rewind case we check to see if the + * "serex" field is set in the softc struct; if it is then issue a noop + * command with the CSE modifier. + * Make the tape available to others, by clearing openf flag. + */ +tmscpclose(dev, flag) + register dev_t dev; + register flag; +{ + register struct tms_info *tms; + register struct uba_device *ui; + + ui = tmsdinfo[TMSUNIT(dev)]; +# ifdef DEBUG + printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); + printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); + if(tmscpdebug)DELAY(10000); +# endif + tms = &tms_info[ui->ui_unit]; + if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) + { + /* device, command, count */ + tmscpcommand (dev, TMS_WRITM, 1); + tmscpcommand (dev, TMS_WRITM, 1); + tmscpcommand (dev, TMS_BSR, 1); + } + if ((minor(dev)&T_NOREWIND) == 0) + /* + * Don't hang waiting for rewind complete. + */ + tmscpcommand(dev, TMS_REW, 0); + else + if (tms->tms_serex) + { +# ifdef DEBUG + printd("tmscpclose: clearing serex\n"); + if(tmscpdebug)DELAY(10000); +# endif + tmscpcommand(dev, TMS_CSE, 1); + } + tprintf_close(tms->tms_tpr); + tms->tms_openf = 0; + return (0); +} + + +/* + * Execute a command on the tape drive a specified number of times. + * This routine sets up a buffer and calls the strategy routine which + * links the buffer onto the drive's buffer queue. + * The start routine will take care of creating a tmscp command packet + * with the command. The start routine is called by the strategy or the + * interrupt routine. + */ + +tmscpcommand (dev, com, count) + register dev_t dev; + int com, count; +{ + register struct uba_device *ui; + register struct buf *bp; + register int s; + int unit = TMSUNIT(dev); + + ui = tmsdinfo[unit]; + bp = &ctmscpbuf[ui->ui_ctlr]; + + s = splbio(); + while (bp->b_flags&B_BUSY) + { + /* + * This special check is because B_BUSY never + * gets cleared in the non-waiting rewind case. + */ + if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) + break; + bp->b_flags |= B_WANTED; + sleep((caddr_t)bp, PRIBIO); + } + bp->b_flags = B_BUSY|B_READ; + splx(s); + /* + * Load the buffer. The b_count field gets used to hold the command + * count. the b_resid field gets used to hold the command mneumonic. + * These 2 fields are "known" to be "safe" to use for this purpose. + * (Most other drivers also use these fields in this way.) + */ + bp->b_dev = dev; + bp->b_bcount = count; + bp->b_resid = com; + bp->b_blkno = 0; + tmscpstrategy(bp); + /* + * In case of rewind from close, don't wait. + * This is the only case where count can be 0. + */ + if (count == 0) + return; + iowait(bp); + if (bp->b_flags&B_WANTED) + wakeup((caddr_t)bp); + bp->b_flags &= B_ERROR; +} + +/* + * Find an unused command packet + */ +struct mscp * +tmscpgetcp(um) + struct uba_ctlr *um; +{ + register volatile struct mscp *mp; + register volatile struct tmscpca *cp; + register struct tmscp_softc *sc; + register int i; + int s; + + s = splbio(); + cp = &tmscp[um->um_ctlr].tmscp_ca; + sc = &tmscp_softc[um->um_ctlr]; + /* + * If no credits, can't issue any commands + * until some outstanding commands complete. + */ + i = sc->sc_lastcmd; +# ifdef DEBUG + printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); +# endif + if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && + (sc->sc_credits >= 2)) + { + sc->sc_credits--; /* This commits to issuing a command */ + cp->ca_cmddsc[i] &= ~TMSCP_INT; + mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; + mp->mscp_unit = mp->mscp_modifier = 0; + mp->mscp_opcode = mp->mscp_flags = 0; + mp->mscp_bytecnt = mp->mscp_buffer = 0; + sc->sc_lastcmd = (i + 1) % NCMD; + (void) splx(s); + return((struct mscp *)mp); + } + (void) splx(s); + return(NULL); +} + + +/* + * Initialize a TMSCP device. Set up UBA mapping registers, + * initialize data structures, and start hardware + * initialization sequence. + */ +tmscpinit (d) + int d; /* index to the controller */ +{ + register struct tmscp_softc *sc; + register struct tmscp *t; + volatile struct tmscpdevice *tmscpaddr; + struct uba_ctlr *um; + + sc = &tmscp_softc[d]; + um = tmscpminfo[d]; + um->um_tab.b_active++; + t = &tmscp[d]; + tmscpaddr = (struct tmscpdevice *)um->um_addr; + if (sc->sc_mapped == 0) + { + /* + * Map the communications area and command + * and response packets into Unibus address + * space. + */ + sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0); + sc->sc_tmscp = (struct tmscp *)(UBAI_ADDR(sc->sc_ubainfo)); + sc->sc_mapped = 1; + } + + /* + * Start the hardware initialization sequence. + */ + tmscpaddr->tmscpip = 0; /* start initialization */ + + while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) + { +# ifdef DEBUG + printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); + DELAY(100000); +# endif + if(tmscpaddr->tmscpsa & TMSCP_ERR) + return(0); /* CHECK */ + } + tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); + /* + * Initialization continues in the interrupt routine. + */ + sc->sc_state = S_STEP1; + sc->sc_credits = 0; + return(1); +} + + +/* + * Start I/O operation + * This code is convoluted. The majority of it was copied from the uda driver. + */ + +tmscpstart(um) + register struct uba_ctlr *um; +{ + register struct buf *bp, *dp; + register volatile struct mscp *mp; + register struct tmscp_softc *sc; + register struct tms_info *tms; + register struct uba_device *ui; + volatile struct tmscpdevice *tmscpaddr; + volatile struct tmscp *tm = &tmscp[um->um_ctlr]; + volatile int i; + int tempi; + char ioctl; /* flag: set true if its an IOCTL command */ + + sc = &tmscp_softc[um->um_ctlr]; + + for(;;) + { + if ((dp = um->um_tab.b_actf) == NULL) + { + /* + * Release unneeded UBA resources and return + * (drive was inactive) + */ + um->um_tab.b_active = 0; + break; + } + if ((bp = dp->b_actf) == NULL) + { + /* + * No more requests for this drive, remove + * from controller queue and look at next drive. + * We know we're at the head of the controller queue. + */ + dp->b_active = 0; + um->um_tab.b_actf = dp->b_hash.le_next; + continue; /* Need to check for loop */ + } + um->um_tab.b_active++; + tmscpaddr = (struct tmscpdevice *)um->um_addr; + ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; + tms = &tms_info[ui->ui_unit]; + if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) + { + tprintf(tms->tms_tpr, + "tms%d: hard error bn%d\n", + minor(bp->b_dev)&03, bp->b_blkno); + log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr, + tmscpaddr->tmscpsa&0xffff, sc->sc_state); + (void)tmscpinit(um->um_ctlr); + /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ + break; + } + /* + * Default is that last command was NOT a write command; + * if a write command is done it will be detected in tmscprsp. + */ + tms->tms_lastiow = 0; + if (ui->ui_flags == 0) + { /* not online */ + if ((mp = tmscpgetcp(um)) == NULL) + break; + mp->mscp_opcode = M_OP_ONLIN; + mp->mscp_unit = ui->ui_slave; + dp->b_active = 2; + um->um_tab.b_actf = dp->b_hash.le_next; /* remove from controller q */ + *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; + if (tmscpaddr->tmscpsa&TMSCP_ERR) + printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, + tmscpaddr->tmscpsa&0xffff); + i = tmscpaddr->tmscpip; + continue; + } + switch (cpunumber) { + + case VAX_8600: + case VAX_780: + i = UBA_NEEDBDP|UBA_CANTWAIT; + break; + case VAX_750: + i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; + break; + case VAX_730: + case VAX_78032: + i = UBA_CANTWAIT; + break; + } /* end switch (cpunumber) */ + /* + * If command is an ioctl command then set the ioctl flag for later use. + * If not (i.e. it is a read or write) then attempt + * to set up a buffer pointer. + */ + ioctl = 0; + if (bp == &ctmscpbuf[um->um_ctlr]) + ioctl = 1; + else + if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) + { + if(dp->b_qsize != 0) + break; /* When a command completes and */ + /* frees a bdp tmscpstart will be called */ + if ((mp = tmscpgetcp(um)) == NULL) + break; +# ifdef DEBUG + printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i); + if(tmscpdebug)DELAY(10000); +# endif + mp->mscp_opcode = M_OP_GTUNT; + mp->mscp_unit = ui->ui_slave; + *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; + if (tmscpaddr->tmscpsa&TMSCP_ERR) + printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr, + tmscpaddr->tmscpsa&0xffff); + i = tmscpaddr->tmscpip; /* initiate polling */ + break; + } +# if defined(VAX750) + if (cpunumber == VAX_750) + tempi = i & 0xfffffff; /* mask off bdp */ + else +# endif + tempi = i; + if ((mp = tmscpgetcp(um)) == NULL) + { + if (!ioctl) /* only need to release if NOT ioctl */ + ubarelse(um->um_ubanum,&tempi); + break; + } + mp->mscp_cmdref = (long)bp; /* pointer to get back */ + mp->mscp_unit = ui->ui_slave; + /* + * If its an ioctl-type command then set up the appropriate + * tmscp command; by doing a switch on the "b_resid" field where + * the command mneumonic is stored. + */ + if (ioctl) + { +# ifdef DEBUG + printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); +# endif + /* + * The reccnt and tmkcnt fields are set to zero by the getcp + * routine (as bytecnt and buffer fields). Thus reccnt and + * tmkcnt are only modified here if they need to be set to + * a non-zero value. + */ + switch ((int)bp->b_resid) { + + case TMS_WRITM: + mp->mscp_opcode = M_OP_WRITM; + break; + case TMS_FSF: + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_tmkcnt = bp->b_bcount; + break; + case TMS_BSF: + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_modifier = M_MD_REVRS; + mp->mscp_tmkcnt = bp->b_bcount; + break; + case TMS_FSR: + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_modifier = M_MD_OBJCT; + mp->mscp_reccnt = bp->b_bcount; + break; + case TMS_BSR: + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; + mp->mscp_reccnt = bp->b_bcount; + break; + /* + * Clear serious exception is done for Rewind & Available cmds + */ + case TMS_REW: + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; + if (bp->b_bcount == 0) + mp->mscp_modifier |= M_MD_IMMED; + tms->tms_serex = 0; + break; + case TMS_OFFL: + mp->mscp_opcode = M_OP_AVAIL; + mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; + tms->tms_serex = 0; + break; + case TMS_SENSE: + mp->mscp_opcode = M_OP_GTUNT; + break; + case TMS_CACHE: + mp->mscp_opcode = M_OP_STUNT; + tms->tms_unitflgs |= M_UF_WBKNV; + mp->mscp_unitflgs = tms->tms_unitflgs; + mp->mscp_format = tms->tms_format; + /* default device dependant parameters */ + mp->mscp_mediaid = 0; + break; + case TMS_NOCACHE: + mp->mscp_opcode = M_OP_STUNT; + tms->tms_unitflgs &= ~(M_UF_WBKNV); + mp->mscp_unitflgs = tms->tms_unitflgs; + mp->mscp_format = tms->tms_format; + /* default device dependant parameters */ + mp->mscp_mediaid = 0; + break; + case TMS_CSE: + /* + * This is a no-op command. It performs a + * clear serious exception only. (Done on a + * non-rewinding close after a serious exception.) + */ + mp->mscp_opcode = M_OP_REPOS; + mp->mscp_modifier = M_MD_CLSEX; + tms->tms_serex = 0; + tms->tms_clserex = 1; + break; + case TMS_LOWDENSITY: + /* + * Set the unit to low density + */ + mp->mscp_opcode = M_OP_STUNT; + mp->mscp_unitflgs = tms->tms_unitflgs; + mp->mscp_mediaid = 0; /* default device dependant parameters */ + if ((tms->tms_fmtmenu & M_TF_800) != 0) + mp->mscp_format = M_TF_800; + else + mp->mscp_format = M_TF_PE & tms->tms_fmtmenu; + tms->tms_format = mp->mscp_format; + break; + case TMS_HIDENSITY: + /* + * Set the unit to high density (format == 0) + */ + mp->mscp_opcode = M_OP_STUNT; + mp->mscp_unitflgs = tms->tms_unitflgs; + mp->mscp_mediaid = 0; /* default device dependant parameters */ + mp->mscp_format = 0; + tms->tms_format = 0; + break; + default: + printf("Bad ioctl on tms unit %d\n", ui->ui_unit); + /* Need a no-op. Reposition no amount */ + mp->mscp_opcode = M_OP_REPOS; + break; + } /* end switch (bp->b_resid) */ + } + else /* Its a read/write command (not an ioctl) */ + { + mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; + mp->mscp_bytecnt = bp->b_bcount; + mp->mscp_buffer = UBAI_ADDR(i) | (UBAI_BDP(i) << 24); + + bp->b_ubinfo = tempi; /* save mapping info */ + } + if (tms->tms_serex == 2) /* if tape mark read */ + { + mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ + tms->tms_serex = 0; + } + *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; +# ifdef DEBUG + printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); + if(tmscpdebug)DELAY(100000); +# endif + i = tmscpaddr->tmscpip; /* initiate polling */ + dp->b_qsize++; + /* + * Move drive to the end of the controller queue + */ + if (dp->b_hash.le_next != NULL) + { + um->um_tab.b_actf = dp->b_hash.le_next; + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + } + /* + * Move buffer to I/O wait queue + */ + dp->b_actf = bp->b_actf; + dp = &tmscpwtab[um->um_ctlr]; + MSCP_APPEND(bp, dp, b_actf); + if (tmscpaddr->tmscpsa&TMSCP_ERR) + { + printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff); + (void)tmscpinit(um->um_ctlr); + break; + } + } /* end for */ + /* + * Check for response ring transitions lost in the + * Race condition + */ + for (i = sc->sc_lastrsp;; i++) + { + i %= NRSP; + if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) + break; + tmscprsp(um, tm, sc, i); + tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; + } + sc->sc_lastrsp = i; +} + + +/* + * Process a response packet + */ +tmscprsp(um, tm, sc, i) + register struct uba_ctlr *um; + register volatile struct tmscp *tm; + register struct tmscp_softc *sc; + int i; +{ + register volatile struct mscp *mp; + register struct tms_info *tms; + struct uba_device *ui; + struct buf *dp, *bp; + int st; + + mp = &tm->tmscp_rsp[i]; + mp->mscp_header.tmscp_msglen = mscp_msglen; + sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ + if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ + return; +# ifdef DEBUG + printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); +# endif + /* + * If it's an error log message (datagram), + * pass it on for more extensive processing. + */ + if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) + { /* check */ + tmserror(um, (struct mslg *)mp); + return; + } + st = mp->mscp_status&M_ST_MASK; + /* + * The controller interrupts as drive 0. + * This means that you must check for controller interrupts + * before you check to see if there is a drive 0. + */ + if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) + { + if (st == M_ST_SUCC) + { +# ifdef DEBUG + printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); + printd("ctlr timeout = %d\n", mp->mscp_cnttmo); +# endif + sc->sc_state = S_RUN; + } + else + sc->sc_state = S_IDLE; + um->um_tab.b_active = 0; + wakeup((caddr_t)um); + return; + } + if (mp->mscp_unit >= NTMS) + return; + if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) + return; + tms = &tms_info[ui->ui_unit]; + /* + * Save endcode, endflags, and status for mtioctl get unit status. + * NOTE: Don't do this on Clear serious exception (reposition no-op); + * which is done on close since this would + * overwrite the real status we want. + */ + if (tms->tms_clserex != 1) + { + tms->tms_endcode = mp->mscp_opcode; + tms->tms_flags = mp->mscp_flags; + tms->tms_status = st; + } + else tms->tms_clserex = 0; + + switch (mp->mscp_opcode) { + case M_OP_ONLIN|M_OP_END: + tms->tms_type = mp->mscp_mediaid; + dp = &tmsutab[ui->ui_unit]; + if (st == M_ST_SUCC) + { + /* + * Link the drive onto the controller queue + */ + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + ui->ui_flags = 1; /* mark it online */ + tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; +# ifdef DEBUG + printd("tmscprsp: unit %d online\n", mp->mscp_unit); +# endif + /* + * This define decodes the Media type identifier + */ +# define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') +# ifdef DEBUG + printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" + ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) + ,F_to_C(mp,3), F_to_C(mp,2) + ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f); +# endif + dp->b_active = 1; + } /* end if st == M_ST_SUCC */ + else + { + if (bp = dp->b_actf) + tprintf(tms->tms_tpr, + "tms%d: hard error bn%d: OFFLINE\n", + minor(bp->b_dev)&03, bp->b_blkno); + else + tprintf(tms->tms_tpr, + "tms%d: hard error: OFFLINE\n", + ui->ui_unit); + while (bp = dp->b_actf) + { + dp->b_actf = bp->b_actf; + bp->b_flags |= B_ERROR; + iodone(bp); + } + } + if(mp->mscp_cmdref!=NULL) + /* Seems to get lost sometimes in uda */ + wakeup((caddr_t)mp->mscp_cmdref); + break; + /* + * The AVAILABLE ATTENTION message occurs when the + * unit becomes available after loading, + * marking the unit offline (ui_flags = 0) will force an + * online command prior to using the unit. + */ + case M_OP_AVATN: + ui->ui_flags = 0; + tms->tms_type = mp->mscp_mediaid; + break; + case M_OP_END: + /* + * An endcode without an opcode (0200) is an invalid command. + * The mscp specification states that this would be a protocol + * type error, such as illegal opcodes. The mscp spec. also + * states that parameter error type of invalid commands should + * return the normal end message for the command. This does not appear + * to be the case. An invalid logical block number returned an endcode + * of 0200 instead of the 0241 (read) that was expected. + */ + + printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", + um->um_ctlr, mp->mscp_opcode, st); + bp = (struct buf *)mp->mscp_cmdref; + /* + * Unlink buffer from I/O wait queue. + * And signal iodone, so the higher level command can exit! + * + */ + dp = &tmscpwtab[um->um_ctlr]; + while (dp && dp->b_actf != bp) + dp = dp->b_actf; + if (dp == NULL) + panic("tmscp: don't work1!"); + dp->b_actf = bp->b_actf; + dp = &tmsutab[ui->ui_unit]; + dp->b_qsize--; + iodone(bp); + break; + case M_OP_WRITE|M_OP_END: + /* mark the last io op as a write */ + tms->tms_lastiow = 1; + case M_OP_READ|M_OP_END: + case M_OP_WRITM|M_OP_END: + case M_OP_REPOS|M_OP_END: + case M_OP_STUNT|M_OP_END: + /* + * The AVAILABLE message occurs when the mt ioctl "rewoffl" is + * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is + * done with the UNLOAD modifier. This performs a rewind, followed + * by marking the unit offline. So mark the unit offline + * software wise as well (ui_flags = 0 and + * tms->tms_openf = 0). + */ + case M_OP_AVAIL|M_OP_END: +# ifdef DEBUG + printd("tmscprsp: position = %d\n", mp->mscp_lbn); +# endif + bp = (struct buf *)mp->mscp_cmdref; + /* + * Only need to release buffer if the command was read or write. + * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. + */ + if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || + mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) + ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); + /* + * Unlink buffer from I/O wait queue. + */ + dp = &tmscpwtab[um->um_ctlr]; + while (dp && dp->b_actf != bp) + dp = dp->b_actf; + if (dp == NULL) + panic("tmscp: don't work2!"); + dp->b_actf = bp->b_actf; +# if defined(VAX750) + if (cpunumber == VAX_750) { + if ((tmscpwtab[um->um_ctlr].b_actf == NULL) && + (um->um_ubinfo != 0)) { + ubarelse(um->um_ubanum, &um->um_ubinfo); + } + else { + if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || + mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) + UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_ubinfo >>28) & 0x0f); + } + } +# endif + dp = &tmsutab[ui->ui_unit]; + dp->b_qsize--; + if (st == M_ST_OFFLN || st == M_ST_AVLBL) + { + ui->ui_flags = 0; /* mark unit offline */ + tms->tms_openf = 0; + tms->tms_type = mp->mscp_mediaid; + /* + * Link the buffer onto the front of the drive queue + */ + bp->b_actf = dp->b_actf; + dp->b_actf = bp; + /* + * Link the drive onto the controller queue + */ + if (dp->b_active == 0) + { + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + dp->b_active = 1; + } +# if defined(VAX750) + if (cpunumber == VAX_750 && um->um_ubinfo == 0) + um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); +# endif + return; + } + if (st != M_ST_SUCC) + { + if (mp->mscp_flags & M_EF_SEREX) + tms->tms_serex = 1; + if (st != M_ST_TAPEM) + { + tprintf(tms->tms_tpr, + "tms%d: hard error bn%d\n", + minor(bp->b_dev)&03, bp->b_blkno); + errinfo(st); /* produces more info */ +# ifdef DEBUG + printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n", + (mp->mscp_status & 177740)>>5, mp->mscp_flags); +# endif + bp->b_flags |= B_ERROR; + } + else + /* Hit a tape mark - Set serex flag to + * a special value so we can clear the + * serious exception on the next command. + */ + tms->tms_serex = 2; + } + /* + * The tmscp spec states that controllers do not have to + * report the number of records or files skipped. So on + * reposition commands we go strictly by cmd status. + */ + if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) + bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; + else + bp->b_resid = 0; + tms->tms_resid = bp->b_resid; + iodone(bp); + break; + + case M_OP_GTUNT|M_OP_END: +# ifdef DEBUG + printd("tmscprsp: GTUNT end packet status = 0%o\n",st); + printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" + ,mp->mscp_unit, mp->mscp_mediaid + ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) + ,F_to_C(mp,1),F_to_C(mp,0) + ,mp->mscp_mediaid & 0x7f + ,mp->mscp_unitid.val[0] + ,mp->mscp_unitid.val[1] + ,mp->mscp_format); +# endif + tms->tms_type = mp->mscp_mediaid; + tms->tms_fmtmenu = mp->mscp_fmtmenu; + tms->tms_unitflgs = mp->mscp_unitflgs; + break; + + default: + printf("tmscp unknown packet\n"); + tmserror(um, (struct mslg *)mp); + } /* end switch mp->mscp_opcode */ +} + + +/* + * Give a meaningful error when the mscp_status field returns an error code. + */ + +errinfo(st) + int st; /* the status code */ +{ + switch(st) { + case M_ST_ICMD: + printf("invalid command\n"); + break; + case M_ST_ABRTD: + printf("command aborted\n"); + break; + case M_ST_OFFLN: + printf("unit offline\n"); + break; + case M_ST_WRTPR: + printf("unit write protected\n"); + break; + case M_ST_COMP: + printf("compare error\n"); + break; + case M_ST_DATA: + printf("data error\n"); + break; + case M_ST_HSTBF: + printf("host buffer access error\n"); + break; + case M_ST_CNTLR: + printf("controller error\n"); + break; + case M_ST_DRIVE: + printf("drive error\n"); + break; + case M_ST_FMTER: + printf("formatter error\n"); + break; + case M_ST_BOT: + printf("BOT encountered\n"); + break; + case M_ST_TAPEM: + printf("tape mark encountered\n"); + break; + case M_ST_RDTRN: + printf("record data truncated\n"); + break; + case M_ST_PLOST: + printf("position lost\n"); + break; + case M_ST_SEX: + printf("serious exception\n"); + break; + case M_ST_LED: + printf("LEOT detected\n"); + break; + } +} + + +/* + * Manage buffers and perform block mode read and write operations. + */ + +void +tmscpstrategy (bp) + register struct buf *bp; +{ + register struct uba_device *ui; + register struct uba_ctlr *um; + register struct buf *dp; + register int unit = TMSUNIT(bp->b_dev); + int s; + + if (unit >= NTMS) + { +# ifdef DEBUG + printd ("tmscpstrategy: bad unit # %d\n",unit); +# endif + bp->b_flags |= B_ERROR; + iodone(bp); + return; + } + ui = tmsdinfo[unit]; + um = ui->ui_mi; + if (ui == 0 || ui->ui_alive == 0) + { + bp->b_flags |= B_ERROR; + iodone(bp); + return; + } + s = splbio(); + /* + * Link the buffer onto the drive queue + */ + dp = &tmsutab[ui->ui_unit]; + MSCP_APPEND(bp, dp, b_actf); + /* + * Link the drive onto the controller queue + */ + if (dp->b_active == 0) + { + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + dp->b_active = 1; + } + /* + * If the controller is not active, start it. + */ + if (um->um_tab.b_active == 0) + { +# if defined(VAX750) + if (cpunumber == VAX_750 + && tmscpwtab[um->um_ctlr].b_actf == NULL) + { + if (um->um_ubinfo != 0) + log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", + um->um_ubinfo); + else + um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); + } +# endif +# ifdef DEBUG + printd10("tmscpstrategy: Controller not active, starting it\n"); +# endif + (void) tmscpstart(um); + } + splx(s); + return; +} + +int +tmscpread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(tmscpstrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +tmscpwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(tmscpstrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +#define DBSIZE 32 + +#define ca_Rspdsc ca_rspdsc[0] +#define ca_Cmddsc ca_rspdsc[1] +#define tmscp_Rsp tmscp_rsp[0] +#define tmscp_Cmd tmscp_cmd[0] + +struct tmscp tmscpd[NTMSCP]; + +tmscpdump(dev) + dev_t dev; +{ +#ifdef notyet + volatile struct tmscpdevice *tmscpaddr; + volatile struct tmscp *tmscp_ubaddr; + char *start; + int num, blk, unit; + register struct uba_regs *uba; + register struct uba_device *ui; + register volatile struct tmscp *tmscpp; + register struct pte *io; + register int i; + + unit = minor(dev) & 03; + if (unit >= NTMS) + return (ENXIO); +# define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) + ui = phys(struct uba_device *, tmsdinfo[unit]); + if (ui->ui_alive == 0) + return (ENXIO); + uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; + ubainit(uba); + tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; + DELAY(2000000); + tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); + + num = btoc(sizeof(struct tmscp)) + 1; + io = (struct pte *)&uba->uba_map[NUBMREG-num]; + for(i = 0; i<num; i++) + *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); + tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); + + tmscpaddr->tmscpip = 0; + while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) + if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); + tmscpaddr->tmscpsa = TMSCP_ERR; + while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) + if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); + tmscpaddr->tmscpsa = (short)((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase); + while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) + if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); + tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); + while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) + if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); + tmscpaddr->tmscpsa = TMSCP_GO; + tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; + tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; + tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ + tmscpp->tmscp_Cmd.mscp_cntflgs = 0; + tmscpp->tmscp_Cmd.mscp_version = 0; + if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { + return(EFAULT); + } + tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; + if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { + return(EFAULT); + } + + num = maxfree; + start = 0; + while (num > 0) + { + blk = num > DBSIZE ? DBSIZE : num; + io = (struct pte *)uba->uba_map; + for (i = 0; i < blk; i++) + *(int *)io++ = (btop(start)+i) | UBAMR_MRV; + *(int *)io = 0; + tmscpp->tmscp_Cmd.mscp_lbn = btop(start); + tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; + tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; +# ifdef MVAX + if( cpu == MVAX_I ) + tmscpp->tmscp_Cmd.mscp_buffer = (long) start; + else +# endif MVAX + tmscpp->tmscp_Cmd.mscp_buffer = 0; + if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) + return(EIO); + start += blk*NBPG; + num -= blk; + } +#endif + return (0); +} + + +/* + * Perform a standalone tmscp command. This routine is only used by tmscpdump. + */ + +tmscpcmd(op, tmscpp, tmscpaddr) + int op; + register volatile struct tmscp *tmscpp; + volatile struct tmscpdevice *tmscpaddr; +{ + volatile int i; + + + tmscpp->tmscp_Cmd.mscp_opcode = op; + tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; + tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; + tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; + tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; + if (tmscpaddr->tmscpsa&TMSCP_ERR) + printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); + i = tmscpaddr->tmscpip; +#ifdef lint + i = i; +#endif + for (;;) + { + if (tmscpp->tmscp_ca.ca_cmdint) + tmscpp->tmscp_ca.ca_cmdint = 0; + if (tmscpp->tmscp_ca.ca_rspint) + break; + } + tmscpp->tmscp_ca.ca_rspint = 0; + if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || + (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) + { + printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, + tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); + return(0); + } + return(1); +} + +/* + * Catch ioctl commands, and call the "command" routine to do them. + */ + +/* ARGSUSED */ +tmscpioctl(dev, cmd, data, flag) + dev_t dev; + int cmd; + caddr_t data; + int flag; +{ + register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; + register callcount; /* number of times to call cmd routine */ + register struct uba_device *ui; + register struct tms_info *tms; + int fcount; /* number of files (or records) to space */ + int error = 0; + register struct mtop *mtop; /* mag tape cmd op to perform */ + register struct mtget *mtget; /* mag tape struct to get info in */ + + /* we depend of the values and order of the TMS ioctl codes here */ + static tmsops[] = + {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, + TMS_CACHE,TMS_NOCACHE}; + + switch (cmd) { + case MTIOCTOP: /* tape operation */ + mtop = (struct mtop *)data; + switch (mtop->mt_op) { + + case MTWEOF: + callcount = mtop->mt_count; + fcount = 1; + break; + case MTFSF: case MTBSF: + case MTFSR: case MTBSR: + callcount = 1; + fcount = mtop->mt_count; + break; + case MTREW: case MTOFFL: case MTNOP: + case MTCACHE: case MTNOCACHE: + callcount = 1; + fcount = 1; /* wait for this rewind */ + break; + default: + return (ENXIO); + } /* end switch mtop->mt_op */ + + if (callcount <= 0 || fcount <= 0) + return (EINVAL); + while (--callcount >= 0) + { + tmscpcommand(dev, tmsops[mtop->mt_op], fcount); + if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && + bp->b_resid) + return (EIO); + if (bp->b_flags & B_ERROR) /* like hitting BOT */ + break; + } + if (bp->b_flags&B_ERROR) + if ((error = bp->b_error)==0) + return (EIO); + return (error); + + case MTIOCGET: + /* + * Return status info associated with the particular UNIT. + */ + ui = tmsdinfo[TMSUNIT(dev)]; + tms = &tms_info[ui->ui_unit]; + mtget = (struct mtget *)data; + mtget->mt_type = MT_ISTMSCP; + mtget->mt_dsreg = tms->tms_flags << 8; + mtget->mt_dsreg |= tms->tms_endcode; + mtget->mt_erreg = tms->tms_status; + mtget->mt_resid = tms->tms_resid; + break; + + default: + return (ENXIO); + } + return (0); +} + + +/* + * Reset (for raw mode use only). + */ + +tmscpreset (uban) + int uban; +{ + register struct uba_ctlr *um; + register struct uba_device *ui; + register struct buf *bp, *dp; + register int unit; + struct buf *nbp; + int d; + + for (d = 0; d < NTMSCP; d++) + { + if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || + um->um_alive == 0) + continue; + printf(" tmscp%d", d); + um->um_tab.b_active = 0; + um->um_tab.b_actf = 0; + tmscp_softc[d].sc_state = S_IDLE; + tmscp_softc[d].sc_mapped = 0; + for (unit = 0; unit < NTMS; unit++) + { + if ((ui = tmsdinfo[unit]) == 0) + continue; + if (ui->ui_alive == 0 || ui->ui_mi != um) + continue; + tmsutab[unit].b_active = 0; + tmsutab[unit].b_qsize = 0; + } + for (bp = tmscpwtab[d].b_actf; bp; bp = nbp) + { + nbp = bp->b_actf; + bp->b_ubinfo = 0; + /* + * Link the buffer onto the drive queue + */ + dp = &tmsutab[TMSUNIT(bp->b_dev)]; + MSCP_APPEND(bp, dp, b_actf); + /* + * Link the drive onto the controller queue + */ + if (dp->b_active == 0) + { + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + dp->b_active = 1; + } + } + (void)tmscpinit(d); + } +} + + +/* + * Process an error log message + * + * Only minimal decoding is done, only "useful" + * information is printed. Eventually should + * send message to an error logger. + */ + +tmserror(um, mp) + register struct uba_ctlr *um; + register struct mslg *mp; +{ + register i; + +# ifdef DEBUG + printd("tmserror:\n"); +# endif + if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) + log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, + mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); + + switch (mp->mslg_format) { + + case M_FM_CNTERR: + log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); + break; + case M_FM_BUSADDR: + log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", + mp->mslg_event, mp->mslg_unitid & 0xffffffff); + break; + case M_FM_TAPETRN: + log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", + mp->mslg_unit, mp->mslg_group, mp->mslg_event); + break; + case M_FM_STIERR: + log(TMS_PRI, "STI error, unit %d, event 0%o\n", + mp->mslg_unit, mp->mslg_event); +#ifdef notdef + /* too painful to do with log() */ + for(i = 0; i < 62;i++) + mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); + mprintf("\n"); +#endif + break; + case M_FM_STIDEL: + log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", + mp->mslg_unit, mp->mslg_event); + break; + case M_FM_STIFEL: + log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", + mp->mslg_unit, mp->mslg_event); + break; + default: + log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", + mp->mslg_unit, mp->mslg_format, mp->mslg_event); + } + + if (tmscperror) + { + register long *p = (long *)mp; + + for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) + printf("%x ", *p++); + printf("\n"); + } +} +#endif diff --git a/sys/arch/vax/uba/tmscpreg.h b/sys/arch/vax/uba/tmscpreg.h new file mode 100644 index 00000000000..de806fcdb53 --- /dev/null +++ b/sys/arch/vax/uba/tmscpreg.h @@ -0,0 +1,120 @@ +/* $NetBSD: tmscpreg.h,v 1.1 1995/02/23 17:53:19 ragge Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tmscpreg.h 7.2 (Berkeley) 5/9/91 + */ + +/* @(#)tmscpreg.h 1.1 11/2/84 84/09/25 */ + +/**************************************************************** + * * + * Licensed from Digital Equipment Corporation * + * Copyright (c) * + * Digital Equipment Corporation * + * Maynard, Massachusetts * + * 1985, 1986 * + * All rights reserved. * + * * + * The Information in this software is subject to change * + * without notice and should not be construed as a commitment * + * by Digital Equipment Corporation. Digital makes no * + * representations about the suitability of this software for * + * any purpose. It is supplied "As Is" without expressed or * + * implied warranty. * + * * + * If the Regents of the University of California or its * + * licensees modify the software in a manner creating * + * diriviative copyright rights, appropriate copyright * + * legends may be placed on the drivative work in addition * + * to that set forth above. * + * * + ****************************************************************/ +/* + * TMSCP registers and structures + */ + +#ifndef _UBA_TMSCPREG_ +#define _UBA_TMSCPREG_ +struct tmscpdevice { + short tmscpip; /* initialization and polling */ + short tmscpsa; /* status and address */ +}; + +#define TMSCP_ERR 0100000 /* error bit */ +#define TMSCP_STEP4 0040000 /* step 4 has started */ +#define TMSCP_STEP3 0020000 /* step 3 has started */ +#define TMSCP_STEP2 0010000 /* step 2 has started */ +#define TMSCP_STEP1 0004000 /* step 1 has started */ +#define TMSCP_NV 0002000 /* no host settable interrupt vector */ +#define TMSCP_QB 0001000 /* controller supports Q22 bus */ +#define TMSCP_DI 0000400 /* controller implements diagnostics */ +#define TMSCP_OD 0000200 /* port allows odd host addr's in the buffer descriptor */ +#define TMSCP_IE 0000200 /* interrupt enable */ +#define TMSCP_MP 0000100 /* port supports address mapping */ +#define TMSCP_LF 0000002 /* host requests last fail response packet */ +#define TMSCP_PI 0000001 /* host requests adapter purge interrupts */ +#define TMSCP_GO 0000001 /* start operation, after init */ + + +/* + * TMSCP Communications Area + */ + +struct tmscpca { + short ca_xxx1; /* unused */ + char ca_xxx2; /* unused */ + char ca_bdp; /* BDP to purge */ + short ca_cmdint; /* command queue transition interrupt flag */ + short ca_rspint; /* response queue transition interrupt flag */ + long ca_rspdsc[NRSP];/* response descriptors */ + long ca_cmddsc[NCMD];/* command descriptors */ +}; + +#define ca_ringbase ca_rspdsc[0] + +#define TMSCP_OWN 0x80000000 /* port owns this descriptor (else host + owns it) */ +#define TMSCP_INT 0x40000000 /* allow interrupt on ring transition */ + +#define TMSCP_MAP 0x80000000 /* modifier for mapped buffer descriptors */ + +/* + * TMSCP packet info (same as MSCP) + */ +struct mscp_header { + short tmscp_msglen; /* length of MSCP packet */ + char tmscp_credits; /* low 4 bits: credits, high 4 bits: msgtype */ + char tmscp_vcid; /* virtual circuit id (connection id) */ +}; +#endif diff --git a/sys/arch/vax/uba/uba.c b/sys/arch/vax/uba/uba.c new file mode 100644 index 00000000000..6f3d9c9eb5e --- /dev/null +++ b/sys/arch/vax/uba/uba.c @@ -0,0 +1,1294 @@ +/* $NetBSD: uba.c,v 1.8 1995/06/16 15:26:11 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1986 The Regents of the University of California. + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uba.c 7.10 (Berkeley) 12/16/90 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + + /* All bugs are subject to removal without further notice */ + +#include "sys/param.h" +#include "sys/types.h" +#include "sys/time.h" +#include "sys/systm.h" +#include "sys/map.h" +#include "sys/buf.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/conf.h" +#include "sys/dkstat.h" +#include "sys/kernel.h" +#include "sys/malloc.h" +#include "sys/device.h" + +#include "machine/pte.h" +#include "machine/cpu.h" +#include "machine/mtpr.h" +#include "machine/nexus.h" +#include "machine/sid.h" +#if VAX630 +#include "machine/uvaxII.h" +#endif +#include "uba.h" +#include "ubareg.h" +#include "ubavar.h" + +int (*vekmatris[NUBA][128])(); +int interinfo[NUBA][128]; +int dkn; +extern int cold; +struct uba_hd uba_hd[NUBA]; + +/* F|r att f} genom kompilatorn :( Nollpekare f|r interrupt... */ +int cvec=0; +volatile int rbr,rcvec; +#if VAX630 || VAX410 +extern struct uvaxIIcpu *uvaxIIcpu_ptr; +#endif +#if VAX630 +extern struct ka630clock *ka630clk_ptr; +#endif + +/* + * Mark addresses starting at "addr" and continuing + * "size" bytes as allocated in the map "ualloc". + * Warn if the new allocation overlaps a previous allocation. + */ +static +csralloc(ualloc, addr, size) + caddr_t ualloc; + u_short addr; + register int size; +{ + register caddr_t p; + int warned = 0; + + p = &ualloc[ubdevreg(addr+size)]; + while (--size >= 0) { + if (*--p && !warned) { + printf( + "WARNING: device registers overlap those for a previous device!\n"); + warned = 1; + } + *p = 1; + } +} + +/* + * Make an IO register area accessible at physical address physa + * by mapping kernel ptes starting at pte. + */ +ioaccess(physa, pte, size) + u_int physa; + u_int *pte; + u_int size; +{ + u_int i = (size>>PG_SHIFT); + u_int v = (physa>>PG_SHIFT); + + do { + *pte = PG_V|PG_KW|v; + pte++; + v++; + } while (--i > 0); + mtpr(0, PR_TBIA); +} + +/* + * General uba interrupt handler. + */ +ubainterrupt(level, uba,vektor){ +/*printf("ubainterrupt: level %x, uba %x, vektor %x\n",level, uba,vektor); */ + (*vekmatris[uba][vektor])(vektor,level,uba,interinfo[uba][vektor]); +} + +/* + * Stray interrupt vector handler, used when nowhere else to + * go to. + */ +ubastray(vektor, level,uba){ + if(cold){ + rbr=level; + rcvec=vektor; + } else { + printf("uba%d: unexpected interrupt at vector %d on level %d", + uba, vektor, level); + } +} + +/* + * Find devices on a UNIBUS. + * Uses per-driver routine to set <br,cvec> into <r11,r10>, + * and then fills in the tables, with help from a per-driver + * slave initialization routine. + * + * Changed this ugly written code assuming special registers + * from the C compiler :( 940516/ragge + */ + +unifind(uhp0, pumem) + struct uba_hd *uhp0; + caddr_t pumem; +{ + register struct uba_device *ui; + register struct uba_ctlr *um; + register struct uba_hd *uhp = uhp0; + u_short *reg, *ap, addr; + struct uba_driver *udp; + int i, (*ivec)(); + caddr_t ualloc; + volatile extern int br, cvec; + volatile extern int rbr, rcvec; +#if DW780 || DWBUA + struct uba_regs *vubp = uhp->uh_uba; +#endif + + /* + * Initialize the UNIBUS, by freeing the map + * registers and the buffered data path registers + */ + uhp->uh_map = (struct map *) + malloc((u_long)(UAMSIZ * sizeof (struct map)), M_DEVBUF, + M_NOWAIT); + if (uhp->uh_map == 0) + panic("no mem for unibus map"); + bzero((caddr_t)uhp->uh_map, (unsigned)(UAMSIZ * sizeof (struct map))); + ubainitmaps(uhp); + + /* + * Initialize space for the UNIBUS interrupt vectors. + * On the 8600, can't use first slot in UNIvec + * (the vectors for the second SBI overlap it); + * move each set of vectors forward. + */ +#if VAX8600 + if (cpu == VAX_8600) + uhp->uh_vec = UNIvec[numuba + 1]; + else +#endif + uhp->Nuh_vec = vekmatris[numuba]; + for (i = 0; i < 128; i++) + uhp->Nuh_vec[i] = ubastray; + + /* + * Set last free interrupt vector for devices with + * programmable interrupt vectors. Use is to decrement + * this number and use result as interrupt vector. + */ + uhp->uh_lastiv = 0x200; + +#ifdef DWBUA + if (uhp->uh_type == DWBUA) + BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; +#endif + +#ifdef DW780 + if (uhp->uh_type == DW780) { + vubp->uba_sr = vubp->uba_sr; + vubp->uba_cr = UBACR_IFS|UBACR_BRIE; + } +#endif + /* + * First configure devices that have unibus memory, + * allowing them to allocate the correct map registers. + */ + ubameminit(numuba); + /* + * Grab some memory to record the umem address space we allocate, + * so we can be sure not to place two devices at the same address. + * + * We could use just 1/8 of this (we only want a 1 bit flag) but + * we are going to give it back anyway, and that would make the + * code here bigger (which we can't give back), so ... + * + * One day, someone will make a unibus with something other than + * an 8K i/o address space, & screw this totally. + */ + ualloc = (caddr_t)malloc((u_long)(8 * 1024), M_TEMP, M_NOWAIT); + if (ualloc == (caddr_t)0) + panic("no mem for unifind"); + bzero(ualloc, 8*1024); + + /* + * Map the first page of UNIBUS i/o + * space to the first page of memory + * for devices which will need to dma + * output to produce an interrupt. + */ + *(int *)(&uhp->uh_mr[0]) = UBAMR_MRV; + +#define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off)) + /* + * Check each unibus mass storage controller. + * For each one which is potentially on this uba, + * see if it is really there, and if it is record it and + * then go looking for slaves. + */ + for (um = ubminit; udp = um->um_driver; um++) { + if (um->um_ubanum != numuba && um->um_ubanum != '?' || + um->um_alive) + continue; + addr = (u_short)(u_long)um->um_addr; + /* + * use the particular address specified first, + * or if it is given as "0", of there is no device + * at that address, try all the standard addresses + * in the driver til we find it + */ + for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { + + if (ualloc[ubdevreg(addr)]) + continue; + reg = ubaddr(uhp, addr); + + if (badaddr((caddr_t)reg, 2)) + continue; + +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + cvec = 0x200; + rcvec = 0x200; + i = (*udp->ud_probe)(reg, um->um_ctlr, um); +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + if (i == 0) + continue; + printf("%s%d at uba%d csr %o ", + udp->ud_mname, um->um_ctlr, numuba, addr); + if (rcvec == 0) { + printf("zero vector\n"); + continue; + } + if (rcvec == 0x200) { + printf("didn't interrupt\n"); + continue; + } + interinfo[numuba][rcvec]=um->um_ctlr; + printf("vec %o, ipl %x\n", rcvec, rbr); + csralloc(ualloc, addr, i); + um->um_alive = 1; + um->um_ubanum = numuba; + um->um_hd = uhp; + um->um_addr = (caddr_t)reg; + udp->ud_minfo[um->um_ctlr] = um; + uhp->Nuh_vec[rcvec] = um->um_intr; + for (ui = ubdinit; ui->ui_driver; ui++) { + int t; + + if (ui->ui_driver != udp || ui->ui_alive || + ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || + ui->ui_ubanum != numuba && ui->ui_ubanum != '?') + continue; + t = ui->ui_ctlr; + ui->ui_ctlr = um->um_ctlr; + if ((*udp->ud_slave)(ui, reg) == 0) + ui->ui_ctlr = t; + else { + ui->ui_alive = 1; + ui->ui_ubanum = numuba; + ui->ui_hd = uhp; + ui->ui_addr = (caddr_t)reg; + ui->ui_physaddr = pumem + ubdevreg(addr); + if (ui->ui_dk && dkn < DK_NDRIVE) + ui->ui_dk = dkn++; + else + ui->ui_dk = -1; + ui->ui_mi = um; + /* ui_type comes from driver */ + udp->ud_dinfo[ui->ui_unit] = ui; + printf("%s%d at %s%d slave %d", + udp->ud_dname, ui->ui_unit, + udp->ud_mname, um->um_ctlr, ui->ui_slave); + (*udp->ud_attach)(ui); + printf("\n"); + } + } + break; + } + } + /* + * Now look for non-mass storage peripherals. + */ + for (ui = ubdinit; udp = ui->ui_driver; ui++) { + if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' || + ui->ui_alive || ui->ui_slave != -1) + continue; + addr = (u_short)(u_long)ui->ui_addr; + + for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { + + if (ualloc[ubdevreg(addr)]) + continue; + reg = ubaddr(uhp, addr); + if (badaddr((caddr_t)reg, 2)) + continue; +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + rcvec = 0x200; + cvec = 0x200; + i = (*udp->ud_probe)(reg, ui); +#ifdef DW780 + if (uhp->uh_type == DW780 && vubp->uba_sr) { + vubp->uba_sr = vubp->uba_sr; + continue; + } +#endif + if (i == 0) + continue; + printf("%s%d at uba%d csr %o ", + ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr); + if (rcvec == 0) { + printf("zero vector\n"); + continue; + } + if (rcvec == 0x200) { + printf("didn't interrupt\n"); + continue; + } + interinfo[numuba][rcvec]=ui->ui_unit; + printf("vec %o, ipl %x\n", rcvec, rbr); + csralloc(ualloc, addr, i); + ui->ui_hd = uhp; + uhp->Nuh_vec[rcvec] = ui->ui_intr; + ui->ui_alive = 1; + ui->ui_ubanum = numuba; + ui->ui_addr = (caddr_t)reg; + ui->ui_physaddr = pumem + ubdevreg(addr); + ui->ui_dk = -1; + /* ui_type comes from driver */ + udp->ud_dinfo[ui->ui_unit] = ui; + (*udp->ud_attach)(ui); + break; + } + } + +#ifdef DW780 + if (uhp->uh_type == DW780) + uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | + UBACR_USEFIE | UBACR_SUEFIE | + (uhp->uh_uba->uba_cr & 0x7c000000); +#endif + numuba++; + +#ifdef AUTO_DEBUG + printf("Unibus allocation map"); + for (i = 0; i < 8*1024; ) { + register n, m; + + if ((i % 128) == 0) { + printf("\n%6o:", i); + for (n = 0; n < 128; n++) + if (ualloc[i+n]) + break; + if (n == 128) { + i += 128; + continue; + } + } + + for (n = m = 0; n < 16; n++) { + m <<= 1; + m |= ualloc[i++]; + } + + printf(" %4x", m); + } + printf("\n"); +#endif + free(ualloc, M_TEMP); +} + + +#ifdef DW780 +char ubasr_bits[] = UBASR_BITS; +#endif + +#define spluba splbio /* IPL 17 */ + +/* + * Do transfer on device argument. The controller + * and uba involved are implied by the device. + * We queue for resource wait in the uba code if necessary. + * We return 1 if the transfer was started, 0 if it was not. + * + * The onq argument must be zero iff the device is not on the + * queue for this UBA. If onq is set, the device must be at the + * head of the queue. In any case, if the transfer is started, + * the device will be off the queue, and if not, it will be on. + * + * Drivers that allocate one BDP and hold it for some time should + * set ud_keepbdp. In this case um_bdp tells which BDP is allocated + * to the controller, unless it is zero, indicating that the controller + * does not now have a BDP. + */ +ubaqueue(ui, onq) + register struct uba_device *ui; + int onq; +{ + register struct uba_ctlr *um = ui->ui_mi; + register struct uba_hd *uh; + register struct uba_driver *ud; + register int s, unit; + + uh = &uba_hd[um->um_ubanum]; + ud = um->um_driver; + s = spluba(); + /* + * Honor exclusive BDP use requests. + */ + if (ud->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) + goto rwait; + if (ud->ud_keepbdp) { + /* + * First get just a BDP (though in fact it comes with + * one map register too). + */ + if (um->um_bdp == 0) { + um->um_bdp = uballoc(um->um_ubanum, + (caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT); + if (um->um_bdp == 0) + goto rwait; + } + /* now share it with this transfer */ + um->um_ubinfo = ubasetup(um->um_ubanum, + um->um_tab.b_actf->b_actf, + um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT); + } else + um->um_ubinfo = ubasetup(um->um_ubanum, + um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT); + if (um->um_ubinfo == 0) + goto rwait; + uh->uh_users++; + if (ud->ud_xclu) + uh->uh_xclu = 1; + splx(s); + if (ui->ui_dk >= 0) { + unit = ui->ui_dk; + dk_busy |= 1<<unit; + dk_xfer[unit]++; + dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; + } + if (onq) + uh->uh_actf = ui->ui_forw; + (*ud->ud_dgo)(um); + return (1); +rwait: + if (!onq) { + ui->ui_forw = NULL; + if (uh->uh_actf == NULL) + uh->uh_actf = ui; + else + uh->uh_actl->ui_forw = ui; + uh->uh_actl = ui; + } + splx(s); + return (0); +} + +ubadone(um) + register struct uba_ctlr *um; +{ + register struct uba_hd *uh = &uba_hd[um->um_ubanum]; + + if (um->um_driver->ud_xclu) + uh->uh_xclu = 0; + uh->uh_users--; + if (um->um_driver->ud_keepbdp) + um->um_ubinfo &= ~BDPMASK; /* keep BDP for misers */ + ubarelse(um->um_ubanum, &um->um_ubinfo); +} + +/* + * Allocate and setup UBA map registers, and bdp's + * Flags says whether bdp is needed, whether the caller can't + * wait (e.g. if the caller is at interrupt level). + * Return value encodes map register plus page offset, + * bdp number and number of map registers. + */ +ubasetup(int uban,struct buf *bp,int flags) { + struct uba_hd *uh = &uba_hd[uban]; + struct pte *pte, *io; + int npf; + int pfnum, temp; + int reg, bdp; + unsigned v; + struct proc *rp; + int a, o, ubinfo; + +#ifdef DW730 + if (uh->uh_type == DW730) + flags &= ~UBA_NEEDBDP; +#endif +#ifdef QBA + if (uh->uh_type == QBA) + flags &= ~UBA_NEEDBDP; +#endif + o = (int)bp->b_un.b_addr & PGOFSET; + npf = btoc(bp->b_bcount + o) + 1; + if (npf > UBA_MAXNMR) + panic("uba xfer too big"); + a = spluba(); + while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) { + if (flags & UBA_CANTWAIT) { + splx(a); + return (0); + } + uh->uh_mrwant++; + sleep((caddr_t)&uh->uh_mrwant, PSWP); + } + if ((flags & UBA_NEED16) && reg + npf > 128) { + /* + * Could hang around and try again (if we can ever succeed). + * Won't help any current device... + */ + rmfree(uh->uh_map, (long)npf, (long)reg); + splx(a); + return (0); + } + bdp = 0; + if (flags & UBA_NEEDBDP) { + while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) { + if (flags & UBA_CANTWAIT) { + rmfree(uh->uh_map, (long)npf, (long)reg); + splx(a); + return (0); + } + uh->uh_bdpwant++; + sleep((caddr_t)&uh->uh_bdpwant, PSWP); + } + uh->uh_bdpfree &= ~(1 << (bdp-1)); + } else if (flags & UBA_HAVEBDP) + bdp = (flags >> 28) & 0xf; + splx(a); + reg--; + ubinfo = UBAI_INFO(o, reg, npf, bdp); + temp = (bdp << 21) | UBAMR_MRV; + if (bdp && (o & 01)) + temp |= UBAMR_BO; + if ((bp->b_flags & B_PHYS) == 0) + pte = (struct pte *)kvtopte(bp->b_un.b_addr); + else if (bp->b_flags & B_PAGET) { + panic("ubasetup: B_PAGET"); + } else { + if( bp->b_flags&B_DIRTY){ + rp=&pageproc[2]; + panic("ubasetup: B_DIRTY"); + } else { + rp =bp->b_proc; + } + v = vax_btop((u_int)bp->b_un.b_addr&0x3fffffff); + if (bp->b_flags & B_UAREA){ + panic("ubasetup: B_UAREA"); + } else { +/* + * It may be better to use pmap_extract() here somewhere, + * but so far we do it "the hard way" :) + */ + u_int *hej; + + if(((u_int)bp->b_un.b_addr<0x40000000)|| + ((u_int)bp->b_un.b_addr>0x7fffffff)){ + hej=rp->p_vmspace->vm_pmap.pm_pcb->P0BR; + } else { + hej=rp->p_vmspace->vm_pmap.pm_pcb->P1BR; + } + pte=(struct pte*)&hej[v]; + } + } + io = &uh->uh_mr[reg]; + while (--npf > 0) { + pfnum = pte->pg_pfn; + if (pfnum == 0) + panic("uba zero uentry"); + pte++; + *(int *)io++ = pfnum | temp; + } + *(int *)io = 0; + return (ubinfo); +} + +/* + * Non buffer setup interface... set up a buffer and call ubasetup. + */ +uballoc(int uban,caddr_t addr,int bcnt,int flags) { + struct buf ubabuf; + + ubabuf.b_un.b_addr = addr; + ubabuf.b_flags = B_BUSY; + ubabuf.b_bcount = bcnt; + /* that's all the fields ubasetup() needs */ + return (ubasetup(uban, &ubabuf, flags)); +} + +/* + * Release resources on uba uban, and then unblock resource waiters. + * The map register parameter is by value since we need to block + * against uba resets on 11/780's. + */ +ubarelse(uban, amr) + int *amr; +{ + register struct uba_hd *uh = &uba_hd[uban]; + register int bdp, reg, npf, s; + int mr; + + /* + * Carefully see if we should release the space, since + * it may be released asynchronously at uba reset time. + */ + s = spluba(); + mr = *amr; + if (mr == 0) { + /* + * A ubareset() occurred before we got around + * to releasing the space... no need to bother. + */ + splx(s); + return; + } + *amr = 0; + bdp = UBAI_BDP(mr); + if (bdp) { + switch (uh->uh_type) { +#ifdef DWBUA + case DWBUA: + BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; + break; +#endif +#ifdef DW780 +sdjhfgsadjkfhgasj + case DW780: + uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; + break; +#endif +#ifdef DW750 + case DW750: + uh->uh_uba->uba_dpr[bdp] |= + UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; + break; +#endif + default: + break; + } + uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ + if (uh->uh_bdpwant) { + uh->uh_bdpwant = 0; + wakeup((caddr_t)&uh->uh_bdpwant); + } + } + /* + * Put back the registers in the resource map. + * The map code must not be reentered, + * nor can the registers be freed twice. + * Unblock interrupts once this is done. + */ + npf = UBAI_NMR(mr); + reg = UBAI_MR(mr) + 1; + rmfree(uh->uh_map, (long)npf, (long)reg); + splx(s); + + /* + * Wakeup sleepers for map registers, + * and also, if there are processes blocked in dgo(), + * give them a chance at the UNIBUS. + */ + if (uh->uh_mrwant) { + uh->uh_mrwant = 0; + wakeup((caddr_t)&uh->uh_mrwant); + } + while (uh->uh_actf && ubaqueue(uh->uh_actf, 1)) + ; +} + +ubapurge(um) + register struct uba_ctlr *um; +{ + register struct uba_hd *uh = um->um_hd; + register int bdp = UBAI_BDP(um->um_ubinfo); + + switch (uh->uh_type) { +#ifdef DWBUA + case DWBUA: + BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; + break; +#endif +#ifdef DW780 + case DW780: + uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; + break; +#endif +#ifdef DW750 + case DW750: + uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; + break; +#endif + default: + break; + } +} + +ubainitmaps(uhp) + register struct uba_hd *uhp; +{ + + if (uhp->uh_memsize > UBA_MAXMR) + uhp->uh_memsize = UBA_MAXMR; + rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); + switch (uhp->uh_type) { +#ifdef DWBUA + case DWBUA: + uhp->uh_bdpfree = (1<<NBDPBUA) - 1; + break; +#endif +#ifdef DW780 + case DW780: + uhp->uh_bdpfree = (1<<NBDP780) - 1; + break; +#endif +#ifdef DW750 + case DW750: + uhp->uh_bdpfree = (1<<NBDP750) - 1; + break; +#endif + default: + break; + } +} + +/* + * Generate a reset on uba number uban. Then + * call each device in the character device table, + * giving it a chance to clean up so as to be able to continue. + */ +ubareset(uban) + int uban; +{ + register struct cdevsw *cdp; + register struct uba_hd *uh = &uba_hd[uban]; + int s; + + s = spluba(); + uh->uh_users = 0; + uh->uh_zvcnt = 0; + uh->uh_xclu = 0; + uh->uh_actf = uh->uh_actl = 0; + uh->uh_bdpwant = 0; + uh->uh_mrwant = 0; + ubainitmaps(uh); + wakeup((caddr_t)&uh->uh_bdpwant); + wakeup((caddr_t)&uh->uh_mrwant); + printf("uba%d: reset", uban); + ubainit(uh->uh_uba); + ubameminit(uban); +/* XXX Intressant, vi m}ste l|sa det h{r med ubareset() p} n}t smart + * s{tt. En l{nkad lista som s{tts upp vid autoconfiggen? Kanske. + * N{r anv{nds dom? Jag vet faktiskt inte; det verkar vara en + * ren sm|rja den gamla koden. F}r peturba lite mer docs... + * 950428/Ragge + */ +/* for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) + (*cdp->d_reset)(uban); + ifubareset(uban); + */ + printf("\n"); + splx(s); +} + +/* + * Init a uba. This is called with a pointer + * rather than a virtual address since it is called + * by code which runs with memory mapping disabled. + * In these cases we really don't need the interrupts + * enabled, but since we run with ipl high, we don't care + * if they are, they will never happen anyways. + * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. + */ +ubainit(uba) + register struct uba_regs *uba; +{ + register struct uba_hd *uhp; +#ifdef QBA + int isphys = 0; +#endif + + for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { + if (uhp->uh_uba == uba) + break; + if (uhp->uh_physuba == uba) { +#ifdef QBA + isphys++; +#endif + break; + } + } + if (uhp >= uba_hd + numuba) { + printf("init unknown uba\n"); + return; + } + + switch (uhp->uh_type) { +#ifdef DWBUA + case DWBUA: + BUA(uba)->bua_csr |= BUACSR_UPI; + /* give devices time to recover from power fail */ + waitabit(500); + break; +#endif +#ifdef DW780 + case DW780: + uba->uba_cr = UBACR_ADINIT; + uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; + while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) + ; + break; +#endif +#ifdef DW750 + case DW750: +#endif +#ifdef DW730 + case DW730: +#endif +#ifdef QBA + case QBA: +#endif +#if DW750 || DW730 || QBA + mtpr(0, PR_IUR); + /* give devices time to recover from power fail */ +#if 0 +/* THIS IS PROBABLY UNNECESSARY */ + waitabit(50); +/* END PROBABLY UNNECESSARY */ +#endif +#ifdef QBA + /* + * Re-enable local memory access + * from the Q-bus. + */ + if (uhp->uh_type == QBA) { + if (isphys) + *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; + else + *(uhp->uh_iopage + QIPCR) = Q_LMEAE; + } +#endif QBA + break; +#endif DW750 || DW730 || QBA + } +} + +#ifdef QBA +/* + * Determine the interrupt priority of a Q-bus + * peripheral. The device probe routine must spl6(), + * attempt to make the device request an interrupt, + * delaying as necessary, then call this routine + * before resetting the device. + */ +qbgetpri() +{ + int pri; + extern int cvec; + + for (pri = 0x17; pri > 0x14; ) { + if (cvec && cvec != 0x200) /* interrupted at pri */ + break; + pri--; + splx(pri - 1); + } + (void) spl0(); + return (pri); +} +#endif + +#ifdef DW780 +int ubawedgecnt = 10; +int ubacrazy = 500; +int zvcnt_max = 5000; /* in 8 sec */ +/* + * This routine is called by the locore code to process a UBA + * error on an 11/780 or 8600. The arguments are passed + * on the stack, and value-result (through some trickery). + * In particular, the uvec argument is used for further + * uba processing so the result aspect of it is very important. + * It must not be declared register. + */ +/*ARGSUSED*/ +ubaerror(uban, uh, ipl, uvec, uba) + register int uban; + register struct uba_hd *uh; + int ipl, uvec; + register struct uba_regs *uba; +{ + register sr, s; + + if (uvec == 0) { + /* + * Declare dt as unsigned so that negative values + * are handled as >8 below, in case time was set back. + */ + u_long dt = time.tv_sec - uh->uh_zvtime; + + uh->uh_zvtotal++; + if (dt > 8) { + uh->uh_zvtime = time.tv_sec; + uh->uh_zvcnt = 0; + } + if (++uh->uh_zvcnt > zvcnt_max) { + printf("uba%d: too many zero vectors (%d in <%d sec)\n", + uban, uh->uh_zvcnt, dt + 1); + printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", + ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, + uba->uba_cnfgr&0xff); + printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", + uba->uba_sr, ubasr_bits, uba->uba_dcr, + (uba->uba_dcr&0x8000000)?"":"NOT "); + ubareset(uban); + } + return; + } + if (uba->uba_cnfgr & NEX_CFGFLT) { + printf("uba%d: sbi fault sr=%b cnfgr=%b\n", + uban, uba->uba_sr, ubasr_bits, + uba->uba_cnfgr, NEXFLT_BITS); + ubareset(uban); + uvec = 0; + return; + } + sr = uba->uba_sr; + s = spluba(); + printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", + uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); + splx(s); + uba->uba_sr = sr; + uvec &= UBABRRVR_DIV; + if (++uh->uh_errcnt % ubawedgecnt == 0) { + if (uh->uh_errcnt > ubacrazy) + panic("uba crazy"); + printf("ERROR LIMIT "); + ubareset(uban); + uvec = 0; + return; + } + return; +} +#endif + +/* + * Look for devices with unibus memory, allow them to configure, then disable + * map registers as necessary. Called during autoconfiguration and ubareset. + * The device ubamem routine returns 0 on success, 1 on success if it is fully + * configured (has no csr or interrupt, so doesn't need to be probed), + * and -1 on failure. + */ +ubameminit(uban) +{ + register struct uba_device *ui; + register struct uba_hd *uh = &uba_hd[uban]; + caddr_t umembase = Tumem(uban) + 0x3e000, addr; +#define ubaoff(off) ((int)(off) & 0x1fff) + + uh->uh_lastmem = 0; + for (ui = ubdinit; ui->ui_driver; ui++) { + if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') + continue; + if (ui->ui_driver->ud_ubamem) { + /* + * During autoconfiguration, need to fudge ui_addr. + */ + addr = ui->ui_addr; + ui->ui_addr = umembase + ubaoff(addr); + switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { + case 1: + ui->ui_alive = 1; + /* FALLTHROUGH */ + case 0: + ui->ui_ubanum = uban; + break; + } + ui->ui_addr = addr; + } + } +#ifdef DW780 +jdhfgsjdkfhgsdjkfghak + /* + * On a DW780, throw away any map registers disabled by rounding + * the map disable in the configuration register + * up to the next 8K boundary, or below the last unibus memory. + */ + if (uh->uh_type == DW780) { + register i; + + i = vax_btop(((uh->uh_lastmem + 8191) / 8192) * 8192); + while (i) + (void) rmget(uh->uh_map, 1, i--); + } +#endif +} + +rmget(){ + showstate(curproc); + panic("rmget() not implemented. (in uba.c)"); +} + +/* + * Allocate UNIBUS memory. Allocates and initializes + * sufficient mapping registers for access. On a 780, + * the configuration register is setup to disable UBA + * response on DMA transfers to addresses controlled + * by the disabled mapping registers. + * On a DW780, should only be called from ubameminit, or in ascending order + * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't + * the last unibus memory would free unusable map registers. + * Doalloc is 1 to allocate, 0 to deallocate. + */ +ubamem(uban, addr, npg, doalloc) + int uban, addr, npg, doalloc; +{ + register struct uba_hd *uh = &uba_hd[uban]; + register int a; + int s; + + a = (addr >> 9) + 1; + s = spluba(); + if (doalloc) + a = rmget(uh->uh_map, npg, a); + else + rmfree(uh->uh_map, (long)npg, (long)a); + splx(s); + if (a) { + register int i, *m; + + m = (int *)&uh->uh_mr[a - 1]; + for (i = 0; i < npg; i++) + *m++ = 0; /* All off, especially 'valid' */ + i = addr + npg * 512; + if (doalloc && i > uh->uh_lastmem) + uh->uh_lastmem = i; + else if (doalloc == 0 && i == uh->uh_lastmem) + uh->uh_lastmem = addr; +#ifdef DW780 + /* + * On a 780, set up the map register disable + * field in the configuration register. Beware + * of callers that request memory ``out of order'' + * or in sections other than 8K multiples. + * Ubameminit handles such requests properly, however. + */ + if (uh->uh_type == DW780) { + i = uh->uh_uba->uba_cr &~ 0x7c000000; + i |= ((uh->uh_lastmem + 8191) / 8192) << 26; + uh->uh_uba->uba_cr = i; + } +#endif + } + return (a); +} + +#include "ik.h" +#include "vs.h" +#if NIK > 0 || NVS > 0 +/* + * Map a virtual address into users address space. Actually all we + * do is turn on the user mode write protection bits for the particular + * page of memory involved. + */ +maptouser(vaddress) + caddr_t vaddress; +{ + + kvtopte(vaddress)->pg_prot = (PG_UW >> 27); +} + +unmaptouser(vaddress) + caddr_t vaddress; +{ + + kvtopte(vaddress)->pg_prot = (PG_KW >> 27); +} +#endif + +resuba() +{ + showstate(curproc); + panic("resuba"); +} + +int +uba_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct sbi_attach_args *sa=(struct sbi_attach_args *)aux; + extern int numuba; + int ubanr; + +#if VAX630 + /* + * The MicroVAXII always has a single QBA. + */ + if (cpu_type == VAX_630) + if (numuba == 0) + return 1; + else + return 0; +#endif + if(numuba) return 0; + if((cf->cf_loc[0]!=sa->nexnum)&&(cf->cf_loc[0]>-1)) + return 0; /* UBA doesn't match spec's */ + + switch(sa->type){ + case NEX_UBA0: + case NEX_UBA1: + case NEX_UBA2: + case NEX_UBA3: + return 1; + + default: + return 0; + } +} + +void +uba_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct sbi_attach_args *sa=(struct sbi_attach_args *)aux; + extern struct uba_hd uba_hd[]; + struct uba_regs *ubar=(struct uba_regs *)sa->nexaddr; + struct uba_hd *uhp = &uba_hd[numuba]; + void ubascan(); + + printf("\n"); + switch (cpunumber) { +#if VAX750 + case VAX_750: + uhp->uh_mr = (void *)ubar->uba_map; + uhp->uh_type = DW750; + uhp->uh_uba = (void*)ubar; + uhp->uh_physuba = (void*)0xf20000+sa->nexnum*0x2000; + uhp->uh_memsize = UBAPAGES; + uhp->uh_mem = Tumem(numuba); + uhp->uh_iopage = Tumem(numuba) + (uhp->uh_memsize * NBPG); + ioaccess(UMEM750(numuba), UMEMmap[numuba], (UBAPAGES+UBAIOPAGES)*NBPG); +/* Now everything should be set up (I hope...) */ +#ifdef notyet + config_scan(ubascan,self); + +#else + unifind(uhp, UMEM750(numuba) + (uhp->uh_memsize * NBPG)); +#endif + break; +#endif +#if VAX630 || VAX410 + case VAX_78032: + switch (cpu_type) { +#if VAX630 + case VAX_630: + uhp->uh_mr = (void *)sa->nexaddr; + uhp->uh_type = QBA; + uhp->uh_uba = (void*)ubar; + uhp->uh_physuba = (void*)QBAMAP630; + uhp->uh_memsize = QBAPAGES; + uhp->uh_mem = Numem; + uhp->uh_iopage = Numem + (uhp->uh_memsize * NBPG); + + /* + * For the MicroVAXII, the qbus address space is not contiguous + * in physical address space. I also map the page that has the + * memory error registers and the watch chip here and init them, + * for want of a better place to do it. + */ + ioaccess(QMEM630, UMEMmap[0], QBAPAGES * NBPG); + ioaccess(QIOPAGE630, UMEMmap[0] + QBAPAGES, UBAIOPAGES * NBPG); + ioaccess(UVAXIICPU, UMEMmap[0] + QBAPAGES + UBAIOPAGES, NBPG); + uvaxIIcpu_ptr = + (struct uvaxIIcpu *)(Numem+(QBAPAGES+UBAIOPAGES)*NBPG); + ioaccess(KA630CLK,UMEMmap[0] + QBAPAGES + UBAIOPAGES + 1,NBPG); + ka630clk_ptr = + (struct ka630clock *)(Numem+(QBAPAGES+UBAIOPAGES+1)*NBPG); + + /* + * Clear restart and boot in progress flags in the CPMBX. + */ + ka630clk_ptr->cpmbx = (ka630clk_ptr->cpmbx & KA630CLK_LANG); + + /* + * Enable memory parity error detection and clear error bits. + */ + uvaxIIcpu_ptr->uvaxII_mser = (UVAXIIMSER_PEN|UVAXIIMSER_MERR| + UVAXIIMSER_LEB); + + /* + * Now that QBus space is mapped, set the local memory external + * access enable. + */ + *((u_short *)(uhp->uh_iopage + QIPCR)) = Q_LMEAE; +/* Now everything should be set up (I hope...) */ +#ifdef notyet + config_scan(ubascan,self); + +#else + unifind(uhp, QIOPAGE630); +#endif + break; +#endif + }; + break; +#endif + }; + numuba++; +} + + + +struct cfdriver ubacd= + { NULL, "uba", uba_match, uba_attach, DV_CPU, sizeof(struct device),1,0}; + + + diff --git a/sys/arch/vax/uba/ubareg.h b/sys/arch/vax/uba/ubareg.h new file mode 100644 index 00000000000..dbd133554a6 --- /dev/null +++ b/sys/arch/vax/uba/ubareg.h @@ -0,0 +1,327 @@ +/* $NetBSD: ubareg.h,v 1.3 1995/02/13 00:44:23 ragge Exp $ */ + +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ubareg.h 7.8 (Berkeley) 5/9/91 + */ + +/* + * VAX UNIBUS adapter registers + */ + +/* + * "UNIBUS" adaptor types. + * This code is used for both UNIBUSes and Q-buses + * with different types of adaptors. + * Definition of a type includes support code for that type. + */ + +#if VAX780 || VAX8600 +#define DW780 1 /* has adaptor regs, sr: 780/785/8600 */ +#else +#undef DW780 +#endif + + +#if VAX750 +#define DW750 2 /* has adaptor regs, no sr: 750, 730 */ +#endif + +#if VAX730 +#define DW730 3 /* has adaptor regs, no sr: 750, 730 */ +#endif + +#if VAX630 || VAX650 +#define QBA 4 /* 22-bit Q-bus, no adaptor regs: uVAX II */ +#endif + +#if VAX8200 || VAX8500 || VAX8800 +#define DWBUA 5 /* BI UNIBUS adaptor: 8200/8500/8800 */ +#endif + +/* + * Size of unibus memory address space in pages + * (also number of map registers). + * QBAPAGES should be 8192, but we don't need nearly that much + * address space, and the return from the allocation routine + * can accommodate at most 2047 (ubavar.h: UBA_MAXMR); + * QBAPAGES must be at least UBAPAGES. Choose pragmatically. + */ +#define UBAPAGES 496 +#define NUBMREG 496 +#if defined(GATEWAY) && !defined(QNIVERT) +#define QBAPAGES 1024 +#else +#define QBAPAGES UBAPAGES +#endif +#define UBAIOADDR 0760000 /* start of I/O page */ +#define UBAIOPAGES 16 + +#ifndef LOCORE +/* + * DWBUA hardware registers. + */ +struct dwbua_regs { + int pad1[456]; /* actually bii regs + pad */ + int bua_csr; /* control and status register */ + int bua_offset; /* vector offset register */ + int bua_fubar; /* failed UNIBUS address register */ + int bua_bifar; /* BI failed address register */ + int bua_udiag[5]; /* micro diagnostics (R/O) */ + int pad2[3]; +/* dpr[0] is for DDP; dpr's 1 through 5 are for BPD's 1 through 5 */ + int bua_dpr[6]; /* data path registers */ + int pad3[10]; + int bua_bdps[20]; /* buffered data path space *//*???*/ + int pad4[8]; + pt_entry_t bua_map[UBAPAGES]; /* unibus map registers */ + int pad5[UBAIOPAGES]; /* no maps for device address space */ +}; + +#ifdef DWBUA +/* bua_csr */ +#define BUACSR_ERR 0x80000000 /* composite error */ +#define BUACSR_BIF 0x10000000 /* BI failure */ +#define BUACSR_SSYNTO 0x08000000 /* slave sync timeout */ +#define BUACSR_UIE 0x04000000 /* unibus interlock error */ +#define BUACSR_IVMR 0x02000000 /* invalid map register */ +#define BUACSR_BADBDP 0x01000000 /* bad BDP select */ +#define BUACSR_BUAEIE 0x00100000 /* bua error interrupt enable (?) */ +#define BUACSR_UPI 0x00020000 /* unibus power init */ +#define BUACSR_UREGDUMP 0x00010000 /* microdiag register dump */ +#define BUACSR_IERRNO 0x000000ff /* mask for internal errror number */ + +/* bua_offset */ +#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */ + +/* bua_dpr */ +#define BUADPR_DPSEL 0x00e00000 /* data path select (?) */ +#define BUADPR_PURGE 0x00000001 /* purge bdp */ + +/* bua_map -- in particular, those bits that are not in DW780s & DW750s */ +#define BUAMR_IOADR 0x40000000 /* I/O address space */ +#define BUAMR_LAE 0x04000000 /* longword access enable */ + /* I see no reason to use either one, though ... act 6 Aug 1987 */ + +#define UBA_PURGEBUA(uba, bdp) \ + (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE) +#else +#define UBA_PURGEBUA(uba, bdp) +#endif + +/* + * DW780/DW750 hardware registers + */ +struct uba_regs { + int uba_cnfgr; /* configuration register */ + int uba_cr; /* control register */ + int uba_sr; /* status register */ + int uba_dcr; /* diagnostic control register */ + int uba_fmer; /* failed map entry register */ + int uba_fubar; /* failed UNIBUS address register */ + int pad1[2]; + int uba_brsvr[4]; + int uba_brrvr[4]; /* receive vector registers */ + int uba_dpr[16]; /* buffered data path register */ + int pad2[480]; + pt_entry_t uba_map[UBAPAGES]; /* unibus map register */ + int pad3[UBAIOPAGES]; /* no maps for device address space */ +}; +#endif + +#ifdef DW780 +/* uba_cnfgr */ +#define UBACNFGR_UBINIT 0x00040000 /* unibus init asserted */ +#define UBACNFGR_UBPDN 0x00020000 /* unibus power down */ +#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */ + +#define UBACNFGR_BITS \ +"\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC" + +/* uba_cr */ +#define UBACR_MRD16 0x40000000 /* map reg disable bit 4 */ +#define UBACR_MRD8 0x20000000 /* map reg disable bit 3 */ +#define UBACR_MRD4 0x10000000 /* map reg disable bit 2 */ +#define UBACR_MRD2 0x08000000 /* map reg disable bit 1 */ +#define UBACR_MRD1 0x04000000 /* map reg disable bit 0 */ +#define UBACR_IFS 0x00000040 /* interrupt field switch */ +#define UBACR_BRIE 0x00000020 /* BR interrupt enable */ +#define UBACR_USEFIE 0x00000010 /* UNIBUS to SBI error field IE */ +#define UBACR_SUEFIE 0x00000008 /* SBI to UNIBUS error field IE */ +#define UBACR_CNFIE 0x00000004 /* configuration IE */ +#define UBACR_UPF 0x00000002 /* UNIBUS power fail */ +#define UBACR_ADINIT 0x00000001 /* adapter init */ + +/* uba_sr */ +#define UBASR_BR7FULL 0x08000000 /* BR7 receive vector reg full */ +#define UBASR_BR6FULL 0x04000000 /* BR6 receive vector reg full */ +#define UBASR_BR5FULL 0x02000000 /* BR5 receive vector reg full */ +#define UBASR_BR4FULL 0x01000000 /* BR4 receive vector reg full */ +#define UBASR_RDTO 0x00000400 /* UNIBUS to SBI read data timeout */ +#define UBASR_RDS 0x00000200 /* read data substitute */ +#define UBASR_CRD 0x00000100 /* corrected read data */ +#define UBASR_CXTER 0x00000080 /* command transmit error */ +#define UBASR_CXTMO 0x00000040 /* command transmit timeout */ +#define UBASR_DPPE 0x00000020 /* data path parity error */ +#define UBASR_IVMR 0x00000010 /* invalid map register */ +#define UBASR_MRPF 0x00000008 /* map register parity failure */ +#define UBASR_LEB 0x00000004 /* lost error */ +#define UBASR_UBSTO 0x00000002 /* UNIBUS select timeout */ +#define UBASR_UBSSYNTO 0x00000001 /* UNIBUS slave sync timeout */ + +#define UBASR_BITS \ +"\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO" + +/* uba_brrvr[] */ +#define UBABRRVR_AIRI 0x80000000 /* adapter interrupt request */ +#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */ +#endif + +/* uba_dpr */ +#ifdef DW780 +#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */ +#define UBADPR_BTE 0x40000000 /* buffer transfer error */ +#define UBADPR_DPF 0x20000000 /* DP function (RO) */ +#define UBADPR_BS 0x007f0000 /* buffer state field */ +#define UBADPR_BUBA 0x0000ffff /* buffered UNIBUS address */ +#define UBA_PURGE780(uba, bdp) \ + ((uba)->uba_dpr[bdp] |= UBADPR_BNE) +#else +#define UBA_PURGE780(uba, bdp) +#endif +#ifdef DW750 +#define UBADPR_ERROR 0x80000000 /* error occurred */ +#define UBADPR_NXM 0x40000000 /* nxm from memory */ +#define UBADPR_UCE 0x20000000 /* uncorrectable error */ +#define UBADPR_PURGE 0x00000001 /* purge bdp */ +/* the DELAY is for a hardware problem */ +#define UBA_PURGE750(uba, bdp) { \ + ((uba)->uba_dpr[bdp] |= (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)); \ + {int N=8;while(N--);} \ +} +#else +#define UBA_PURGE750(uba, bdp) +#endif + +/* + * Macros for fast buffered data path purging in time-critical routines. + * + * Too bad C pre-processor doesn't have the power of LISP in macro + * expansion... + */ + +/* THIS IS WRONG, should use pointer to uba_hd */ +#if DWBUA || DW780 || DW750 +#define UBAPURGE(uba, bdp) { \ + switch (MACHID(cpu_type)) { \ + case VAX_8200: UBA_PURGEBUA(uba, bdp); break; \ + case VAX_8600: case VAX_780: UBA_PURGE780((uba), (bdp)); break; \ + case VAX_750: UBA_PURGE750((uba), (bdp)); break; \ + } \ +} +#else +#define UBAPURGE(uba, bdp) +#endif + + + +/* uba_mr[] */ +#define UBAMR_MRV 0x80000000 /* map register valid */ +#define UBAMR_BO 0x02000000 /* byte offset bit */ +#define UBAMR_DPDB 0x01e00000 /* data path designator field */ +#define UBAMR_SBIPFN 0x001fffff /* SBI page address field */ + +#define UBAMR_DPSHIFT 21 /* shift to data path designator */ + +/* + * Number of unibus buffered data paths and possible uba's per cpu type. + */ +#define NBDP8600 15 +#define NBDP780 15 +#define NBDPBUA 5 +#define NBDP750 3 +#define NBDP730 0 +#define MAXNBDP 15 + +/* + * Symbolic BUS addresses for UBAs. + */ + +#if VAX630 || VAX650 +#define QBAMAP630 ((struct pte *)0x20088000) +#define QMEM630 0x30000000 +#define QIOPAGE630 0x20000000 +/* + * Q-bus control registers + */ +#define QIPCR 0x1f40 /* from start of iopage */ +/* bits in QIPCR */ +#define Q_DBIRQ 0x0001 /* doorbell interrupt request */ +#define Q_LMEAE 0x0020 /* local mem external access enable */ +#define Q_DBIIE 0x0040 /* doorbell interrupt enable */ +#define Q_AUXHLT 0x0100 /* auxiliary processor halt */ +#define Q_DMAQPE 0x8000 /* Q22 bus address space parity error */ +#endif + +#if VAX730 +#define UMEM730 0xfc0000 +#endif + +#if VAX750 +#define UMEM750(i) (0xfc0000-(i)*0x40000) +#endif + +#if VAX780 +#define UMEM780(i) (0x20100000+(i)*0x40000) +#endif + +#if VAX8200 /* BEWARE, argument is node, not ubanum */ +#define UMEM8200(i) (0x20400000+(i)*0x40000) +#endif + +#if VAX8600 +#define UMEMA8600(i) (0x20100000+(i)*0x40000) +#define UMEMB8600(i) (0x22100000+(i)*0x40000) +#endif + +/* + * Macro to offset a UNIBUS device address, often expressed as + * something like 0172520, by forcing it into the last 8K + * of UNIBUS memory space. + */ +#define ubdevreg(addr) ((addr) & 017777) diff --git a/sys/arch/vax/uba/ubavar.h b/sys/arch/vax/uba/ubavar.h new file mode 100644 index 00000000000..24052ad19b6 --- /dev/null +++ b/sys/arch/vax/uba/ubavar.h @@ -0,0 +1,266 @@ +/* $NetBSD: ubavar.h,v 1.6 1995/05/11 16:53:17 jtc Exp $ */ + +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ubavar.h 7.7 (Berkeley) 6/28/90 + */ + +/* + * This file contains definitions related to the kernel structures + * for dealing with the unibus adapters. + * + * Each uba has a uba_hd structure. + * Each unibus controller which is not a device has a uba_ctlr structure. + * Each unibus device has a uba_device structure. + */ + +#ifndef LOCORE + +#include "sys/buf.h" +/* + * Per-uba structure. + * + * This structure holds the interrupt vector for the uba, + * and its address in physical and virtual space. At boot time + * we determine the devices attached to the uba's and their + * interrupt vectors, filling in uh_vec. We free the map + * register and bdp resources of the uba into the structures + * defined here. + * + * During normal operation, resources are allocated and returned + * to the structures here. We watch the number of passive releases + * on each uba, and if the number is excessive may reset the uba. + * + * When uba resources are needed and not available, or if a device + * which can tolerate no other uba activity (rk07) gets on the bus, + * then device drivers may have to wait to get to the bus and are + * queued here. It is also possible for processes to block in + * the unibus driver in resource wait (mrwant, bdpwant); these + * wait states are also recorded here. + */ +struct uba_hd { + int uh_type; /* type of adaptor */ + struct uba_regs *uh_uba; /* virt addr of uba adaptor regs */ + struct uba_regs *uh_physuba; /* phys addr of uba adaptor regs */ + struct pte *uh_mr; /* start of page map */ + int uh_memsize; /* size of uba memory, pages */ + caddr_t uh_mem; /* start of uba memory address space */ + caddr_t uh_iopage; /* start of uba io page */ + int (**Nuh_vec)(); /* interrupt vector */ + struct uba_device *uh_actf; /* head of queue to transfer */ + struct uba_device *uh_actl; /* tail of queue to transfer */ + short uh_mrwant; /* someone is waiting for map reg */ + short uh_bdpwant; /* someone awaits bdp's */ + int uh_bdpfree; /* free bdp's */ + int uh_hangcnt; /* number of ticks hung */ + int uh_zvcnt; /* number of recent 0 vectors */ + long uh_zvtime; /* time over which zvcnt accumulated */ + int uh_zvtotal; /* total number of 0 vectors */ + int uh_errcnt; /* number of errors */ + int uh_lastiv; /* last free interrupt vector */ + short uh_users; /* transient bdp use count */ + short uh_xclu; /* an rk07 is using this uba! */ + int uh_lastmem; /* limit of any unibus memory */ +#define UAMSIZ 100 + struct map *uh_map; /* register free map */ +}; + +/* given a pointer to uba_regs, find DWBUA registers */ +/* this should be replaced with a union in uba_hd */ +#define BUA(uba) ((struct dwbua_regs *)(uba)) + +/* + * Per-controller structure. + * (E.g. one for each disk and tape controller, and other things + * which use and release buffered data paths.) + * + * If a controller has devices attached, then there are + * cross-referenced uba_drive structures. + * This structure is the one which is queued in unibus resource wait, + * and saves the information about unibus resources which are used. + * The queue of devices waiting to transfer is also attached here. + */ +struct uba_ctlr { + struct uba_driver *um_driver; + short um_ctlr; /* controller index in driver */ + short um_ubanum; /* the uba it is on */ + short um_alive; /* controller exists */ + int (*um_intr)(); /* interrupt handler(s) */ + caddr_t um_addr; /* address of device in i/o space */ + struct uba_hd *um_hd; +/* the driver saves the prototype command here for use in its go routine */ + int um_cmd; /* communication to dgo() */ + int um_ubinfo; /* save unibus registers, etc */ + int um_bdp; /* for controllers that hang on to bdp's */ + struct buf um_tab; /* queue of devices for this controller */ +}; + +/* + * Per ``device'' structure. + * (A controller has devices or uses and releases buffered data paths). + * (Everything else is a ``device''.) + * + * If a controller has many drives attached, then there will + * be several uba_device structures associated with a single uba_ctlr + * structure. + * + * This structure contains all the information necessary to run + * a unibus device such as a dz or a dh. It also contains information + * for slaves of unibus controllers as to which device on the slave + * this is. A flags field here can also be given in the system specification + * and is used to tell which dz lines are hard wired or other device + * specific parameters. + */ +struct uba_device { + struct uba_driver *ui_driver; + short ui_unit; /* unit number on the system */ + short ui_ctlr; /* mass ctlr number; -1 if none */ + short ui_ubanum; /* the uba it is on */ + short ui_slave; /* slave on controller */ + int (*ui_intr)(); /* interrupt handler(s) */ + caddr_t ui_addr; /* address of device in i/o space */ + short ui_dk; /* if init 1 set to number for iostat */ + int ui_flags; /* parameter from system specification */ + short ui_alive; /* device exists */ + short ui_type; /* driver specific type information */ + caddr_t ui_physaddr; /* phys addr, for standalone (dump) code */ +/* this is the forward link in a list of devices on a controller */ + struct uba_device *ui_forw; +/* if the device is connected to a controller, this is the controller */ + struct uba_ctlr *ui_mi; + struct uba_hd *ui_hd; +}; + +/* + * Per-driver structure. + * + * Each unibus driver defines entries for a set of routines + * as well as an array of types which are acceptable to it. + * These are used at boot time by the configuration program. + */ +struct uba_driver { + int (*ud_probe)(); /* see if a driver is really there */ + int (*ud_slave)(); /* see if a slave is there */ + int (*ud_attach)(); /* setup driver for a slave */ + int (*ud_dgo)(); /* fill csr/ba to start transfer */ + u_short *ud_addr; /* device csr addresses */ + char *ud_dname; /* name of a device */ + struct uba_device **ud_dinfo; /* backpointers to ubdinit structs */ + char *ud_mname; /* name of a controller */ + struct uba_ctlr **ud_minfo; /* backpointers to ubminit structs */ + short ud_xclu; /* want exclusive use of bdp's */ + short ud_keepbdp; /* hang on to bdp's once allocated */ + int (*ud_ubamem)(); /* see if dedicated memory is present */ +}; +#endif + +/* + * Flags to UBA map/bdp allocation routines + */ +#define UBA_NEEDBDP 0x01 /* transfer needs a bdp */ +#define UBA_CANTWAIT 0x02 /* don't block me */ +#define UBA_NEED16 0x04 /* need 16 bit addresses only */ +#define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */ + +/* + * Macros to bust return word from map allocation routines. + * SHOULD USE STRUCTURE TO STORE UBA RESOURCE ALLOCATION: + */ +#ifdef notyet +struct ubinfo { + long ub_addr; /* unibus address: mr + boff */ + int ub_nmr; /* number of registers, 0 if empty */ + int ub_bdp; /* bdp number, 0 if none */ +}; +#define UBAI_MR(i) (((i) >> 9) & 0x7ff) /* starting map register */ +#define UBAI_BOFF(i) ((i)&0x1ff) /* page offset */ +#else +#define UBAI_BDP(i) ((int)(((unsigned)(i)) >> 28)) +#define BDPMASK 0xf0000000 +#define UBAI_NMR(i) ((int)((i) >> 20) & 0xff) /* max 255 (=127.5K) */ +#define UBA_MAXNMR 255 +#define UBAI_MR(i) ((int)((i) >> 9) & 0x7ff) /* max 2047 */ +#define UBA_MAXMR 2047 +#define UBAI_BOFF(i) ((int)((i) & 0x1ff)) +#define UBAI_ADDR(i) ((int)((i) & 0xfffff)) /* uba addr (boff+mr) */ +#define UBAI_INFO(off, mr, nmr, bdp) \ + (((bdp) << 28) | ((nmr) << 20) | ((mr) << 9) | (off)) +#endif + +#ifndef LOCORE +#ifdef _KERNEL +#define ubago(ui) ubaqueue(ui, 0) + +/* + * UBA related kernel variables + */ +int numuba; /* number of uba's */ +struct uba_hd uba_hd[]; + +/* + * Ubminit and ubdinit initialize the mass storage controller and + * device tables specifying possible devices. + */ +extern struct uba_ctlr ubminit[]; +extern struct uba_device ubdinit[]; + +/* + * UNIBUS device address space is mapped by UMEMmap + * into virtual address umem[][]. + * The IO page is mapped to the last 8K of each. + * This should be enlarged for the Q22 bus. + */ +extern struct pte *UMEMmap[]; /* uba device addr pte's */ +/* extern char umem[][512*NBPG]; /* uba device addr space */ +extern char *Numem; +#define Tumem(x) (Numem+(UBAPAGES+UBAIOPAGES)*NBPG*x) + +/* + * Since some VAXen vector their unibus interrupts + * just adjacent to the system control block, we must + * allocate space there when running on ``any'' cpu. This space is + * used for the vectors for all ubas. + */ +extern int (*UNIvec[][128])(); /* unibus vec for ubas */ +extern int (*eUNIvec)(); /* end of unibus vec */ + +#if defined(VAX780) || defined(VAX8600) +/* + * On DW780's, we must set the scb vectors for the nexus of the + * UNIbus adaptors to vector to locore unibus adaptor interrupt dispatchers + * which make 780's look like the other VAXen. + */ +extern Xua0int(), Xua1int(), Xua2int(), Xua3int(); +#endif VAX780 +#endif /* _KERNEL */ +#endif !LOCORE diff --git a/sys/arch/vax/uba/ubavec.s b/sys/arch/vax/uba/ubavec.s new file mode 100644 index 00000000000..7d388d3f920 --- /dev/null +++ b/sys/arch/vax/uba/ubavec.s @@ -0,0 +1,112 @@ +/* $NetBSD: ubavec.s,v 1.2 1995/02/23 17:53:22 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +/* + * Interrupt vectors for Unibus; already at the right place at boot. + * This allocation should be done in some other way, 8600 has its + * second SCB at the same place as 750's first UBA vector... foolish. + */ + +#define UBAVEC(lab,off) .long lab+(off)*8+1; +#define UBAVEC2(lab,off) UBAVEC(lab,off);UBAVEC(lab,off+1) +#define UBAVEC4(lab,off) UBAVEC2(lab,off);UBAVEC2(lab,off+2) +#define UBAVEC8(lab,off) UBAVEC4(lab,off);UBAVEC4(lab,off+4) +#define UBAVEC16(lab,off) UBAVEC8(lab,off);UBAVEC8(lab,off+8) + +.globl _UNIvec, _eUNIvec, ubaett + +_UNIvec: + UBAVEC16(ubaett,0);UBAVEC16(ubaett,16); + UBAVEC16(ubaett,32);UBAVEC16(ubaett,48); + UBAVEC16(ubaett,64);UBAVEC16(ubaett,80); + UBAVEC16(ubaett,96);UBAVEC16(ubaett,112); + UBAVEC16(ubatva,0);UBAVEC16(ubatva,16); + UBAVEC16(ubatva,32);UBAVEC16(ubatva,48); + UBAVEC16(ubatva,64);UBAVEC16(ubatva,80); + UBAVEC16(ubatva,96);UBAVEC16(ubatva,112); + UBAVEC16(ubatre,0);UBAVEC16(ubatre,16); + UBAVEC16(ubatre,32);UBAVEC16(ubatre,48); + UBAVEC16(ubatre,64);UBAVEC16(ubatre,80); + UBAVEC16(ubatre,96);UBAVEC16(ubatre,112); + UBAVEC16(ubafyra,0);UBAVEC16(ubafyra,16); + UBAVEC16(ubafyra,32);UBAVEC16(ubafyra,48); + UBAVEC16(ubafyra,64);UBAVEC16(ubafyra,80); + UBAVEC16(ubafyra,96);UBAVEC16(ubafyra,112); +_eUNIvec: + +#define PR(uba) .align 2;pushr $0x3f;jsb uba ; +#define UBAJSB4(uba) PR(uba);PR(uba);PR(uba);PR(uba); +#define UBAJSB16(uba) UBAJSB4(uba);UBAJSB4(uba);UBAJSB4(uba);UBAJSB4(uba); +#define UBAJSB64(uba) UBAJSB16(uba);UBAJSB16(uba);UBAJSB16(uba);UBAJSB16(uba) + +ubaett: + UBAJSB64(ett);UBAJSB64(ett);UBAJSB64(ett);UBAJSB64(ett); +ubatva: + UBAJSB64(tva);UBAJSB64(tva);UBAJSB64(tva);UBAJSB64(tva); +ubatre: + UBAJSB64(tre);UBAJSB64(tre);UBAJSB64(tre);UBAJSB64(tre); +ubafyra: + UBAJSB64(fyra);UBAJSB64(fyra);UBAJSB64(fyra);UBAJSB64(fyra); + + +ett: subl3 $ubaett, (sp), r0 + ashl $-3, r0, (sp) + pushl $0 + brb 1f + +tva: subl3 $ubatva, (sp), r0 + ashl $-3, r0, (sp) + pushl $1 + brb 1f + +tre: subl3 $ubatre, (sp), r0 + ashl $-3, r0, (sp) + pushl $2 + brb 1f + + .globl ett,tva,tre,fyra +fyra: subl3 $ubafyra, (sp), r0 + ashl $-3, r0, (sp) + pushl $3 + +1: mfpr $PR_IPL, -(sp) + calls $3, _ubainterrupt + popr $0x3f + rei + + + + + + diff --git a/sys/arch/vax/uba/uda.c b/sys/arch/vax/uba/uda.c new file mode 100644 index 00000000000..fcf8f57e0ec --- /dev/null +++ b/sys/arch/vax/uba/uda.c @@ -0,0 +1,2424 @@ +/* $NetBSD: uda.c,v 1.8 1995/08/31 22:24:39 ragge Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)uda.c 7.32 (Berkeley) 2/13/91 + */ + +/* + * UDA50/MSCP device driver + */ + +#define POLLSTATS + +/* + * TODO + * write bad block forwarding code + */ + +#include "uda.h" +#include "ra.h" + +#if NUDA > 0 + +/* + * CONFIGURATION OPTIONS. The next three defines are tunable -- tune away! + * + * COMPAT_42 enables 4.2/4.3 compatibility (label mapping) + * + * NRSPL2 and NCMDL2 control the number of response and command + * packets respectively. They may be any value from 0 to 7, though + * setting them higher than 5 is unlikely to be of any value. + * If you get warnings about your command ring being too small, + * try increasing the values by one. + * + * MAXUNIT controls the maximum unit number (number of drives per + * controller) we are prepared to handle. + * + * DEFAULT_BURST must be at least 1. + */ +#define COMPAT_42 + +#define NRSPL2 5 /* log2 number of response packets */ +#define NCMDL2 5 /* log2 number of command packets */ +#define MAXUNIT 8 /* maximum allowed unit number */ +#define DEFAULT_BURST 4 /* default DMA burst size */ + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/buf.h" +#include "sys/conf.h" +#include "sys/file.h" +#include "sys/ioctl.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/map.h" +#include "sys/device.h" +#include "sys/dkstat.h" +#include "sys/disklabel.h" +#include "sys/syslog.h" +#include "sys/stat.h" + +#include "machine/pte.h" +#include "machine/sid.h" +#include "machine/cpu.h" + +#include "vax/uba/ubareg.h" +#include "vax/uba/ubavar.h" + +#define NRSP (1 << NRSPL2) +#define NCMD (1 << NCMDL2) + +#include "vax/uba/udareg.h" +#include "vax/vax/mscp.h" +#include "vax/vax/mscpvar.h" +#include "machine/mtpr.h" + +extern int cold; + +/* + * This macro is for delay during init. Some MSCP clone card (Dilog) + * can't handle fast read from its registers, and therefore need + * a delay between them. + */ +#define DELAYTEN 1000 +#define Wait_step( mask, result, status ) { \ + status = 1; \ + if ((udaddr->udasa & mask) != result) { \ + int count = 0; \ + while ((udaddr->udasa & mask) != result) { \ + DELAY(100); \ + count += 1; \ + if (count > DELAYTEN) \ + break; \ + } \ + if (count > DELAYTEN) \ + status = 0; \ + } \ + } + +/* + * UDA communications area and MSCP packet pools, per controller. + */ +struct uda { + struct udaca uda_ca; /* communications area */ + struct mscp uda_rsp[NRSP]; /* response packets */ + struct mscp uda_cmd[NCMD]; /* command packets */ +} uda[NUDA]; + +/* + * Software status, per controller. + */ +struct uda_softc { + struct uda *sc_uda; /* Unibus address of uda struct */ + short sc_state; /* UDA50 state; see below */ + short sc_flags; /* flags; see below */ + int sc_micro; /* microcode revision */ + int sc_ivec; /* interrupt vector address */ + short sc_ipl; /* interrupt priority, Q-bus */ + struct mscp_info sc_mi;/* MSCP info (per mscpvar.h) */ +#ifndef POLLSTATS + int sc_wticks; /* watchdog timer ticks */ +#else + short sc_wticks; + short sc_ncmd; +#endif +} uda_softc[NUDA]; + +#ifdef POLLSTATS +struct udastats { + int ncmd; + int cmd[NCMD + 1]; +} udastats = { NCMD + 1 }; +#endif + +/* + * Controller states + */ +#define ST_IDLE 0 /* uninitialised */ +#define ST_STEP1 1 /* in `STEP 1' */ +#define ST_STEP2 2 /* in `STEP 2' */ +#define ST_STEP3 3 /* in `STEP 3' */ +#define ST_SETCHAR 4 /* in `Set Controller Characteristics' */ +#define ST_RUN 5 /* up and running */ + +/* + * Flags + */ +#define SC_MAPPED 0x01 /* mapped in Unibus I/O space */ +#define SC_INSTART 0x02 /* inside udastart() */ +#define SC_GRIPED 0x04 /* griped about cmd ring too small */ +#define SC_INSLAVE 0x08 /* inside udaslave() */ +#define SC_DOWAKE 0x10 /* wakeup when ctlr init done */ +#define SC_STARTPOLL 0x20 /* need to initiate polling */ + +/* + * Device to unit number and partition and back + */ +#define UNITSHIFT 3 +#define UNITMASK 7 +#define udaunit(dev) (minor(dev) >> UNITSHIFT) +#define udapart(dev) (minor(dev) & UNITMASK) +#define udaminor(u, p) (((u) << UNITSHIFT) | (p)) + +/* + * Drive status, per drive + */ +struct ra_info { + daddr_t ra_dsize; /* size in sectors */ +/* u_long ra_type; /* drive type */ + u_long ra_mediaid; /* media id */ + int ra_state; /* open/closed state */ + struct ra_geom { /* geometry information */ + u_short rg_nsectors; /* sectors/track */ + u_short rg_ngroups; /* track groups */ + u_short rg_ngpc; /* groups/cylinder */ + u_short rg_ntracks; /* ngroups*ngpc */ + u_short rg_ncyl; /* ra_dsize/ntracks/nsectors */ +#ifdef notyet + u_short rg_rctsize; /* size of rct */ + u_short rg_rbns; /* replacement blocks per track */ + u_short rg_nrct; /* number of rct copies */ +#endif + } ra_geom; + int ra_wlabel; /* label sector is currently writable */ + u_long ra_openpart; /* partitions open */ + u_long ra_bopenpart; /* block partitions open */ + u_long ra_copenpart; /* character partitions open */ +} ra_info[NRA]; + +/* + * Software state, per drive + */ +#define CLOSED 0 +#define WANTOPEN 1 +#define RDLABEL 2 +#define OPEN 3 +#define OPENRAW 4 + +/* + * Definition of the driver for autoconf. + */ +int udaprobe(), udaslave(), udaattach(), udadgo(), udaintr(); +struct uba_ctlr *udaminfo[NUDA]; +struct uba_device *udadinfo[NRA]; +struct disklabel udalabel[NRA]; + +u_short udastd[] = { 0 }; +struct uba_driver udadriver = + { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda", + udaminfo }; + +/* + * More driver definitions, for generic MSCP code. + */ +int udadgram(), udactlrdone(), udaunconf(), udaiodone(); +int udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb(); + +struct buf udautab[NRA]; /* per drive transfer queue */ + +struct mscp_driver udamscpdriver = + { MAXUNIT, NRA, UNITSHIFT, udautab, udalabel, udadinfo, + udadgram, udactlrdone, udaunconf, udaiodone, + udaonline, udagotstatus, udareplace, udaioerror, udabb, + "uda", "ra" }; + +/* + * Miscellaneous private variables. + */ +char udasr_bits[] = UDASR_BITS; + +struct uba_device *udaip[NUDA][MAXUNIT]; + /* inverting pointers: ctlr & unit => Unibus + device pointer */ + +int udaburst[NUDA] = { 0 }; /* burst size, per UDA50, zero => default; + in data space so patchable via adb */ + +struct mscp udaslavereply; /* get unit status response packet, set + for udaslave by udaunconf, via udaintr */ + +static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr + info to slave routine; instead, we remember + the last ctlr argument to probe */ + +int udawstart; +void udawatch(); /* watchdog timer */ + +/* + * Externals + */ +int hz; + +/* + * Poke at a supposed UDA50 to see if it is there. + * This routine duplicates some of the code in udainit() only + * because autoconf has not set up the right information yet. + * We have to do everything `by hand'. + */ +udaprobe(reg, ctlr, um) + caddr_t reg; + int ctlr; + struct uba_ctlr *um; +{ +/* int br, cvec; */ + struct uda_softc *sc; + volatile struct udadevice *udaddr; + struct mscp_info *mi; + extern int cpu_type; + int timeout, tries, count; +#ifdef notyet + int s; +#endif + +#ifdef VAX750 + /* + * The UDA50 wants to share BDPs on 750s, but not on 780s or + * 8600s. (730s have no BDPs anyway.) Toward this end, we + * here set the `keep bdp' flag in the per-driver information + * if this is a 750. (We just need to do it once, but it is + * easiest to do it now, for each UDA50.) + */ + if (MACHID(cpu_type) == VAX_750) + udadriver.ud_keepbdp = 1; +#endif +/* printf("udaprobe\n"); */ + probeum = um; /* remember for udaslave() */ + /* + * Set up the controller-specific generic MSCP driver info. + * Note that this should really be done in the (nonexistent) + * controller attach routine. + */ + sc = &uda_softc[ctlr]; + mi = &sc->sc_mi; + mi->mi_md = &udamscpdriver; + mi->mi_ctlr = um->um_ctlr; + mi->mi_tab = (void*)&um->um_tab; + mi->mi_ip = udaip[ctlr]; + mi->mi_cmd.mri_size = NCMD; + mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc; + mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd; + mi->mi_rsp.mri_size = NRSP; + mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc; + mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp; +#ifdef ragge + mi->mi_wtab.b_actf = NULL; +#else + mi->mi_wtab.b_actf = &mi->mi_wtab; +#endif +/* Was: mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; */ + + /* + * More controller specific variables. Again, this should + * be in the controller attach routine. + */ + if (udaburst[ctlr] == 0) + udaburst[ctlr] = DEFAULT_BURST; + + /* + * Get an interrupt vector. Note that even if the controller + * does not respond, we keep the vector. This is not a serious + * problem; but it would be easily fixed if we had a controller + * attach routine. Sigh. + */ + sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); + udaddr = (struct udadevice *) reg; + + /* + * Initialise the controller (partially). The UDA50 programmer's + * manual states that if initialisation fails, it should be retried + * at least once, but after a second failure the port should be + * considered `down'; it also mentions that the controller should + * initialise within ten seconds. Or so I hear; I have not seen + * this manual myself. + */ +#ifdef notyet + s = spl6(); +#endif + tries = 0; +again: + udaddr->udaip = 0; /* start initialisation */ + + count = 0; + while ( count < DELAYTEN ) { + if ( (udaddr->udasa & UDA_STEP1) != 0 ) + break; + DELAY(10000); + count += 1; + } + + /* nothing there */ + if ( count == DELAYTEN ) + return(0); + + udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | + (sc->sc_ivec >> 2); + + count = 0; + while (count < DELAYTEN) { + if ((udaddr->udasa & UDA_STEP2 ) != 0) + break; + DELAY(10000); + count += 1; + } + + if (count == DELAYTEN) { + printf("udaprobe: uda%d: init step2 no change.\n", + um->um_ctlr); + goto bad; + } + + /* should have interrupted by now */ +#ifdef notyet + sc->sc_ipl = br = qbgetpri(); +#else + sc->sc_ipl = 0x15; +#endif + return (sizeof (struct udadevice)); +bad: + if (++tries < 2) + goto again; +#ifdef notyet + splx(s); +#endif + return (0); +} + +/* + * Find a slave. We allow wildcard slave numbers (something autoconf + * is not really prepared to deal with); and we need to know the + * controller number to talk to the UDA. For the latter, we keep + * track of the last controller probed, since a controller probe + * immediately precedes all slave probes for that controller. For the + * former, we simply put the unit number into ui->ui_slave after we + * have found one. + * + * Note that by the time udaslave is called, the interrupt vector + * for the UDA50 has been set up (so that udaunconf() will be called). + */ +udaslave(ui, reg) + register struct uba_device *ui; + caddr_t reg; +{ + register struct uba_ctlr *um = probeum; + volatile struct mscp *mp; + volatile struct uda_softc *sc; + int next = 0, timeout, tries; + volatile int i; + +#ifdef lint + i = 0; i = i; +#endif + /* + * Make sure the controller is fully initialised, by waiting + * for it if necessary. + */ + sc = &uda_softc[um->um_ctlr]; + if (sc->sc_state == ST_RUN) + goto findunit; + tries = 0; +again: + if (udainit(ui->ui_ctlr)) + return (0); + timeout = todr() + 1000; /* 10 seconds */ + while (todr() < timeout) { + if (sc->sc_state == ST_RUN) /* made it */ + goto findunit; + } + if (++tries < 2) + goto again; + printf("uda%d: controller hung\n", um->um_ctlr); + return (0); + + /* + * The controller is all set; go find the unit. Grab an + * MSCP packet and send out a Get Unit Status command, with + * the `next unit' modifier if we are looking for a generic + * unit. We set the `in slave' flag so that udaunconf() + * knows to copy the response to `udaslavereply'. + */ +findunit: + udaslavereply.mscp_opcode = 0; + sc->sc_flags |= SC_INSLAVE; + if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) + panic("udaslave"); /* `cannot happen' */ + mp->mscp_opcode = M_OP_GETUNITST; + if (ui->ui_slave == '?') { + mp->mscp_unit = next; + mp->mscp_modifier = M_GUM_NEXTUNIT; + } else { + mp->mscp_unit = ui->ui_slave; + mp->mscp_modifier = 0; + } + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + i = ((struct udadevice *) reg)->udaip; /* initiate polling */ + mp = &udaslavereply; + timeout = todr() + 1000; + while (todr() < timeout) + if (mp->mscp_opcode) + goto gotit; + printf("uda%d: no response to Get Unit Status request\n", + um->um_ctlr); + sc->sc_flags &= ~SC_INSLAVE; + return (0); + +gotit: + sc->sc_flags &= ~SC_INSLAVE; + + /* + * Got a slave response. If the unit is there, use it. + */ + switch (mp->mscp_status & M_ST_MASK) { + + case M_ST_SUCCESS: /* worked */ + case M_ST_AVAILABLE: /* found another drive */ + break; /* use it */ + + case M_ST_OFFLINE: + /* + * Figure out why it is off line. It may be because + * it is nonexistent, or because it is spun down, or + * for some other reason. + */ + switch (mp->mscp_status & ~M_ST_MASK) { + + case M_OFFLINE_UNKNOWN: + /* + * No such drive, and there are none with + * higher unit numbers either, if we are + * using M_GUM_NEXTUNIT. + */ + return (0); + + case M_OFFLINE_UNMOUNTED: + /* + * The drive is not spun up. Use it anyway. + * + * N.B.: this seems to be a common occurrance + * after a power failure. The first attempt + * to bring it on line seems to spin it up + * (and thus takes several minutes). Perhaps + * we should note here that the on-line may + * take longer than usual. + */ + break; + + default: + /* + * In service, or something else equally unusable. + */ + printf("uda%d: unit %d off line: ", um->um_ctlr, + mp->mscp_unit); + mscp_printevent(mp); + goto try_another; + } + break; + + default: + printf("uda%d: unable to get unit status: ", um->um_ctlr); + mscp_printevent(mp); + return (0); + } + + /* + * Does this ever happen? What (if anything) does it mean? + */ + if (mp->mscp_unit < next) { + printf("uda%d: unit %d, next %d\n", + um->um_ctlr, mp->mscp_unit, next); + return (0); + } + + if (mp->mscp_unit >= MAXUNIT) { + printf("uda%d: cannot handle unit number %d (max is %d)\n", + um->um_ctlr, mp->mscp_unit, MAXUNIT - 1); + return (0); + } + + /* + * See if we already handle this drive. + * (Only likely if ui->ui_slave=='?'.) + */ + if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) { +try_another: + if (ui->ui_slave != '?') + return (0); + next = mp->mscp_unit + 1; + goto findunit; + } + + /* + * Voila! + */ + uda_rasave(ui->ui_unit, mp, 0); + ui->ui_flags = 0; /* not on line, nor anything else */ + ui->ui_slave = mp->mscp_unit; + return (1); +} + +/* + * Attach a found slave. Make sure the watchdog timer is running. + * If this disk is being profiled, fill in the `wpms' value (used by + * what?). Set up the inverting pointer, and attempt to bring the + * drive on line and read its label. + */ +udaattach(ui) + register struct uba_device *ui; +{ + register int unit = ui->ui_unit; + + if (udawstart == 0) { + timeout(udawatch, (caddr_t) 0, hz); + udawstart++; + } + + /* + * Floppies cannot be brought on line unless there is + * a disk in the drive. Since an ONLINE while cold + * takes ten seconds to fail, and (when notyet becomes now) + * no sensible person will swap to one, we just + * defer the ONLINE until someone tries to use the drive. + * + * THIS ASSUMES THAT DRIVE TYPES ?X? ARE FLOPPIES + */ + if (MSCP_MID_ECH(1, ra_info[unit].ra_mediaid) == 'X' - '@') { + printf(": floppy"); + return; + } + if (ui->ui_dk >= 0) + dk_wpms[ui->ui_dk] = (60 * 31 * 256); /* approx */ + udaip[ui->ui_ctlr][ui->ui_slave] = ui; + + if (uda_rainit(ui, 0)) + printf(": offline"); + else if (ra_info[unit].ra_state == OPEN) { + printf(": %s, size = %d sectors", + udalabel[unit].d_typename, ra_info[unit].ra_dsize); +#ifdef notyet + addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]); +#endif + } +} + +/* + * Initialise a UDA50. Return true iff something goes wrong. + */ +udainit(ctlr) + int ctlr; +{ + register struct uda_softc *sc; + register struct udadevice *udaddr; + struct uba_ctlr *um; + int timo, ubinfo, count; +/* printf("udainit\n"); */ + sc = &uda_softc[ctlr]; + um = udaminfo[ctlr]; + if ((sc->sc_flags & SC_MAPPED) == 0) { + /* + * Map the communication area and command and + * response packets into Unibus space. + */ + ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr], + sizeof (struct uda), UBA_CANTWAIT); + if (ubinfo == 0) { + printf("uda%d: uballoc map failed\n", ctlr); + return (-1); + } + sc->sc_uda = (struct uda *) UBAI_ADDR(ubinfo); + sc->sc_flags |= SC_MAPPED; + } + + /* + * While we are thinking about it, reset the next command + * and response indicies. + */ + sc->sc_mi.mi_cmd.mri_next = 0; + sc->sc_mi.mi_rsp.mri_next = 0; + + /* + * Start up the hardware initialisation sequence. + */ +#define STEP0MASK (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \ + UDA_STEP1 | UDA_NV) + + sc->sc_state = ST_IDLE; /* in case init fails */ + udaddr = (struct udadevice *)um->um_addr; + udaddr->udaip = 0; + count = 0; + while (count < DELAYTEN) { + if ((udaddr->udasa & UDA_STEP1) != 0) + break; + DELAY(10000); + count += 1; + } + if (count == DELAYTEN) { + printf("uda%d: timeout during init\n", ctlr); + return (-1); + } + + if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) { + printf("uda%d: init failed, sa=%b\n", ctlr, + udaddr->udasa, udasr_bits); + udasaerror(um, 0); + return (-1); + } + + /* + * Success! Record new state, and start step 1 initialisation. + * The rest is done in the interrupt handler. + */ + sc->sc_state = ST_STEP1; + udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | + (sc->sc_ivec >> 2); + return (0); +} + +/* + * Open a drive. + */ +/*ARGSUSED*/ +udaopen(dev, flag, fmt) + dev_t dev; + int flag, fmt; +{ + register int unit; + register struct uba_device *ui; + register struct uda_softc *sc; + register struct disklabel *lp; + register struct partition *pp; + register struct ra_info *ra; + int s, i, part, mask, error = 0; + daddr_t start, end; +/* printf("udaopen\n"); */ + /* + * Make sure this is a reasonable open request. + */ + unit = udaunit(dev); + if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0) + return (ENXIO); + + /* + * Make sure the controller is running, by (re)initialising it if + * necessary. + */ + sc = &uda_softc[ui->ui_ctlr]; + s = splbio(); + if (sc->sc_state != ST_RUN) { + if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) { + splx(s); + return (EIO); + } + /* + * In case it does not come up, make sure we will be + * restarted in 10 seconds. This corresponds to the + * 10 second timeouts in udaprobe() and udaslave(). + */ + sc->sc_flags |= SC_DOWAKE; + timeout(wakeup, (caddr_t) sc, 10 * hz); + sleep((caddr_t) sc, PRIBIO); + if (sc->sc_state != ST_RUN) { + splx(s); + printf("uda%d: controller hung\n", ui->ui_ctlr); + return (EIO); + } + untimeout(wakeup, (caddr_t) sc); + } + + /* + * Wait for the state to settle + */ + ra = &ra_info[unit]; + while (ra->ra_state != OPEN && ra->ra_state != OPENRAW && + ra->ra_state != CLOSED) + if (error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH, + devopn, 0)) { + splx(s); + return (error); + } + + /* + * If not on line, or we are not sure of the label, reinitialise + * the drive. + */ + if ((ui->ui_flags & UNIT_ONLINE) == 0 || + (ra->ra_state != OPEN && ra->ra_state != OPENRAW)) + error = uda_rainit(ui, flag); + splx(s); + if (error) + return (error); + + part = udapart(dev); + lp = &udalabel[unit]; + if (part >= lp->d_npartitions) + return (ENXIO); + /* + * Warn if a partition is opened that overlaps another + * already open, unless either is the `raw' partition + * (whole disk). + */ +#define RAWPART 2 /* 'c' partition */ /* XXX */ + mask = 1 << part; + if ((ra->ra_openpart & mask) == 0 && part != RAWPART) { + pp = &lp->d_partitions[part]; + start = pp->p_offset; + end = pp->p_offset + pp->p_size; + for (pp = lp->d_partitions, i = 0; + i < lp->d_npartitions; pp++, i++) { + if (pp->p_offset + pp->p_size <= start || + pp->p_offset >= end || i == RAWPART) + continue; + if (ra->ra_openpart & (1 << i)) + log(LOG_WARNING, + "ra%d%c: overlaps open partition (%c)\n", + unit, part + 'a', i + 'a'); + } + } + switch (fmt) { + case S_IFCHR: + ra->ra_copenpart |= mask; + break; + case S_IFBLK: + ra->ra_bopenpart |= mask; + break; + } + ra->ra_openpart |= mask; + return (0); +} + +/* ARGSUSED */ +udaclose(dev, flags, fmt) + dev_t dev; + int flags, fmt; +{ + register int unit = udaunit(dev); + register struct ra_info *ra = &ra_info[unit]; + int s, mask = (1 << udapart(dev)); +/* printf("udaclose\n"); */ + switch (fmt) { + case S_IFCHR: + ra->ra_copenpart &= ~mask; + break; + case S_IFBLK: + ra->ra_bopenpart &= ~mask; + break; + } + ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; + + /* + * Should wait for I/O to complete on this partition even if + * others are open, but wait for work on blkflush(). + */ + if (ra->ra_openpart == 0) { + s = splbio(); + while (udautab[unit].b_actf) + sleep((caddr_t)&udautab[unit], PZERO - 1); + splx(s); + ra->ra_state = CLOSED; + ra->ra_wlabel = 0; + } + return (0); +} + +/* + * Initialise a drive. If it is not already, bring it on line, + * and set a timeout on it in case it fails to respond. + * When on line, read in the pack label. + */ +uda_rainit(ui, flags) + volatile struct uba_device *ui; + int flags; +{ + register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; + register struct disklabel *lp; + register struct mscp *mp; + register int unit = ui->ui_unit; + register struct ra_info *ra; + char *msg, *readdisklabel(); + int s, i; + volatile int hej; + void udastrategy(); + extern int cold; +/* printf("uda_rainit\n"); */ + ra = &ra_info[unit]; + if ((ui->ui_flags & UNIT_ONLINE) == 0) { + mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); + mp->mscp_opcode = M_OP_ONLINE; + mp->mscp_unit = ui->ui_slave; + mp->mscp_cmdref = (long)&ui->ui_flags; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + ra->ra_state = WANTOPEN; + if (!cold) + s = splbio(); + hej = ((struct udadevice *)ui->ui_addr)->udaip; + + if (cold) { + i = todr() + 1000; + while ((ui->ui_flags & UNIT_ONLINE) == 0) + if (todr() > i) + break; + } else { + timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); + sleep((caddr_t)&ui->ui_flags, PSWP + 1); + splx(s); + untimeout(wakeup, (caddr_t)&ui->ui_flags); + } + if (ra->ra_state != OPENRAW) { + ra->ra_state = CLOSED; + wakeup((caddr_t)ra); + return (EIO); + } + } + + lp = &udalabel[unit]; + lp->d_secsize = DEV_BSIZE; + lp->d_secperunit = ra->ra_dsize; + + if (flags & O_NDELAY) + return (0); + ra->ra_state = RDLABEL; + /* + * Set up default sizes until we have the label, or longer + * if there is none. Set secpercyl, as readdisklabel wants + * to compute b_cylin (although we do not need it), and set + * nsectors in case diskerr is called. + */ + lp->d_secpercyl = 1; + lp->d_npartitions = 1; + lp->d_secsize = 512; + lp->d_secperunit = ra->ra_dsize; + lp->d_nsectors = ra->ra_geom.rg_nsectors; + lp->d_partitions[0].p_size = lp->d_secperunit; + lp->d_partitions[0].p_offset = 0; + + /* + * Read pack label. + */ + if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp,NULL)) + != NULL) { + if (cold) + printf(": %s", msg); + else + log(LOG_ERR, "ra%d: %s", unit, msg); +#ifdef COMPAT_42 + if (udamaptype(unit, lp)) + ra->ra_state = OPEN; + else + ra->ra_state = OPENRAW; +#else + ra->ra_state = OPENRAW; + uda_makefakelabel(ra, lp); +#endif + } else + ra->ra_state = OPEN; + wakeup((caddr_t)ra); + return (0); +} + +/* + * Copy the geometry information for the given ra from a + * GET UNIT STATUS response. If check, see if it changed. + */ +uda_rasave(unit, mp, check) + int unit; + register struct mscp *mp; + int check; +{ + register struct ra_info *ra = &ra_info[unit]; +/* printf("uda_rasave\n"); */ + if (check && ra->ra_mediaid != mp->mscp_guse.guse_mediaid) { + printf("ra%d: changed types! was %d now %d\n", unit, + ra->ra_mediaid, mp->mscp_guse.guse_mediaid); + ra->ra_state = CLOSED; /* ??? */ + } + /* ra->ra_type = mp->mscp_guse.guse_drivetype; */ + ra->ra_mediaid = mp->mscp_guse.guse_mediaid; + ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt; + ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group; + ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc; + ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc; + /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */ +#ifdef notyet + ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize; + ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt; + ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct; +#endif +} + +/* + * Queue a transfer request, and if possible, hand it to the controller. + * + * This routine is broken into two so that the internal version + * udastrat1() can be called by the (nonexistent, as yet) bad block + * revectoring routine. + */ +void +udastrategy(bp) + register struct buf *bp; +{ + register int unit; + register struct uba_device *ui; + register struct ra_info *ra; + struct partition *pp; + int p; + daddr_t sz, maxsz; +/* printf("udastrategy\n"); */ + /* + * Make sure this is a reasonable drive to use. + */ + if ((unit = udaunit(bp->b_dev)) >= NRA || + (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || + (ra = &ra_info[unit])->ra_state == CLOSED) { + bp->b_error = ENXIO; + goto bad; + } + + /* + * If drive is open `raw' or reading label, let it at it. + */ + if (ra->ra_state < OPEN) { + udastrat1(bp); + return; + } + p = udapart(bp->b_dev); + if ((ra->ra_openpart & (1 << p)) == 0) { + bp->b_error = ENODEV; + goto bad; + } + + /* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. + */ + pp = &udalabel[unit].d_partitions[p]; + maxsz = pp->p_size; + if (pp->p_offset + pp->p_size > ra->ra_dsize) + maxsz = ra->ra_dsize - pp->p_offset; + sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + if (bp->b_blkno + pp->p_offset <= LABELSECTOR && +#if LABELSECTOR != 0 + bp->b_blkno + pp->p_offset + sz > LABELSECTOR && +#endif + (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } + if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ + if (bp->b_blkno == maxsz) { + bp->b_resid = bp->b_bcount; + biodone(bp); + return; + } + /* or truncate if part of it fits */ + sz = maxsz - bp->b_blkno; + if (sz <= 0) { + bp->b_error = EINVAL; /* or hang it up */ + goto bad; + } + bp->b_bcount = sz << DEV_BSHIFT; + } + udastrat1(bp); + return; +bad: + bp->b_flags |= B_ERROR; + biodone(bp); +} + +/* + * Work routine for udastrategy. + */ +udastrat1(bp) + register struct buf *bp; +{ + register int unit = udaunit(bp->b_dev); + register struct uba_ctlr *um; + register struct buf *dp; + struct uba_device *ui; + int s = splbio(); +/* printf("udastrat1\n"); */ + /* + * Append the buffer to the drive queue, and if it is not + * already there, the drive to the controller queue. (However, + * if the drive queue is marked to be requeued, we must be + * awaiting an on line or get unit status command; in this + * case, leave it off the controller queue.) + */ + um = (ui = udadinfo[unit])->ui_mi; + dp = &udautab[unit]; + MSCP_APPEND(bp, dp, b_actf); + if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { + MSCP_APPEND(dp, &um->um_tab, b_hash.le_next); + dp->b_active++; + } +/* Was: MSCP_APPEND(bp, dp, av_forw); + if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { + MSCP_APPEND(dp, &um->um_tab, b_forw); + dp->b_active++; + } +*/ + /* + * Start activity on the controller. Note that unlike other + * Unibus drivers, we must always do this, not just when the + * controller is not active. + */ + udastart(um); + splx(s); +} + +int +udaread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(udastrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +udawrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(udastrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +/* + * Start up whatever transfers we can find. + * Note that udastart() must be called at splbio(). + */ +udastart(um) + register struct uba_ctlr *um; +{ + volatile struct uda_softc *sc = &uda_softc[um->um_ctlr]; + register struct buf *bp, *dp; + register struct mscp *mp; + struct uba_device *ui; + volatile struct udadevice *udaddr; + struct partition *pp; + int sz; + volatile int i; +/* printf("udastart\n"); */ +#ifdef lint + i = 0; i = i; +#endif + /* + * If it is not running, try (again and again...) to initialise + * it. If it is currently initialising just ignore it for now. + */ + if (sc->sc_state != ST_RUN) { + if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr)) + printf("uda%d: still hung\n", um->um_ctlr); + return; + } + + /* + * If um_cmd is nonzero, this controller is on the Unibus + * resource wait queue. It will not help to try more requests; + * instead, when the Unibus unblocks and calls udadgo(), we + * will call udastart() again. + */ + if (um->um_cmd) + return; + + sc->sc_flags |= SC_INSTART; + udaddr = (struct udadevice *) um->um_addr; + +loop: + /* + * Service the drive at the head of the queue. It may not + * need anything, in which case it might be shutting down + * in udaclose(). + */ + if ((dp = um->um_tab.b_actf) == NULL) + goto out; + if ((bp = dp->b_actf) == NULL) { + dp->b_active = 0; + um->um_tab.b_actf = dp->b_hash.le_next; +/* Was: um->um_tab.b_actf = dp->b_forw; */ + if (ra_info[dp - udautab].ra_openpart == 0) + wakeup((caddr_t)dp); /* finish close protocol */ + goto loop; + } + + if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ + udasaerror(um, 1); + goto out; + } + + /* + * Get an MSCP packet, then figure out what to do. If + * we cannot get a command packet, the command ring may + * be too small: We should have at least as many command + * packets as credits, for best performance. + */ + if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) { + if (sc->sc_mi.mi_credits > MSCP_MINCREDITS && + (sc->sc_flags & SC_GRIPED) == 0) { + log(LOG_NOTICE, "uda%d: command ring too small\n", + um->um_ctlr); + sc->sc_flags |= SC_GRIPED;/* complain only once */ + } + goto out; + } + + /* + * Bring the drive on line if it is not already. Get its status + * if we do not already have it. Otherwise just start the transfer. + */ + ui = udadinfo[udaunit(bp->b_dev)]; + if ((ui->ui_flags & UNIT_ONLINE) == 0) { + mp->mscp_opcode = M_OP_ONLINE; + goto common; + } + if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { + mp->mscp_opcode = M_OP_GETUNITST; +common: +if (ui->ui_flags & UNIT_REQUEUE) panic("udastart"); + /* + * Take the drive off the controller queue. When the + * command finishes, make sure the drive is requeued. + */ + um->um_tab.b_actf = dp->b_hash.le_next; +/* Was: um->um_tab.b_actf = dp->b_forw; */ + dp->b_active = 0; + ui->ui_flags |= UNIT_REQUEUE; + mp->mscp_unit = ui->ui_slave; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + sc->sc_flags |= SC_STARTPOLL; +#ifdef POLLSTATS + sc->sc_ncmd++; +#endif + goto loop; + } + + pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; + mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; + mp->mscp_unit = ui->ui_slave; + mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset; + sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ? + (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount; + /* mscp_cmdref is filled in by mscp_go() */ + + /* + * Drop the packet pointer into the `command' field so udadgo() + * can tell what to start. If ubago returns 1, we can do another + * transfer. If not, um_cmd will still point at mp, so we will + * know that we are waiting for resources. + */ + um->um_cmd = (int)mp; + if (ubago(ui)) + goto loop; + + /* + * All done, or blocked in ubago(). If we managed to + * issue some commands, start up the beast. + */ +out: + if (sc->sc_flags & SC_STARTPOLL) { +#ifdef POLLSTATS + udastats.cmd[sc->sc_ncmd]++; + sc->sc_ncmd = 0; +#endif + i = ((struct udadevice *)um->um_addr)->udaip; + } + sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); +} + +/* + * Start a transfer. + * + * If we are not called from within udastart(), we must have been + * blocked, so call udastart to do more requests (if any). If + * this calls us again immediately we will not recurse, because + * that time we will be in udastart(). Clever.... + */ +udadgo(um) + register struct uba_ctlr *um; +{ + struct uda_softc *sc = &uda_softc[um->um_ctlr]; + struct mscp *mp = (struct mscp *)um->um_cmd; +/* printf("udago\n"); */ + um->um_tab.b_active++; /* another transfer going */ + + /* + * Fill in the MSCP packet and move the buffer to the + * I/O wait queue. Mark the controller as no longer on + * the resource queue, and remember to initiate polling. + */ + mp->mscp_seq.seq_buffer = UBAI_ADDR(um->um_ubinfo) | + (UBAI_BDP(um->um_ubinfo) << 24); + mscp_go(&sc->sc_mi, mp, um->um_ubinfo); + um->um_cmd = 0; + um->um_ubinfo = 0; /* tyke it awye */ + sc->sc_flags |= SC_STARTPOLL; +#ifdef POLLSTATS + sc->sc_ncmd++; +#endif + if ((sc->sc_flags & SC_INSTART) == 0) + udastart(um); +} + +udaiodone(mi, bp, info) + register struct mscp_info *mi; + struct buf *bp; + int info; +{ + register struct uba_ctlr *um = udaminfo[mi->mi_ctlr]; +/* printf("udaiodone\n"); */ + um->um_ubinfo = info; + ubadone(um); + biodone(bp); + if (um->um_bdp && mi->mi_wtab.b_actf == &mi->mi_wtab) + ubarelse(um->um_ubanum, &um->um_bdp); +/* Was: if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab) + ubarelse(um->um_ubanum, &um->um_bdp); */ + um->um_tab.b_active--; /* another transfer done */ +} + +static struct saerr { + int code; /* error code (including UDA_ERR) */ + char *desc; /* what it means: Efoo => foo error */ +} saerr[] = { + { 0100001, "Eunibus packet read" }, + { 0100002, "Eunibus packet write" }, + { 0100003, "EUDA ROM and RAM parity" }, + { 0100004, "EUDA RAM parity" }, + { 0100005, "EUDA ROM parity" }, + { 0100006, "Eunibus ring read" }, + { 0100007, "Eunibus ring write" }, + { 0100010, " unibus interrupt master failure" }, + { 0100011, "Ehost access timeout" }, + { 0100012, " host exceeded command limit" }, + { 0100013, " unibus bus master failure" }, + { 0100014, " DM XFC fatal error" }, + { 0100015, " hardware timeout of instruction loop" }, + { 0100016, " invalid virtual circuit id" }, + { 0100017, "Eunibus interrupt write" }, + { 0104000, "Efatal sequence" }, + { 0104040, " D proc ALU" }, + { 0104041, "ED proc control ROM parity" }, + { 0105102, "ED proc w/no BD#2 or RAM parity" }, + { 0105105, "ED proc RAM buffer" }, + { 0105152, "ED proc SDI" }, + { 0105153, "ED proc write mode wrap serdes" }, + { 0105154, "ED proc read mode serdes, RSGEN & ECC" }, + { 0106040, "EU proc ALU" }, + { 0106041, "EU proc control reg" }, + { 0106042, " U proc DFAIL/cntl ROM parity/BD #1 test CNT" }, + { 0106047, " U proc const PROM err w/D proc running SDI test" }, + { 0106055, " unexpected trap" }, + { 0106071, "EU proc const PROM" }, + { 0106072, "EU proc control ROM parity" }, + { 0106200, "Estep 1 data" }, + { 0107103, "EU proc RAM parity" }, + { 0107107, "EU proc RAM buffer" }, + { 0107115, " test count wrong (BD 12)" }, + { 0112300, "Estep 2" }, + { 0122240, "ENPR" }, + { 0122300, "Estep 3" }, + { 0142300, "Estep 4" }, + { 0, " unknown error code" } +}; + +/* + * If the error bit was set in the controller status register, gripe, + * then (optionally) reset the controller and requeue pending transfers. + */ +udasaerror(um, doreset) + register struct uba_ctlr *um; + int doreset; +{ + register int code = ((struct udadevice *)um->um_addr)->udasa; + register struct saerr *e; +/*printf("udasaerror\n"); */ + if ((code & UDA_ERR) == 0) + return; + for (e = saerr; e->code; e++) + if (e->code == code) + break; + printf("uda%d: controller error, sa=0%o (%s%s)\n", + um->um_ctlr, code, e->desc + 1, + *e->desc == 'E' ? " error" : ""); + if (doreset) { + mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); + (void) udainit(um->um_ctlr); + } +} + +/* + * Interrupt routine. Depending on the state of the controller, + * continue initialisation, or acknowledge command and response + * interrupts, and process responses. + */ +udaintr(vektor,level,uba,ctlr) +{ + struct uba_ctlr *um = udaminfo[ctlr]; + volatile struct uda_softc *sc = &uda_softc[ctlr]; + volatile struct udadevice *udaddr = (struct udadevice *)um->um_addr; + struct uda *ud; + struct mscp *mp; + volatile int i, wait_status; + extern int cpu_type; + +#ifdef QBA + if(cpunumber == VAX_78032) + splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */ +#endif + sc->sc_wticks = 0; /* reset interrupt watchdog */ + + /* + * Combinations during steps 1, 2, and 3: STEPnMASK + * corresponds to which bits should be tested; + * STEPnGOOD corresponds to the pattern that should + * appear after the interrupt from STEPn initialisation. + * All steps test the bits in ALLSTEPS. + */ +#define ALLSTEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) + +#define STEP1MASK (ALLSTEPS | UDA_IE | UDA_NCNRMASK) +#define STEP1GOOD (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2) + +#define STEP2MASK (ALLSTEPS | UDA_IE | UDA_IVECMASK) +#define STEP2GOOD (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2)) + +#define STEP3MASK ALLSTEPS +#define STEP3GOOD UDA_STEP4 + + switch (sc->sc_state) { + + case ST_IDLE: + /* + * Ignore unsolicited interrupts. + */ + log(LOG_WARNING, "uda%d: stray intr\n", ctlr); + return; + + case ST_STEP1: + /* + * Begin step two initialisation. + */ + i = 0; + Wait_step(STEP1MASK, STEP1GOOD, wait_status); + if (!wait_status) { +initfailed: + printf("uda%d: init step %d failed, sa=%b\n", + ctlr, i, udaddr->udasa, udasr_bits); + udasaerror(um, 0); + sc->sc_state = ST_IDLE; + if (sc->sc_flags & SC_DOWAKE) { + sc->sc_flags &= ~SC_DOWAKE; + wakeup((caddr_t)sc); + } + return; + } + udaddr->udasa = (int)&sc->sc_uda->uda_ca.ca_rspdsc[0] | + (MACHID(cpu_type) == VAX_780 || MACHID(cpu_type) + == VAX_8600 ? UDA_PI : 0); + sc->sc_state = ST_STEP2; + return; + + case ST_STEP2: + /* + * Begin step 3 initialisation. + */ + i = 2; + Wait_step(STEP2MASK, STEP2GOOD, wait_status); + if (!wait_status) + goto initfailed; + + udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16; + sc->sc_state = ST_STEP3; + return; + + case ST_STEP3: + /* + * Set controller characteristics (finish initialisation). + */ + i = 3; + Wait_step(STEP3MASK, STEP3GOOD, wait_status); + if (!wait_status) + goto initfailed; + + i = udaddr->udasa & 0xff; + if (i != sc->sc_micro) { + sc->sc_micro = i; + printf("uda%d: version %d model %d\n", + ctlr, i & 0xf, i >> 4); + } + + /* + * Present the burst size, then remove it. Why this + * should be done this way, I have no idea. + * + * Note that this assumes udaburst[ctlr] > 0. + */ + udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; + udaddr->udasa = UDA_GO; + printf("uda%d: DMA burst size set to %d\n", + ctlr, udaburst[ctlr]); + + udainitds(ctlr); /* initialise data structures */ + + /* + * Before we can get a command packet, we need some + * credits. Fake some up to keep mscp_getcp() happy, + * get a packet, and cancel all credits (the right + * number should come back in the response to the + * SCC packet). + */ + sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; + mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); + if (mp == NULL) /* `cannot happen' */ + panic("udaintr"); + sc->sc_mi.mi_credits = 0; + mp->mscp_opcode = M_OP_SETCTLRC; + mp->mscp_unit = 0; + mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | + M_CF_THIS; + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; + i = udaddr->udaip; + sc->sc_state = ST_SETCHAR; + return; + + case ST_SETCHAR: + case ST_RUN: + /* + * Handle Set Ctlr Characteristics responses and operational + * responses (via mscp_dorsp). + */ + break; + + default: + printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); + panic("udastate"); + } + + if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ + udasaerror(um, 1); + return; + } + + ud = &uda[ctlr]; + + /* + * Handle buffer purge requests. + */ + if (ud->uda_ca.ca_bdp) { + UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); + ud->uda_ca.ca_bdp = 0; + udaddr->udasa = 0; /* signal purge complete */ + } + + /* + * Check for response and command ring transitions. + */ + if (ud->uda_ca.ca_rspint) { + ud->uda_ca.ca_rspint = 0; + mscp_dorsp(&sc->sc_mi); + } + if (ud->uda_ca.ca_cmdint) { + ud->uda_ca.ca_cmdint = 0; + MSCP_DOCMD(&sc->sc_mi); + } + udastart(um); +} + +/* + * Initialise the various data structures that control the UDA50. + */ +udainitds(ctlr) + int ctlr; +{ + register struct uda *ud = &uda[ctlr]; + register struct uda *uud = uda_softc[ctlr].sc_uda; + register struct mscp *mp; + register int i; +/* printf("udainitds\n"); */ + for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { + ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | + (long)&uud->uda_rsp[i].mscp_cmdref; + mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; + mp->mscp_msglen = MSCP_MSGLEN; + } + for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { + ud->uda_ca.ca_cmddsc[i] = MSCP_INT | + (long)&uud->uda_cmd[i].mscp_cmdref; + mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; + mp->mscp_msglen = MSCP_MSGLEN; + } +} + +/* + * Handle an error datagram. + */ +udadgram(mi, mp) + struct mscp_info *mi; + struct mscp *mp; +{ +/* printf("udadgram\n"); */ + mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); + /* + * SDI status information bytes 10 and 11 are the microprocessor + * error code and front panel code respectively. These vary per + * drive type and are printed purely for field service information. + */ + if (mp->mscp_format == M_FM_SDI) + printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", + mp->mscp_erd.erd_sdistat[10], + mp->mscp_erd.erd_sdistat[11]); +} + +/* + * The Set Controller Characteristics command finished. + * Record the new state of the controller. + */ +udactlrdone(mi, mp) + register struct mscp_info *mi; + struct mscp *mp; +{ + register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; +/* printf("udactlrdone\n"); */ + if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) + sc->sc_state = ST_RUN; + else { + printf("uda%d: SETCTLRC failed: ", + mi->mi_ctlr, mp->mscp_status); + mscp_printevent(mp); + sc->sc_state = ST_IDLE; + } + if (sc->sc_flags & SC_DOWAKE) { + sc->sc_flags &= ~SC_DOWAKE; + wakeup((caddr_t)sc); + } +} + +/* + * Received a response from an as-yet unconfigured drive. Configure it + * in, if possible. + */ +udaunconf(mi, mp) + struct mscp_info *mi; + register struct mscp *mp; +{ +/* printf("udaunconf\n"); */ + /* + * If it is a slave response, copy it to udaslavereply for + * udaslave() to look at. + */ + if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && + (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { + bcopy(mp, &udaslavereply, sizeof(struct mscp)); +/* udaslavereply = *mp; */ + return (MSCP_DONE); + } + + /* + * Otherwise, it had better be an available attention response. + */ + if (mp->mscp_opcode != M_OP_AVAILATTN) + return (MSCP_FAILED); + + /* do what autoconf does */ + return (MSCP_FAILED); /* not yet, arwhite, not yet */ +} + +/* + * A drive came on line. Check its type and size. Return DONE if + * we think the drive is truly on line. In any case, awaken anyone + * sleeping on the drive on-line-ness. + */ +udaonline(ui, mp) + register struct uba_device *ui; + struct mscp *mp; +{ + register struct ra_info *ra = &ra_info[ui->ui_unit]; +/* printf("udaonline\n"); */ + wakeup((caddr_t)&ui->ui_flags); + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + if (!cold) + printf("uda%d: ra%d", ui->ui_ctlr, ui->ui_unit); + printf(": attempt to bring on line failed: "); + mscp_printevent(mp); + ra->ra_state = CLOSED; + return (MSCP_FAILED); + } + + ra->ra_state = OPENRAW; + ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; + if (!cold) + printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, + ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); + /* can now compute ncyl */ + ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / + ra->ra_geom.rg_nsectors; + return (MSCP_DONE); +} + +/* + * We got some (configured) unit's status. Return DONE if it succeeded. + */ +udagotstatus(ui, mp) + register struct uba_device *ui; + register struct mscp *mp; +{ +/* printf("udagotstatus\n"); */ + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("uda%d: attempt to get status for ra%d failed: ", + ui->ui_ctlr, ui->ui_unit); + mscp_printevent(mp); + return (MSCP_FAILED); + } + /* record for (future) bad block forwarding and whatever else */ + uda_rasave(ui->ui_unit, mp, 1); + return (MSCP_DONE); +} + +/* + * A transfer failed. We get a chance to fix or restart it. + * Need to write the bad block forwaring code first.... + */ +/*ARGSUSED*/ +udaioerror(ui, mp, bp) + register struct uba_device *ui; + register struct mscp *mp; + struct buf *bp; +{ +/* printf("udaioerror\n"); */ + if (mp->mscp_flags & M_EF_BBLKR) { + /* + * A bad block report. Eventually we will + * restart this transfer, but for now, just + * log it and give up. + */ + log(LOG_ERR, "ra%d: bad block report: %d%s\n", + ui->ui_unit, mp->mscp_seq.seq_lbn, + mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); + } else { + /* + * What the heck IS a `serious exception' anyway? + * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION + * FOR THEIR OWN CONTROLLERS. + */ + if (mp->mscp_flags & M_EF_SEREX) + log(LOG_ERR, "ra%d: serious exception reported\n", + ui->ui_unit); + } + return (MSCP_FAILED); +} + +/* + * A replace operation finished. + */ +/*ARGSUSED*/ +udareplace(ui, mp) + struct uba_device *ui; + struct mscp *mp; +{ + + panic("udareplace"); +} + +/* + * A bad block related operation finished. + */ +/*ARGSUSED*/ +udabb(ui, mp, bp) + struct uba_device *ui; + struct mscp *mp; + struct buf *bp; +{ + + panic("udabb"); +} + + +/* + * I/O controls. + */ +udaioctl(dev, cmd, data, flag) + dev_t dev; + int cmd; + caddr_t data; + int flag; +{ + register int unit = udaunit(dev); + register struct disklabel *lp; + register struct ra_info *ra = &ra_info[unit]; + int error = 0; +/* printf("udaioctl\n"); */ + lp = &udalabel[unit]; + + switch (cmd) { + + case DIOCGDINFO: + *(struct disklabel *)data = *lp; + break; + + case DIOCGPART: + ((struct partinfo *)data)->disklab = lp; + ((struct partinfo *)data)->part = + &lp->d_partitions[udapart(dev)]; + break; + + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else + error = setdisklabel(lp, (struct disklabel *)data, + (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0); + break; + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + error = EBADF; + else + ra->ra_wlabel = *(int *)data; + break; + + case DIOCWDINFO: + if ((flag & FWRITE) == 0) + error = EBADF; + else if ((error = setdisklabel(lp, (struct disklabel *)data, + (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart,0)) == 0) { + int wlab; + + ra->ra_state = OPEN; + /* simulate opening partition 0 so write succeeds */ + ra->ra_openpart |= (1 << 0); /* XXX */ + wlab = ra->ra_wlabel; + ra->ra_wlabel = 1; + error = writedisklabel(dev, udastrategy, lp,0); + ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; + ra->ra_wlabel = wlab; + } + break; + +#ifdef notyet + case UDAIOCREPLACE: + /* + * Initiate bad block replacement for the given LBN. + * (Should we allow modifiers?) + */ + error = EOPNOTSUPP; + break; + + case UDAIOCGMICRO: + /* + * Return the microcode revision for the UDA50 running + * this drive. + */ + *(int *)data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; + break; +#endif + + default: + error = ENOTTY; + break; + } + return (error); +} + +/* + * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) + * on that Unibus, and requeue outstanding I/O. + */ +udareset(uban) + int uban; +{ + register struct uba_ctlr *um; + register struct uda_softc *sc; + register int ctlr; +/* printf("udareset\n"); */ + for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { + if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || + um->um_alive == 0) + continue; + printf(" uda%d", ctlr); + + /* + * Our BDP (if any) is gone; our command (if any) is + * flushed; the device is no longer mapped; and the + * UDA50 is not yet initialised. + */ + if (um->um_bdp) { + printf("<%d>", UBAI_BDP(um->um_bdp)); + um->um_bdp = 0; + } + um->um_ubinfo = 0; + um->um_cmd = 0; + sc->sc_flags &= ~SC_MAPPED; + sc->sc_state = ST_IDLE; + + /* reset queues and requeue pending transfers */ + mscp_requeue(&sc->sc_mi); + + /* + * If it fails to initialise we will notice later and + * try again (and again...). Do not call udastart() + * here; it will be done after the controller finishes + * initialisation. + */ + if (udainit(ctlr)) + printf(" (hung)"); + } +} + +/* + * Watchdog timer: If the controller is active, and no interrupts + * have occurred for 30 seconds, assume it has gone away. + */ +void +udawatch() +{ + register int i; + register struct uba_ctlr *um; + register struct uda_softc *sc; + timeout(udawatch, (caddr_t) 0, hz); /* every second */ + for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { + if ((um = udaminfo[i]) == 0 || !um->um_alive) + continue; + if (sc->sc_state == ST_IDLE) + continue; + if (sc->sc_state == ST_RUN && !um->um_tab.b_active) + sc->sc_wticks = 0; + else if (++sc->sc_wticks >= 30) { + sc->sc_wticks = 0; + printf("uda%d: lost interrupt\n", i); + ubareset(um->um_ubanum); + } + } +} + +/* + * Do a panic dump. We set up the controller for one command packet + * and one response packet, for which we use `struct uda1'. + */ +struct uda1 { + struct uda1ca uda1_ca; /* communications area */ + struct mscp uda1_rsp; /* response packet */ + struct mscp uda1_cmd; /* command packet */ +} uda1; + +#define DBSIZE 32 /* dump 16K at a time */ + +udadump(dev) + dev_t dev; +{ + struct udadevice *udaddr; + struct uda1 *ud_ubaddr; + char *start; + int num, blk, unit, maxsz, blkoff, reg; + struct partition *pp; + struct uba_regs *uba; + struct uba_device *ui; + struct uda1 *ud; + struct pte *io; + int i; + + /* + * Make sure the device is a reasonable place on which to dump. + */ + unit = udaunit(dev); + if (unit >= NRA) + return (ENXIO); +#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) + ui = phys(struct uba_device *, udadinfo[unit]); + if (ui == NULL || ui->ui_alive == 0) + return (ENXIO); + + /* + * Find and initialise the UBA; get the physical address of the + * device registers, and of communications area and command and + * response packet. + */ + uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; + ubainit(uba); + udaddr = (struct udadevice *)ui->ui_physaddr; + ud = phys(struct uda1 *, &uda1); +printf("H{r.\n"); + /* + * Map the ca+packets into Unibus I/O space so the UDA50 can get + * at them. Use the registers at the end of the Unibus map (since + * we will use the registers at the beginning to map the memory + * we are dumping). + */ + num = btoc(sizeof(struct uda1)) + 1; + reg = NUBMREG - num; + io = (void *)&uba->uba_map[reg]; + for (i = 0; i < num; i++) + *(int *)io++ = UBAMR_MRV | (vax_btop(ud) + i); + ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); + + /* + * Initialise the controller, with one command and one response + * packet. + */ + udaddr->udaip = 0; + if (udadumpwait(udaddr, UDA_STEP1)) + return (EFAULT); + udaddr->udasa = UDA_ERR; + if (udadumpwait(udaddr, UDA_STEP2)) + return (EFAULT); + udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; + if (udadumpwait(udaddr, UDA_STEP3)) + return (EFAULT); + udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; + if (udadumpwait(udaddr, UDA_STEP4)) + return (EFAULT); + uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; + udaddr->udasa = UDA_GO; + + /* + * Set up the command and response descriptor, then set the + * controller characteristics and bring the drive on line. + * Note that all uninitialised locations in uda1_cmd are zero. + */ + ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; + ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; + /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ + /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ + if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) + return (EFAULT); + ud->uda1_cmd.mscp_unit = ui->ui_slave; + if (udadumpcmd(M_OP_ONLINE, ud, ui)) + return (EFAULT); + + pp = phys(struct partition *, + &udalabel[unit].d_partitions[udapart(dev)]); + maxsz = pp->p_size; + blkoff = pp->p_offset; + + /* + * Dump all of physical memory, or as much as will fit in the + * space provided. + */ + start = 0; + printf("Dumpar {r inte implementerade {n :) \n"); + asm("halt"); +/* num = maxfree; */ + if (dumplo + num >= maxsz) + num = maxsz - dumplo; + blkoff += dumplo; + + /* + * Write out memory, DBSIZE pages at a time. + * N.B.: this code depends on the fact that the sector + * size == the page size. + */ + while (num > 0) { + blk = num > DBSIZE ? DBSIZE : num; + io = (void *)uba->uba_map; + /* + * Map in the pages to write, leaving an invalid entry + * at the end to guard against wild Unibus transfers. + * Then do the write. + */ + for (i = 0; i < blk; i++) + *(int *)io++ = UBAMR_MRV | (vax_btop(start) + i); + *(int *)io = 0; + ud->uda1_cmd.mscp_unit = ui->ui_slave; + ud->uda1_cmd.mscp_seq.seq_lbn = vax_btop(start) + blkoff; + ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; + if (udadumpcmd(M_OP_WRITE, ud, ui)) + return (EIO); + start += blk << PGSHIFT; + num -= blk; + } + return (0); /* made it! */ +} + +/* + * Wait for some of the bits in `bits' to come on. If the error bit + * comes on, or ten seconds pass without response, return true (error). + */ +udadumpwait(udaddr, bits) + register struct udadevice *udaddr; + register int bits; +{ + register int timo = todr() + 1000; + + while ((udaddr->udasa & bits) == 0) { + if (udaddr->udasa & UDA_ERR) { + printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); + return (1); + } + if (todr() >= timo) { + printf("timeout\ndump "); + return (1); + } + } + return (0); +} + +/* + * Feed a command to the UDA50, wait for its response, and return + * true iff something went wrong. + */ +udadumpcmd(op, ud, ui) + int op; + register struct uda1 *ud; + struct uba_device *ui; +{ + volatile struct udadevice *udaddr; + volatile int n; +#define mp (&ud->uda1_rsp) + + udaddr = (struct udadevice *)ui->ui_physaddr; + ud->uda1_cmd.mscp_opcode = op; + ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; + ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; + ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; + ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; + if (udaddr->udasa & UDA_ERR) { + printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); + return (1); + } + n = udaddr->udaip; + n = todr() + 1000; + for (;;) { + if (todr() > n) { + printf("timeout\ndump "); + return (1); + } + if (ud->uda1_ca.ca_cmdint) + ud->uda1_ca.ca_cmdint = 0; + if (ud->uda1_ca.ca_rspint == 0) + continue; + ud->uda1_ca.ca_rspint = 0; + if (mp->mscp_opcode == (op | M_OP_END)) + break; + printf("\n"); + switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { + + case MSCPT_SEQ: + printf("sequential"); + break; + + case MSCPT_DATAGRAM: + mscp_decodeerror("uda", ui->ui_ctlr, mp); + printf("datagram"); + break; + + case MSCPT_CREDITS: + printf("credits"); + break; + + case MSCPT_MAINTENANCE: + printf("maintenance"); + break; + + default: + printf("unknown (type 0x%x)", + MSCP_MSGTYPE(mp->mscp_msgtc)); + break; + } + printf(" ignored\ndump "); + ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; + } + if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { + printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, + mp->mscp_opcode, mp->mscp_status); + return (1); + } + return (0); +#undef mp +} + +/* + * Return the size of a partition, if known, or -1 if not. + */ +udasize(dev) + dev_t dev; +{ + register int unit = udaunit(dev); + register struct uba_device *ui; + + if (unit >= NRA || (ui = udadinfo[unit]) == NULL || + ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || + ra_info[unit].ra_state != OPEN) + return (-1); + return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size); +} + +#ifdef COMPAT_42 +/* + * Tables mapping unlabelled drives. + */ +struct size { + daddr_t nblocks; + daddr_t blkoff; +} ra60_sizes[8] = { + 15884, 0, /* A=sectors 0 thru 15883 */ + 33440, 15884, /* B=sectors 15884 thru 49323 */ + 400176, 0, /* C=sectors 0 thru 400175 */ + 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ + 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ + 350852, 49324, /* F=sectors 49324 thru 400175 */ + 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ + 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ +}, ra70_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 33440, 15972, /* B=blk 15972 thru 49323 */ + -1, 0, /* C=blk 0 thru end */ + 15884, 341220, /* D=blk 341220 thru 357103 */ + 55936, 357192, /* E=blk 357192 thru 413127 */ + -1, 413457, /* F=blk 413457 thru end */ + -1, 341220, /* G=blk 341220 thru end */ + 291346, 49731, /* H=blk 49731 thru 341076 */ +}, ra80_sizes[8] = { + 15884, 0, /* A=sectors 0 thru 15883 */ + 33440, 15884, /* B=sectors 15884 thru 49323 */ + 242606, 0, /* C=sectors 0 thru 242605 */ + 0, 0, /* D=unused */ + 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ + 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ + 192696, 49910, /* G=sectors 49910 thru 242605 */ + 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ +}, ra81_sizes[8] ={ +/* + * These are the new standard partition sizes for ra81's. + * An RA_COMPAT system is compiled with D, E, and F corresponding + * to the 4.2 partitions for G, H, and F respectively. + */ +#ifndef UCBRA + 15884, 0, /* A=sectors 0 thru 15883 */ + 66880, 16422, /* B=sectors 16422 thru 83301 */ + 891072, 0, /* C=sectors 0 thru 891071 */ +#ifdef RA_COMPAT + 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ + 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ + 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ +#else + 15884, 375564, /* D=sectors 375564 thru 391447 */ + 307200, 391986, /* E=sectors 391986 thru 699185 */ + 191352, 699720, /* F=sectors 699720 thru 891071 */ +#endif RA_COMPAT + 515508, 375564, /* G=sectors 375564 thru 891071 */ + 291346, 83538, /* H=sectors 83538 thru 374883 */ + +/* + * These partitions correspond to the sizes used by sites at Berkeley, + * and by those sites that have received copies of the Berkeley driver + * with deltas 6.2 or greater (11/15/83). + */ +#else UCBRA + + 15884, 0, /* A=sectors 0 thru 15883 */ + 33440, 15884, /* B=sectors 15884 thru 49323 */ + 891072, 0, /* C=sectors 0 thru 891071 */ + 15884, 242606, /* D=sectors 242606 thru 258489 */ + 307200, 258490, /* E=sectors 258490 thru 565689 */ + 325382, 565690, /* F=sectors 565690 thru 891071 */ + 648466, 242606, /* G=sectors 242606 thru 891071 */ + 193282, 49324, /* H=sectors 49324 thru 242605 */ + +#endif UCBRA +}, ra82_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 66880, 16245, /* B=blk 16245 thru 83124 */ + -1, 0, /* C=blk 0 thru end */ + 15884, 375345, /* D=blk 375345 thru 391228 */ + 307200, 391590, /* E=blk 391590 thru 698789 */ + -1, 699390, /* F=blk 699390 thru end */ + -1, 375345, /* G=blk 375345 thru end */ + 291346, 83790, /* H=blk 83790 thru 375135 */ +}, ra90_sizes[8] = { + 15884, 0, /* A=sectors 0 thru 15883 */ + 66880, 16146, /* B=sectors 16146 thru 83025 */ + 2376153,0, /* C=sectors 0 thru 2376152 */ + 15884, 374946, /* D=sectors 374946 thru 390829 */ + 307200, 391092, /* E=sectors 391092 thru 698291 */ + 1677390,698763, /* F=sectors 698763 thru 2376152 */ + 2001207,374946, /* G=sectors 374946 thru 2376152 */ + 291346, 83421, /* H=sectors 83421 thru 374766 */ +}, ra92_sizes[8] = { + 15884, 0, /* A=sectors 0 thru 15883 */ + 66880, 16146, /* B=sectors 16146 thru 83025 */ + 2941263,0, /* C=sectors 0 thru 2941262 */ + 15884, 374946, /* D=sectors 374946 thru 390829 */ + 307200, 391092, /* E=sectors 391092 thru 698291 */ + 2242500,698763, /* F=sectors 698763 thru 2941262 */ + 2566317,374946, /* G=sectors 374946 thru 2941262 */ + 291346, 83421, /* H=sectors 83421 thru 374766 */ +}, rc25_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 10032, 15884, /* B=blk 15884 thru 49323 */ + -1, 0, /* C=blk 0 thru end */ + 0, 0, /* D=blk 340670 thru 356553 */ + 0, 0, /* E=blk 356554 thru 412489 */ + 0, 0, /* F=blk 412490 thru end */ + -1, 25916, /* G=blk 49324 thru 131403 */ + 0, 0, /* H=blk 131404 thru end */ +}, rd52_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 9766, 15884, /* B=blk 15884 thru 25649 */ + -1, 0, /* C=blk 0 thru end */ + 0, 0, /* D=unused */ + 0, 0, /* E=unused */ + 0, 0, /* F=unused */ + -1, 25650, /* G=blk 25650 thru end */ + 0, 0, /* H=unused */ +}, rd53_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 33440, 15884, /* B=blk 15884 thru 49323 */ + -1, 0, /* C=blk 0 thru end */ + 0, 0, /* D=unused */ + 33440, 0, /* E=blk 0 thru 33439 */ + -1, 33440, /* F=blk 33440 thru end */ + -1, 49324, /* G=blk 49324 thru end */ + -1, 15884, /* H=blk 15884 thru end */ +}, rd54_sizes[8] = { + 15884, 0, /* A=blk 0 thru 15883 */ + 33440, 15884, /* B=blk 15884 thru 49323 */ + -1, 0, /* C=blk 0 thru end */ + 130938, 49324, /* D=blk 49324 thru 180261 */ + 130938, 180262, /* E=blk 180262 thru 311199 (end) */ + 0, 0, /* F=unused */ + 261876, 49324, /* G=blk 49324 thru 311199 (end) */ + 0, 0, /* H=unused */ +}, rx50_sizes[8] = { + 800, 0, /* A=blk 0 thru 799 */ + 0, 0, + -1, 0, /* C=blk 0 thru end */ + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, +}; + +/* + * Media ID decoding table. + */ +struct udatypes { + u_long ut_id; /* media drive ID */ + char *ut_name; /* drive type name */ + struct size *ut_sizes; /* partition tables */ + int ut_nsectors, ut_ntracks, ut_ncylinders; +} udatypes[] = { + { MSCP_MKDRIVE2('R', 'A', 60), "ra60", ra60_sizes, 42, 4, 2382 }, + { MSCP_MKDRIVE2('R', 'A', 70), "ra70", ra70_sizes, 33, 11, 1507 }, + { MSCP_MKDRIVE2('R', 'A', 80), "ra80", ra80_sizes, 31, 14, 559 }, + { MSCP_MKDRIVE2('R', 'A', 81), "ra81", ra81_sizes, 51, 14, 1248 }, + { MSCP_MKDRIVE2('R', 'A', 82), "ra82", ra82_sizes, 57, 15, 1423 }, + { MSCP_MKDRIVE2('R', 'A', 90), "ra90", ra90_sizes, 69, 13, 2649 }, + { MSCP_MKDRIVE2('R', 'A', 92), "ra92", ra92_sizes, 69, 13, 3279 }, + { MSCP_MKDRIVE2('R', 'C', 25), "rc25-removable", + rc25_sizes, 42, 4, 302 }, + { MSCP_MKDRIVE3('R', 'C', 'F', 25), "rc25-fixed", + rc25_sizes, 42, 4, 302 }, + { MSCP_MKDRIVE2('R', 'D', 52), "rd52", rd52_sizes, 18, 7, 480 }, + { MSCP_MKDRIVE2('R', 'D', 53), "rd53", rd53_sizes, 17, 8, 1019 }, + { MSCP_MKDRIVE2('R', 'D', 32), "rd54-from-rd32", + rd54_sizes, 17, 15, 1220 }, + { MSCP_MKDRIVE2('R', 'D', 54), "rd54", rd54_sizes, 17, 15, 1220 }, + { MSCP_MKDRIVE2('R', 'X', 50), "rx50", rx50_sizes, 10, 1, 80 }, + 0 +}; + +#define NTYPES (sizeof(udatypes) / sizeof(*udatypes)) + +udamaptype(unit, lp) + int unit; + register struct disklabel *lp; +{ + register struct udatypes *ut; + register struct size *sz; + register struct partition *pp; + register char *p; + register int i; + register struct ra_info *ra = &ra_info[unit]; + + i = MSCP_MEDIA_DRIVE(ra->ra_mediaid); + for (ut = udatypes; ut->ut_id; ut++) + if (ut->ut_id == i && + ut->ut_nsectors == ra->ra_geom.rg_nsectors && + ut->ut_ntracks == ra->ra_geom.rg_ntracks && + ut->ut_ncylinders == ra->ra_geom.rg_ncyl) + goto found; + + /* not one we know; fake up a label for the whole drive */ + uda_makefakelabel(ra, lp); + i = ra->ra_mediaid; /* print the port type too */ + addlog(": no partition table for %c%c %c%c%c%d, size %d;\n\ +using (s,t,c)=(%d,%d,%d)", + MSCP_MID_CHAR(4, i), MSCP_MID_CHAR(3, i), + MSCP_MID_CHAR(2, i), MSCP_MID_CHAR(1, i), + MSCP_MID_CHAR(0, i), MSCP_MID_NUM(i), lp->d_secperunit, + lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); + if (!cold) + addlog("\n"); + return (0); +found: + p = ut->ut_name; + for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) + lp->d_typename[i] = *p++; + lp->d_typename[i] = 0; + sz = ut->ut_sizes; + lp->d_nsectors = ut->ut_nsectors; + lp->d_ntracks = ut->ut_ntracks; + lp->d_ncylinders = ut->ut_ncylinders; + lp->d_npartitions = 8; + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; + for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { + pp->p_offset = sz->blkoff; + if ((pp->p_size = sz->nblocks) == (u_long)-1) + pp->p_size = ra->ra_dsize - sz->blkoff; + } + return (1); +} +#endif /* COMPAT_42 */ + +/* + * Construct a label for a drive from geometry information + * if we have no better information. + */ +uda_makefakelabel(ra, lp) + register struct ra_info *ra; + register struct disklabel *lp; +{ + lp->d_nsectors = ra->ra_geom.rg_nsectors; + lp->d_ntracks = ra->ra_geom.rg_ntracks; + lp->d_ncylinders = ra->ra_geom.rg_ncyl; + lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; + bcopy("ra??", lp->d_typename, sizeof("ra??")); + lp->d_npartitions = 1; + lp->d_partitions[0].p_offset = 0; + lp->d_partitions[0].p_size = lp->d_secperunit; +} +#endif /* NUDA > 0 */ diff --git a/sys/arch/vax/uba/udareg.h b/sys/arch/vax/uba/udareg.h new file mode 100644 index 00000000000..f6107a49605 --- /dev/null +++ b/sys/arch/vax/uba/udareg.h @@ -0,0 +1,107 @@ +/* $NetBSD: udareg.h,v 1.2 1994/10/26 08:02:51 cgd Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udareg.h 7.3 (Berkeley) 5/8/91 + */ + +/* + * UDA50 registers and structures + */ + +/* + * Writing any value to udaip starts initialisation. Reading from it + * when the UDA is running makes the UDA look through the command ring + * to find any new commands. Reading udasa gives status; writing it + * during initialisation sets things up. + */ +struct udadevice { + u_short udaip; /* initialisation and polling */ + u_short udasa; /* status and address */ +}; + +/* + * Bits in UDA status register during initialisation + */ +#define UDA_ERR 0x8000 /* error */ +#define UDA_STEP4 0x4000 /* step 4 has started */ +#define UDA_STEP3 0x2000 /* step 3 has started */ +#define UDA_STEP2 0x1000 /* step 2 has started */ +#define UDA_STEP1 0x0800 /* step 1 has started */ +#define UDA_NV 0x0400 /* no host settable interrupt vector */ +#define UDA_QB 0x0200 /* controller supports Q22 bus */ +#define UDA_DI 0x0100 /* controller implements diagnostics */ +#define UDA_IE 0x0080 /* interrupt enable */ +#define UDA_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */ +#define UDA_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */ +#define UDA_PI 0x0001 /* host requests adapter purge interrupts */ + +/* + * Bits in UDA status register after initialisation + */ +#define UDA_GO 0x0001 /* run */ + +#define UDASR_BITS \ +"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO" + +/* + * UDA Communications Area. Note that this structure definition + * requires NRSP and NCMD to be defined already. + */ +struct udaca { + short ca_xxx1; /* unused */ + char ca_xxx2; /* unused */ + char ca_bdp; /* BDP to purge */ + short ca_cmdint; /* command ring transition flag */ + short ca_rspint; /* response ring transition flag */ + long ca_rspdsc[NRSP];/* response descriptors */ + long ca_cmddsc[NCMD];/* command descriptors */ +}; + +/* + * Simplified routines (e.g., uddump) reprogram the UDA50 for one command + * and one response at a time; uda1ca is like udaca except that it provides + * exactly one command and response descriptor. + */ +struct uda1ca { + short ca_xxx1; + char ca_xxx2; + char ca_bdp; + short ca_cmdint; + short ca_rspint; + long ca_rspdsc; + long ca_cmddsc; +}; diff --git a/sys/arch/vax/vax/autoconf.c b/sys/arch/vax/vax/autoconf.c new file mode 100644 index 00000000000..9967b2de7ef --- /dev/null +++ b/sys/arch/vax/vax/autoconf.c @@ -0,0 +1,339 @@ +/* $NetBSD: autoconf.c,v 1.4 1995/06/05 16:26:23 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#include "sys/param.h" +#include "machine/cpu.h" +#include "machine/sid.h" +#include "machine/loconf.h" +#include "sys/types.h" +#include "sys/device.h" +#include "sys/reboot.h" +#include "sys/conf.h" +#include "machine/param.h" +#include "machine/vmparam.h" +#include "machine/nexus.h" +#include "machine/../vax/gencons.h" +#include "vm/vm.h" + +#define BACKPLANE 0 +#define BIBUSS 1 +#define SBIBUSS 2 +struct bp_conf { + char *type; + int num; + int partyp; +}; + +extern int cold; + +int cpu_notsupp(),cpu_notgen(); +#ifdef VAX750 +int ka750_mchk(),ka750_memerr(),ka750_clock(),ka750_conf(); +int nexty750[]={ NEX_MEM16, NEX_MEM16, NEX_MEM16, NEX_MEM16, + NEX_MBA, NEX_MBA, NEX_MBA, NEX_MBA, + NEX_UBA0, NEX_UBA1, NEX_ANY, NEX_ANY, + NEX_ANY, NEX_ANY, NEX_ANY, NEX_ANY}; +#endif +#if VAX730 +int nexty730[NNEX730] = { + NEX_MEM16, NEX_ANY, NEX_ANY, NEX_ANY, + NEX_ANY, NEX_ANY, NEX_ANY, NEX_ANY, +}; +#endif +#if VAX630 +int uvaxII_mchk(), uvaxII_memerr(), uvaxII_clock(), uvaxII_conf(); +#endif + +struct cpu_dep cpu_calls[VAX_MAX+1]={ + /* Type 0,noexist */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#ifdef VAX780 /* Type 1, 11/{780,782,785} */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX750 /* Type 2, 11/750 */ + cpu_notgen,ka750_clock,ka750_mchk,ka750_memerr,ka750_conf, +#else + cpu_notgen,cpu_notgen,cpu_notgen,cpu_notgen,cpu_notgen, +#endif +#ifdef VAX730 /* Type 3, 11/{730,725}, ceauciesco-vax */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX8600 /* Type 4, 8600/8650 (11/{790,795}) */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX8200 /* Type 5, 8200, 8300, 8350 */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX8800 /* Type 6, 85X0, 8700, 88X0 */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX610 /* Type 7, KA610 */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +#ifdef VAX630 /* Type 8, KA630 or KA410 (uVAX II) */ + cpu_notgen,uvaxII_clock,uvaxII_mchk,uvaxII_memerr,uvaxII_conf, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif + /* Type 9, not used */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#ifdef VAX650 /* Type 10, KA65X (uVAX III) */ + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#else + cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp,cpu_notsupp, +#endif +}; + +cpu_notgen() +{ + conout("This cputype not generated.\n"); + asm("halt"); +} +cpu_notsupp() +{ + conout("This cputype not supported.\n"); + asm("halt"); +} + +configure() +{ + extern int boothowto; + + + if (!config_rootfound("backplane", NULL)) + panic("backplane not configured"); + +#if GENERIC + if ((boothowto & RB_ASKNAME) == 0) + setroot(); + setconf(); +#else + setroot(); +#endif + /* + * Configure swap area and related system + * parameter based on device(s) used. + */ + gencnslask(); /* XXX inte g|ras h{r */ + swapconf(); + cold=0; + mtpr(GC_CCF, PR_TXDB); /* Clear cold start flag in cpu */ +} + + +int +printut(aux, hej) + void *aux; + char *hej; +{ + if(hej) printf("printut %s\n",hej); + return(UNSUPP); +} + +int +backplane_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + if(cf->cf_unit==0&&strcmp(cf->cf_driver->cd_name,"backplane")==0) + return 1; /* First (and only) backplane */ + + return(0); +} + +void +backplane_attach(parent, self, hej) + struct device *parent, *self; + void *hej; +{ + struct bp_conf bp; + int i,ccpu,cmem,cbi,csbi; + + printf("\n"); + + switch(cpunumber){ + case VAX_750: + case VAX_78032: + cmem=cbi=0; + ccpu=csbi=1; + break; + } + + bp.partyp=BACKPLANE; + bp.type="cpu"; + for(i=0;i<ccpu;i++){ + bp.num=i; + config_found(self, &bp, printut); + } + bp.type="mem"; + for(i=0;i<cmem;i++){ + bp.num=i; + config_found(self, &bp, printut); + } + bp.type="bi"; + for(i=0;i<cbi;i++){ + bp.num=i; + config_found(self, &bp, printut); + } + bp.type="sbi"; + for(i=0;i<csbi;i++){ + bp.num=i; + config_found(self, &bp, printut); + } +} + +int +cpu_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct bp_conf *bp=aux; + + if(strcmp(cf->cf_driver->cd_name,"cpu")) + return 0; + + switch (cpunumber) { +#ifdef VAX750 + case VAX_750: + if(cf->cf_unit==0&&bp->partyp==BACKPLANE) + return 1; + break; +#endif +#ifdef VAX630 + case VAX_78032: + if(cf->cf_unit==0&&bp->partyp==BACKPLANE) + return 1; + break; +#endif + }; + + return 0; +} + +void +cpu_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + extern int cpu_type; + extern char cpu_model[]; + + switch (cpunumber) { +#ifdef VAX750 + case VAX_750: + printf(": 11/750, hardware rev %d, ucode rev %d\n", + V750HARDW(cpu_type), V750UCODE(cpu_type)); + printf("cpu0 at backplane0: "); + if(mfpr(PR_ACCS)&0xff){ + printf("FPA present, enabling\n"); + mtpr(0x8000,PR_ACCS); + } else printf("no FPA\n"); + strcpy(cpu_model,"VAX 11/750"); + break; +#endif +#if VAX630 + case VAX_78032: + printf(": MicroVAXII CPU\n"); + strcpy(cpu_model, "MicroVAX 78032/78132"); + break; +#endif + }; +} + +int nmcr=0; + +int +mem_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct sbi_attach_args *sa=(struct sbi_attach_args *)aux; + + if((cf->cf_loc[0]!=sa->nexnum)&&(cf->cf_loc[0]>-1)) + return 0; /* memory doesn't match spec's */ + switch(sa->type){ + case NEX_MEM16: + return 1; + } + return 0; +} + +void +mem_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct sbi_attach_args *sa=(struct sbi_attach_args *)aux; + + switch(cpunumber){ +#ifdef VAX750 + case VAX_750: + ka750_memenable(sa,self); + break; +#endif + + default: + break; + } + +} + +struct cfdriver backplanecd = + { 0, "backplane", backplane_match, backplane_attach, + DV_DULL, sizeof(struct device) }; + +struct cfdriver cpucd = + { 0, "cpu", cpu_match, cpu_attach, DV_CPU, sizeof(struct device) }; + + +struct cfdriver memcd = + { 0, "mem", mem_match, mem_attach, DV_CPU, sizeof(struct device) }; + + diff --git a/sys/arch/vax/vax/clock.c b/sys/arch/vax/vax/clock.c new file mode 100644 index 00000000000..96539e5c4db --- /dev/null +++ b/sys/arch/vax/vax/clock.c @@ -0,0 +1,210 @@ +/* $NetBSD: clock.c,v 1.7.2.1 1995/10/15 14:17:17 ragge Exp $ */ +/* + * Copyright (c) 1995 Ludd, University of Lule}, Sweden. + * 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 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. + */ + + +#include <sys/param.h> +#include <sys/kernel.h> + +#include "machine/mtpr.h" +#include "machine/sid.h" + +#define SEC_PER_DAY (60*60*24) + +extern int todrstopped; + +static unsigned long year; /* start of current year in seconds */ +static unsigned long year_len; /* length of current year in 100th of seconds */ + +/* + * microtime() should return number of usecs in struct timeval. + * We may get wrap-arounds, but that will be fixed with lasttime + * check. This may fault within 10 msecs. + */ +void +microtime(tvp) + struct timeval *tvp; +{ + u_int int_time, tmp_year; + int s, i; + static struct timeval lasttime; + + s = splhigh(); + int_time = mfpr(PR_TODR); + + asm ("movc3 %0,(%1),(%2)" + : + : "r" (sizeof(struct timeval)),"r" (&time),"r"(tvp) + :"r0","r1","r2","r3","r4","r5"); + + i = mfpr(PR_ICR) + tick; /* Get current interval count */ + tvp->tv_usec += i; + while (tvp->tv_usec > 1000000) { + tvp->tv_sec++; + tvp->tv_usec -= 1000000; + } + if (tvp->tv_sec == lasttime.tv_sec && + tvp->tv_usec <= lasttime.tv_usec && + (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { + tvp->tv_sec++; + tvp->tv_usec -= 1000000; + } + bcopy(tvp, &lasttime, sizeof(struct timeval)); + if (int_time > year_len) { + mtpr(mfpr(PR_TODR) - year_len, PR_TODR); + year += year_len / 100; + tmp_year = year / SEC_PER_DAY / 365 + 2; + year_len = 100 * SEC_PER_DAY * + ((tmp_year % 4 && tmp_year != 32) ? 365 : 366); + } + splx(s); +} + +/* + * Sets year to the year in fs_time and then calculates the number of + * 100th of seconds in the current year and saves that info in year_len. + * fs_time contains the time set in the superblock in the root filesystem. + * If the clock is started, it then checks if the time is valid + * compared with the time in fs_time. If the clock is stopped, an + * alert is printed and the time is temporary set to the time in fs_time. + */ + +void +inittodr(fs_time) + time_t fs_time; +{ + + unsigned long tmp_year, sluttid, year_ticks; + int clock_stopped; + + sluttid = fs_time; + year = (fs_time / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY; + tmp_year = year / SEC_PER_DAY / 365 + 2; + year_len = 100 * SEC_PER_DAY * + ((tmp_year % 4 && tmp_year != 32) ? 365 : 366); + + switch (cpunumber) { +#if VAX750 + case VAX_750: + year_ticks = mfpr(PR_TODR); + clock_stopped = todrstopped; + break; +#endif +#if VAX630 || VAX410 + case VAX_78032: + year_ticks = uvaxII_gettodr(&clock_stopped); + break; +#endif + default: + year_ticks = 0; + clock_stopped = 1; + }; + + if (clock_stopped){ + printf( + "Internal clock not started. Using time from file system.\n"); + switch (cpunumber) { +#if VAX750 + case VAX_750: + /*+1 so the clock won't be stopped */ + mtpr((fs_time - year) * 100 + 1, PR_TODR); + break; +#endif +#if VAX630 || VAX410 + case VAX_78032: + uvaxII_settodr((fs_time - year) * 100 + 1); + break; +#endif + }; + todrstopped = 0; + } else if (year_ticks / 100 > fs_time - year + SEC_PER_DAY * 3) { + printf( + "WARNING: Clock has gained %d days - CHECK AND RESET THE DATE.\n", + (year_ticks / 100 - (fs_time - year)) / SEC_PER_DAY); + sluttid = year + (year_ticks / 100); + } else if (year_ticks / 100 < fs_time - year) { + printf( + "WARNING: Clock has lost time - CHECK AND RESET THE DATE.\n"); + } else sluttid = year + (year_ticks / 100); + time.tv_sec = sluttid; +} + +/* + * Resettodr restores the time of day hardware after a time change. + */ + +void +resettodr() +{ + + unsigned long tmp_year; + + year = (time.tv_sec / SEC_PER_DAY / 365) * 365 * SEC_PER_DAY; + tmp_year = year / SEC_PER_DAY / 365 + 2; + year_len = 100 * SEC_PER_DAY * + ((tmp_year % 4 && tmp_year != 32) ? 365 : 366); + switch (cpunumber) { +#if VAX750 + case VAX_750: + mtpr((time.tv_sec - year) * 100 + 1, PR_TODR); + break; +#endif +#if VAX630 || VAX410 + case VAX_78032: + uvaxII_settodr((time.tv_sec - year) * 100 + 1); + break; +#endif + }; + todrstopped = 0; +} + +/* + * Unfortunately the 78032 cpu chip (MicroVAXII cpu) does not have a functional + * todr register, so this function is necessary. + * (the x and y variables are used to confuse the optimizer enough to ensure + * that the code actually loops:-) + */ +int +todr() +{ + int delaycnt, x = 4, y = 4; + static int todr_val; + + if (cpunumber != VAX_78032) + return (mfpr(PR_TODR)); + + /* + * Loop for approximately 10msec and then return todr_val + 1. + */ + delaycnt = 5000; + while (delaycnt > 0) + delaycnt = delaycnt - x + 3 + y - 4; + return (++todr_val); +} diff --git a/sys/arch/vax/vax/conf.c b/sys/arch/vax/vax/conf.c new file mode 100644 index 00000000000..483a5848457 --- /dev/null +++ b/sys/arch/vax/vax/conf.c @@ -0,0 +1,469 @@ +/* $NetBSD: conf.c,v 1.14 1995/08/17 17:41:05 thorpej Exp $ */ + +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)conf.c 7.18 (Berkeley) 5/9/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/conf.h> +#include <sys/vnode.h> + +int ttselect __P((dev_t, int, struct proc *)); + +#ifndef LKM +#define lkmenodev enodev +#else +int lkmenodev(); +#endif + +#include "hp.h" /* 0 */ +bdev_decl(hp); + +#include "tu.h" +bdev_decl(ht); + +#include "rk.h" +bdev_decl(rk); + +bdev_decl(sw); + +#include "te.h" +bdev_decl(tm); + +#include "tmscp.h" +bdev_decl(tmscp); + +#include "ts.h" +bdev_decl(ts); + +#include "mu.h" +bdev_decl(mt); + +#if 0 /* defined(VAX750) || defined(VAX730) */ +#define NCTU 1 +#else +#define NCTU 0 +#endif +bdev_decl(tu); + +#include "uda.h" +bdev_decl(uda); + +#include "kdb.h" +bdev_decl(kdb); + +#include "up.h" +bdev_decl(up); + +#include "tj.h" +bdev_decl(ut); + +#include "rb.h" +bdev_decl(idc); + +#include "rx.h" +bdev_decl(rx); + +#include "uu.h" +bdev_decl(uu); + +#include "rl.h" +bdev_decl(rl); + +#include "ccd.h" +bdev_decl(ccd); + +struct bdevsw bdevsw[] = +{ + bdev_disk_init(NHP,hp), /* 0: RP0?/RM0? */ + bdev_tape_init(NTU,ht), /* 1: TU77 w/ TM03 */ + bdev_disk_init(NUP,up), /* 2: SC-21/SC-31 */ + bdev_disk_init(NRK,rk), /* 3: RK06/07 */ + bdev_swap_init(1,sw), /* 4: swap pseudo-device */ + bdev_tape_init(NTE,tm), /* 5: TM11/TE10 */ + bdev_tape_init(NTS,ts), /* 6: TS11 */ + bdev_tape_init(NMU,mt), /* 7: TU78 */ + bdev_tape_init(NCTU,tu), /* 8: Console TU58 on 730/750 */ + bdev_disk_init(NUDA,uda), /* 9: UDA50/RA?? */ + bdev_tape_init(NTJ,ut), /* 10: TU45 */ + bdev_disk_init(NRB,idc), /* 11: IDC (RB730) */ + bdev_disk_init(NRX,rx), /* 12: RX01/02 on unibus */ + bdev_disk_init(NUU,uu), /* 13: TU58 on DL11 */ + bdev_disk_init(NRL,rl), /* 14: RL01/02 */ + bdev_tape_init(NTMSCP,tmscp), /* 15: TMSCP tape */ + bdev_disk_init(NKDB,kdb), /* 16: KDB50/RA?? */ + bdev_disk_init(NCCD,ccd), /* 17: concatenated disk driver */ +}; +int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + +/* + * Console routines for VAX console. There are always an generic console, + * but maybe we should care about RD, QDSS etc? + */ +#include <dev/cons.h> + +#define gencnpollc nullcnpollc +cons_decl(gen); + +struct consdev constab[]={ +/* Generic console, should always be present */ + cons_init(gen), + +#ifdef notyet +/* We may not always use builtin console, sometimes RD */ + { rdcnprobe, rdcninit, rdcngetc, rdcnputc }, +#endif + { 0 } +}; + +/* Special for console storage */ +#define dev_type_rw(n) int n __P((dev_t, int, int, struct proc *)) + +/* plotters - open, close, write, ioctl, select */ +#define cdev_plotter_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev } + +/* console mass storage - open, close, read/write */ +#define cdev_cnstore_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \ + (dev_type_mmap((*))) enodev } + +#define cdev_lp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), (dev_type_ioctl((*))) enodev, \ + (dev_type_stop((*))) enodev, 0, seltrue, (dev_type_mmap((*))) enodev } + +/* graphic display adapters */ +#define cdev_graph_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev } + +/* Ingres */ +#define cdev_ingres_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) nullop, \ + (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) nullop, 0, (dev_type_select((*))) nullop, \ + (dev_type_mmap((*))) enodev } + + + +cdev_decl(cn); +cdev_decl(ctty); +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); +cdev_decl(sw); +#include "pty.h" +#define ptstty ptytty +#define ptsioctl ptyioctl +cdev_decl(pts); +#define ptctty ptytty +#define ptcioctl ptyioctl +cdev_decl(ptc); +cdev_decl(log); +#ifdef LKM +#define NLKM 1 +#else +#define NLKM 0 +#endif +cdev_decl(lkm); + +cdev_decl(hp); +cdev_decl(rk); +cdev_decl(tm); +cdev_decl(tmscp); +cdev_decl(ts); +cdev_decl(mt); +cdev_decl(uda); +cdev_decl(up); +cdev_decl(ut); +cdev_decl(idc); +cdev_decl(fd); +cdev_decl(gencn); +cdev_decl(rx); +cdev_decl(rl); +cdev_decl(kdb); +cdev_decl(ccd); + +#include "ct.h" +cdev_decl(ct); +#include "dh.h" +cdev_decl(dh); +#include "dmf.h" +cdev_decl(dmf); + +#include "np.h" +cdev_decl(np); + +#if VAX8600 +#define NCRL 1 +#else +#define NCRL 0 +#endif +#define crlread crlrw +#define crlwrite crlrw +cdev_decl(crl); + +#if VAX8200 +#define NCRX 1 +#else +#define NCRX 0 +#endif +#define crxread crxrw +#define crxwrite crxrw +cdev_decl(crx); + +#if VAX780 +#define NFL 1 +#else +#define NFL 0 +#endif +#define flread flrw +#define flwrite flrw +cdev_decl(fl); + +#include "dz.h" +cdev_decl(dz); + +#include "vp.h" +cdev_decl(vp); + +#include "lp.h" +cdev_decl(lp); + +#include "va.h" +cdev_decl(va); + +#include "lpa.h" +cdev_decl(lpa); + +#include "dn.h" +cdev_decl(dn); + +#include "ik.h" +cdev_decl(ik); + +#include "ps.h" +cdev_decl(ps); + +#include "ad.h" +cdev_decl(ad); + +#include "dhu.h" +cdev_decl(dhu); + +#include "dmz.h" +cdev_decl(dmz); + +#include "qv.h" +cdev_decl(qv); + +#include "qd.h" +cdev_decl(qd); + +#if defined(INGRES) +#define NII 1 +#else +#define NII 0 +#endif +cdev_decl(ii); + +struct cdevsw cdevsw[] = +{ + cdev_cn_init(1,cn), /* 0: virtual console */ + cdev_tty_init(NDZ,dz), /* 1: DZ11 */ + cdev_ctty_init(1,ctty), /* 2: controlling terminal */ + cdev_mm_init(1,mm), /* 3: /dev/{null,mem,kmem,...} */ + cdev_disk_init(NHP,hp), /* 4: Massbuss disk */ + cdev_notdef(), /* 5 */ + cdev_plotter_init(NVP,vp), /* 6: Versatec plotter */ + cdev_swap_init(1,sw), /* 7 */ + cdev_cnstore_init(NFL,fl), /* 8: 11/780 console floppy */ + cdev_disk_init(NUDA,uda), /* 9: MSCP disk interface */ + cdev_plotter_init(NVA,va), /* 10: Benson-Varian plotter */ + cdev_disk_init(NRK,rk), /* 11: RK06/07 */ + cdev_tty_init(NDH,dh), /* 12: DH-11/DM-11 */ + cdev_disk_init(NUP,up), /* 13: SC-21/SC-31 */ + cdev_tape_init(NTE,tm), /* 14: TM11/TE10 */ + cdev_lp_init(NLP,lp), /* 15: LP-11 line printer */ + cdev_tape_init(NTS,ts), /* 16: TS11 */ + cdev_tape_init(NTJ,ut), /* 17: TU45 */ + cdev_lp_init(NCT,ct), /* 18: phototypesetter interface */ + cdev_tape_init(NMU,mt), /* 19: TU78 */ + cdev_tty_init(NPTY,pts), /* 20: pseudo-tty slave */ + cdev_ptc_init(NPTY,ptc), /* 21: pseudo-tty master */ + cdev_tty_init(NDMF,dmf), /* 22: DMF32 */ + cdev_disk_init(NRB,idc), /* 23: IDC (RB730) */ + cdev_lp_init(NDN,dn), /* 24: DN-11 autocall unit */ + cdev_tty_init(1,gencn), /* 25: Generic console (mtpr...) */ + cdev_audio_init(NLPA,lpa), /* 26 ??? */ + cdev_graph_init(NPS,ps), /* 27: E/S graphics device */ + cdev_lkm_init(NLKM,lkm), /* 28: loadable module driver */ + cdev_ch_init(NAD,ad), /* 29: DT A/D converter */ + cdev_disk_init(NRX,rx), /* 30: RX01/02 on unibus */ + cdev_graph_init(NIK,ik), /* 31: Ikonas frame buffer */ + cdev_disk_init(NRL,rl), /* 32: RL01/02 on unibus */ + cdev_log_init(1,log), /* 33: /dev/klog */ + cdev_tty_init(NDHU,dhu), /* 34: DHU-11 */ + cdev_cnstore_init(NCRL,crl), /* 35: Console RL02 on 8600 */ + cdev_notdef(), /* 36: was vs100 interface. ??? */ + cdev_tty_init(NDMZ,dmz), /* 37: DMZ32 */ + cdev_tape_init(NTMSCP,tmscp), /* 38: TMSCP tape */ + cdev_audio_init(NNP,np), /* 39: NP Intelligent Board */ + cdev_graph_init(NQV,qv), /* 40: QVSS graphic display */ + cdev_graph_init(NQD,qd), /* 41: QDSS graphic display */ + cdev_notdef(), /* 42 */ + cdev_ingres_init(NII,ii), /* 43: Ingres device */ + cdev_notdef(), /* 44 was Datakit */ + cdev_notdef(), /* 45 was Datakit */ + cdev_notdef(), /* 46 was Datakit */ + cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_notdef(), /* 50 */ + cdev_cnstore_init(NCRX,crx), /* 51: Console RX50 at 8200 */ + cdev_disk_init(NKDB,kdb), /* 52: KDB50/RA?? */ + cdev_fd_init(1,fd), /* 53: file descriptor pseudo-device */ + cdev_disk_init(NCCD,ccd), /* 54: concatenated disk driver */ +}; +int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +int mem_no = 3; /* major device number of memory special file */ + +/* + * Swapdev is a fake device implemented + * in sw.c used only internally to get to swstrategy. + * It cannot be provided to the users, because the + * swstrategy routine munches the b_dev and b_blkno entries + * before calling the appropriate driver. This would horribly + * confuse, e.g. the hashing routines. Instead, /dev/drum is + * provided as a character (raw) device. + */ +dev_t swapdev = makedev(4, 0); + +int chrtoblktbl[] = { + NODEV, /* 0 */ + NODEV, /* 1 */ + NODEV, /* 2 */ + NODEV, /* 3 */ + 0, /* 4 */ + 1, /* 5 */ + NODEV, /* 6 */ + NODEV, /* 7 */ + NODEV, /* 8 */ + 9, /* 9 */ + NODEV, /* 10 */ + 3, /* 11 */ + NODEV, /* 12 */ + 2, /* 13 */ + 5, /* 14 */ + NODEV, /* 15 */ + 6, /* 16 */ + 10, /* 17 */ + NODEV, /* 18 */ + 7, /* 19 */ + NODEV, /* 20 */ + NODEV, /* 21 */ + NODEV, /* 22 */ + 11, /* 23 */ + NODEV, /* 24 */ + NODEV, /* 25 */ + NODEV, /* 26 */ + NODEV, /* 27 */ + NODEV, /* 28 */ + NODEV, /* 29 */ + 12, /* 30 */ + NODEV, /* 31 */ + 14, /* 32 */ + NODEV, /* 33 */ + NODEV, /* 34 */ + NODEV, /* 35 */ + NODEV, /* 36 */ + NODEV, /* 37 */ + 15, /* 38 */ + NODEV, /* 39 */ + NODEV, /* 40 */ + NODEV, /* 41 */ + NODEV, /* 42 */ + NODEV, /* 43 */ + NODEV, /* 44 */ + NODEV, /* 45 */ + NODEV, /* 46 */ + NODEV, /* 47 */ + NODEV, /* 48 */ + NODEV, /* 49 */ + NODEV, /* 50 */ + NODEV, /* 51 */ + 16, /* 52 */ + NODEV, /* 53 */ + 17, /* 54 */ +}; + +chrtoblk(dev) + dev_t dev; +{ + if(major(dev)>=nchrdev) return(NODEV); + return chrtoblktbl[major(dev)]==NODEV?NODEV: + makedev(chrtoblktbl[major(dev)],minor(dev)); +} + +/* + * Returns true if dev is /dev/mem or /dev/kmem. + */ +iskmemdev(dev) + dev_t dev; +{ + + return (major(dev) == 3 && minor(dev) < 2); +} + +/* + * Returns true if dev is /dev/zero. + * ?? Shall I use 12 as /dev/zero? + */ +iszerodev(dev) + dev_t dev; +{ + + return (major(dev) == 3 && minor(dev) == 12); +} diff --git a/sys/arch/vax/vax/db_disasm.c b/sys/arch/vax/vax/db_disasm.c new file mode 100644 index 00000000000..0b93e6d9567 --- /dev/null +++ b/sys/arch/vax/vax/db_disasm.c @@ -0,0 +1,347 @@ +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/reboot.h> + +#include <ddb/db_variables.h> + +#include <machine/db_machdep.h> + + + +struct vax_insn { + char *insn; + int nargs; +} instr[] = { + "halt", 0, + "nop", 0, + "rei", 0, + "bpt", 0, + "ret", 0, + "rsb", 0, + "ldpctx", 0, + "svpctx", 0, + "cvtps", 4, + "cvtsp", 4, + "index", 6, + "crc", 4, + "prober", 3, + "probew", 3, + "insque", 2, + "remque", 2, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, + "", -1, +}; + + +/* + * Disassemble instruction at 'loc'. 'altfmt' specifies an + * (optional) alternate format. Return address of start of + * next instruction. + */ +db_addr_t +db_disasm(loc, altfmt) + db_addr_t loc; + boolean_t altfmt; +{ + char *i_pl; + int inr, i; + + i_pl = loc; + inr = *i_pl; + + if (instr[*i_pl].nargs < 0) { + printf("Ok{nd instruktion: %2x",*i_pl&0xff); + i_pl++; + } else { + printf("\t%s\t",instr[inr].insn); + i_pl++; + for (i=0;i<instr[inr].nargs;i++) { + i_pl = argprint(i_pl); + if (i<instr[inr].nargs-1) + printf(","); + } + } + + + + return i_pl; +} + +argprint(plats) + char *plats; +{ + switch (*plats&0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + printf("$%x",*plats++); + break; + + case 0xe0: + if (*plats++&15 == 15) { + printf("%8x",*(unsigned *)plats + plats); + plats += 4; + } else { + printf("Oinpl. s{tt."); + } + break; + default: + printf("Oinpl. s{tt."); + } + return plats; +} diff --git a/sys/arch/vax/vax/db_machdep.c b/sys/arch/vax/vax/db_machdep.c new file mode 100644 index 00000000000..e924f940fff --- /dev/null +++ b/sys/arch/vax/vax/db_machdep.c @@ -0,0 +1,216 @@ +/* $NetBSD: db_machdep.c,v 1.2 1995/07/05 09:54:09 ragge Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) + */ + +/* + * Interface to new debugger. + * Taken from i386 port and modified for vax. + */ +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/systm.h> /* just for boothowto --eichin */ + +#include <ddb/db_variables.h> + +#include <vm/vm.h> + +#include <machine/db_machdep.h> +#include <machine/trap.h> +#include <machine/../vax/gencons.h> + +#include <setjmp.h> + +extern jmp_buf *db_recover; + +int db_active = 0; + +/* + * kdb_trap - field a TRACE or BPT trap + */ +int +kdb_trap(frame) + struct trapframe *frame; +{ + int s; + +#if 0 + if ((boothowto&RB_KDB) == 0) + return(0); +#endif + + switch (frame->trap) { + case T_BPTFLT: /* breakpoint */ + case T_TRCTRAP: /* single_step */ + break; + default: + kdbprinttrap(frame->trap, frame->code); + if (db_recover != 0) { + db_error("Faulted in DDB; continuing...\n"); + /*NOTREACHED*/ + } + } + bcopy(frame, &ddb_regs, sizeof(struct trapframe)); + + /* XXX Should switch to interrupt stack here. */ + + + s = splddb(); + mtpr(0, PR_RXCS); + mtpr(0, PR_TXCS); + db_active++; + db_trap(frame->trap, frame->code); + db_active--; + mtpr(GC_RIE, PR_RXCS); + mtpr(GC_TIE, PR_TXCS); + splx(s); + + bcopy(&ddb_regs, frame, sizeof(struct trapframe)); + + return (1); +} + +extern char *traptypes[]; +extern int no_traps; + +/* + * Print trap reason. + */ +kdbprinttrap(type, code) + int type, code; +{ + db_printf("kernel: "); + if (type >= no_traps || type < 0) + db_printf("type %d", type); + else + db_printf("%s", traptypes[type]); + db_printf(" trap, code=%x\n", code); +} + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(addr, size, data) + vm_offset_t addr; + register int size; + register char *data; +{ + register char *src; + + src = (char *)addr; + while (--size >= 0) + *data++ = *src++; +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(addr, size, data) + vm_offset_t addr; + register int size; + register char *data; +{ + register char *dst; + + dst = addr; + for (;size;size--) + *dst++ = *data++; +} + +int +Debugger() +{ + int s = splx(0xe); /* Is this good? We must lower anyway... */ + mtpr(0xf, PR_SIRR); /* beg for debugger */ + splx(s); +} + +/* + * Machine register set. + * XXX - lost stackpointer. + */ +struct db_variable db_regs[] = { + "r0", &ddb_regs.r0, FCN_NULL, + "r1", &ddb_regs.r1, FCN_NULL, + "r2", &ddb_regs.r2, FCN_NULL, + "r3", &ddb_regs.r3, FCN_NULL, + "r4", &ddb_regs.r4, FCN_NULL, + "r5", &ddb_regs.r5, FCN_NULL, + "r6", &ddb_regs.r6, FCN_NULL, + "r7", &ddb_regs.r7, FCN_NULL, + "r8", &ddb_regs.r8, FCN_NULL, + "r9", &ddb_regs.r9, FCN_NULL, + "r10", &ddb_regs.r10, FCN_NULL, + "r11", &ddb_regs.r11, FCN_NULL, + "ap", &ddb_regs.ap, FCN_NULL, + "fp", &ddb_regs.fp, FCN_NULL, + "pc", &ddb_regs.pc, FCN_NULL, + "psl", &ddb_regs.psl, FCN_NULL, +}; +struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); + +void +db_stack_trace_cmd(addr, have_addr, count, modif) + db_expr_t addr; + boolean_t have_addr; + db_expr_t count; + char *modif; +{ + printf("db_stack_trace_cmd - addr %x, have_addr %x, count %x, modif %x\n",addr, have_addr, count, modif); +} + +static int ddbescape = 0; + +int +kdbrint(tkn) + int tkn; +{ + + if (ddbescape && ((tkn & 0x7f) == 'D')) { + mtpr(0xf, PR_SIRR); + return 1; + } + + if ((ddbescape == 0) && ((tkn & 0x7f) == 27)) { + ddbescape = 1; + return 1; + } + + if (ddbescape) { + ddbescape = 0; + return 2; + } + + ddbescape = 0; + return 0; +} + + diff --git a/sys/arch/vax/vax/disksubr.c b/sys/arch/vax/vax/disksubr.c new file mode 100644 index 00000000000..f59565a52dc --- /dev/null +++ b/sys/arch/vax/vax/disksubr.c @@ -0,0 +1,293 @@ +/* $NetBSD: disksubr.c,v 1.6 1995/05/08 19:10:53 ragge Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +#include "param.h" +#include "systm.h" +#include "buf.h" +#include "dkbad.h" +#include "disklabel.h" +#include "syslog.h" +#include "machine/macros.h" + +/* XXX encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkpart(dev) (minor(dev) & 7) +#define dkminor(unit, part) (((unit) << 3) | (part)) + +#define b_cylin b_resid + +#define RAW_PART 3 + +/* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. Adjust transfer + * if needed, and signal errors or early completion. + */ +int +bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel) +{ + struct partition *p = lp->d_partitions + dkpart(bp->b_dev); + int labelsect = lp->d_partitions[0].p_offset; + int maxsz = p->p_size, + sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + + /* overwriting disk label ? */ + /* XXX should also protect bootstrap in first 8K */ + if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && +#if LABELSECTOR != 0 + bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && +#endif + (bp->b_flags & B_READ) == 0 && wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } + +#if defined(DOSBBSECTOR) && defined(notyet) + /* overwriting master boot record? */ + if (bp->b_blkno + p->p_offset <= DOSBBSECTOR && + (bp->b_flags & B_READ) == 0 && wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } +#endif + + /* beyond partition? */ + if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ + if (bp->b_blkno == maxsz) { + bp->b_resid = bp->b_bcount; + return(0); + } + /* or truncate if part of it fits */ + sz = maxsz - bp->b_blkno; + if (sz <= 0) { + bp->b_error = EINVAL; + goto bad; + } + bp->b_bcount = sz << DEV_BSHIFT; + } + + /* calculate cylinder for disksort to order transfers with */ + bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl; + return(1); + +bad: + bp->b_flags |= B_ERROR; + return(-1); +} + +/* NYFIL */ + +/* encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkpart(dev) (minor(dev) & 7) +#define dkminor(unit, part) (((unit) << 3) | (part)) + +/* + * Check new disk label for sensibility + * before setting it. + */ +setdisklabel(olp, nlp, openmask, osdep) + register struct disklabel *olp, *nlp; + u_long openmask; + struct cpu_disklabel *osdep; +{ + return cpu_setdisklabel(olp, nlp, openmask, osdep); +} + + +/* + * Write disk label back to device after modification. + */ +writedisklabel(dev, strat, lp, osdep) + dev_t dev; + void (*strat)(); + register struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + return cpu_writedisklabel(dev, strat, lp, osdep); +} +/* + * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +/* + * Attempt to read a disk label from a device + * using the indicated stategy routine. + * The label must be partly set up before this: + * secpercyl and anything required in the strategy routine + * (e.g., sector size) must be filled in before calling us. + * Returns null on success and an error string on failure. + */ +char * +readdisklabel(dev, strat, lp, osdep) + dev_t dev; + void (*strat)(); + register struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + register struct buf *bp; + struct disklabel *dlp; + char *msg = NULL; + + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + lp->d_npartitions = 1; + if (lp->d_partitions[0].p_size == 0) + lp->d_partitions[0].p_size = 0x1fffffff; + lp->d_partitions[0].p_offset = 0; + + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + bp->b_blkno = LABELSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylin = LABELSECTOR / lp->d_secpercyl; + (*strat)(bp); + if (biowait(bp)) { + msg = "I/O error"; + } else for (dlp = (struct disklabel *)bp->b_un.b_addr; + dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); + dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { + if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { + if (msg == NULL) + msg = "no disk label"; + } else if (dlp->d_npartitions > MAXPARTITIONS || + dkcksum(dlp) != 0) + msg = "disk label corrupted"; + else { + *lp = *dlp; + msg = NULL; + break; + } + } + bp->b_flags = B_INVAL | B_AGE; + brelse(bp); + return (msg); +} + +/* + * Check new disk label for sensibility + * before setting it. + */ +cpu_setdisklabel(olp, nlp, openmask, osdep) + register struct disklabel *olp, *nlp; + u_long openmask; + struct cpu_disklabel *osdep; +{ + register i; + register struct partition *opp, *npp; + + if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || + dkcksum(nlp) != 0) + return (EINVAL); + while ((i = ffs((long)openmask)) != 0) { + i--; + openmask &= ~(1 << i); + if (nlp->d_npartitions <= i) + return (EBUSY); + opp = &olp->d_partitions[i]; + npp = &nlp->d_partitions[i]; + if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size) + return (EBUSY); + /* + * Copy internally-set partition information + * if new label doesn't include it. XXX + */ + if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { + npp->p_fstype = opp->p_fstype; + npp->p_fsize = opp->p_fsize; + npp->p_frag = opp->p_frag; + npp->p_cpg = opp->p_cpg; + } + } + nlp->d_checksum = 0; + nlp->d_checksum = dkcksum(nlp); + *olp = *nlp; + return (0); +} + +/* encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkminor(unit, part) (((unit) << 3) | (part)) + +/* + * Write disk label back to device after modification. + */ +cpu_writedisklabel(dev, strat, lp, osdep) + dev_t dev; + int (*strat)(); + register struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + struct buf *bp; + struct disklabel *dlp; + int labelpart; + int error = 0; + + labelpart = dkpart(dev); + if (lp->d_partitions[labelpart].p_offset != 0) { + if (lp->d_partitions[0].p_offset != 0) + return (EXDEV); /* not quite right */ + labelpart = 0; + } + bp = geteblk((int)lp->d_secsize); + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); + bp->b_blkno = LABELSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_READ; + (*strat)(bp); + if (error = biowait(bp)) + goto done; + for (dlp = (struct disklabel *)bp->b_un.b_addr; + dlp <= (struct disklabel *) + (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); + dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { + if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && + dkcksum(dlp) == 0) { + *dlp = *lp; + bp->b_flags = B_WRITE; + (*strat)(bp); + error = biowait(bp); + goto done; + } + } + error = ESRCH; +done: + brelse(bp); + return (error); +} diff --git a/sys/arch/vax/vax/emulate.s b/sys/arch/vax/vax/emulate.s new file mode 100644 index 00000000000..7a6fc026577 --- /dev/null +++ b/sys/arch/vax/vax/emulate.s @@ -0,0 +1,1297 @@ +/* $NetBSD: emulate.s,v 1.1 1995/02/24 01:35:08 ragge Exp $ */ +/* + * Copyright (c) 1986, 1987 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mt. Xinu. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)emulate.s 7.5 (Berkeley) 6/28/90 + */ + +#if VAX630 || VAX650 +/* + * String instruction emulation - MicroVAX only. These routines are called + * from locore.s when an "emulate" fault occurs on the MicroVAX. They are + * called with the stack set up as follows: + * + * (sp): Return address of trap handler + * 4(sp): Instruction Opcode (also holds PSL result from emulator) + * 8(sp): Instruction PC + * 12(sp): Operand 1 + * 16(sp): Operand 2 + * 20(sp): Operand 3 + * 24(sp): Operand 4 + * 28(sp): Operand 5 + * 32(sp): Operand 6 + * 36(sp): old Register 11 + * 40(sp): old Register 10 + * 44(sp): Return PC + * 48(sp): Return PSL + * 52(sp): TOS before instruction + * + * R11 and r10 are available for use. If any routine needs to use r9-r1 + * they need to save them first (unless those registers are SUPPOSED to be + * messed with by the "instruction"). These routines leave their results + * in registers 0-5 explicitly, as needed, and use the macros defined below + * to link up with calling routine. + */ + +#define return rsb +#define savepsl movpsl 4(sp) +#define setpsl(reg) movl reg,4(sp) +#define overflowpsl movl $2,4(sp) +#define arg1 12(sp) +#define arg2 16(sp) +#define arg3 20(sp) +#define arg4 24(sp) +#define arg5 28(sp) +#define arg6 32(sp) +#define argub(num,reg) movzbl 8+4*num(sp),reg +#define arguw(num,reg) movzwl 8+4*num(sp),reg +#define argul(num,reg) movl 8+4*num(sp),reg +#define argb(num,reg) cvtbl 8+4*num(sp),reg +#define argw(num,reg) cvtwl 8+4*num(sp),reg +#define argl(num,reg) movl 8+4*num(sp),reg +#define toarg(reg,num) movl reg,8+4*num(sp) + + + .text + .align 1 + .globl _EMcrc +_EMcrc: + argl(1,r11) # (1) table address == r11 + argl(2,r0) # (2) initial crc == r0 + argl(4,r3) # (4) source address == r3 + arguw(3,r2) # (3) source length == r2 + jeql Lcrc_out +Lcrc_loop: + xorb2 (r3)+,r0 + extzv $0,$4,r0,r10 + extzv $4,$28,r0,r1 + xorl3 r1,(r11)[r10],r0 + extzv $0,$4,r0,r10 + extzv $4,$28,r0,r1 + xorl3 r1,(r11)[r10],r0 + sobgtr r2,Lcrc_loop + tstl r0 +Lcrc_out: + savepsl + clrl r1 + return + + + .align 1 + .globl _EMmovtc +_EMmovtc: + arguw(1,r0) # (1) source length == r0 + argl(2,r1) # (2) source address == r1 + argub(3,r11) # (3) fill character == r11 + argl(4,r3) # (4) table address == r3 + argl(6,r5) # (6) destination address == r5 + arguw(5,r4) # (5) destination length == r4 + jeql Lmovtc_out +Lmovtc_loop: + tstl r0 + jeql Lmovtc_2loop + movzbl (r1)+,r2 + movb (r3)[r2],(r5)+ + decl r0 + sobgtr r4,Lmovtc_loop + jbr Lmovtc_out +Lmovtc_2loop: + movb r11,(r5)+ + sobgtr r4,Lmovtc_2loop +Lmovtc_out: + cmpl r4,r0 + savepsl + clrl r2 + return + + + .align 1 + .globl _EMmovtuc +_EMmovtuc: + arguw(1,r0) # (1) source length == r0 + argl(2,r1) # (2) source address == r1 + argub(3,r11) # (3) escape character == r11 + argl(4,r3) # (4) table address == r3 + argl(6,r5) # (6) destination address == r5 + arguw(5,r4) # (5) destination length == r4 + jeql Lmovtuc_out +Lmovtuc_loop: + tstl r0 + jeql Lmovtuc_out + movzbl (r1),r2 + movzbl (r3)[r2],r2 + cmpl r2,r11 + jeql Lmovtuc_out + movzbl (r1)+,r2 + movb (r3)[r2],(r5)+ + decl r0 + sobgtr r4,Lmovtuc_loop +Lmovtuc_out: + cmpl r4,r0 + savepsl + clrl r2 + return + + + .align 1 + .globl _EMmatchc +_EMmatchc: + argl(2,r10) # (2) substring address == r10 + arguw(3,r2) # (3) source length == r2 + argl(4,r3) # (4) source address == r3 + arguw(1,r11) # (1) substring length == r11 + jeql Lmatchc_out # temp source address == r1 + addl2 r10,r11 # temp substring address == r0 + tstl r2 + jeql Lmatchc_out +Lmatchc_loop: + cmpb (r10),(r3) + jneq Lmatchc_fail + movl r3,r1 + movl r10,r0 +Lmatchc_2loop: + cmpl r0,r11 + jeql Lmatchc_succ + cmpb (r0)+,(r1)+ + jeql Lmatchc_2loop +Lmatchc_fail: + incl r3 + sobgtr r2,Lmatchc_loop + movl r10,r1 + subl3 r10,r11,r0 + jbr Lmatchc_out +Lmatchc_succ: + movl r1,r3 + movl r11,r1 + clrl r0 +Lmatchc_out: + savepsl + return + + + .align 1 + .globl _EMspanc +_EMspanc: + argl(2,r1) # (2) string address == r1 + argub(4,r2) # (4) character-mask == r2 + argl(3,r3) # (3) table address == r3 + arguw(1,r0) # (1) string length == r0 + jeql Lspanc_out +Lspanc_loop: + movzbl (r1),r11 + mcomb (r3)[r11],r11 + bicb3 r11,r2,r11 + jeql Lspanc_out + incl r1 + sobgtr r0,Lspanc_loop +Lspanc_out: + savepsl + clrl r2 + return + + + .align 1 + .globl _EMscanc +_EMscanc: + argl(2,r1) # (2) string address == r1 + argub(4,r2) # (4) character-mask == r2 + argl(3,r3) # (3) table address == r3 + arguw(1,r0) # (1) string length == r0 + jeql Lscanc_out +Lscanc_loop: + movzbl (r1),r11 + mcomb (r3)[r11],r11 + bicb3 r11,r2,r11 + jneq Lscanc_out + incl r1 + sobgtr r0,Lscanc_loop +Lscanc_out: + savepsl + clrl r2 + return + + + .align 1 + .globl _EMskpc +_EMskpc: + argub(1,r11) # (1) character == r11 + argl(3,r1) # (3) string address == r1 + arguw(2,r0) # (2) string length == r0 + jeql Lskpc_out # forget zero length strings +Lskpc_loop: + cmpb (r1),r11 + jneq Lskpc_out + incl r1 + sobgtr r0,Lskpc_loop +Lskpc_out: + tstl r0 # be sure of condition codes + savepsl + return + + + .align 1 + .globl _EMlocc +_EMlocc: + argub(1,r11) # (1) character == r11 + argl(3,r1) # (3) string address == r1 + arguw(2,r0) # (2) string length == r0 + jeql Lskpc_out # forget zero length strings +Llocc_loop: + cmpb (r1),r11 + jeql Llocc_out + incl r1 + sobgtr r0,Llocc_loop +Llocc_out: + tstl r0 # be sure of condition codes + savepsl + return + + + .align 1 + .globl _EMcmpc3 +_EMcmpc3: + argl(2,r1) # (2) string1 address == r1 + argl(3,r3) # (3) string2 address == r3 + arguw(1,r0) # (1) strings length == r0 + jeql Lcmpc3_out +Lcmpc3_loop: + cmpb (r1),(r3) + jneq Lcmpc3_out + incl r1 + incl r3 + sobgtr r0,Lcmpc3_loop +Lcmpc3_out: + savepsl + movl r0,r2 + return + + + .align 1 + .globl _EMcmpc5 +_EMcmpc5: + argl(2,r1) # (2) string1 address == r1 + argub(3,r11) # (1) fill character == r11 + arguw(4,r2) # (1) string2 length == r2 + argl(5,r3) # (3) string2 address == r3 + arguw(1,r0) # (1) string1 length == r0 + jeql Lcmpc5_str2 +Lcmpc5_loop: + tstl r2 + jeql Lcmpc5_str1loop + cmpb (r1),(r3) + jneq Lcmpc5_out + incl r1 + incl r3 + decl r2 + sobgtr r0,Lcmpc5_loop +Lcmpc5_str2: + tstl r2 + jeql Lcmpc5_out +Lcmpc5_str2loop: + cmpb r11,(r3) + jneq Lcmpc5_out + incl r3 + sobgtr r2,Lcmpc5_str2loop + jbr Lcmpc5_out +Lcmpc5_str1loop: + cmpb (r1),r11 + jneq Lcmpc5_out + incl r1 + sobgtr r0,Lcmpc5_str1loop +Lcmpc5_out: + savepsl + return + + +/* + * Packed Decimal string operations + */ + +#define POSITIVE $12 +#define NEGATIVE $13 +#define NEGATIVEalt $11 + + + .align 1 + .globl _EMaddp4 +_EMaddp4: + toarg(r9,6) # save register r9 in arg6 spot + arguw(1,r11) # (1) source length == r11 + argl(2,r10) # (2) source address == r10 + arguw(3,r9) # (3) destination length == r9 + argl(4,r3) # (4) destination address == r3 + ashl $-1,r11,r11 + addl2 r11,r10 # source address of LSNibble + incl r11 # source length is in bytes + ashl $-1,r9,r9 + addl2 r9,r3 # r3 = destination address of LSNibble + incl r9 # destination length is in bytes + toarg(r3,5) + extzv $0,$4,(r3),r2 # set standard +/- indicators in destination + cmpl r2,NEGATIVE + jeql L112 + cmpl r2,NEGATIVEalt + jeql L111 + insv POSITIVE,$0,$4,(r3) + jbr L112 +L111: + insv NEGATIVE,$0,$4,(r3) +L112: + extzv $0,$4,(r10),r2 # r2 = standard +/- of source + cmpl r2,NEGATIVE + jeql L114 + cmpl r2,NEGATIVEalt + jeql L113 + movl POSITIVE,r2 + jbr L114 +L113: + movl NEGATIVE,r2 +L114: + cmpl r11,r9 # if source is longer than destination + jleq L115 + movl r9,r11 # set source length == destination length +L115: + extzv $4,$4,(r3),r9 # r9 = LSDigit of destination + extzv $4,$4,(r10),r1 # r1 = LSDigit of source + extzv $0,$4,(r3),r0 + cmpl r0,r2 # if signs of operands are not equal + jeql Laddp4_same # do a subtraction + clrl r2 # r2 is non-zero if result is non-zero + subl2 r1,r9 # r9 = "addition" of operands high nibble + jbr L119 # jump into addition loop +Laddp4_diff_loop: + decl r3 + extzv $0,$4,(r3),r0 + addl2 r0,r1 # r1 = carry + next (low) nibble of source + decl r10 + extzv $0,$4,(r10),r0 + subl2 r0,r1 # r1 -= next (low) nibble of destination + jgeq L121 # if negative result + mnegl $1,r9 # r9 == carry = -1 + addl2 $10,r1 # r1 == result += 10 + jbr L122 # else +L121: + clrl r9 # r9 == carry = 0 +L122: + insv r1,$0,$4,(r3) # store result low nibble + bisl2 r1,r2 + extzv $4,$4,(r3),r0 + addl2 r0,r9 # r9 = carry + next (high) nibble of source + extzv $4,$4,(r10),r0 + subl2 r0,r9 # r9 -= next (high) nibble of destination +L119: + jgeq L117 # if negative result + mnegl $1,r1 # r1 == carry = -1 + addl2 $10,r9 # r9 == result += 10 + jbr L118 # else +L117: + clrl r1 # r1 == carry = 0 +L118: + insv r9,$4,$4,(r3) # store result high nibble + bisl2 r9,r2 # r2 is non-zero if result is non-zero + decl r11 # while (--source length) + jneq Laddp4_diff_loop + argl(4,r10) # r10 = address of destination MSNibble + jbr Laddp4_diff_carry +Laddp4_diff_carlop: + decl r3 + extzv $0,$4,(r3),r0 + addl2 r0,r1 # r1 == carry += next (low) nibble + jgeq L127 # if less than zero + movl r1,r9 # r9 == carry (must be -1) + movl $9,r1 # r1 == result = 9 + jbr L128 +L127: # else + clrl r9 # r9 == carry = 0 +L128: + insv r1,$0,$4,(r3) # store result + bisl2 r1,r2 + extzv $4,$4,(r3),r0 + addl2 r0,r9 # r9 == carry += next (high) nibble + jgeq L129 # if less than zero + movl r9,r1 # r1 == carry (must be -1) + movl $9,r9 # r9 == result = 9 + jbr L130 +L129: + clrl r1 +L130: + insv r9,$4,$4,(r3) # store result + bisl2 r9,r2 +Laddp4_diff_carry: + cmpl r3,r10 + jneq Laddp4_diff_carlop + tstl r1 # if carry out of MSN then fix up result + jeql Laddp4_add_done + argl(5,r3) # r3 == address of LSN of destination + extzv $0,$4,(r3),r0 + cmpl r0,NEGATIVE # switch sign of result + jneq L132 + insv POSITIVE,$0,$4,(r3) + jbr L133 +L132: + insv NEGATIVE,$0,$4,(r3) +L133: + extzv $4,$4,(r3),r0 # normalize result (carry out of MSN into LSN) + subl3 r0,$10,r9 # r9 = 10 - destination LSNibble + jbr L134 +L137: + movl $9,r1 +Laddp4_diff_norm: + insv r9,$4,$4,(r3) + cmpl r3,r10 # while (not at MSNibble) + jeql Laddp4_add_done + decl r3 + extzv $0,$4,(r3),r0 # low nibble = (9 + carry) - low nibble + subl2 r0,r1 + cmpl r1,$9 + jleq L135 + clrl r1 + movl $10,r9 + jbr L136 +L135: + movl $9,r9 +L136: + insv r1,$0,$4,(r3) + extzv $4,$4,(r3),r0 # high nibble = (9 + carry) - high nibble + subl2 r0,r9 +L134: + cmpl r9,$9 + jleq L137 + clrl r9 + movl $10,r1 + jbr Laddp4_diff_norm + +Laddp4_same: # operands are of the same sign + clrl r2 + addl2 r1,r9 + jbr L139 +Laddp4_same_loop: + decl r3 + extzv $0,$4,(r3),r0 + addl2 r0,r1 # r1 == carry += next (low) nibble of dest + decl r10 + extzv $0,$4,(r10),r0 + addl2 r0,r1 # r1 += next (low) nibble of source + cmpl r1,$9 # if result > 9 + jleq L141 + movl $1,r9 # r9 == carry = 1 + subl2 $10,r1 # r1 == result -= 10 + jbr L142 +L141: # else + clrl r9 # r9 == carry = 0 +L142: + insv r1,$0,$4,(r3) # store result + bisl2 r1,r2 + extzv $4,$4,(r10),r0 + addl2 r0,r9 # ditto for high nibble + extzv $4,$4,(r3),r0 + addl2 r0,r9 +L139: + cmpl r9,$9 + jleq L143 + movl $1,r1 + subl2 $10,r9 + jbr L144 +L143: + clrl r1 +L144: + insv r9,$4,$4,(r3) + bisl2 r9,r2 + sobgtr r11,Laddp4_same_loop # while (--source length) + argl(4,r10) # r10 = destination address of MSNibble + jbr Laddp4_same_carry +Laddp4_same_cloop: + decl r3 + extzv $0,$4,(r3),r0 # propagate carry up to MSNibble of destination + addl2 r0,r1 + cmpl r1,$10 + jneq L147 + movl $1,r9 + clrl r1 + jbr L148 +L147: + clrl r9 +L148: + insv r1,$0,$4,(r3) + bisl2 r1,r2 + extzv $4,$4,(r3),r0 + addl2 r0,r9 + cmpl r9,$10 + jneq L149 + movl $1,r1 + clrl r9 + jbr L150 +L149: + clrl r1 +L150: + insv r9,$4,$4,(r3) + bisl2 r9,r2 +Laddp4_same_carry: + cmpl r3,r10 + jneq Laddp4_same_cloop + +Laddp4_add_done: + argl(5,r3) # r3 = destination address of LSNibble + tstl r2 # if zero result + jneq L151 + savepsl # remember that for condition codes + insv POSITIVE,$0,$4,(r3) # make sure sign of result is positive + jbr Laddp4_out +L151: # else + extzv $0,$4,(r3),r0 + cmpl r0,NEGATIVE # if result is negative + jneq Laddp4_out + mnegl r2,r2 # remember THAT in Cond Codes + savepsl +Laddp4_out: + argl(4,r3) + argl(2,r1) + clrl r0 + clrl r2 + argl(6,r9) # restore r9 from stack + return + + + .align 1 + .globl _EMmovp +_EMmovp: + arguw(1,r11) # (1) string length == r11 + argl(2,r10) # (1) source address == r10 + argl(3,r3) # (1) destination address == r3 + # we will need arg2 and arg3 later + clrl r2 # r2 == non-zero if source is non-zero + ashl $-1,r11,r11 # length is number of bytes, not nibbles + jeql Lmovp_zlen +Lmovp_copy: + bisb2 (r10),r2 # keep track of non-zero source + movb (r10)+,(r3)+ # move two nibbles + sobgtr r11,Lmovp_copy # loop for length of source +Lmovp_zlen: + extzv $4,$4,(r10),r0 # look at least significant nibble + bisl2 r0,r2 + extzv $0,$4,(r10),r0 # check sign nibble + cmpl r0,NEGATIVEalt + jeql Lmovp_neg + cmpl r0,NEGATIVE + jneq Lmovp_pos +Lmovp_neg: # source was negative + mnegl r2,r2 +Lmovp_pos: + tstl r2 # set condition codes + savepsl + jeql Lmovp_zero + movb (r10),(r3) # move last byte if non-zero result + jbr Lmovp_out +Lmovp_zero: + movb POSITIVE,(r3) # otherwise, make result zero and positive +Lmovp_out: + clrl r0 + argl(2,r1) + clrl r2 + argl(3,r3) + return + + +/* + * Definitions for Editpc instruction + * + * Here are the commands and their corresponding hex values: + * + * EPend 0x00 + * EPend_float 0x01 + * EPclear_signif 0x02 + * EPset_signif 0x03 + * EPstore_sign 0x04 + * EPload_fill 0x40 + * EPload_sign 0x41 + * EPload_plus 0x42 + * EPload_minus 0x43 + * EPinsert 0x44 + * EPblank_zero 0x45 + * EPreplace_sign 0x46 + * EPadjust_input 0x47 + * EPfill 0x80 + * EPmove 0x90 + * EPfloat 0xa0 + * + * + * r4 is carved up as follows: + * + * ------------------------------------------- + * | N Z V C | + * ------------------------------------------- + * + * fill character is stuffed into arg5 space + * sign character is stuffed into arg6 space + */ + +#define SIGNIFBIT $0 +#define setsignif bisl2 $1,r4 +#define clsignif bicl2 $1,r4 +#define OVERFLOWBIT $1 +#define setoverflow bisl2 $2,r4 +#define cloverflow bicl2 $2,r4 +#define ZEROBIT $2 +#define setzero bisl2 $4,r4 +#define clzero bicl2 $4,r4 +#define NEGATIVEBIT $3 +#define setnegative bisl2 $8,r4 +#define clnegative bicl2 $8,r4 +#define putfill movb arg5,(r5)+ +#define setfill(reg) movb reg,arg5 +#define putsign movb arg6,(r5)+ +#define setsign(reg) movb reg,arg6 + + + .align 1 + .globl _EMeditpc +_EMeditpc: + arguw(1,r11) # (1) source length == r11 + argl(2,r10) # (2) source address == r10 + argl(3,r3) # (3) pattern address == r3 + argl(4,r5) # (4) destination address == r5 +/* # we will need arg1 and arg2 later */ +/* # arg5 and arg6 are used for fill and sign - r0 is free */ + setfill($32) # fill character is ' ' + setsign($32) # sign character is ' ' + clrl r4 # clear flags + ashl $-1,r11,r11 # source length / 2 + addl3 r11,r10,r2 + extzv $4,$4,(r2),r1 # r1 == least significant nibble of source +L169: + cmpl r2,r10 + jeql L170 + tstb -(r2) # loop over source packed decimal number + jeql L169 + incl r1 # r1 is non-zero if source is non-zero +L170: + addl3 r11,r10,r2 + tstl r1 + jeql L172 # source is zero - set flags + extzv $0,$4,(r2),r11 + cmpl r11,NEGATIVEalt + jeql L9998 # source is negative - set sign and flags + cmpl r11,NEGATIVE + jneq L175 +L9998: + setnegative + setsign($45) # sign character is '-' + jbr L175 +L172: + setzero +L175: + arguw(1,r2) # (1) source length == r2 +Ledit_case: + movzbl (r3)+,r11 # get next edit command (pattern) + cmpl r11,$128 + jlss L180 + extzv $0,$4,r11,r1 # command has a "count" arg - into r1 + ashl $-4,r11,r11 # and shift over +L180: + jbc $6,r11,L181 # "shift" those commands > 64 to 16 and up + subl2 $48,r11 +L181: + caseb r11,$0,$0x18 # "do" the command + # r11 is available for use, r1 has "count" in it +Lcaseb_label: + .word Le_end - Lcaseb_label # 00 + .word Le_end_float - Lcaseb_label # 01 + .word Le_clear_signif - Lcaseb_label # 02 + .word Le_set_signif - Lcaseb_label # 03 + .word Le_store_sign - Lcaseb_label # 04 + .word Le_end - Lcaseb_label # 05 + .word Le_end - Lcaseb_label # 06 + .word Le_end - Lcaseb_label # 07 + .word Le_fill - Lcaseb_label # 80 + .word Le_move - Lcaseb_label # 90 + .word Le_float - Lcaseb_label # a0 + .word Le_end - Lcaseb_label # b0 + .word Le_end - Lcaseb_label # c0 + .word Le_end - Lcaseb_label # d0 + .word Le_end - Lcaseb_label # e0 + .word Le_end - Lcaseb_label # f0 + .word Le_load_fill - Lcaseb_label # 40 + .word Le_load_sign - Lcaseb_label # 41 + .word Le_load_plus - Lcaseb_label # 42 + .word Le_load_minus - Lcaseb_label # 43 + .word Le_insert - Lcaseb_label # 44 + .word Le_blank_zero - Lcaseb_label # 45 + .word Le_replace_sign - Lcaseb_label # 46 + .word Le_adjust_input - Lcaseb_label # 47 +Le_end: + arguw(1,r0) + argl(2,r1) + clrl r2 + decl r3 + setpsl(r4) + clrl r4 + return + +Le_end_float: + jbs SIGNIFBIT,r4,Ledit_case # if significance not set + putsign # drop in the sign + # fall into... +Le_set_signif: + setsignif + jbr Ledit_case + +Le_clear_signif: + clsignif + jbr Ledit_case + +Le_store_sign: + putsign + jbr Ledit_case + +Le_load_fill: + setfill((r3)+) + jbr Ledit_case + +Le_load_plus: + jbs NEGATIVEBIT,r4,Lpattern_inc # if non-negative + # fall into... +Le_load_sign: + setsign((r3)+) + jbr Ledit_case + +Le_load_minus: + jbs NEGATIVEBIT,r4,Le_load_sign # if negative load the sign + incl r3 # else increment pattern + jbr Ledit_case + +Le_insert: + jbc SIGNIFBIT,r4,L196 # if significance set, put next byte + movb (r3)+,(r5)+ + jbr Ledit_case +L196: # else put in fill character + putfill + # and throw away character in pattern +Le_replace_sign: # we dont do anything with +Lpattern_inc: # replace sign cause we dont + incl r3 # get negative zero + jbr Ledit_case + +Le_blank_zero: + jbc ZEROBIT,r4,Lpattern_inc # if zero + movzbl (r3)+,r11 # next byte is a count + jeql Ledit_case + subl2 r11,r5 # to back up over output and replace +L200: + putfill # with fill character + sobgtr r11,L200 + jbr Ledit_case + +Le_adjust_input: + movzbl (r3)+,r0 # get count of nibbles from pattern + subl3 r2,r0,r11 + jgeq Ledit_case # if length of source is > this number +L204: # discard digits in source + jlbc r2,L206 # use low bit of length to choose nibble + bitb $0xf0,(r10) # high nibble + jeql L208 + setsignif # set significance and overflow if + setoverflow # wasted digit is non-zero + jbr L208 +L206: + bitb $0xf,(r10) # low nibble + jeql L209 + setsignif + setoverflow +L209: + incl r10 # increment to next byte +L208: + decl r2 # decrement source length + incl r11 # continue till were out of excess + jlss L204 + jbr Ledit_case + +Le_fill: + tstl r1 # put (count in r1) fill characters + jeql Ledit_case +Le_fill_loop: + putfill + sobgtr r1,Le_fill_loop + jbr Ledit_case + +Le_move: + tstl r1 # move (count in r1) characters + jeql Ledit_case # from source to destination +L214: + jlbc r2,L215 # read a nibble + extzv $4,$4,(r10),r11 + jbr L216 +L215: + extzv $0,$4,(r10),r11 + incl r10 +L216: + decl r2 # source length CAN go negative here... + tstl r11 + jeql L218 # if non-zero + setsignif # set significance +L218: + jbc SIGNIFBIT,r4,L219 # if significance set + addb3 $48,r11,(r5)+ # put 0 + digit into destination + jbr L220 +L219: # else put fill character + putfill +L220: + sobgtr r1,L214 + jbr Ledit_case + +Le_float: # move with floating sign character + tstl r1 + jeql Ledit_case +L221: + jlbc r2,L222 + extzv $4,$4,(r10),r11 + jbr L223 +L222: + extzv $0,$4,(r10),r11 + incl r10 +L223: + decl r2 # source length CAN go negative here... + tstl r11 + jeql L225 + jbs SIGNIFBIT,r4,L226 + putsign +L226: + setsignif +L225: + jbc SIGNIFBIT,r4,L227 + addb3 $48,r11,(r5)+ + jbr L228 +L227: + putfill +L228: + sobgtr r1,L221 + jbr Ledit_case + + + .align 1 + .globl _EMashp +_EMashp: + argb(1,r11) # (1) scale (number to shift) == r11 + arguw(2,r10) # (2) source length == r10 + argl(3,r1) # (3) source address == r1 + argub(4,r2) # (4) rounding factor == r2 + arguw(5,r3) # (5) destination length == r3 + toarg(r6,3)/* # arg3 holds register 6 from caller */ + argl(6,r6) # (6) destination address == r6 +/* + # we need arg6 for later + # arg1 is used for temporary storage + # arg2 holds "even or odd" destination length + # arg4 is used as general storage + # arg5 is used as general storage +*/ + ashl $-1,r3,r0 # destination length is number of bytes + addl2 r0,r6 # destination address == least sig nibble + toarg(r6,1) # save in arg1 spot for later + ashl $-1,r10,r0 + addl2 r0,r1 # source address == least sig nibble + extzv $0,$4,(r1),r0 # determine sign of source + cmpl r0,NEGATIVEalt + jeql Lashp_neg + cmpl r0,NEGATIVE + jeql Lashp_neg + movb POSITIVE,(r6) + jbr L245 +Lashp_neg: + movb NEGATIVE,(r6) +L245: + clrl arg2 # arg2 is 1 if dstlen is even, 0 if odd + blbs r3,L246 + incl arg2 + bisl2 $1,r3 # r3<0> counts digits going into destination +L246: # and is flip-flop for which nibble to + tstl r11 # write in destination (1 = high, 0 = low) + jgeq Lashp_left # (it must start out odd) + addl2 r11,r10 # scale is negative (right shift) + jgeq Lashp_right + clrl r10 # test for shifting whole number out + jbr Lashp_setround +Lashp_right: + divl3 $2,r11,r0 + addl2 r0,r1 # source address == MSNibble to be shifted off + jlbc r11,L249 + extzv $4,$4,(r1),r0 + addl2 r0,r2 # round = last nibble to be shifted off + round + jbr Lashp_setround +L249: + extzv $0,$4,(r1),r0 + addl2 r0,r2 # round = last nibble to be shifted off + round +Lashp_setround: # r11<0> now is flip-flop for which nibble to + incl r11 # read from source (1 == high, 0 == low) + cmpl r2,$9 # set rounding factor to one if nibble shifted + jleq Lashp_noround # off + round argument was 10 or greater + movl $1,r2 + jbr Lashp_shift +Lashp_zloop: + jlbs r3,L257 # dont need to clear high nibble twice + clrb -(r6) # clear low (and high) nib of next byte in dest +L257: + sobgtr r3,L258 # move to next nibble in destination, but + incl r3 # dont go beyond the end. +L258: + decl r11 +Lashp_left: # while scale is positive + jneq Lashp_zloop + incl r11 # r11<0> is flip-plop ... (incl sets it to one) +Lashp_noround: + clrl r2 # no more rounding +Lashp_shift: + clrl arg4 # arg4 will be used for result condition codes + tstl r10 + jeql Lashp_round +Lashp_shloop: + jlbc r11,L260 + extzv $4,$4,(r1),r0 + jbr L261 +L260: + decl r1 + extzv $0,$4,(r1),r0 +L261: + incl r11 # flip the source nibble flip/flop + addl2 r0,r2 # round += next nibble + cmpl r2,$10 # if round == 10 + jneq L262 + clrl arg5 # then result = 0 and round = 1 + movl $1,r2 + jbr L263 +L262: # else + movl r2,arg5 # store result and round = 0 + clrl r2 +L263: + bisl2 arg5,arg4 # remember if result was nonzero in arg4 + decl r3 # move to next nibble early to check + cmpl r3,arg2 # if weve moved passed destination limits + jgeq Lashp_noovfl # test the result for possible overflow + movl arg2,r3 # ignore zero nibbles + tstl arg5 # if the nibble was non-zero, overflow + jeql L265 + jbr Lashp_overfl +Lashp_noovfl: # else + jlbs r3,L264 + insv arg5,$4,$4,(r6) # put the result into destination (high or low) + jbr L265 +L264: + movb arg5,-(r6) +L265: + sobgtr r10,Lashp_shloop # loop for length of source + +Lashp_round: + tstl r2 # take care of round out of high nibble + jeql Lashp_zeroround + decl r3 + cmpl r3,arg2 # if weve moved passed destination limits + jlss Lashp_overfl # then overflow + jlbs r3,L266 + insv arg5,$4,$4,(r6) # put the round into destination (high or low) + jbr Lashp_zeroround +L266: + movb arg5,-(r6) + +Lashp_zeroround: + argl(1,r10) # r10 = address of destination LSNibble + argl(6,r3) # r3 = address of destination MSNibble + movl arg4,r11 # r11 = non-zero if destination == non-zero + savepsl + jbr L267 +Lashp_zerofill: + clrb -(r6) # fill up MSNs of destination with zeros +L267: + cmpl r3,r6 + jneq Lashp_zerofill + extzv $0,$4,(r10),r0 # test for negative result + cmpl r0,NEGATIVE + jneq Lashp_out + mnegl r11,r11 + savepsl + jneq Lashp_out # turn -0 into 0 + insv POSITIVE,$0,$4,(r10) +Lashp_out: + clrl r0 + argl(3,r6) # restore r6 from stack + return +Lashp_overfl: # do overflow + clrl r2 + overflowpsl + jbr Lashp_out + + + .align 1 + .globl _EMcvtlp +_EMcvtlp: + arguw(2,r10) # (2) destination length == r10 + argl(3,r3) # (3) destination address == r3 + ashl $-1,r10,r10 + addl2 r10,r3 # destination address points to Least Sig byte + incl r10 # length is # of bytes, not nibbles + argl(1,r11) # (1) source == r11 + savepsl + jgeq Lcvtlp_pos + movb NEGATIVE,(r3) # source is negative + divl3 $10,r11,r0 + mull3 $10,r0,r1 + subl3 r11,r1,r2 # r2 = source mod 10 + mnegl r0,r11 # source = -(source / 10) + jbr Lcvtlp_cvt +Lcvtlp_pos: + movb POSITIVE,(r3) # source is non-negative + divl3 $10,r11,r0 + mull3 $10,r0,r1 + subl3 r1,r11,r2 # r2 = source mod 10 + movl r0,r11 # source = source / 10 +Lcvtlp_cvt: + insv r2,$4,$4,(r3) # store least significant digit + tstl r11 + jeql Lcvtlp_zloop +Lcvtlp_loop: # while source is non-zero + decl r10 # and for length of destination ... + jeql Lcvtlp_over + divl3 $10,r11,r1 # r1 = source / 10 + mull3 $10,r1,r0 + subl2 r0,r11 # source = source mod 10 + movb r11,-(r3) # store low "nibble" in next significant byte + divl3 $10,r1,r11 # source = r1 / 10 + mull3 $10,r11,r0 + subl2 r0,r1 # r1 = source mod 10 + insv r1,$4,$4,(r3) # store high nibble + tstl r11 + jneq Lcvtlp_loop # quit if source becomes zero +Lcvtlp_zloop: # fill any remaining bytes with zeros + decl r10 + jeql Lcvtlp_out + clrb -(r3) + jbr Lcvtlp_zloop +Lcvtlp_over: + overflowpsl +Lcvtlp_out: + clrl r1 # r0 is already zero + clrl r2 + return + + + .align 1 + .globl _EMcvtpl +_EMcvtpl: + arguw(1,r11) # (1) source length == r11 + argl(2,r10) # (2) source address == r10 + clrl r3 # r3 == destination + movl r10,r1 # r1 set up now for return + ashl $-1,r11,r11 # source length is number of bytes + jeql Lcvtpl_zero +Lcvtpl_loop: # for source length + mull2 $10,r3 # destination *= 10 + extzv $4,$4,(r10),r0 + addl2 r0,r3 # destination += high nibble + mull2 $10,r3 # destination *= 10 + extzv $0,$4,(r10),r0 + addl2 r0,r3 # destination += low nibble + incl r10 + sobgtr r11,Lcvtpl_loop +Lcvtpl_zero: # least significant byte + mull2 $10,r3 + extzv $4,$4,(r10),r0 + addl2 r0,r3 # dest = 10 * dest + high nibble + savepsl + extzv $0,$4,(r10),r2 # test sign nibble + cmpl r2,NEGATIVE + jeql Lcvtpl_neg + cmpl r2,NEGATIVEalt + jneq Lcvtpl_out +Lcvtpl_neg: # source was negative - negate destination + mnegl r3,r3 + savepsl +Lcvtpl_out: + toarg(r3,3) + clrl r0 + clrl r2 + clrl r3 + return + + + .align 1 + .globl _EMcvtps +_EMcvtps: + return + + + .align 1 + .globl _EMcvtsp +_EMcvtsp: + return + + + .align 1 + .globl _EMaddp6 +_EMaddp6: + return + + + .align 1 + .globl _EMsubp4 +_EMsubp4: + return + + + .align 1 + .globl _EMsubp6 +_EMsubp6: + return + + + .align 1 + .globl _EMcvtpt +_EMcvtpt: + return + + + .align 1 + .globl _EMmulp +_EMmulp: + return + + + .align 1 + .globl _EMcvttp +_EMcvttp: + return + + + .align 1 + .globl _EMdivp +_EMdivp: + return + + + .align 1 + .globl _EMcmpp3 +_EMcmpp3: + return + + + .align 1 + .globl _EMcmpp4 +_EMcmpp4: + return + + +#endif UVAXII + + +#ifdef notdef +/* + * Emulation OpCode jump table: + * ONLY GOES FROM 0xf8 (-8) TO 0x3B (59) + */ +#define EMUTABLE 0x43 +#define NOEMULATE .long noemulate +#define EMULATE(a) .long _EM/**/a + .globl _emJUMPtable +_emJUMPtable: +/* f8 */ EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE +/* fc */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 00 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 04 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 08 */ EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc) +/* 0c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 10 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 14 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 18 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 1c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 20 */ EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6) +/* 24 */ EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp) +/* 28 */ NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc) +/* 2c */ NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc) +/* 30 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE +/* 34 */ EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4) +/* 38 */ EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc) + +/* + * The following is called with the stack set up as follows: + * + * (sp): Opcode + * 4(sp): Instruction PC + * 8(sp): Operand 1 + * 12(sp): Operand 2 + * 16(sp): Operand 3 + * 20(sp): Operand 4 + * 24(sp): Operand 5 + * 28(sp): Operand 6 + * 32(sp): Operand 7 (unused) + * 36(sp): Operand 8 (unused) + * 40(sp): Return PC + * 44(sp): Return PSL + * 48(sp): TOS before instruction + * + * Each individual routine is called with the stack set up as follows: + * + * (sp): Return address of trap handler + * 4(sp): Opcode (will get return PSL) + * 8(sp): Instruction PC + * 12(sp): Operand 1 + * 16(sp): Operand 2 + * 20(sp): Operand 3 + * 24(sp): Operand 4 + * 28(sp): Operand 5 + * 32(sp): Operand 6 + * 36(sp): saved register 11 + * 40(sp): saved register 10 + * 44(sp): Return PC + * 48(sp): Return PSL + * 52(sp): TOS before instruction + */ + +SCBVEC(emulate): + movl r11,32(sp) # save register r11 in unused operand + movl r10,36(sp) # save register r10 in unused operand + cvtbl (sp),r10 # get opcode + addl2 $8,r10 # shift negative opcodes + subl3 r10,$EMUTABLE,r11 # forget it if opcode is out of range + bcs noemulate + movl _emJUMPtable[r10],r10 # call appropriate emulation routine + jsb (r10) # routines put return values into regs 0-5 + movl 32(sp),r11 # restore register r11 + movl 36(sp),r10 # restore register r10 + insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot + addl2 $40,sp # adjust stack for return + rei +noemulate: + addl2 $48,sp # adjust stack for + .word 0xffff # "reserved instruction fault" +SCBVEC(emulateFPD): + .word 0xffff # "reserved instruction fault" +#endif diff --git a/sys/arch/vax/vax/gencons.c b/sys/arch/vax/vax/gencons.c new file mode 100644 index 00000000000..ddf31f6ef87 --- /dev/null +++ b/sys/arch/vax/vax/gencons.c @@ -0,0 +1,292 @@ +/* $NetBSD: gencons.c,v 1.6 1995/08/21 03:24:46 ragge Exp $ */ + +/* + * Copyright (c) 1994 Gordon W. Ross + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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. + * + * kd.c,v 1.2 1994/05/05 04:46:51 gwr Exp $ + */ + + /* All bugs are subject to removal without further notice */ + +#include "sys/param.h" +#include "sys/proc.h" +#include "sys/systm.h" +#include "sys/ioctl.h" +#include "sys/tty.h" +#include "sys/file.h" +#include "sys/conf.h" +#include "sys/device.h" +#include "sys/reboot.h" + +#include "dev/cons.h" + +#include "machine/mtpr.h" +#include "machine/../vax/gencons.h" + +struct tty *gencn_tty[1]; + +int consinied = 0; + +int gencnparam(); +void gencnstart(); + +int +gencnopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit; + struct tty *tp; + + unit = minor(dev); + if (unit) return ENXIO; + + tp = gencn_tty[0]; + + tp->t_oproc = gencnstart; + tp->t_param = gencnparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + 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; + gencnparam(tp, &tp->t_termios); + ttsetwater(tp); + } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) + return EBUSY; + tp->t_state |= TS_CARR_ON; + mtpr(GC_RIE, PR_RXCS); /* Turn on interrupts */ + mtpr(GC_TIE, PR_TXCS); + + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +gencnclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp = gencn_tty[0]; + + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return (0); +} + +struct tty * +gencntty(dev) + dev_t dev; +{ + return gencn_tty[0]; /* XXX */ +} + +int +gencnread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp = gencn_tty[0]; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +gencnwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp = gencn_tty[0]; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +int +gencnioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int error; + int unit = minor(dev); + struct tty *tp = gencn_tty[0]; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) return error; + + return ENOTTY; +} + +void +gencnstart(tp) + struct tty *tp; +{ + struct clist *cl; + int s, ch; + + s = spltty(); + if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) + goto out; + cl = &tp->t_outq; + + if(cl->c_cc){ + tp->t_state |= TS_BUSY; + ch = getc(cl); + mtpr(ch, PR_TXDB); + } else { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)cl); + } + selwakeup(&tp->t_wsel); + } + +out: splx(s); +} + +gencnrint() +{ + struct tty *tp; + int i, j; + + tp = gencn_tty[0]; + i = mfpr(PR_RXDB); + +#ifdef DDB + j = kdbrint(i); + + if (j == 1) /* Escape received, just return */ + return; + + if (j == 2) /* Second char wasn't 'D' */ + (*linesw[tp->t_line].l_rint)(27, tp); +#endif + + (*linesw[tp->t_line].l_rint)(i,tp); + return; +} + +int +gencnstop(tp, flag) + struct tty *tp; + int flag; +{ +} + +gencntint() +{ + struct tty *tp; + + tp = gencn_tty[0]; + tp->t_state &= ~TS_BUSY; + + gencnstart(tp); +} + +int +gencnparam(tp, t) + struct tty *tp; + struct termios *t; +{ + /* XXX - These are ignored... */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + return 0; +} + +int +gencnprobe(cndev) + struct consdev *cndev; +{ + int i; + + for (i = 0; i < nchrdev; i++) + if (cdevsw[i].d_open == gencnopen) { + cndev->cn_dev = makedev(i,0); + cndev->cn_pri = CN_NORMAL; + break; + } + return 0; +} + +int +gencninit(cndev) + struct consdev *cndev; +{ +} + +gencnslask() +{ + gencn_tty[0] = ttymalloc(); +} + +int +gencnputc(dev,ch) + dev_t dev; + int ch; +{ + while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ + ; + mtpr(ch, PR_TXDB); /* xmit character */ + if(ch == 10) + gencnputc(dev, 13); /* CR/LF */ + +} + +int +gencngetc(dev) + dev_t dev; +{ + while ((mfpr(PR_RXCS) & GC_DON) == 0) /* Receive chr */ + ; + return mfpr(PR_RXDB) & 0x7f; +} + +conout(str) + char *str; +{ + while (*str) + gencnputc(0, *str++); +} diff --git a/sys/arch/vax/vax/gencons.h b/sys/arch/vax/vax/gencons.h new file mode 100644 index 00000000000..cd985437709 --- /dev/null +++ b/sys/arch/vax/vax/gencons.h @@ -0,0 +1,55 @@ +/* $NetBSD: gencons.h,v 1.3 1995/06/05 16:26:38 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +/* + * Some definitions for generic console interface (PR 32-35) + */ + +/* PR_TXCS */ +#define GC_RDY 0x80 /* Console ready to xmit chr */ +#define GC_TIE 0x40 /* xmit interrupt enable */ + +/* PR_RXCS */ +#define GC_DON 0x80 /* character received */ +#define GC_RIE 0x40 /* recv interrupt enable */ + +/* PR_RXDB */ +#define GC_ERR 0x8000 /* received character error */ +#define GC_CON 0xf00 /* mfpr($PR_RXDB)&GC_CON==0 then console chr */ + +/* PR_TXDB */ +#define GC_BOOT 0xf02 /* boot machine */ +#define GC_CCF 0xf04 /* clear cold start flag */ diff --git a/sys/arch/vax/vax/intvec.s b/sys/arch/vax/vax/intvec.s new file mode 100644 index 00000000000..997d93ec959 --- /dev/null +++ b/sys/arch/vax/vax/intvec.s @@ -0,0 +1,398 @@ +/* $NetBSD: intvec.s,v 1.11 1995/06/16 15:36:40 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "vax/include/mtpr.h" +#include "vax/include/pte.h" +#include "vax/include/trap.h" +#include "uba.h" + +#define TRAPCALL(namn, typ) \ + .align 2; namn ## :;.globl namn ;pushl $0; pushl $typ; jbr trap; + +#define TRAPARGC(namn, typ) \ + .align 2; namn ## :;.globl namn ; pushl $typ; jbr trap; + +#define FASTINTR(namn, rutin) \ + .align 2; namn ## :;.globl namn ;pushr $0x3f; \ + calls $0,_ ## rutin ;popr $0x3f;rei +#define STRAY(scbnr,vecnr) \ + .align 2;stray ## vecnr ## :;pushr $0x3f;pushl $ ## 0x ## vecnr; \ + pushl $scbnr; calls $2,_stray ; popr $0x3f; rei; +#define KSTACK 0 +#define ISTACK 1 +#define INTVEC(label,stack) \ + .long label+stack; + .text + + .globl _kernbase,_rpb +_kernbase: +_rpb: +/* + * First page in memory we have rpb; so that we know where :-) + * Second page contain scb, and thereafter uba vectors. + * Virtual adress is 0x80000000. + */ + .space 512 /* rpb takes one page */ + + INTVEC(stray00, ISTACK) # Unused., 0 + INTVEC(mcheck, ISTACK) # Machine Check., 4 + INTVEC(invkstk, ISTACK) # Kernel Stack Invalid., 8 + INTVEC(stray0C, ISTACK) # Power Failed., C + INTVEC(privinflt, KSTACK) # Privileged/Reserved Instruction. + INTVEC(stray14, ISTACK) # Customer Reserved Instruction, 14 + INTVEC(resopflt, KSTACK) # Reserved Operand/Boot Vector(?), 18 + INTVEC(resadflt, KSTACK) # # Reserved Address Mode., 1C + INTVEC(access_v, KSTACK) # Access Control Violation, 20 + INTVEC(transl_v, KSTACK) # Translation Invalid, 24 + INTVEC(tracep, KSTACK) # Trace Pending, 28 + INTVEC(breakp, KSTACK) # Breakpoint Instruction, 2C + INTVEC(stray30, ISTACK) # Compatibility Exception, 30 + INTVEC(arithflt, KSTACK) # Arithmetic Fault, 34 + INTVEC(stray38, ISTACK) # Unused, 38 + INTVEC(stray3C, ISTACK) # Unused, 3C + INTVEC(syscall, KSTACK) # main syscall trap, chmk, 40 + INTVEC(resopflt, KSTACK) # chme, 44 + INTVEC(resopflt, KSTACK) # chms, 48 + INTVEC(resopflt, KSTACK) # chmu, 4C + INTVEC(stray50, ISTACK) # System Backplane Exception, 50 + INTVEC(stray54, ISTACK) # Corrected Memory Read, 54 + INTVEC(stray58, ISTACK) # System Backplane Alert, 58 + INTVEC(stray5C, ISTACK) # System Backplane Fault, 5C + INTVEC(stray60, ISTACK) # Memory Write Timeout, 60 + INTVEC(stray64, ISTACK) # Unused, 64 + INTVEC(stray68, ISTACK) # Unused, 68 + INTVEC(stray6C, ISTACK) # Unused, 6C + INTVEC(stray70, ISTACK) # Unused, 70 + INTVEC(stray74, ISTACK) # Unused, 74 + INTVEC(stray78, ISTACK) # Unused, 78 + INTVEC(stray7C, ISTACK) # Unused, 7C + INTVEC(stray80, ISTACK) # Unused, 80 + INTVEC(stray84, ISTACK) # Unused, 84 + INTVEC(astintr, KSTACK) # Asynchronous Sustem Trap, AST + INTVEC(stray8C, ISTACK) # Unused, 8C + INTVEC(stray90, ISTACK) # Unused, 90 + INTVEC(stray94, ISTACK) # Unused, 94 + INTVEC(stray98, ISTACK) # Unused, 98 + INTVEC(stray9C, ISTACK) # Unused, 9C + INTVEC(softclock,ISTACK) # Software clock interrupt + INTVEC(strayA4, ISTACK) # Unused, A4 + INTVEC(strayA8, ISTACK) # Unused, A8 + INTVEC(strayAC, ISTACK) # Unused, AC + INTVEC(netint, ISTACK) # Network interrupt + INTVEC(strayB4, ISTACK) # Unused, B4 + INTVEC(strayB8, ISTACK) # Unused, B8 + INTVEC(ddbtrap, ISTACK) # Kernel debugger trap, BC + INTVEC(hardclock,ISTACK) # Interval Timer + INTVEC(strayC4, ISTACK) # Unused, C4 + INTVEC(emulate, KSTACK) # Subset instruction emulation + INTVEC(strayCC, ISTACK) # Unused, CC + INTVEC(strayD0, ISTACK) # Unused, D0 + INTVEC(strayD4, ISTACK) # Unused, D4 + INTVEC(strayD8, ISTACK) # Unused, D8 + INTVEC(strayDC, ISTACK) # Unused, DC + INTVEC(strayE0, ISTACK) # Unused, E0 + INTVEC(strayE4, ISTACK) # Unused, E4 + INTVEC(strayE8, ISTACK) # Unused, E8 + INTVEC(strayEC, ISTACK) # Unused, EC + INTVEC(strayF0, ISTACK) # Console Storage Recieve Interrupt + INTVEC(strayF4, ISTACK) # Console Storage Transmit Interrupt + INTVEC(consrint, ISTACK) # Console Terminal Recieve Interrupt + INTVEC(constint, ISTACK) # Console Terminal Transmit Interrupt + + + .globl _V_DEVICE_VEC +_V_DEVICE_VEC: .space 0x100 + +#if NUBA +#include "vax/uba/ubavec.s" +#endif + +#if NUBA>4 /* Safety belt */ +#error "Number of bus adapters must be increased in ubavec.s" +#endif + + STRAY(0, 00) + + .align 2 +# +# mcheck is the badaddress trap, also called when referencing +# a invalid address (busserror) +# _memtest (memtest in C) holds the address to continue execution +# at when returning from a intentional test. +# +mcheck: .globl mcheck + tstl _cold # Ar we still in coldstart? + bneq L4 # Yes. + + pushr $0x3f + pushab 24(sp) + calls $1, _machinecheck + popr $0x3f + addl2 (sp)+,sp + + rei + +L4: addl2 (sp)+,sp # remove info pushed on stack + mtpr $0xF,$PR_MCESR # clear the bus error bit + movl _memtest,(sp) # REI to new adress + rei + + TRAPCALL(invkstk, T_KSPNOTVAL) + STRAY(0, 0C) + + TRAPCALL(privinflt, T_PRIVINFLT) + STRAY(0, 14) + TRAPCALL(resopflt, T_RESOPFLT) + TRAPCALL(resadflt, T_RESADFLT) + + .align 2 +transl_v: .globl transl_v # Translation violation, 20 + pushl $T_TRANSFLT +L3: bbc $1,4(sp),L1 + bisl2 $T_PTEFETCH, (sp) +L1: bbc $2,4(sp),L2 + bisl2 $T_WRITE, (sp) +L2: movl (sp), 4(sp) + addl2 $4, sp + jbr trap + + + .align 2 +access_v:.globl access_v # Access cntrl viol fault, 24 + blbs (sp), ptelen + pushl $T_ACCFLT + jbr L3 + +ptelen: movl $T_PTELEN, (sp) # PTE must expand (or send segv) + jbr trap; + + TRAPCALL(tracep, T_TRCTRAP) + TRAPCALL(breakp, T_BPTFLT) + STRAY(0, 30) + + TRAPARGC(arithflt, T_ARITHFLT) + + STRAY(0, 38) + STRAY(0, 3C) + + + + + + .align 2 # Main system call + .globl syscall +syscall: + pushl $T_SYSCALL + pushr $0xfff + pushl ap + pushl fp + pushl sp # pointer to syscall frame; defined in trap.h + calls $1,_syscall + movl (sp)+,fp + movl (sp)+,ap + popr $0xfff + addl2 $8,sp + mtpr $0x1f,$PR_IPL # Be sure we can REI + rei + + STRAY(0, 44) + STRAY(0, 48) + STRAY(0, 4C) + STRAY(0, 50) + STRAY(0, 54) + STRAY(0, 58) + STRAY(0, 5C) + STRAY(0, 60) + STRAY(0, 64) + STRAY(0, 68) + STRAY(0, 6C) + STRAY(0, 70) + STRAY(0, 74) + STRAY(0, 78) + STRAY(0, 7C) + STRAY(0, 80) + STRAY(0, 84) + + TRAPCALL(astintr, T_ASTFLT) + + STRAY(0, 8C) + STRAY(0, 90) + STRAY(0, 94) + STRAY(0, 98) + STRAY(0, 9C) + + FASTINTR(softclock, softclock) + + STRAY(0, A4) + STRAY(0, A8) + STRAY(0, AC) + + FASTINTR(netint, netintr) #network packet interrupt + + STRAY(0, B4) + STRAY(0, B8) + TRAPCALL(ddbtrap,T_KDBTRAP) + + .align 2 + .globl hardclock +hardclock: mtpr $0xc1,$PR_ICCS # Reset interrupt flag + pushr $0x3f + pushl sp + addl2 $24,(sp) + calls $1,_hardclock + popr $0x3f + rei + + STRAY(0, C4) + STRAY(0, CC) + STRAY(0, D0) + STRAY(0, D4) + STRAY(0, D8) + STRAY(0, DC) + STRAY(0, E0) + STRAY(0, E4) + STRAY(0, E8) + STRAY(0, EC) + STRAY(0, F0) + STRAY(0, F4) + + FASTINTR(consrint, gencnrint) + FASTINTR(constint, gencntint) + +trap: pushr $0xfff + pushl ap + pushl fp + pushl sp + calls $1,_arithflt + movl (sp)+,fp + movl (sp)+,ap + popr $0xfff + addl2 $8,sp + mtpr $0x1f,$PR_IPL # Be sure we can REI + rei + +#if VAX630 || VAX650 +/* + * Table of emulated Microvax instructions supported by emulate.s. + * Use noemulate to convert unimplemented ones to reserved instruction faults. + */ + .globl _emtable +_emtable: +/* f8 */ .long _EMashp; .long _EMcvtlp; .long noemulate; .long noemulate +/* fc */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 00 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 04 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 08 */ .long _EMcvtps; .long _EMcvtsp; .long noemulate; .long _EMcrc +/* 0c */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 10 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 14 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 18 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 1c */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 20 */ .long _EMaddp4; .long _EMaddp6; .long _EMsubp4; .long _EMsubp6 +/* 24 */ .long _EMcvtpt; .long _EMmulp; .long _EMcvttp; .long _EMdivp +/* 28 */ .long noemulate; .long _EMcmpc3; .long _EMscanc; .long _EMspanc +/* 2c */ .long noemulate; .long _EMcmpc5; .long _EMmovtc; .long _EMmovtuc +/* 30 */ .long noemulate; .long noemulate; .long noemulate; .long noemulate +/* 34 */ .long _EMmovp; .long _EMcmpp3; .long _EMcvtpl; .long _EMcmpp4 +/* 38 */ .long _EMeditpc; .long _EMmatchc; .long _EMlocc; .long _EMskpc +#endif +/* + * The following is called with the stack set up as follows: + * + * (sp): Opcode + * 4(sp): Instruction PC + * 8(sp): Operand 1 + * 12(sp): Operand 2 + * 16(sp): Operand 3 + * 20(sp): Operand 4 + * 24(sp): Operand 5 + * 28(sp): Operand 6 + * 32(sp): Operand 7 (unused) + * 36(sp): Operand 8 (unused) + * 40(sp): Return PC + * 44(sp): Return PSL + * 48(sp): TOS before instruction + * + * Each individual routine is called with the stack set up as follows: + * + * (sp): Return address of trap handler + * 4(sp): Opcode (will get return PSL) + * 8(sp): Instruction PC + * 12(sp): Operand 1 + * 16(sp): Operand 2 + * 20(sp): Operand 3 + * 24(sp): Operand 4 + * 28(sp): Operand 5 + * 32(sp): Operand 6 + * 36(sp): saved register 11 + * 40(sp): saved register 10 + * 44(sp): Return PC + * 48(sp): Return PSL + * 52(sp): TOS before instruction + * See the VAX Architecture Reference Manual, Section B-5 for more + * information. + */ + + .align 2 + .globl emulate +emulate: +#if VAX630 || VAX650 + movl r11,32(sp) # save register r11 in unused operand + movl r10,36(sp) # save register r10 in unused operand + cvtbl (sp),r10 # get opcode + addl2 $8,r10 # shift negative opcodes + subl3 r10,$0x43,r11 # forget it if opcode is out of range + bcs noemulate + movl _emtable[r10],r10 # call appropriate emulation routine + jsb (r10) # routines put return values into regs 0-5 + movl 32(sp),r11 # restore register r11 + movl 36(sp),r10 # restore register r10 + insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot + addl2 $40,sp # adjust stack for return + rei +noemulate: + addl2 $48,sp # adjust stack for +#endif + .word 0xffff # "reserved instruction fault" + + .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt +_intrnames: + .long 0 +_eintrnames: +_intrcnt: + .long 0 +_eintrcnt: + diff --git a/sys/arch/vax/vax/ka750.c b/sys/arch/vax/vax/ka750.c new file mode 100644 index 00000000000..4dc30a4dafc --- /dev/null +++ b/sys/arch/vax/vax/ka750.c @@ -0,0 +1,236 @@ +/* $NetBSD: ka750.c,v 1.5.2.1 1995/10/15 14:18:49 ragge Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1988 The Regents of the University of California. + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ka750.c 7.4 (Berkeley) 5/9/91 + * @(#)autoconf.c 7.20 (Berkeley) 5/9/91 + */ + +/* All bugs are subject to removal without further notice */ + +#if VAX750 + +#include "sys/param.h" +#include "sys/types.h" +#include "sys/device.h" +#include "machine/ka750.h" +#include "machine/nexus.h" +#include "machine/pte.h" +#include "machine/mtpr.h" +#include "vax/uba/ubavar.h" +#include "vax/uba/ubareg.h" + +#include "mba.h" +#include "uba.h" + +#include "vm/vm.h" +#include "vm/vm_kern.h" +#include "vax/include/pmap.h" + +struct nexus *nexus; + +int +ka750_conf() +{ + extern char cpu_model[]; + + strcpy(cpu_model,"VAX 11/750"); + config_rootfound("backplane",(void *)75); +} + +int +conf_750(){ + extern int cpu_type, nmba, numuba; + + printf(": 11/750, hardware rev %d, ucode rev %d\n", + V750HARDW(cpu_type), V750UCODE(cpu_type)); +} + +ka750_clock(){ + u_int i; +/* + * It's time to start clocks in system... + */ + i=~10000; /* Complement of 10000 milliseconds */ + mtpr(i,PR_NICR); /* Load in count register */ + mtpr(0x51,PR_ICCS); /* Start clock and enable interrupt */ + if(mfpr(PR_TODR)){ + /* todr running */ + return 0; + } else { + /* Start TODR register. */ + mtpr(1,PR_TODR); + return 1; + } + +} + +#if NMBA < 1 +/* + * Dummy routine; should never be called. + * Should also be somewhere else, but it doesn't matter right now :) + */ +mbainterrupt(){return;} +#endif + + +/* + * 750-specific code. + */ + + +#include "sys/param.h" + +/* #include "mem.h" */ + +extern volatile caddr_t mcraddr[]; + +struct mcr750 { + int mc_err; /* error bits */ + int mc_inh; /* inhibit crd */ + int mc_inf; /* info bits */ +}; + +#define M750_ICRD 0x10000000 /* inhibit crd interrupts, in [1] */ +#define M750_UNCORR 0xc0000000 /* uncorrectable error, in [0] */ +#define M750_CORERR 0x20000000 /* correctable error, in [0] */ + +#define M750_INH(mcr) ((mcr)->mc_inh = 0) +#define M750_ENA(mcr) ((mcr)->mc_err = (M750_UNCORR|M750_CORERR), \ + (mcr)->mc_inh = M750_ICRD) +#define M750_ERR(mcr) ((mcr)->mc_err & (M750_UNCORR|M750_CORERR)) + +#define M750_SYN(err) ((err) & 0x7f) +#define M750_ADDR(err) (((err) >> 9) & 0x7fff) + +/* enable crd interrupts */ +ka750_memenable(sa,self) + struct sbi_attach_args *sa; + struct device *self; +{ + extern int nmcr; + int k,l,m,cardinfo; + struct mcr750 *mcr=(struct mcr750 *)sa->nexaddr; + + mcraddr[self->dv_unit]=(caddr_t)sa->nexaddr; + + /* We will use this info for error reporting - later! */ + cardinfo=mcr->mc_inf; + switch((cardinfo>>24)&3){ + case 0: printf(": L0011 "); + break; + case 1: printf(": L0016 "); + m=cardinfo&0xaaaa; + for(k=l=0;k<16;k++){if(m&1)l++;m>>=1;} + printf("with %d M8750",l); + break; + case 3: printf(": L0022 "); + m=cardinfo&0x5555; + for(k=l=0;k<16;k++){if(m&1)l++;m>>=1;} + printf("with %d M7199",l); + m=cardinfo&0xaaaa; + if(m){ + for(k=l=0;k<16;k++){if(m&1)l++;m>>=1;} + printf(" and %d M8750",l); + } + break; + } + printf("\n"); + + + M750_ENA((struct mcr750 *)mcraddr[0]); +} + +/* log crd errors */ +ka750_memerr() +{ + register struct mcr750 *mcr = (struct mcr750 *)mcraddr[0]; + register int err; + + if (M750_ERR(mcr)) { + err = mcr->mc_err; /* careful with i/o space refs */ + printf("mcr0: %s", err & M750_UNCORR ? + "hard error" : "soft ecc"); + printf(" addr %x syn %x\n", M750_ADDR(err), M750_SYN(err)); + M750_INH(mcr); + } +} + +char *mc750[]={"0","1","2","3","4","5","6","7","8","9","10","11","12","13", + "14","15"}; + +struct mc750frame { + int mc5_bcnt; /* byte count == 0x28 */ + int mc5_summary; /* summary parameter (as above) */ + int mc5_va; /* virtual address register */ + int mc5_errpc; /* error pc */ + int mc5_mdr; + int mc5_svmode; /* saved mode register */ + int mc5_rdtimo; /* read lock timeout */ + int mc5_tbgpar; /* tb group parity error register */ + int mc5_cacherr; /* cache error register */ + int mc5_buserr; /* bus error register */ + int mc5_mcesr; /* machine check status register */ + int mc5_pc; /* trapped pc */ + int mc5_psl; /* trapped psl */ +}; + +#define MC750_TBERR 2 /* type code of cp tbuf par */ +#define MC750_TBPAR 4 /* tbuf par bit in mcesr */ + +ka750_mchk(cmcf) + caddr_t cmcf; +{ + register struct mc750frame *mcf = (struct mc750frame *)cmcf; + register int type = mcf->mc5_summary; + int mcsr = mfpr(PR_MCSR); + + printf("machine check %x: %s%s\n", type, mc750[type&0xf], + (type&0xf0) ? " abort" : " fault"); + printf( +"\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n", + mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode, + mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr); + printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n", + mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl, + mcsr); + mtpr(0, PR_TBIA); + mtpr(0xf, PR_MCESR); + if (type == MC750_TBERR && (mcf->mc5_mcesr&0xe) == MC750_TBPAR) { + printf("tbuf par: flushing and returning\n"); + return (0); + } + return (-1); +} +#endif diff --git a/sys/arch/vax/vax/locore.c b/sys/arch/vax/vax/locore.c new file mode 100644 index 00000000000..ffb7b9b42f9 --- /dev/null +++ b/sys/arch/vax/vax/locore.c @@ -0,0 +1,149 @@ +/* $NetBSD: locore.c,v 1.8 1995/06/16 15:36:42 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#include "sys/param.h" +#include "sys/types.h" +#include "sys/reboot.h" + +#include "vm/vm.h" + +#include "machine/cpu.h" +#include "machine/sid.h" +#include "machine/uvaxII.h" +#include "machine/loconf.h" +#include "machine/param.h" +#include "machine/vmparam.h" +#include "machine/pcb.h" + +#define ROUND_PAGE(x) (((uint)(x)+PAGE_SIZE-1)& ~(PAGE_SIZE-1)) + +u_int proc0paddr; +volatile int cpunumber, *Sysmap, boothowto, cpu_type; +volatile char *esym; +extern volatile int bootdev; + +/* + * Start is called from boot; the first routine that is called + * in kernel. Kernel stack is setup somewhere in a safe place; + * but we need to move it to a better known place. Memory + * management is disabled, and no interrupt system is active. + * We shall be at kernel stack when called; not interrupt stack. + */ + +start(how, dev) +{ + extern u_int *end; + extern void *scratch; + register curtop; + + mtpr(0x1f,PR_IPL); /* No interrupts before istack is ok, please */ +#ifdef COMPAT_RENO + asm(" + movl r9,_esym + movl r10,_bootdev + movl r11,_boothowto + jsb ett +ett: cmpl (sp)+,$0x80000000 + bleq tvo # New boot + pushl $0x001f0000 + pushl $to_kmem + rei +tvo: movl (sp)+,_boothowto + movl (sp)+,_bootdev +to_kmem: + "); +#else + bootdev=dev; + boothowto=how; +#endif + +/* + * FIRST we must set up kernel stack, directly after end. + * This is the only thing we have to setup here, rest in pmap. + */ + + PAGE_SIZE = NBPG*2; /* Set logical page size */ +#ifdef DDB + if ((boothowto & RB_KDB) != 0) + proc0paddr = ROUND_PAGE(esym) | 0x80000000; + else +#endif + proc0paddr = ROUND_PAGE(&end); + + mtpr(proc0paddr, PR_PCBB); /* must be set before ksp for some cpus */ + mtpr(proc0paddr+UPAGES*NBPG,PR_KSP); /* new kernel stack */ + + /* + * Set logical page size and put Sysmap on its place. + */ + Sysmap=(u_int *)ROUND_PAGE(mfpr(PR_KSP)); + + /* Be sure some important internal registers have safe values */ + ((struct pcb *)proc0paddr)->P0LR = 0; + ((struct pcb *)proc0paddr)->P0BR = 0; + ((struct pcb *)proc0paddr)->P1LR = 0; + ((struct pcb *)proc0paddr)->P1BR = (void *)0x80000000; + ((struct pcb *)proc0paddr)->iftrap = NULL; + mtpr(0,PR_P0LR); + mtpr(0,PR_P0BR); + mtpr(0,PR_P1LR); + mtpr(0x80000000,PR_P1BR); + + mtpr(512,PR_SCBB); /* SCB at physical addr 512 */ + mtpr(0,PR_ESP); /* Must be zero, used in page fault routine */ + mtpr(AST_NO,PR_ASTLVL); + + cninit(); + + /* Count up memory etc... early machine dependent routines */ + if((cpunumber=MACHID(mfpr(PR_SID)))>VAX_MAX) cpunumber=0; + cpu_type=mfpr(PR_SID); +#if VAX630 || VAX410 + if (cpunumber == VAX_78032) + cpu_type=(((*UVAXIISID) >> 24) & 0xff)|(cpu_type & 0xff000000); +#endif + pmap_bootstrap(); + + ((struct pcb *)proc0paddr)->framep = scratch; + + /* + * change mode down to userspace is done by faking an stack + * frame that is setup in cpu_set_kpc(). Not done by returning + * from main anymore. + */ + main(); + + /* NOTREACHED */ +} diff --git a/sys/arch/vax/vax/machdep.c b/sys/arch/vax/vax/machdep.c new file mode 100644 index 00000000000..b50c1a9bd8f --- /dev/null +++ b/sys/arch/vax/vax/machdep.c @@ -0,0 +1,715 @@ +/* $NetBSD: machdep.c,v 1.19.2.1 1995/10/15 14:06:18 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. + * All rights reserved. + * + * Changed for the VAX port (and for readability) /IC + * + * This code is derived from software contributed to Berkeley by the Systems + * Programming Group of the University of Utah Computer Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: machdep.c 1.63 91/04/24 + * + * @(#)machdep.c 7.16 (Berkeley) 6/3/91 + */ + +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/map.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/time.h" +#include "sys/signal.h" +#include "sys/kernel.h" +#include "sys/reboot.h" +#include "sys/msgbuf.h" +#include "sys/buf.h" +#include "sys/mbuf.h" +#include "sys/reboot.h" +#include "sys/conf.h" +#include "sys/callout.h" +#include "sys/device.h" +#include "sys/exec.h" +#include "sys/mount.h" +#ifdef SYSVMSG +#include "sys/msg.h" +#endif +#ifdef SYSVSEM +#include "sys/sem.h" +#endif +#ifdef SYSVSHM +#include "sys/shm.h" +#endif +#include "machine/sid.h" +#include "machine/pte.h" +#include "machine/mtpr.h" +#include "machine/cpu.h" +#include "machine/macros.h" +#include "machine/nexus.h" +#include "machine/trap.h" +#include "machine/reg.h" +#include "machine/../vax/gencons.h" +#include "vm/vm_kern.h" +#include "net/netisr.h" + +#include <sys/syscallargs.h> + +#include "ppp.h" /* For NERISR_PPP */ + +/* + * We do these external declarations here, maybe they should be done + * somewhere else... + */ +int nmcr, nmba, numuba, cold = 1; +caddr_t mcraddr[MAXNMCR]; +int astpending; +int want_resched; +char machine[] = "vax"; +char cpu_model[100]; +int msgbufmapped = 0; +struct msgbuf *msgbufp; +int physmem; +struct cfdriver nexuscd; +int todrstopped = 0, glurg; +int dumpsize = 0; + +caddr_t allocsys __P((caddr_t)); + +#define valloclim(name, type, num, lim) \ + (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) + +#ifdef BUFPAGES +int bufpages = BUFPAGES; +#else +int bufpages = 0; +#endif +int nswbuf = 0; +#ifdef NBUF +int nbuf = NBUF; +#else +int nbuf = 0; +#endif + +cpu_startup() +{ + caddr_t v, tempaddr; + extern char version[]; + int base, residual, i, sz; + vm_offset_t minaddr, maxaddr; + vm_size_t size; + extern int cpu_type, boothowto, startpmapdebug; + extern unsigned int avail_end; + + /* + * Initialize error message buffer. + */ + msgbufmapped = 1; + +#ifdef VAX750 + if (cpunumber == VAX_750) + if (!mfpr(PR_TODR)) + mtpr(todrstopped = 1, PR_TODR); +#endif + /* + * Good {morning,afternoon,evening,night}. + */ + printf("%s\n", version); + printf("realmem = %d\n", avail_end); + physmem = btoc(avail_end); + panicstr = NULL; + mtpr(AST_NO, PR_ASTLVL); + spl0(); + + dumpsize = physmem + 1; + + /* + * Find out how much space we need, allocate it, and then give + * everything true virtual addresses. + */ + sz = (int) allocsys((caddr_t) 0); + if ((v = (caddr_t) kmem_alloc(kernel_map, round_page(sz))) == 0) + panic("startup: no room for tables"); + if (allocsys(v) - v != sz) + panic("startup: table size inconsistency"); + + /* + * Now allocate buffers proper. They are different than the above in + * that they usually occupy more virtual memory than physical. + */ + size = MAXBSIZE * nbuf; + buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *) & buffers, + &maxaddr, size, TRUE); + minaddr = (vm_offset_t) buffers; + if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t) 0, + &minaddr, size, FALSE) != KERN_SUCCESS) + panic("startup: cannot allocate buffers"); + if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { + /* don't want to alloc more physical mem than needed */ + bufpages = btoc(MAXBSIZE) * nbuf; + } + base = bufpages / nbuf; + residual = bufpages % nbuf; + for (i = 0; i < nbuf; i++) { + vm_size_t curbufsize; + vm_offset_t curbuf; + + /* + * First <residual> buffers get (base+1) physical pages + * allocated for them. The rest get (base) physical pages. + * + * The rest of each buffer occupies virtual space, but has no + * physical memory allocated for it. + */ + curbuf = (vm_offset_t) buffers + i * MAXBSIZE; + curbufsize = CLBYTES * (i < residual ? base + 1 : base); + vm_map_pageable(buffer_map, curbuf, curbuf + curbufsize, FALSE); + vm_map_simplify(buffer_map, curbuf); + } + + /* + * Allocate a submap for exec arguments. This map effectively limits + * the number of processes exec'ing at any time. + */ + exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, + 16 * NCARGS, TRUE); + + /* + * Finally, allocate mbuf pool. Since mclrefcnt is an off-size we + * use the more space efficient malloc in place of kmem_alloc. + */ + + mclrefcnt = (char *) malloc(NMBCLUSTERS + CLBYTES / MCLBYTES, + M_MBUF, M_NOWAIT); + bzero(mclrefcnt, NMBCLUSTERS + CLBYTES / MCLBYTES); + mb_map = kmem_suballoc(kernel_map, (vm_offset_t *) & mbutl, &maxaddr, + VM_MBUF_SIZE, FALSE); + /* + * Initialize callouts + */ + + callfree = callout; + for (i = 1; i < ncallout; i++) + callout[i - 1].c_next = &callout[i]; + callout[i - 1].c_next = NULL; + + printf("avail mem = %d\n", ptoa(cnt.v_free_count)); + printf("Using %d buffers containing %d bytes of memory.\n", + nbuf, bufpages * CLBYTES); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + + bufinit(); + + /* + * Configure the system. + */ + configure(); +} + +/* + * Allocate space for system data structures. We are given a starting + * virtual address and we return a final virtual address; along the way we + * set each data structure pointer. + * + * We call allocsys() with 0 to find out how much space we want, allocate that + * much and fill it with zeroes, and then call allocsys() again with the + * correct base virtual address. + */ +caddr_t +allocsys(v) + register caddr_t v; +{ + +#define valloc(name, type, num) \ + v = (caddr_t)(((name) = (type *)v) + (num)) + +#ifdef REAL_CLISTS + valloc(cfree, struct cblock, nclist); +#endif + valloc(callout, struct callout, ncallout); + valloc(swapmap, struct map, nswapmap = maxproc * 2); +#ifdef SYSVSHM + valloc(shmsegs, struct shmid_ds, shminfo.shmmni); +#endif +#ifdef SYSVSEM + valloc(sema, struct semid_ds, seminfo.semmni); + valloc(sem, struct sem, seminfo.semmns); + /* This is pretty disgusting! */ + valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); +#endif +#ifdef SYSVMSG + valloc(msgpool, char, msginfo.msgmax); + valloc(msgmaps, struct msgmap, msginfo.msgseg); + valloc(msghdrs, struct msg, msginfo.msgtql); + valloc(msqids, struct msqid_ds, msginfo.msgmni); +#endif + + /* + * Determine how many buffers to allocate (enough to hold 5% of total + * physical memory, but at least 16). Allocate 1/2 as many swap + * buffer headers as file i/o buffers. + */ + if (bufpages == 0) + if (physmem < btoc(2 * 1024 * 1024)) + bufpages = (physmem / 10) / CLSIZE; + else + bufpages = (physmem / 20) / CLSIZE; + if (nbuf == 0) { + nbuf = bufpages; + if (nbuf < 16) + nbuf = 16; + } + if (nswbuf == 0) { + nswbuf = (nbuf / 2) & ~1; /* force even */ + if (nswbuf > 256) + nswbuf = 256; /* sanity */ + } + valloc(swbuf, struct buf, nswbuf); + valloc(buf, struct buf, nbuf); + return v; +} + +long dumplo = 0; + +dumpconf() +{ + int nblks; + extern int dumpdev; + + /* + * XXX include the final RAM page which is not included in physmem. + */ + dumpsize = physmem + 1; + if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { + nblks = (*bdevsw[major(dumpdev)].d_psize) (dumpdev); + if (dumpsize > btoc(dbtob(nblks - dumplo))) + dumpsize = btoc(dbtob(nblks - dumplo)); + else if (dumplo == 0) + dumplo = nblks - btodb(ctob(dumpsize)); + } + /* + * Don't dump on the first CLBYTES (why CLBYTES?) in case the dump + * device includes a disk label. + */ + if (dumplo < btodb(CLBYTES)) + dumplo = btodb(CLBYTES); +} + +cpu_initclocks() +{ + (cpu_calls[cpunumber].cpu_clock) (); +} + +cpu_sysctl() +{ + printf("cpu_sysctl:\n"); + return (EOPNOTSUPP); +} + +void +setstatclockrate(hzrate) + int hzrate; +{ + panic("setstatclockrate"); +} + +consinit() +{ +#ifdef DDB + db_machine_init(); + ddb_init(); +#endif +} + +int +sys_sigreturn(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct trapframe *scf; + struct sigcontext *cntx; + + scf = p->p_addr->u_pcb.framep; + cntx = SCARG(uap, sigcntxp); + + /* Compatibility mode? */ + if ((cntx->sc_ps & (PSL_IPL | PSL_IS)) || + ((cntx->sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) || + (cntx->sc_ps & PSL_CM)) { + return (EINVAL); + } + if (cntx->sc_onstack & 01) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = cntx->sc_mask & ~sigcantmask; + + scf->fp = cntx->sc_fp; + scf->ap = cntx->sc_ap; + scf->pc = cntx->sc_pc; + scf->psl = cntx->sc_ps; + mtpr(cntx->sc_sp, PR_USP); + return (EJUSTRETURN); +} + +struct trampframe { + u_int sig; /* Signal number */ + u_int code; /* Info code */ + u_int scp; /* Pointer to struct sigcontext */ + u_int r0, r1, r2, r3, r4, r5; /* Registers saved when + * interrupt */ + u_int pc; /* Address of signal handler */ + u_int arg; /* Pointer to first (and only) sigreturn + * argument */ +}; + +void +sendsig(catcher, sig, mask, code) + sig_t catcher; + int sig, mask; + u_long code; +{ + struct proc *p = curproc; + struct sigacts *psp = p->p_sigacts; + struct trapframe *syscf; + struct sigcontext *sigctx; + struct trampframe *trampf; + u_int *cursp; + int oonstack; + extern char sigcode[], esigcode[]; + /* + * Allocate and validate space for the signal handler context. Note + * that if the stack is in P0 space, the call to grow() is a nop, and + * the useracc() check will fail if the process has not already + * allocated the space with a `brk'. We shall allocate space on the + * stack for both struct sigcontext and struct calls... + */ + /* First check what stack to work on */ + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && + (psp->ps_sigonstack & sigmask(sig))) { + cursp = (u_int *) (psp->ps_sigstk.ss_base + + psp->ps_sigstk.ss_size); + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + cursp = (u_int *) mfpr(PR_USP); + if ((u_int) cursp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) + (void) grow(p, (u_int) cursp); + + /* Set up positions for structs on stack */ + sigctx = (struct sigcontext *) ((u_int) cursp - + sizeof(struct sigcontext)); + trampf = (struct trampframe *) ((u_int) sigctx - + sizeof(struct trampframe)); + cursp = (u_int *) sigctx - 2; /* Place for pointer to arg list in + * sigreturn */ + + syscf = p->p_addr->u_pcb.framep; + if (useracc((caddr_t) cursp, sizeof(struct sigcontext) + + sizeof(struct trampframe), B_WRITE) == 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + SIGACTION(p, SIGILL) = SIG_DFL; + sig = sigmask(SIGILL); + p->p_sigignore &= ~sig; + p->p_sigcatch &= ~sig; + p->p_sigmask &= ~sig; + psignal(p, SIGILL); + return; + } + /* Set up pointers for sigreturn args */ + trampf->arg = (int) sigctx; + trampf->pc = (u_int) catcher; + trampf->scp = (int) sigctx; + trampf->code = code; + trampf->sig = sig; + + + sigctx->sc_pc = syscf->pc; + sigctx->sc_ps = syscf->psl; + sigctx->sc_ap = syscf->ap; + sigctx->sc_fp = syscf->fp; + sigctx->sc_sp = mfpr(PR_USP); + sigctx->sc_onstack = oonstack; + sigctx->sc_mask = mask; + + syscf->pc = (u_int) (((char *) PS_STRINGS) - (esigcode - sigcode)); + syscf->psl = PSL_U | PSL_PREVU; + syscf->ap = (u_int) cursp; + mtpr(cursp, PR_USP); +} + +int waittime = -1; + +boot(howto) + int howto; +{ + if ((howto & RB_NOSYNC) == 0 && waittime < 0) { + waittime = 0; + vfs_shutdown(); + /* + * If we've been adjusting the clock, the todr will be out of + * synch; adjust it now. + */ + resettodr(); + } + splhigh(); /* extreme priority */ + if (howto & RB_HALT) { + printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n"); + for (;;); + } else { + if (howto & RB_DUMP) + dumpsys(); + asm("movl %0,r5":: "g" (howto)); /* How to boot */ + mtpr(GC_BOOT, PR_TXDB); /* boot command */ + asm("halt"); + } +} + +netintr() +{ +#ifdef INET + if (netisr & (1 << NETISR_ARP)) { + netisr &= ~(1 << NETISR_ARP); + arpintr(); + } + if (netisr & (1 << NETISR_IP)) { + netisr &= ~(1 << NETISR_IP); + ipintr(); + } +#endif +#ifdef NS + if (netisr & (1 << NETISR_NS)) { + netisr &= ~(1 << NETISR_NS); + nsintr(); + } +#endif +#ifdef ISO + if (netisr & (1 << NETISR_ISO)) { + netisr &= ~(1 << NETISR_ISO); + clnlintr(); + } +#endif +#ifdef CCITT + if (netisr & (1 << NETISR_CCITT)) { + netisr &= ~(1 << NETISR_CCITT); + ccittintr(); + } +#endif +#if NPPP > 0 + if (netisr & (1 << NETISR_PPP)) { + pppintr(); + } +#endif +} + +machinecheck(frame) + u_int frame; +{ + if ((*cpu_calls[cpunumber].cpu_mchk) (frame) == 0) + return; + (*cpu_calls[cpunumber].cpu_memerr) (); + panic("machine check"); +} + +dumpsys() +{ + extern int dumpdev; + + msgbufmapped = 0; + if (dumpdev == NODEV) + return; + /* + * For dumps during autoconfiguration, if dump device has already + * configured... + */ + if (dumpsize == 0) + dumpconf(); + if (dumplo < 0) + return; + printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); + printf("dump "); + switch ((*bdevsw[major(dumpdev)].d_dump) (dumpdev)) { + + case ENXIO: + printf("device bad\n"); + break; + + case EFAULT: + printf("device not ready\n"); + break; + + case EINVAL: + printf("area improper\n"); + break; + + case EIO: + printf("i/o error\n"); + break; + + default: + printf("succeeded\n"); + break; + } +} + +fuswintr() +{ + panic("fuswintr: need to be implemented"); +} + +suibyte(base, byte) + int byte; + void *base; +{ + panic("suibyte: need to be implemented"); +} + +suswintr() +{ + panic("suswintr: need to be implemented"); +} + +int +process_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = p->p_addr->u_pcb.framep; + + regs->r0 = tf->r0; + regs->r1 = tf->r1; + regs->r2 = tf->r2; + regs->r3 = tf->r3; + regs->r4 = tf->r4; + regs->r5 = tf->r5; + regs->r6 = tf->r6; + regs->r7 = tf->r7; + regs->r8 = tf->r8; + regs->r9 = tf->r9; + regs->r10 = tf->r10; + regs->r11 = tf->r11; + regs->ap = tf->ap; + regs->fp = tf->fp; + regs->sp = mfpr(PR_USP); + regs->pc = tf->pc; + regs->psl = tf->psl; + return 0; +} + +int +process_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = p->p_addr->u_pcb.framep; + + tf->r0 = regs->r0; + tf->r1 = regs->r1; + tf->r2 = regs->r2; + tf->r3 = regs->r3; + tf->r4 = regs->r4; + tf->r5 = regs->r5; + tf->r6 = regs->r6; + tf->r7 = regs->r7; + tf->r8 = regs->r8; + tf->r9 = regs->r9; + tf->r10 = regs->r10; + tf->r11 = regs->r11; + tf->ap = regs->ap; + tf->fp = regs->fp; + mtpr(regs->sp, PR_USP); + tf->pc = regs->pc; + tf->psl = regs->psl; + return 0; +} + +int +process_set_pc(p, addr) + struct proc *p; + caddr_t addr; +{ + void *ptr; + struct trapframe *tf; + + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + ptr = (char *) p->p_addr->u_pcb.framep; + tf = ptr; + + tf->pc = (u_int) addr; + + return (0); +} + +int +process_sstep(p, sstep) + struct proc *p; +{ + void *ptr; + struct trapframe *tf; + + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + ptr = p->p_addr->u_pcb.framep; + tf = ptr; + + if (sstep) + tf->psl |= PSL_T; + else + tf->psl &= ~PSL_T; + + return (0); +} + +#undef setsoftnet +setsoftnet() +{ + panic("setsoftnet"); +} + +ns_cksum() +{ + panic("ns_cksum"); +} diff --git a/sys/arch/vax/vax/mem.c b/sys/arch/vax/vax/mem.c new file mode 100644 index 00000000000..645007fb8fe --- /dev/null +++ b/sys/arch/vax/vax/mem.c @@ -0,0 +1,191 @@ +/* $NetBSD: mem.c,v 1.7 1995/04/10 16:49:25 mycroft Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mem.c 8.3 (Berkeley) 1/12/94 + */ + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/buf.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/malloc.h> + +#include <machine/pte.h> +#include <machine/mtpr.h> + +#include <vm/vm.h> + +extern unsigned int vmmap, avail_end; +caddr_t zeropage; + +/*ARGSUSED*/ +int +mmopen(dev, flag, mode) + dev_t dev; + int flag, mode; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev, flag, mode) + dev_t dev; + int flag, mode; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + register vm_offset_t o, v; + register int c; + register struct iovec *iov; + int error = 0; + static int physlock; + + if (minor(dev) == 0) { + /* lock against other uses of shared vmmap */ + while (physlock > 0) { + physlock++; + error = tsleep((caddr_t)&physlock, PZERO | PCATCH, + "mmrw", 0); + if (error) + return (error); + } + physlock = 1; + } + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + switch (minor(dev)) { + +/* minor device 0 is physical memory */ + case 0: + v = uio->uio_offset; + if (v < 0 || v >= avail_end) { + error = EFAULT; + goto unlock; + } + pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, + trunc_page(v), uio->uio_rw == UIO_READ ? + VM_PROT_READ : VM_PROT_WRITE, TRUE); + o = uio->uio_offset & PGOFSET; + c = min(uio->uio_resid, (int)(NBPG - o)); + error = uiomove((caddr_t)vmmap + o, c, uio); + pmap_remove(pmap_kernel(), (vm_offset_t)vmmap, + (vm_offset_t)vmmap + NBPG); + continue; + +/* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + c = min(iov->iov_len, MAXPHYS); + if (!kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); + error = uiomove((caddr_t)v, c, uio); + continue; + +/* minor device 2 is EOF/RATHOLE */ + case 2: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + +/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ + case 12: + if (uio->uio_rw == UIO_WRITE) { + c = iov->iov_len; + break; + } + if (zeropage == NULL) { + zeropage = (caddr_t) + malloc(CLBYTES, M_TEMP, M_WAITOK); + bzero(zeropage, CLBYTES); + } + c = min(iov->iov_len, CLBYTES); + error = uiomove(zeropage, c, uio); + continue; + + default: + return (ENXIO); + } + if (error) + break; + iov->iov_base += c; + iov->iov_len -= c; + uio->uio_offset += c; + uio->uio_resid -= c; + } + if (minor(dev) == 0) { +unlock: + if (physlock > 1) + wakeup((caddr_t)&physlock); + physlock = 0; + } + return (error); +} + +int +mmmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + + return (EOPNOTSUPP); +} diff --git a/sys/arch/vax/vax/mscp.c b/sys/arch/vax/vax/mscp.c new file mode 100644 index 00000000000..a4af2b4bc08 --- /dev/null +++ b/sys/arch/vax/vax/mscp.c @@ -0,0 +1,962 @@ +/* $NetBSD: mscp.c,v 1.4.2.1 1995/10/15 14:18:52 ragge Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscp.c 7.5 (Berkeley) 12/16/90 + */ + +/* + * MSCP generic driver routines + */ + +#include "sys/param.h" +#include "sys/buf.h" +#include "sys/errno.h" +#include "sys/dkstat.h" +#include "sys/ioctl.h" +#include "sys/disklabel.h" +#include "sys/syslog.h" + +#include "../uba/ubavar.h" + +#include "mscp.h" +#include "mscpvar.h" + +#define PCMD PSWP /* priority for command packet waits */ + +/* + * During transfers, mapping info is saved in the buffer's b_resid. + */ +#define b_info b_resid + +/* + * Get a command packet. Second argument is true iff we are + * to wait if necessary. Return NULL if none are available and + * we cannot wait. + */ +struct mscp * +mscp_getcp(mi, canwait) + register struct mscp_info *mi; + int canwait; +{ +#define mri (&mi->mi_cmd) + register struct mscp *mp; + register int i; + int s = splbio(); + +again: + /* + * Ensure that we have some command credits, and + * that the next command packet is free. + */ + if (mi->mi_credits <= MSCP_MINCREDITS) { + if (!canwait) { + splx(s); + return (NULL); + } + mi->mi_wantcredits = 1; + sleep((caddr_t) &mi->mi_wantcredits, PCMD); + goto again; + } + i = mri->mri_next; + if (mri->mri_desc[i] & MSCP_OWN) { + if (!canwait) { + splx(s); + return (NULL); + } + mi->mi_wantcmd = 1; + sleep((caddr_t) &mi->mi_wantcmd, PCMD); + goto again; + } + mi->mi_credits--; + mri->mri_desc[i] &= ~MSCP_INT; + mri->mri_next = (mri->mri_next + 1) % mri->mri_size; + splx(s); + mp = &mri->mri_ring[i]; + + /* + * Initialise some often-zero fields. + * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + mp->mscp_msglen = MSCP_MSGLEN; + mp->mscp_flags = 0; + mp->mscp_modifier = 0; + mp->mscp_seq.seq_bytecount = 0; + mp->mscp_seq.seq_buffer = 0; + mp->mscp_seq.seq_mapbase = 0; +/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; +/*???*/ mp->mscp_sccc.sccc_copyspd = 0; + return (mp); +#undef mri +} + +#ifdef AVOID_EMULEX_BUG +int mscp_aeb_xor = 0x8000bb80; +#endif + +/* + * Do a device go. The driver calls this once it has allocated + * resources for the transfer. Save the resource information in + * bp->b_ubinfo, and finish the MSCP packet. + * + * N.B.: If we were blocked for some time, the drive could have gone + * off line and might still be that way. We should probably handle + * such a case by changing this command into an on line request and + * not dequeuing the transfer after all. + */ +mscp_go(mi, mp, info) + register struct mscp_info *mi; + register struct mscp *mp; + int info; +{ + register struct buf *bp, *dp; + + /* + * Now is also the time to move the transfer off the + * controller and drive queues, and shuffle the drive + * queue on the controller queue. The idea is to try + * to keep as many drives busy as possible---to deal + * the controller's credits out to the drives in a `fair + * share' arrangement. (To do this fully would be more + * trouble than it is worth, though.) + */ + dp = mi->mi_tab->b_actf; + bp = dp->b_actf; + dp->b_actf = bp->b_actf; /* transfer off drive queue */ + mi->mi_tab->b_actf = dp->b_hash.le_next;/* drive off ctlr queue */ + MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); /* then back again */ +/* Was: dp->b_actf = bp->av_forw; /* transfer off drive queue */ +/* Was: mi->mi_tab->b_actf = dp->b_forw;/* drive off ctlr queue */ +/* Was: MSCP_APPEND(dp, mi->mi_tab, b_forw); /* then back again */ + + /* + * Move the buffer to the I/O wait queue. + */ + { + struct buf *tmp; + + bp->b_actf=&mi->mi_wtab; + if(mi->mi_wtab.b_actf==&mi->mi_wtab){ + mi->mi_wtab.b_actf=bp; + } else { + tmp=mi->mi_wtab.b_actf; + while(tmp->b_actf!=&mi->mi_wtab) tmp=tmp->b_actf; + tmp->b_actf=bp; + }} + +/* Was: bp->av_back = mi->mi_wtab.av_back; +/* Was: bp->av_forw = &mi->mi_wtab; +/* Was: mi->mi_wtab.av_back->av_forw = bp; +/* Was: mi->mi_wtab.av_back = bp; + + /* + * Save the mapping info, finish the command packet, and give + * it to the device. The device's dgo routine should then + * initiate polling. + */ + bp->b_info = info; +#ifdef AVOID_EMULEX_BUG + /* + * The Emulex SC41/MS will occasionally zero the lower half word + * of the command reference number. The upper half word remains + * intact. To keep running, we convert the buffer address into + * a small but nonzero integer that is unique over all pending + * transfers, and store that value in the upper half word. To + * catch occurrances of the bug (so that we can gripe to Emulex), + * we also put a nonzero value in the lower word. + */ + { + register u_int i = mi->mi_nextbp; + + do { /* find a free value */ + if (mi->mi_bp[i] == 0) + goto found; + i = (i + 1) % AEB_MAX_BP; + } while (i != mi->mi_nextbp); + panic("mscp_go: AEB_MAX_BP too small"); +found: + mi->mi_bp[i++] = bp; + mi->mi_nextbp = i % AEB_MAX_BP; + mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor; + } +#else + mp->mscp_cmdref = (long) bp; +#endif + *mp->mscp_addr |= MSCP_OWN | MSCP_INT; +} + +/* + * Handle a response ring transition. + */ +mscp_dorsp(mi) + register struct mscp_info *mi; +{ + register struct uba_device *ui; + register struct buf *bp; + register struct mscp *mp; + register int nextrsp; + struct mscp_driver *md = mi->mi_md; + char *ctlrname, *drivename; + int st, error, info; + + ctlrname = md->md_mname; + drivename = md->md_dname; + nextrsp = mi->mi_rsp.mri_next; +loop: + if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) { + /* + * No more responses. Remember the next expected + * response index. Check to see if we have some + * credits back, and wake up sleepers if so. + */ + mi->mi_rsp.mri_next = nextrsp; + if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) { + mi->mi_wantcredits = 0; + wakeup((caddr_t) &mi->mi_wantcredits); + } + return; + } + + /* + * Found a response. Update credit information. If there is + * nothing else to do, jump to `done' to get the next response. + */ + mp = &mi->mi_rsp.mri_ring[nextrsp]; + mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc); + switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { + + case MSCPT_SEQ: + break; + + case MSCPT_DATAGRAM: + (*md->md_dgram)(mi, mp); + goto done; + + case MSCPT_CREDITS: + goto done; + + case MSCPT_MAINTENANCE: + default: + printf("%s%d: unit %d: unknown message type 0x%x ignored\n", + ctlrname, mi->mi_ctlr, mp->mscp_unit, + MSCP_MSGTYPE(mp->mscp_msgtc)); + goto done; + } + + /* + * Controllers are allowed to interrupt as any drive, so we + * must check the command before checking for a drive. + */ + if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) { + (*md->md_ctlrdone)(mi, mp); + goto done; + } + + /* + * Find the drive info. If there is none, and this is an + * available attention response, try configuring a new drive. + */ + if (mp->mscp_unit > md->md_ndpc) { + printf("%s%d: unit %d out of range\n", + ctlrname, mi->mi_ctlr, mp->mscp_unit); + goto done; + } + if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) { + if ((*md->md_unconf)(mi, mp) != MSCP_DONE) { + printf("%s%d: unit %d not configured, ", + ctlrname, mi->mi_ctlr, mp->mscp_unit); + if (mp->mscp_opcode == M_OP_AVAILATTN) + printf("available attn"); + else + printf("stray response op 0x%x status 0x%x", + mp->mscp_opcode, mp->mscp_status); + printf(" ignored\n"); + } + goto done; + } + + /* + * Handle individual responses. + */ + st = mp->mscp_status & M_ST_MASK; + error = 0; + switch (mp->mscp_opcode) { + + case M_OP_END: + /* + * The controller presents a bogus END packet when + * a read/write command is given with an illegal + * block number. This is contrary to the MSCP + * specification (ENDs are to be given only for + * invalid commands), but that is the way of it. + */ + if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) { + printf("%s%d: bad lbn (%d)?\n", drivename, + ui->ui_unit, mp->mscp_seq.seq_lbn); + error = EIO; + goto rwend; + } + goto unknown; + + case M_OP_ONLINE | M_OP_END: + /* + * Finished an ON LINE request. Call the driver to + * find out whether it succeeded. If so, mark it on + * line. + */ + if (ui->ui_flags & UNIT_ONLINE) { + printf("%s%d: duplicate ONLINE ignored\n", + drivename, ui->ui_unit); + break; + } + if ((*md->md_online)(ui, mp) == MSCP_DONE) + ui->ui_flags |= UNIT_ONLINE; + break; + + case M_OP_GETUNITST | M_OP_END: + /* + * Got unit status. Call the driver to find out + * whether it succeeded, and if so, mark it. + */ + if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE) + ui->ui_flags |= UNIT_HAVESTATUS; + break; + + case M_OP_AVAILATTN: + /* + * The drive went offline and we did not notice. + * Mark it off line now, to force an on line request + * next, so we can make sure it is still the same + * drive. + * + * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS + * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON + * LINE. IS IT WORTH FIXING?? + */ + ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); +#ifdef notyet + (*md->md_offline)(ui, mp); +#endif + break; + + case M_OP_READ | M_OP_END: + case M_OP_WRITE | M_OP_END: + /* + * A transfer finished. Get the buffer, and release its + * map registers via ubadone(). If the command finished + * with an off line or available status, the drive went + * off line (the idiot controller does not tell us until + * it comes back *on* line, or until we try to use it). + */ + if (mp->mscp_cmdref == 0) { + /* + * No buffer means there is a bug somewhere! + */ + printf("%s%d: io done, but no buffer?\n", + drivename, ui->ui_unit); + mscp_hexdump(mp); + break; + } + +rwend: +#ifdef AVOID_EMULEX_BUG + { + register u_short *p = (u_short *) &mp->mscp_cmdref; + + /* + * Note any errors on the part of the controller. + * The lower word should be zero after exclusive + * or'ing with mscp_aeb_xor, and the upper should + * then be in the range [1..AEB_MAX_BP]. + */ + mp->mscp_cmdref ^= mscp_aeb_xor; + p[1]--; + if (p[1] >= AEB_MAX_BP) + panic("unrecoverable Emulex screwup"); + if (p[0] == 0) + mi->mi_ok++; + else { + /* + * Calculate the expected response, + * assuming p[1] is correct. The + * actual response is then the expected + * response xor p[0]. + */ + int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor; + + log(LOG_WARNING, "\ +Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n", + ctlrname, mi->mi_ctlr, + mi->mi_ok, sb, sb ^ p[0]); + mi->mi_ok = 0; + } + /* convert index back to buffer, and mark free */ + bp = mi->mi_bp[p[1]]; + mi->mi_bp[p[1]] = 0; + } +#else + bp = (struct buf *) mp->mscp_cmdref; +#ifdef MSCP_PARANOIA + { + register struct buf *q = mi->mi_wtab.av_forw; + + /* + * Ensure that this response corresponds to + * some outstanding request. If not, ignore + * it entirely. This will likely cause a + * Unibus reset soon, after which the controller + * just might behave. + */ + while (q != bp && q != &mi->mi_wtab) + q = q->av_forw; + if (q != bp) { + printf("%s%d: bad response packet ignored\n", + ctlrname, mi->mi_ctlr); + mscp_hexdump(mp); + goto out; + } + } +#endif MSCP_PARANOIA +#endif AVOID_EMULEX_BUG + + /* + * Mark any error-due-to-bad-LBN (via `goto rwend'). + * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE + * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + if (error) { + bp->b_flags |= B_ERROR; + bp->b_error = error; + } + if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) { + ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); +#ifdef notyet + (*md->md_offline)(ui, mp); +#endif + } + + /* + * Unlink the transfer from the wait queue mi_wtab. + * If there are no more transfers on the drive queue + * for this drive, and it is a profiled disk, turn + * off its busy bit. + */ + + + { /* Insane */ + struct buf *tmp; + + tmp=bp->b_actf; + if(!tmp){ + printf("Found 0 - bad!\n"); + asm("halt"); + } + while(tmp->b_actf!=bp){ + if(!tmp){ + printf("Got lost in chains...\n"); + asm("halt"); + } + tmp=tmp->b_actf; + } + tmp->b_actf=bp->b_actf; + } + if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_hash.le_next == NULL) + dk_busy &= ~(1 << ui->ui_dk); + +/* Was: bp->av_back->av_forw = bp->av_forw; + bp->av_forw->av_back = bp->av_back; + if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL) + dk_busy &= ~(1 << ui->ui_dk); +*/ + /* + * If the transfer has something to do with bad + * block forwarding, let the driver handle the + * rest. + */ + if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) { + (*md->md_bb)(ui, mp, bp); + goto out; + } + + /* + * If the transfer failed, give the driver a crack + * at fixing things up. + */ + if (st != M_ST_SUCCESS) { + switch ((*md->md_ioerr)(ui, mp, bp)) { + + case MSCP_DONE: /* fixed */ + break; + + case MSCP_RESTARTED: /* still working on it */ + goto out; + + case MSCP_FAILED: /* no luck */ + diskerr(bp, drivename, "hard error", + LOG_PRINTF, -1, md->md_lab ? + &md->md_lab[ui->ui_unit] : md->md_lab); + mscp_printevent(mp); + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + break; + } + } + + /* + * Set the residual count and mark the transfer as + * done. If the I/O wait queue is now empty, release + * the shared BDP, if any. + */ + info = bp->b_info; /* we are about to clobber it */ + bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; + (*md->md_iodone)(mi, bp, info); +out: + break; + + case M_OP_REPLACE | M_OP_END: + /* + * A replace operation finished. Just let the driver + * handle it (if it does replaces). + */ + if (md->md_replace == NULL) + printf("%s%d: bogus REPLACE end\n", + drivename, ui->ui_unit); + else + (*md->md_replace)(ui, mp); + break; + + default: + /* + * If it is not one of the above, we cannot handle it. + * (And we should not have received it, for that matter.) + */ +unknown: + printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n", + mi->mi_md->md_dname, ui->ui_unit, + mp->mscp_opcode, mp->mscp_status); + mscp_hexdump(mp); + break; + } + + /* + * If the drive needs to be put back in the controller queue, + * do that now. (`bp' below ought to be `dp', but they are all + * struct buf *.) Note that b_active was cleared in the driver; + * we presume that there is something to be done, hence reassert it. + */ + if (ui->ui_flags & UNIT_REQUEUE) { + bp = &md->md_utab[ui->ui_unit]; + if (bp->b_active) panic("mscp_dorsp requeue"); + MSCP_APPEND(bp, mi->mi_tab, b_hash.le_next); +/* Was: MSCP_APPEND(bp, mi->mi_tab, b_forw); */ + bp->b_active = 1; + ui->ui_flags &= ~UNIT_REQUEUE; + } + +done: + /* + * Give back the response packet, and take a look at the next. + */ + mp->mscp_msglen = MSCP_MSGLEN; + mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; + nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; + goto loop; +} + +/* + * Dump the entire contents of an MSCP packet in hex. Mainly useful + * for debugging.... + */ +mscp_hexdump(mp) + register struct mscp *mp; +{ + register long *p = (long *) mp; + register int i = mp->mscp_msglen; + + if (i > 256) /* sanity */ + i = 256; + i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ + while (--i >= 0) + printf("0x%x ", *p++); + printf("\n"); +} + +/* + * Requeue outstanding transfers, e.g., after bus reset. + * Also requeue any drives that have on line or unit status + * info pending. + */ +mscp_requeue(mi) + struct mscp_info *mi; +{ + register struct uba_device *ui; + register struct mscp_driver *md = mi->mi_md; + register struct buf *bp, *dp; + register int unit; + struct buf *nextbp; + + /* + * Clear the controller chain. Mark everything un-busy; we + * will soon fix any that are in fact busy. + */ + mi->mi_tab->b_actf = NULL; + mi->mi_tab->b_active = 0; + for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { + ui = md->md_dinfo[unit]; + if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) + continue; /* not ours */ + dp->b_hash.le_next = NULL; + dp->b_active = 0; + } + + /* + * Scan the wait queue, linking buffers onto drive queues. + * Note that these must be put at the front of the drive queue, + * lest we reorder I/O operations. + */ + for (bp = *mi->mi_wtab.b_actb; bp != &mi->mi_wtab; bp = nextbp) { + nextbp = *bp->b_actb; + dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; + bp->b_actf = dp->b_actf; + if (dp->b_actf == NULL) + dp->b_actb = (void *)bp; + dp->b_actf = bp; + } + mi->mi_wtab.b_actf = *mi->mi_wtab.b_actb = &mi->mi_wtab; + + /* + * Scan for drives waiting for on line or status responses, + * and for drives with pending transfers. Put these on the + * controller queue, and mark the controller busy. + */ + for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { + ui = md->md_dinfo[unit]; + if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) + continue; + ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); + if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) + continue; + ui->ui_flags &= ~UNIT_REQUEUE; + MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); + + dp->b_active = 1; + mi->mi_tab->b_active = 1; + } + +#ifdef AVOID_EMULEX_BUG + /* + * ... and clear the index-to-buffer table. + */ + for (unit = 0; unit < AEB_MAX_BP; unit++) + mi->mi_bp[unit] = 0; +#endif +} + + +/* + * MSCP error reporting + */ + +/* + * Messages for the various subcodes. + */ +static char unknown_msg[] = "unknown subcode"; + +/* + * Subcodes for Success (0) + */ +static char *succ_msgs[] = { + "normal", /* 0 */ + "spin down ignored", /* 1 = Spin-Down Ignored */ + "still connected", /* 2 = Still Connected */ + unknown_msg, + "dup. unit #", /* 4 = Duplicate Unit Number */ + unknown_msg, + unknown_msg, + unknown_msg, + "already online", /* 8 = Already Online */ + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + unknown_msg, + "still online", /* 16 = Still Online */ +}; + +/* + * Subcodes for Invalid Command (1) + */ +static char *icmd_msgs[] = { + "invalid msg length", /* 0 = Invalid Message Length */ +}; + +/* + * Subcodes for Command Aborted (2) + */ +/* none known */ + +/* + * Subcodes for Unit Offline (3) + */ +static char *offl_msgs[] = { + "unknown drive", /* 0 = Unknown, or online to other ctlr */ + "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ + "inoperative", /* 2 = Unit Inoperative */ + unknown_msg, + "duplicate", /* 4 = Duplicate Unit Number */ + unknown_msg, + unknown_msg, + unknown_msg, + "in diagnosis", /* 8 = Disabled by FS or diagnostic */ +}; + +/* + * Subcodes for Unit Available (4) + */ +/* none known */ + +/* + * Subcodes for Media Format Error (5) + */ +static char *media_fmt_msgs[] = { + "fct unread - edc", /* 0 = FCT unreadable */ + "invalid sector header",/* 1 = Invalid Sector Header */ + "not 512 sectors", /* 2 = Not 512 Byte Sectors */ + "not formatted", /* 3 = Not Formatted */ + "fct ecc", /* 4 = FCT ECC */ +}; + +/* + * Subcodes for Write Protected (6) + * N.B.: Code 6 subcodes are 7 bits higher than other subcodes + * (i.e., bits 12-15). + */ +static char *wrprot_msgs[] = { + unknown_msg, + "software", /* 1 = Software Write Protect */ + "hardware", /* 2 = Hardware Write Protect */ +}; + +/* + * Subcodes for Compare Error (7) + */ +/* none known */ + +/* + * Subcodes for Data Error (8) + */ +static char *data_msgs[] = { + "forced error", /* 0 = Forced Error (software) */ + unknown_msg, + "header compare", /* 2 = Header Compare Error */ + "sync timeout", /* 3 = Sync Timeout Error */ + unknown_msg, + unknown_msg, + unknown_msg, + "uncorrectable ecc", /* 7 = Uncorrectable ECC */ + "1 symbol ecc", /* 8 = 1 bit ECC */ + "2 symbol ecc", /* 9 = 2 bit ECC */ + "3 symbol ecc", /* 10 = 3 bit ECC */ + "4 symbol ecc", /* 11 = 4 bit ECC */ + "5 symbol ecc", /* 12 = 5 bit ECC */ + "6 symbol ecc", /* 13 = 6 bit ECC */ + "7 symbol ecc", /* 14 = 7 bit ECC */ + "8 symbol ecc", /* 15 = 8 bit ECC */ +}; + +/* + * Subcodes for Host Buffer Access Error (9) + */ +static char *host_buffer_msgs[] = { + unknown_msg, + "odd xfer addr", /* 1 = Odd Transfer Address */ + "odd xfer count", /* 2 = Odd Transfer Count */ + "non-exist. memory", /* 3 = Non-Existent Memory */ + "memory parity", /* 4 = Memory Parity Error */ +}; + +/* + * Subcodes for Controller Error (10) + */ +static char *cntlr_msgs[] = { + unknown_msg, + "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ + "edc", /* 2 = Error Detection Code? */ + "inconsistant internal data struct",/* 3 = Internal Error */ +}; + +/* + * Subcodes for Drive Error (11) + */ +static char *drive_msgs[] = { + unknown_msg, + "sdi command timeout", /* 1 = SDI Command Timeout */ + "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ + "positioner", /* 3 = Positioner Error */ + "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ + "drive clock dropout", /* 5 = Lost Drive Clock */ + "lost recvr ready", /* 6 = Lost Receiver Ready */ + "drive detected error", /* 7 = Drive Error */ + "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ +}; + +/* + * The following table correlates message codes with the + * decoding strings. + */ +struct code_decode { + char *cdc_msg; + int cdc_nsubcodes; + char **cdc_submsgs; +} code_decode[] = { +#define SC(m) sizeof (m) / sizeof (m[0]), m + "success", SC(succ_msgs), + "invalid command", SC(icmd_msgs), + "command aborted", 0, 0, + "unit offline", SC(offl_msgs), + "unit available", 0, 0, + "media format error", SC(media_fmt_msgs), + "write protected", SC(wrprot_msgs), + "compare error", 0, 0, + "data error", SC(data_msgs), + "host buffer access error", SC(host_buffer_msgs), + "controller error", SC(cntlr_msgs), + "drive error", SC(drive_msgs), +#undef SC +}; + +/* + * Print the decoded error event from an MSCP error datagram. + */ +mscp_printevent(mp) + struct mscp *mp; +{ + register int event = mp->mscp_event; + register struct code_decode *cdc; + int c, sc; + char *cm, *scm; + + /* + * The code is the lower six bits of the event number (aka + * status). If that is 6 (write protect), the subcode is in + * bits 12-15; otherwise, it is in bits 5-11. + * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + c = event & M_ST_MASK; + sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; + if (c >= sizeof code_decode / sizeof code_decode[0]) + cm = "- unknown code", scm = "??"; + else { + cdc = &code_decode[c]; + cm = cdc->cdc_msg; + if (sc >= cdc->cdc_nsubcodes) + scm = unknown_msg; + else + scm = cdc->cdc_submsgs[sc]; + } + printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); +} + +/* + * Print the code and logical block number for an error packet. + * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE + * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ +mscp_decodeerror(name, ctlr, mp) + char *name; + int ctlr; + register struct mscp *mp; +{ + /* + * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and + * the logical block number. Code 0 is a regular block; code 6 + * is a replacement block. The remaining codes are currently + * undefined. The code is in the upper four bits of the header + * (bits 0-27 are the lbn). + */ + int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); + static char *codemsg[16] = { + "lbn", "code 1", "code 2", "code 3", + "code 4", "code 5", "rbn", "code 7", + "code 8", "code 9", "code 10", "code 11", + "code 12", "code 13", "code 14", "code 15" + }; +#define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) +#define BADLBN(h) ((h) & 0xfffffff) + + printf("%s%d: %s error datagram%s:", name, ctlr, + issoft ? "soft" : "hard", + mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); + switch (mp->mscp_format & 0377) { + + case M_FM_CTLRERR: /* controller error */ + break; + + case M_FM_BUSADDR: /* host memory access error */ + printf(" memory addr 0x%x:", mp->mscp_erd.erd_busaddr); + break; + + case M_FM_DISKTRN: + printf(" unit %d: level %d retry %d, %s %d:", + mp->mscp_unit, + mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, + BADCODE(mp->mscp_erd.erd_hdr), + BADLBN(mp->mscp_erd.erd_hdr)); + break; + + case M_FM_SDI: + printf(" unit %d: %s %d:", mp->mscp_unit, + BADCODE(mp->mscp_erd.erd_hdr), + BADLBN(mp->mscp_erd.erd_hdr)); + break; + + case M_FM_SMLDSK: + printf(" unit %d: small disk error, cyl %d:", + mp->mscp_unit, mp->mscp_erd.erd_sdecyl); + break; + + default: + printf(" unit %d: unknown error, format 0x%x:", + mp->mscp_unit, mp->mscp_format); + } + mscp_printevent(mp); +#undef BADCODE +#undef BADLBN +} diff --git a/sys/arch/vax/vax/mscp.h b/sys/arch/vax/vax/mscp.h new file mode 100644 index 00000000000..76817ce5984 --- /dev/null +++ b/sys/arch/vax/vax/mscp.h @@ -0,0 +1,472 @@ +/* $NetBSD: mscp.h,v 1.2 1994/10/26 08:03:18 cgd Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscp.h 7.5 (Berkeley) 6/28/90 + */ + +/* + * Definitions for the Mass Storage Control Protocol + * I WISH I KNEW WHAT MORE OF THESE WERE. IT SURE WOULD BE NICE + * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. + */ + +/* + * Control message opcodes + */ +#define M_OP_ABORT 0x01 /* Abort command */ +#define M_OP_GETCMDST 0x02 /* Get command status command */ +#define M_OP_GETUNITST 0x03 /* Get unit status command */ +#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */ +#define M_OP_SEREX 0x07 /* Serious exception end message */ +#define M_OP_AVAILABLE 0x08 /* Available command */ +#define M_OP_ONLINE 0x09 /* Online command */ +#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */ +#define M_OP_DTACCPATH 0x0b /* Determine access paths command */ +#define M_OP_ACCESS 0x10 /* Access command */ +#define M_OP_COMPCD 0x11 /* Compare controller data command */ +#define M_OP_ERASE 0x12 /* Erase command */ +#define M_OP_FLUSH 0x13 /* Flush command */ +#define M_OP_REPLACE 0x14 /* Replace command */ +#define M_OP_COMPHD 0x20 /* Compare host data command */ +#define M_OP_READ 0x21 /* Read command */ +#define M_OP_WRITE 0x22 /* Write command */ +#define M_OP_AVAILATTN 0x40 /* Available attention message */ +#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */ +#define M_OP_ACCPATH 0x42 /* Access path attention message */ +#define M_OP_END 0x80 /* End message flag */ + + +/* + * Generic command modifiers + */ +#define M_MD_EXPRS 0x8000 /* Express request */ +#define M_MD_COMP 0x4000 /* Compare */ +#define M_MD_CLSEX 0x2000 /* Clear serious exception */ +#define M_MD_ERROR 0x1000 /* Force error */ +#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */ +#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */ +#define M_MD_SECOR 0x0200 /* Suppress error correction */ +#define M_MD_SEREC 0x0100 /* Suppress error recovery */ +#define M_MD_SSHDW 0x0080 /* Suppress shadowing */ +#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */ +#define M_MD_WBKVL 0x0020 /* Write back (volatile) */ +#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */ + +/* + * AVAILABLE command modifiers + */ +#define M_AVM_ALLCD 0x0002 /* All class drivers */ +#define M_AVM_SPINDOWN 0x0001 /* Spin down */ + +/* + * FLUSH command modifiers + */ +#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */ +#define M_FLM_VOLATILE 0x0002 /* Volatile only */ + +/* + * GET UNIT STATUS command modifiers + */ +#define M_GUM_NEXTUNIT 0x0001 /* Next unit */ + +/* + * ONLINE command modifiers + */ +#define M_OLM_RIP 0x0001 /* Allow self destruction */ +#define M_OLM_IGNMF 0x0002 /* Ignore media format error */ + +/* + * ONLINE and SET UNIT CHARACTERISTICS command modifiers + */ +#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */ +#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */ +#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */ +#define M_OSM_SETWRPROT 0x0004 /* Set write protect */ + +/* + * REPLACE command modifiers + */ +#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */ + +/* + * End message flags + */ +#define M_EF_BBLKR 0x80 /* Bad block reported */ +#define M_EF_BBLKU 0x40 /* Bad block unreported */ +#define M_EF_ERLOG 0x20 /* Error log generated */ +#define M_EF_SEREX 0x10 /* Serious exception */ + +/* + * Controller flags + */ +#define M_CF_ATTN 0x80 /* Enable attention messages */ +#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */ +#define M_CF_OTHER 0x20 /* Enable other host's error log messages */ +#define M_CF_THIS 0x10 /* Enable this host's error log messages */ +#define M_CF_MLTHS 0x04 /* Multi-host */ +#define M_CF_SHADW 0x02 /* Shadowing */ +#define M_CF_576 0x01 /* 576 byte sectors */ + +/* + * Unit flags + */ +#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */ +#define M_UF_INACT 0x4000 /* Inactive shadow set unit */ +#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */ +#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */ +#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */ +#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */ +#define M_UF_RMVBL 0x0080 /* Removable media */ +#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */ +#define M_UF_576 0x0004 /* 576 byte sectors */ +#define M_UF_CMPWR 0x0002 /* Compare writes */ +#define M_UF_CMPRD 0x0001 /* Compare reads */ + +/* + * Error Log message format codes + */ +#define M_FM_CTLRERR 0x00 /* Controller error */ +#define M_FM_BUSADDR 0x01 /* Host memory access error */ +#define M_FM_DISKTRN 0x02 /* Disk transfer error */ +#define M_FM_SDI 0x03 /* SDI error */ +#define M_FM_SMLDSK 0x04 /* Small disk error */ + +/* + * Error Log message flags + */ +#define M_LF_SUCC 0x80 /* Operation successful */ +#define M_LF_CONT 0x40 /* Operation continuing */ +#define M_LF_SQNRS 0x01 /* Sequence number reset */ + +/* + * Status codes + */ +#define M_ST_MASK 0x1f /* Status code mask */ +#define M_ST_SUCCESS 0x00 /* Success */ +#define M_ST_INVALCMD 0x01 /* Invalid command */ +#define M_ST_ABORTED 0x02 /* Command aborted */ +#define M_ST_OFFLINE 0x03 /* Unit offline */ +#define M_ST_AVAILABLE 0x04 /* Unit available */ +#define M_ST_MFMTERR 0x05 /* Media format error */ +#define M_ST_WRPROT 0x06 /* Write protected */ +#define M_ST_COMPERR 0x07 /* Compare error */ +#define M_ST_DATAERR 0x08 /* Data error */ +#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */ +#define M_ST_CTLRERR 0x0a /* Controller error */ +#define M_ST_DRIVEERR 0x0b /* Drive error */ +#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */ + +/* + * Subcodes of M_ST_OFFLINE + */ +#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */ +#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */ +#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */ +#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */ +#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */ + +/* + * An MSCP packet begins with a header giving the length of + * the entire packet (including the header itself)(?), two bytes + * of device specific data, and the a whole bunch of variants + * depending on message type. + * + * N.B.: In most cases we distinguish between a `command' and + * an `end' variant as well. The command variant is that which + * is given to the controller; the `end' variant is its response. + */ + +/* + * Generic sequential message variant (command and response). + */ +struct mscpv_seq { + long seq_bytecount; /* byte count */ +#define seq_rbn seq_bytecount /* aka RBN (replace) */ +#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */ + long seq_buffer; /* buffer descriptor */ + long seq_mapbase; /* page map (first PTE) phys address */ + long seq_xxx1; /* ? */ /* unused */ + long seq_lbn; /* logical block number */ + long seq_xxx2; /* ? */ /* unused */ + long *seq_addr; /* pointer to cmd descriptor */ + long seq_software[4]; /* reserved to software; unused */ +}; + +/* + * Set Controller Characteristics command variant + */ +struct mscpv_sccc { + u_short sccc_version; /* MSCP version number */ + u_short sccc_ctlrflags; /* controller flags */ + u_short sccc_hosttimo; /* host timeout */ + u_short sccc_usefrac; /* use fraction */ + long sccc_time; /* time and date */ + long sccc_xxx1; /* ? */ + long sccc_errlgfl; /* ? */ + short sccc_xxx2; /* ? */ + short sccc_copyspd; /* ? */ +}; + +/* + * Set Controller Characteristics end variant + */ +struct mscpv_scce { + u_short scce_version; /* MSCP version number */ + u_short scce_ctlrflags; /* controller flags */ + u_short scce_ctlrtimo; /* controller timeout */ + u_short scce_ctlrcmdl; /* ??? */ + quad_t scce_ctlrid; /* controller ID */ + long scce_xxx[3]; /* ? */ + long scce_volser; /* volume serial number */ +}; + +/* + * On Line command variant + */ +struct mscpv_onlc { + long onlc_xxx1[4]; /* ? */ + long onlc_errlgfl; /* error log flag? */ + short onlc_xxx2; /* ? */ + short onlc_copyspd; /* copy speed? */ +}; + +/* + * On Line end variant + */ +struct mscpv_onle { + long onle_xxx1[3]; /* ? */ +/*???*/ short onle_xxx2; /* ? */ + u_char onle_drivetype; /* drive type index (same in guse) */ + char onle_xxx3; /* ? */ + long onle_mediaid; /* media type id (same in guse) */ + long onle_xxx4; /* ? */ + long onle_unitsize; /* unit size in sectors */ + long onle_volser; /* volume serial number */ +}; + +/* + * Get Unit Status end variant (and Avail Attn?) + */ +struct mscpv_guse { + u_short guse_multunit; /* multi-unit code */ + u_short guse_unitflags; /* unit flags */ + long guse_hostid; /* host id */ + long guse_unitid0; /*???*/ + short guse_unitid1; /*???*/ + u_char guse_drivetype; /* drive type index */ + u_char guse_unitid2; /*???*/ + long guse_mediaid; /* media type id (encoded) */ + short guse_shadowunit; /* shadow unit */ + short guse_shadowstat; /* shadow status */ + u_short guse_nspt; /* sectors per track */ + u_short guse_group; /* track group size */ + u_short guse_ngpc; /* groups per cylinder */ + u_short guse_xxx; /* reserved */ + u_short guse_rctsize; /* RCT size (sectors) */ + u_char guse_nrpt; /* RBNs per track */ + u_char guse_nrct; /* number of RCTs */ +}; + +/* + * Macros to break up and build media IDs. An ID encodes the port + * type in the top 10 bits, and the drive type in the remaining 22. + * The 10 bits, and 15 of the 22, are in groups of 5, with the value + * 0 representing space and values 1..26 representing A..Z. The low + * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50 + * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known + * in part in uda.c. + * + * The casts below are just to make pcc generate better code. + */ +#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */ +#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */ +#define MSCP_MID_ECH(n, id) (((long)(id) >> ((n) * 5 + 7)) & 0x1f) +#define MSCP_MID_CHAR(n, id) \ + (MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ') +#define MSCP_MID_NUM(id) ((id) & 0x7f) +/* for, e.g., RA81 */ +#define MSCP_MKDRIVE2(a, b, n) \ + (((a) - '@') << 17 | ((b) - '@') << 12 | (n)) +/* for, e.g., RRD50 */ +#define MSCP_MKDRIVE3(a, b, c, n) \ + (((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n)) + +/* + * Error datagram variant. + */ +struct mscpv_erd { + quad_t erd_ctlrid; /* controller ID */ + u_char erd_ctlrsoftware; /* controller software version */ + u_char erd_ctlrhardware; /* controller hardware version */ + u_short erd_multiunit; /* multi-unit code (?) */ + union { + u_long un_busaddr; /* bus address, if mem access err */ + quad_t un_unitid; /* unit id, otherwise */ + } erd_un1; +#define erd_busaddr erd_un1.un_busaddr +#define erd_unitid erd_un1.un_unitid + u_char erd_unitsoftware; /* unit software version */ + u_char erd_unithardware; /* unit hardware version */ + union { + u_char un_b[2]; /* level, retry (if disk xfer err) */ + u_short un_s; /* cylinder (if small disk error) */ + } erd_un2; +#define erd_level erd_un2.un_b[0] +#define erd_retry erd_un2.un_b[1] +#define erd_sdecyl erd_un2.un_s + long erd_volser; /* volume serial number */ + u_long erd_hdr; /* `header' (block number) */ + u_char erd_sdistat[12]; /* SDI status information (?) */ +}; + +/* + * I am making brash assumptions about the first four bytes of all + * MSCP packets. These appear to be true for both UDA50s and TMSCP + * devices (TU81, TA81, TK50). DEC claim that these four bytes are + * not part of MSCP itself, yet at least the length is necessary + * for, e.g., error checking. + */ +struct mscp { + u_short mscp_msglen; /* length in bytes */ + u_char mscp_msgtc; /* type (high 4 bits) and credits */ + u_char mscp_vcid; /* virtual circuit ID */ + long mscp_cmdref; /* command reference number */ + u_short mscp_unit; /* unit number */ + u_short mscp_seqnum; /* sequence number */ + u_char mscp_opcode; /* opcode */ +#define mscp_format mscp_opcode /* aka format (datagrams) */ + u_char mscp_flags; /* flags */ + u_short mscp_modifier; /* modifier (commands) */ +#define mscp_status mscp_modifier /* aka status (ends) */ +#define mscp_event mscp_modifier /* aka event (datagrams) */ + union { + struct mscpv_seq un_seq; /* generic sequential msg */ + struct mscpv_sccc un_sccc; /* SCC command */ + struct mscpv_scce un_scce; /* SCC end */ + struct mscpv_onlc un_onlc; /* on line command */ + struct mscpv_onle un_onle; /* on line end */ + struct mscpv_guse un_guse; /* get unit status */ + struct mscpv_erd un_erd; /* error datagram */ + } mscp_un; +/*???*/ long mscp_xxx; /* pad to 64 bytes */ +}; + +/* + * Define message length according to the DEC specifications by dropping + * the four byte header. + */ +#define MSCP_MSGLEN (sizeof (struct mscp) - 4) + +/* + * Shorthand + */ + +/* + * Generic packet + */ +#define mscp_seq mscp_un.un_seq + +/* + * Set Controller Characteristics packet + */ +#define mscp_sccc mscp_un.un_sccc + +/* + * Set Controller Characteristics end packet + */ +#define mscp_scce mscp_un.un_scce + +/* + * Online / Set Unit Characteristics command packet + */ +#define mscp_onlc mscp_un.un_onlc + +/* + * Online end packet + */ +#define mscp_onle mscp_un.un_onle + +/* + * Get Unit Status end packet + */ +#define mscp_guse mscp_un.un_guse + +/* + * MSCP Error Log packet + */ +#define mscp_erd mscp_un.un_erd + +/* + * MSCP seq_addr field actually belongs to overall packet. + */ +#define mscp_addr mscp_seq.seq_addr + +/* + * Macros to break up mscp_msgtc, and types. + */ +#define MSCP_MSGTYPE(m) ((m) & 0xf0) +#define MSCP_CREDITS(m) ((m) & 0x0f) + +#define MSCPT_SEQ 0x00 /* sequential message */ +#define MSCPT_DATAGRAM 0x10 /* error datagram */ +#define MSCPT_CREDITS 0x20 /* credit notification */ +#define MSCPT_MAINTENANCE 0xf0 /* who knows */ + + +/* + * Here begin more perhaps brash assumptions about MSCP devices... + */ + +/* + * MSCP controllers have `command rings' and `response rings'. A + * command ring is a pool of MSCP packets that the host uses to give + * commands to the controller; a response ring is a pool of MSCP + * packets that the controller uses to give back responses. Entries + * in the command and response rings are `owned' by either the host + * or the controller; only the owner is allowed to alter any of the + * fields in the MSCP packet. Thus, free command packets are owned + * by the host, and free response packets by the controller. When + * the host gives a packet to the controller, it tells the controller + * by touching a device register; when the controller gives a response + * to the host, it generates an interrupt if enabled, and sets + * a device register as well. + * + * The pool is `described' by a set of pointers to the packets, along + * with the two flags below. + */ +#define MSCP_OWN 0x80000000 /* controller owns this packet */ +#define MSCP_INT 0x40000000 /* controller should interrupt */ diff --git a/sys/arch/vax/vax/mscpvar.h b/sys/arch/vax/vax/mscpvar.h new file mode 100644 index 00000000000..8b9a63a6ce3 --- /dev/null +++ b/sys/arch/vax/vax/mscpvar.h @@ -0,0 +1,219 @@ +/* $NetBSD: mscpvar.h,v 1.5.2.1 1995/10/15 14:18:53 ragge Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mscpvar.h 7.3 (Berkeley) 6/28/90 + */ + +/* + * MSCP generic driver configuration + */ + +/* + * Enabling MSCP_PARANOIA makes the response code perform various checks + * on the hardware. (Right now it verifies only the buffer pointer in + * mscp_cmdref.) + * + * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying + * transfers in progress, which gets around a rather peculiar bug in the + * SC41/MS. Enabling MSCP_PARANOIA instead should work, but will cause + * `extra' Unibus resets. + * + * Either of these flags can simply be included as an `options' line in + * your configuration file. + */ + +/* #define MSCP_PARANOIA */ +/* #define AVOID_EMULEX_BUG */ + +/* + * Per driver information. + * + * md_ndpc sets the maximum unit number allowed in response packets. + * md_nunits is the number of drives attached to all controllers. + * md_unitshift is the divisor for converting a minor device number + * to a unit index for the device queues in md_utab. + * + * The routines are called from the generic response dispatcher. + * THE FOLLOWING IS OUT OF DATE + * The first three (dgram, ctlrdone, and unconf) get passed a pointer + * to the uba_ctlr and to the packet; the rest get a pointer to the + * uba_device and to the packet (`um, mp' and `ui, mp' respectively). + * The routines unconf, online, gotstatus, and ioerr are functions + * and should return one of the values given below. In addition, + * the ioerr and bb routines get a third argument, `bp': a pointer + * to the buffer describing the transfer in error. + * END OUT OF DATE + */ +struct mscp_driver { + int md_ndpc; /* number of drives per ctlr */ + int md_nunits; /* total number drives (all ctlrs) */ + int md_unitshift; /* device number to unit: >> count */ + struct buf *md_utab; /* pointer to device queues */ + struct disklabel *md_lab; /* pointer to devicee disklabels */ + struct uba_device **md_dinfo; /* pointer to device info */ + int (*md_dgram)(); /* error datagram */ + int (*md_ctlrdone)(); /* controller operation complete */ + int (*md_unconf)(); /* response from unconfigured drive */ + int (*md_iodone)(); /* normal I/O is done */ + int (*md_online)(); /* drive on line */ + int (*md_gotstatus)(); /* got unit status */ + int (*md_replace)(); /* replace done */ + int (*md_ioerr)(); /* read or write failed */ + int (*md_bb)(); /* B_BAD io done */ + char *md_mname; /* name of controllers */ + char *md_dname; /* name of drives */ +}; + +/* + * Return values from functions. + * MSCP_RESTARTED is peculiar to I/O errors. + */ +#define MSCP_DONE 0 /* all ok */ +#define MSCP_FAILED 1 /* no go */ +#define MSCP_RESTARTED 2 /* transfer restarted */ + +/* + * Ring information, per ring (one each for commands and responses). + */ +struct mscp_ri { + int mri_size; /* ring size */ + int mri_next; /* next (expected|free) */ + long *mri_desc; /* base address of descriptors */ + struct mscp *mri_ring; /* base address of packets */ +}; + +/* + * Per device information. + * + * mi_ip is a pointer to the inverting pointers (things that get `ui's + * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!). + * + * mi_wtab holds a queue of those transfers that were started but have + * not yet finished. Other Unibus drivers do not need this as they hand + * out requests one at a time. MSCP devices, however, take a slew of + * requests and pick their own order to execute them. This means that + * we have to have a place to move transfers that were given to the + * controller, so we can tell those apart from those that have not yet + * been handed out; mi_wtab is that place. + */ +struct mscp_info { + struct mscp_driver *mi_md; /* pointer to driver info */ + int mi_ctlr; /* controller index */ + struct buf *mi_tab; /* pointer to ctlr's drive queue */ + struct uba_device **mi_ip; /* pointer to inverting pointers */ + struct mscp_ri mi_cmd; /* MSCP command ring info */ + struct mscp_ri mi_rsp; /* MSCP response ring info */ + short mi_credits; /* transfer credits */ + char mi_wantcmd; /* waiting for command packet */ + char mi_wantcredits; /* waiting for transfer credits */ + struct buf mi_wtab; /* transfer wait queue */ +#ifdef AVOID_EMULEX_BUG +#define AEB_MAX_BP 32 /* max pend xfers (power of 2) XXX */ + volatile struct buf *mi_bp[AEB_MAX_BP]; /* xfer no. to buffer */ + u_int mi_nextbp; /* generates unique xfer no's */ + int mi_ok; /* for error rate statistics */ +#endif AVOID_EMULEX_BUG +}; + +/* + * We have run out of credits when mi_credits is <= MSCP_MINCREDITS. + * It is still possible to issue one command in this case, but it must + * not be a data transfer. E.g., `get command status' or `abort command' + * is legal, while `read' is not. + */ +#define MSCP_MINCREDITS 1 + +/* + * Flags for mscp_getcp(). + */ +#define MSCP_WAIT 1 +#define MSCP_DONTWAIT 0 + +struct mscp *mscp_getcp(); /* get a command packet */ + +/* + * Unit flags + */ +#define UNIT_ONLINE 0x01 /* drive is on line */ +#define UNIT_HAVESTATUS 0x02 /* got unit status */ +#define UNIT_REQUEUE 0x04 /* requeue after response */ + +/* + * Handle a command ring transition: wake up sleepers for command packets. + * This is too simple to bother with a function call. + */ +#define MSCP_DOCMD(mi) { \ + if ((mi)->mi_wantcmd) { \ + (mi)->mi_wantcmd = 0; \ + wakeup((caddr_t) &(mi)->mi_wantcmd); \ + } \ +} + +/* + * The following macro appends a buffer to a drive queue or a drive to + * a controller queue, given the name of the forward link. Use as + * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)', + * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab' + * is a controller queue. (That is, the forward link for controller + * queues is `b_forw'; for drive queues, it is `av_forw'.) + * + * Changed to new buf structure 940605/Ragge + */ +#define MSCP_APPEND(bp, queue, link) { \ + struct buf *tmp; \ + \ + (bp)->link = NULL; \ + if ((queue)->b_actf == NULL) \ + (queue)->b_actf = (bp); \ + else { \ + tmp=(queue)->b_actf; \ + while(tmp->link) tmp=tmp->link; \ + tmp->link = (bp); \ + } \ +} + +/* Old APPEND macro */ +/* +#define APPEND(bp, queue, link) { \ + (bp)->link = NULL; \ + if ((queue)->b_actf == NULL) \ + (queue)->b_actf = (bp); \ + else \ + (queue)->b_actl->link = (bp); \ + (queue)->b_actl = (bp); \ +} +*/ diff --git a/sys/arch/vax/vax/pmap.c b/sys/arch/vax/vax/pmap.c new file mode 100644 index 00000000000..b113a553f67 --- /dev/null +++ b/sys/arch/vax/vax/pmap.c @@ -0,0 +1,916 @@ +/* $NetBSD: pmap.c,v 1.17 1995/08/22 04:34:17 ragge Exp $ */ +#define DEBUG +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#include "sys/types.h" +#include "sys/param.h" +#include "sys/queue.h" +#include "sys/malloc.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/msgbuf.h" +#include "vm/vm.h" +#include "vm/vm_page.h" +#include "vm/vm_kern.h" +#include "vax/include/pte.h" +#include "vax/include/pcb.h" +#include "vax/include/mtpr.h" +#include "vax/include/loconf.h" +#include "vax/include/macros.h" +#include "vax/include/sid.h" + +#include "uba.h" + +pt_entry_t *pmap_virt2pte(pmap_t, u_int); + +#define PTE_TO_PV(pte) (PHYS_TO_PV((pte&PG_FRAME)<<PG_SHIFT)) + + +struct pmap kernel_pmap_store; +unsigned int gurkskit[50],istack; + +static pv_entry_t alloc_pv_entry(); +static void free_pv_entry(); + +static int prot_array[]={ PG_NONE, PG_RO, PG_RW, PG_RW, + PG_RO, PG_RO, PG_RW, PG_RW }; + +static int kernel_prot[]={ PG_NONE, PG_KR, PG_KW, PG_KW, + PG_RO,PG_KR,PG_KW,PG_URKW}; + +static pv_entry_t pv_head =NULL; +static unsigned int pv_count=0; +vm_offset_t ptemapstart,ptemapend; + +extern uint etext; +extern u_int *pte_cmap; +extern int maxproc; +extern struct vmspace vmspace0; +extern int edata, end; +uint* UMEMmap; +void* Numem; +void *scratch; +uint sigsida; +#ifdef DEBUG +int startpmapdebug=0; +extern int startsysc, faultdebug; +#endif +unsigned int *valueptr=gurkskit, vmmap; +pt_entry_t *Sysmap; +vm_map_t pte_map; + +vm_offset_t avail_start, avail_end; +vm_offset_t virtual_avail, virtual_end; /* Available virtual memory */ + +/* + * pmap_bootstrap(). + * Called as part of vm bootstrap, allocates internal pmap structures. + * Assumes that nothing is mapped, and that kernel stack is located + * immediately after end. + */ + +void +pmap_bootstrap() +{ + uint i; + extern u_int sigcode, esigcode, proc0paddr; + extern char *esym; + struct pmap *p0pmap=&vmspace0.vm_pmap; + vm_offset_t pend=0; +#define ROUND_PAGE(x) (((uint)(x) + PAGE_SIZE-1)& ~(PAGE_SIZE - 1)) + + /* These are in phys memory */ + istack = ROUND_PAGE((uint)Sysmap + SYSPTSIZE * 4); + (u_int)scratch = istack + ISTACK_SIZE; + mtpr(scratch, PR_ISP); /* set interrupt stack pointer */ + msgbufp = (void *)(scratch + NBPG * 4); + (u_int)pv_table = (int)ROUND_PAGE(sizeof(struct msgbuf)) + + (u_int)msgbufp; + +/* Count up phys memory */ + while (!badaddr(pend, 4)) + pend += NBPG * 128; + +#if VAX630 + if (cpu_type == VAX_630) + pend -= 8 * NBPG; /* Avoid console scratchpad */ +#endif +#if VAX650 + if (cpu_type == VAX_650) + pend -= 64 * NBPG; +#endif +/* These are virt only */ + vmmap = ROUND_PAGE(pv_table + (pend / PAGE_SIZE)); + (u_int)Numem = vmmap + NBPG * 2; + + (pt_entry_t *)UMEMmap=kvtopte(Numem); + (pt_entry_t *)pte_cmap=kvtopte(vmmap); + + avail_start=ROUND_PAGE(vmmap)&0x7fffffff; + avail_end=pend-ROUND_PAGE(sizeof(struct msgbuf)); + virtual_avail=ROUND_PAGE((uint)Numem+NUBA*NBPG*NBPG); + virtual_end=SYSPTSIZE*NBPG+KERNBASE; +#ifdef DEBUG + printf("Sysmap %x, istack %x, scratch %x\n",Sysmap,istack,scratch); + printf("etext %x, edata %x, end %x, esym %x\n", + &etext,&edata, &end, esym); + printf("SYSPTSIZE %x, USRPTSIZE %x\n",SYSPTSIZE,USRPTSIZE); + printf("pv_table %x, vmmap %x, Numem %x, pte_cmap %x\n", + pv_table,vmmap,Numem,pte_cmap); + printf("avail_start %x, avail_end %x\n",avail_start,avail_end); + printf("virtual_avail %x,virtual_end %x\n",virtual_avail,virtual_end); + printf("clearomr: %x \n",(uint)vmmap-(uint)Sysmap); + printf("faultdebug %x, startsysc %x\n",&faultdebug, &startsysc); + printf("startpmapdebug %x\n",&startpmapdebug); +#endif + + blkclr(Sysmap,(uint)vmmap-(uint)Sysmap); + pmap_map(0x80000000,0,2*NBPG,VM_PROT_READ|VM_PROT_WRITE); +#ifdef DDB + pmap_map(0x80000400,2*NBPG,(vm_offset_t)(&etext), + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); +#else + pmap_map(0x80000400,2*NBPG,(vm_offset_t)(&etext),VM_PROT_EXECUTE); +#endif + pmap_map((vm_offset_t)(&etext),(vm_offset_t)&etext, + (vm_offset_t)Sysmap,VM_PROT_READ|VM_PROT_WRITE); + pmap_map((vm_offset_t)Sysmap,(vm_offset_t)Sysmap,istack, + VM_PROT_READ|VM_PROT_WRITE); + pmap_map(istack,istack,istack+NBPG,VM_PROT_NONE);/* Red zone */ + pmap_map(istack+NBPG,istack+NBPG,(vm_offset_t)scratch, + VM_PROT_READ|VM_PROT_WRITE); + pmap_map((vm_offset_t)scratch,(vm_offset_t)scratch, + (vm_offset_t)msgbufp, VM_PROT_READ|VM_PROT_WRITE); + pmap_map((vm_offset_t)msgbufp, (vm_offset_t)msgbufp, + (vm_offset_t)pv_table, VM_PROT_ALL); + pmap_map((vm_offset_t)pv_table,(vm_offset_t)pv_table,vmmap, + VM_PROT_READ|VM_PROT_WRITE); + + /* Init kernel pmap */ + pmap_kernel()->ref_count = 1; + simple_lock_init(&pmap_kernel()->pm_lock); + p0pmap->pm_pcb=(struct pcb *)proc0paddr; + + /* used for signal trampoline code */ + sigsida=(u_int)(scratch+NBPG)&0x7fffffff; + bcopy(&sigcode, (void *)sigsida, (u_int)&esigcode-(u_int)&sigcode); + + p0pmap->pm_pcb->P1BR = (void *)0x80000000; + p0pmap->pm_pcb->P0BR = 0; + p0pmap->pm_pcb->P1LR = 0x200000; + p0pmap->pm_pcb->P0LR = AST_PCB; + mtpr(0x80000000, PR_P1BR); + mtpr(0, PR_P0BR); + mtpr(0x200000, PR_P1LR); + mtpr(AST_PCB, PR_P0LR); +/* + * Now everything should be complete, start virtual memory. + */ + mtpr((uint)Sysmap&0x7fffffff,PR_SBR); /* Where is SPT? */ + mtpr(SYSPTSIZE,PR_SLR); + mtpr(1,PR_MAPEN); + bzero(valueptr, 200); +} + +/****************************************************************************** * + * pmap_init() + * + ****************************************************************************** + * + * Called as part of vm init. + * + */ + +void +pmap_init(s, e) + vm_offset_t s,e; +{ + + /* reserve place on SPT for UPT */ + pte_map = kmem_suballoc(kernel_map, &ptemapstart, &ptemapend, + USRPTSIZE * 4, TRUE); +} + +/****************************************************************************** + * + * pmap_create() + * + ****************************************************************************** + * + * pmap_t pmap_create(phys_size) + * + * Create a pmap for a new task. + * + * Allocate a pmap form kernel memory with malloc. + * Clear the pmap. + * Allocate a ptab for the pmap. + * + */ +pmap_t +pmap_create(phys_size) + vm_size_t phys_size; +{ + pmap_t pmap; + +#ifdef DEBUG +if(startpmapdebug)printf("pmap_create: phys_size %x\n",phys_size); +#endif + if(phys_size) return NULL; + +/* Malloc place for pmap struct */ + + pmap = (pmap_t) malloc(sizeof(struct pmap), M_VMPMAP, M_WAITOK); + pmap_pinit(pmap); + + return (pmap); +} + + +/* + * Release any resources held by the given physical map. + * Called when a pmap initialized by pmap_pinit is being released. + * Should only be called if the map contains no valid mappings. + */ +void +pmap_release(pmap) + struct pmap *pmap; +{ +#ifdef DEBUG +if(startpmapdebug)printf("pmap_release: pmap %x\n",pmap); +#endif + + if (pmap->pm_pcb->P0BR) + kmem_free_wakeup(pte_map, (vm_offset_t)pmap->pm_pcb->P0BR, + (pmap->pm_pcb->P0LR & ~AST_MASK) * 4); + + if (pmap->pm_pcb->P1BR) + kmem_free_wakeup(pte_map, (vm_offset_t)pmap->pm_stack, + (0x200000 - pmap->pm_pcb->P1LR) * 4); + + bzero(pmap, sizeof(struct pmap)); +} + + +/* + * pmap_destroy(pmap): Remove a reference from the pmap. + * If the pmap is NULL then just return else decrese pm_count. + * If this was the last reference we call's pmap_relaese to release this pmap. + * OBS! remember to set pm_lock + */ + +void +pmap_destroy(pmap) + pmap_t pmap; +{ + int count; + +#ifdef DEBUG +if(startpmapdebug)printf("pmap_destroy: pmap %x\n",pmap); +#endif + if (pmap == NULL) + return; + + simple_lock(&pmap->pm_lock); + count = --pmap->ref_count; + simple_unlock(&pmap->pm_lock); + + if (!count) { + pmap_release(pmap); + free((caddr_t)pmap, M_VMPMAP); + } +} + +void +pmap_enter(pmap, v, p, prot, wired) + register pmap_t pmap; + vm_offset_t v; + vm_offset_t p; + vm_prot_t prot; + boolean_t wired; +{ + u_int j, i, pte, s, *patch; + pv_entry_t pv, tmp; + + if (v > 0x7fffffff) pte = kernel_prot[prot] | PG_PFNUM(p) | PG_V; + else pte = prot_array[prot] | PG_PFNUM(p) | PG_V; + s = splimp(); + pv = PHYS_TO_PV(p); + +#ifdef DEBUG +if(startpmapdebug) +printf("pmap_enter: pmap: %x,virt %x, phys %x,pv %x prot %x\n", + pmap,v,p,pv,prot); +#endif + if (!pmap) return; + if (wired) pte |= PG_W; + + + if (v < 0x40000000) { + patch = (int *)pmap->pm_pcb->P0BR; + i = (v >> PG_SHIFT); + if (i >= (pmap->pm_pcb->P0LR&~AST_MASK)) + pmap_expandp0(pmap, i); + patch = (int *)pmap->pm_pcb->P0BR; + } else if (v < (u_int)0x80000000) { + patch = (int *)pmap->pm_pcb->P1BR; + i = (v - 0x40000000) >> PG_SHIFT; + if (i < pmap->pm_pcb->P1LR) + panic("pmap_enter: must expand P1"); + } else { + patch = (int *)Sysmap; + i = (v - (u_int)0x80000000) >> PG_SHIFT; + } + + if ((patch[i] & PG_FRAME) == (pte & PG_FRAME)) { /* no map change */ + if ((patch[i] & PG_W) != (pte & PG_W)) { /* wiring change */ + pmap_change_wiring(pmap, v, wired); + } else if ((patch[i] & PG_PROT) != (pte & PG_PROT)) { + patch[i] &= ~PG_PROT; + patch[i++] |= prot_array[prot]; + patch[i] &= ~PG_PROT; + patch[i] |= prot_array[prot]; + mtpr(v, PR_TBIS); + mtpr(v + NBPG, PR_TBIS); + } else if ((patch[i] & PG_V) == 0) { + if (patch[i] & PG_SREF) { + patch[i] &= ~PG_SREF; + patch[i] |= PG_V | PG_REF; + } else patch[i] |= PG_V; + if (patch[++i] & PG_SREF) { + patch[i] &= ~PG_SREF; + patch[i] |= PG_V | PG_REF; + } else patch[i] |= PG_V; + mtpr(v, PR_TBIS); + mtpr(v + NBPG, PR_TBIS); + } /* else nothing to do */ + splx(s); + return; + } + + if (!pv->pv_pmap) { + pv->pv_pmap = pmap; + pv->pv_next = NULL; + pv->pv_va = v; + } else { + tmp = alloc_pv_entry(); + tmp->pv_pmap = pmap; + tmp->pv_next = pv->pv_next; + tmp->pv_va = v; + pv->pv_next = tmp; + } + patch[i++] = pte++; + patch[i] = pte; + mtpr(v, PR_TBIS); + mtpr(v + NBPG, PR_TBIS); + splx(s); +} + +void * +pmap_bootstrap_alloc(size) + int size; +{ + void *mem; + + size = round_page(size); + mem = (void *)virtual_avail; + virtual_avail = pmap_map(virtual_avail, avail_start, + avail_start + size, VM_PROT_READ|VM_PROT_WRITE); + avail_start += size; + blkclr(mem, size); + return (mem); +} + +vm_offset_t +pmap_map(virtuell, pstart, pend, prot) + vm_offset_t virtuell, pstart, pend; + int prot; +{ + vm_offset_t count; + int *pentry; + +#ifdef DEBUG +if(startpmapdebug)printf("pmap_map: virt %x, pstart %x, pend %x\n",virtuell, pstart, pend); +#endif + + pstart=(uint)pstart &0x7fffffff; + pend=(uint)pend &0x7fffffff; + virtuell=(uint)virtuell &0x7fffffff; + (uint)pentry= (((uint)(virtuell)>>PGSHIFT)*4)+(uint)Sysmap; + for(count=pstart;count<pend;count+=NBPG){ + *pentry++ = (count>>PGSHIFT)|kernel_prot[prot]|PG_V; + } + mtpr(0,PR_TBIA); + return(virtuell+(count-pstart)+0x80000000); +} + +vm_offset_t +pmap_extract(pmap, va) + pmap_t pmap; + vm_offset_t va; +{ + + int *pte, nypte; +#ifdef DEBUG +if(startpmapdebug)printf("pmap_extract: pmap %x, va %x\n",pmap, va); +#endif + + pte=(int *)pmap_virt2pte(pmap,va); + if(pte) return(((*pte&PG_FRAME)<<PG_SHIFT)+((u_int)va&PGOFSET)); + else return 0; +} + +/* + * pmap_protect( pmap, vstart, vend, protect) + */ +void +pmap_protect(pmap, start, end, prot) + pmap_t pmap; + vm_offset_t start; + vm_offset_t end; + vm_prot_t prot; +{ + int pte, *patch, s; + +#ifdef DEBUG +if(startpmapdebug) printf("pmap_protect: pmap %x, start %x, end %x, prot %x\n", + pmap, start, end,prot); +#endif + if(pmap==NULL) return; + s=splimp(); + if(start>0x7fffffff) pte=kernel_prot[prot]; + else pte=prot_array[prot]; + + if(end<0x40000000){ + while((end>>PG_SHIFT)>(pmap->pm_pcb->P0LR&~AST_MASK)) + pmap_expandp0(pmap,(end>>PG_SHIFT)); + } else if(end<(u_int)0x80000000){ + u_int i; + i=(start&0x3fffffff)>>PG_SHIFT; + if(i<pmap->pm_pcb->P1LR) + start=((pmap->pm_pcb->P1LR)<<PG_SHIFT)+0x40000000; + i=(end&0x3fffffff)>>PG_SHIFT; + if(i<pmap->pm_pcb->P1LR) return; + } + while (start < end) { + patch = (int *)pmap_virt2pte(pmap,start); + if(patch){ + *patch&=(~PG_PROT); + *patch|=pte; + mtpr(start,PR_TBIS); + } + start += NBPG; + } + mtpr(0,PR_TBIA); + splx(s); +} + +/* + * pmap_remove(pmap, start, slut) removes all valid mappings between + * the two virtual adresses start and slut from pmap pmap. + * NOTE: all adresses between start and slut may not be mapped. + */ + +void +pmap_remove(pmap, start, slut) + pmap_t pmap; + vm_offset_t start, slut; +{ + u_int *ptestart, *pteslut,i,s,*temp; + pv_entry_t pv; + vm_offset_t countup; + +#ifdef DEBUG +if(startpmapdebug) printf("pmap_remove: pmap=0x %x, start=0x %x, slut=0x %x\n", + pmap, start, slut); +#endif + + if(!pmap) return; + if(!pmap->pm_pcb&&start<0x80000000) return; /* No page registers */ +/* First, get pte first address */ + if(start<0x40000000){ /* P0 */ + if(!(temp=pmap->pm_pcb->P0BR)) return; /* No page table */ + ptestart=&temp[start>>PG_SHIFT]; + pteslut=&temp[slut>>PG_SHIFT]; + if(pteslut>&temp[(pmap->pm_pcb->P0LR&~AST_MASK)]) + pteslut=&temp[(pmap->pm_pcb->P0LR&~AST_MASK)]; + } else if(start>0x7fffffff){ /* System region */ + ptestart=(u_int *)&Sysmap[(start&0x3fffffff)>>PG_SHIFT]; + pteslut=(u_int *)&Sysmap[(slut&0x3fffffff)>>PG_SHIFT]; + } else { /* P1 (stack) region */ + if(!(temp=pmap->pm_pcb->P1BR)) return; /* No page table */ + pteslut=&temp[(slut&0x3fffffff)>>PG_SHIFT]; + ptestart=&temp[(start&0x3fffffff)>>PG_SHIFT]; + if(ptestart<&temp[pmap->pm_pcb->P1LR]) + ptestart=&temp[pmap->pm_pcb->P1LR]; + } + +#ifdef DEBUG +if(startpmapdebug) +printf("pmap_remove: ptestart %x, pteslut %x, pv %x\n",ptestart, pteslut,pv); +#endif + + s=splimp(); + for(countup=start;ptestart<pteslut;ptestart+=2, countup+=PAGE_SIZE){ + + if(!(*ptestart&PG_FRAME)) + continue; /* not valid phys addr,no mapping */ + + pv=PTE_TO_PV(*ptestart); + if(!remove_pmap_from_mapping(pv,pmap)){ + panic("pmap_remove: pmap not in pv_table"); + } + *ptestart=0; + *(ptestart+1)=0; + } + mtpr(0,PR_TBIA); + splx(s); +} + + +remove_pmap_from_mapping(pv, pmap) + pv_entry_t pv; + pmap_t pmap; +{ + pv_entry_t temp_pv,temp2; + + if(!pv->pv_pmap&&pv->pv_next) + panic("remove_pmap_from_mapping: j{ttefel"); + + if(pv->pv_pmap==pmap){ + if(pv->pv_next){ + temp_pv=pv->pv_next; + pv->pv_pmap=temp_pv->pv_pmap; + pv->pv_va=temp_pv->pv_va; + pv->pv_next=temp_pv->pv_next; + free_pv_entry(temp_pv); + } else { + bzero(pv,sizeof(struct pv_entry)); + } + } else { + temp_pv=pv; + while(temp_pv->pv_next){ + if(temp_pv->pv_next->pv_pmap==pmap){ + temp2=temp_pv->pv_next; + temp_pv->pv_next=temp2->pv_next; + free_pv_entry(temp2); + return 1; + } + temp_pv=temp_pv->pv_next; + } + return 0; + } + return 1; +} + +void +pmap_copy_page(src, dst) + vm_offset_t src; + vm_offset_t dst; +{ + int s; + extern uint vmmap; + +#ifdef DEBUG +if(startpmapdebug)printf("pmap_copy_page: src %x, dst %x\n",src, dst); +#endif + s=splimp(); + pte_cmap[0]=(src>>PGSHIFT)|PG_V|PG_RO; + pte_cmap[1]=(dst>>PGSHIFT)|PG_V|PG_KW; + mtpr(vmmap,PR_TBIS); + mtpr(vmmap+NBPG,PR_TBIS); + bcopy((void *)vmmap, (void *)vmmap+NBPG, NBPG); + pte_cmap[0]=((src+NBPG)>>PGSHIFT)|PG_V|PG_RO; + pte_cmap[1]=((dst+NBPG)>>PGSHIFT)|PG_V|PG_RW; + mtpr(vmmap,PR_TBIS); + mtpr(vmmap+NBPG,PR_TBIS); + bcopy((void *)vmmap, (void *)vmmap+NBPG, NBPG); + splx(s); +} + +pv_entry_t +alloc_pv_entry() +{ + pv_entry_t temporary; + + if(!pv_head) { + temporary=(pv_entry_t)malloc(sizeof(struct pv_entry), + M_VMPVENT, M_NOWAIT); +#ifdef DEBUG +if(startpmapdebug) printf("alloc_pv_entry: %x\n",temporary); +#endif + } else { + temporary=pv_head; + pv_head=temporary->pv_next; + pv_count--; + } + bzero(temporary, sizeof(struct pv_entry)); + return temporary; +} + +void +free_pv_entry(entry) + pv_entry_t entry; +{ + if(pv_count>=100) { /* Should be a define? */ + free(entry, M_VMPVENT); + } else { + entry->pv_next=pv_head; + pv_head=entry; + pv_count++; + } +} + +boolean_t +pmap_is_referenced(pa) + vm_offset_t pa; +{ + struct pv_entry *pv; + u_int *pte,spte=0; + + pv=PHYS_TO_PV(pa); + + if(!pv->pv_pmap) return 0; + + do { + pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); + spte|=*pte++; + spte|=*pte; + } while(pv=pv->pv_next); + return((spte&PG_REF)?1:0); +} + +boolean_t +pmap_is_modified(pa) + vm_offset_t pa; +{ + struct pv_entry *pv; + u_int *pte, spte=0; + + pv=PHYS_TO_PV(pa); + if(!pv->pv_pmap) return 0; + do { + pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); + spte|=*pte++; + spte|=*pte; + } while(pv=pv->pv_next); + return((spte&PG_M)?1:0); +} + +/* + * Reference bits are simulated and connected to logical pages, + * not physical. This makes reference simulation much easier. + */ + +void +pmap_clear_reference(pa) + vm_offset_t pa; +{ + struct pv_entry *pv; + int *pte,s,i; +/* + * Simulate page reference bit + */ + pv=PHYS_TO_PV(pa); +#ifdef DEBUG +if(startpmapdebug) printf("pmap_clear_reference: pa %x, pv %x\n",pa,pv); +#endif + + pv->pv_flags&=~PV_REF; + if(!pv->pv_pmap) return; + + do { + pte=(int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); + *pte&= ~(PG_REF|PG_V); + *pte++|=PG_SREF; + *pte&= ~(PG_REF|PG_V); + *pte|=PG_SREF; + } while(pv=pv->pv_next); + mtpr(0,PR_TBIA); +} + +void +pmap_clear_modify(pa) + vm_offset_t pa; +{ + struct pv_entry *pv; + u_int *pte,spte=0,s; + + pv=PHYS_TO_PV(pa); + if(!pv->pv_pmap) return; + do { + pte=(u_int *)pmap_virt2pte(pv->pv_pmap,pv->pv_va); + *pte++&= ~PG_M; + *pte&= ~PG_M; + } while(pv=pv->pv_next); +} + +void +pmap_change_wiring(pmap, va, wired) + register pmap_t pmap; + vm_offset_t va; + boolean_t wired; +{ + int *pte; +#ifdef DEBUG +if(startpmapdebug) printf("pmap_change_wiring: pmap %x, va %x, wired %x\n", + pmap, va, wired); +#endif + + pte=(int *)pmap_virt2pte(pmap,va); + if(!pte) return; /* no pte allocated */ + if(wired) *pte|=PG_W; + else *pte&=~PG_W; +} + +/* + * pmap_page_protect: + * + * Lower the permission for all mappings to a given page. + */ +void +pmap_page_protect(pa, prot) + vm_offset_t pa; + vm_prot_t prot; +{ + pv_entry_t pv,opv; + u_int s,*pte,*pte1,nyprot,kprot; + +#ifdef DEBUG +if(startpmapdebug) printf("pmap_page_protect: pa %x, prot %x\n",pa, prot); +#endif + pv = PHYS_TO_PV(pa); + if(!pv->pv_pmap) return; + nyprot=prot_array[prot]; + kprot=kernel_prot[prot]; + + switch (prot) { + + case VM_PROT_ALL: + break; + case VM_PROT_READ: + case VM_PROT_READ|VM_PROT_EXECUTE: + do { + pte=pte1=(int *)pmap_virt2pte(pv->pv_pmap, pv->pv_va); + s=splimp(); + *pte1++&=~PG_PROT; + *pte1&=~PG_PROT; + if(pv->pv_va>0x7fffffff){ + *pte|=kprot; + *pte1|=kprot; + } else{ + *pte|=nyprot; + *pte1|=nyprot; + } + splx(s); + } while(pv=pv->pv_next); + mtpr(0,PR_TBIA); + break; + + default: + + pte=(int *)pmap_virt2pte(pv->pv_pmap, pv->pv_va); + s = splimp(); + *pte++=0; + *pte=0; + opv=pv; + pv=pv->pv_next; + bzero(opv,sizeof(struct pv_entry)); + while(pv){ + pte=(int *)pmap_virt2pte(pv->pv_pmap, pv->pv_va); + *pte++=0; + *pte=0; + opv=pv; + pv=pv->pv_next; + free_pv_entry(opv); + } + + mtpr(0,PR_TBIA); + splx(s); + break; + } +} + +/* + * pmap_zero_page zeros the specified (machine independent) + * page by mapping the page into virtual memory and using + * bzero to clear its contents, one machine dependent page + * at a time. + */ +void +pmap_zero_page(phys) + vm_offset_t phys; +{ + int s; + +#ifdef DEBUG +if(startpmapdebug)printf("pmap_zero_page(phys %x, vmmap %x, pte_cmap %x\n", + phys,vmmap,pte_cmap); +#endif + s=splimp(); + pte_cmap[0]=(phys>>PG_SHIFT)|PG_V|PG_KW; + pte_cmap[1]=pte_cmap[0]+1; + mtpr(vmmap,PR_TBIS); + mtpr(vmmap+NBPG,PR_TBIS); + bzero((void *)vmmap,NBPG*2); + pte_cmap[0]=pte_cmap[1]=0; + mtpr(vmmap,PR_TBIS); + mtpr(vmmap+NBPG,PR_TBIS); + splx(s); +} + +pt_entry_t * +pmap_virt2pte(pmap,vaddr) + pmap_t pmap; + u_int vaddr; +{ + u_int *pte,scr; + + if(vaddr<0x40000000){ + pte=pmap->pm_pcb->P0BR; + if((vaddr>>PG_SHIFT)>(pmap->pm_pcb->P0LR&~AST_MASK)) return 0; + } else if(vaddr<(u_int)0x80000000){ + pte=pmap->pm_pcb->P1BR; + if(((vaddr&0x3fffffff)>>PG_SHIFT)<pmap->pm_pcb->P1LR) return 0; + } else { + pte=(u_int *)Sysmap; + } + + vaddr&=(u_int)0x3fffffff; + + return((pt_entry_t *)&pte[vaddr>>PG_SHIFT]); +} + +pmap_expandp0(pmap,ny_storlek) + struct pmap *pmap; +{ + u_int tmp,s,size,osize,oaddr,astlvl,*i,j; + + astlvl=pmap->pm_pcb->P0LR&AST_MASK; + osize=(pmap->pm_pcb->P0LR&~AST_MASK)*4; + size=ny_storlek*4; + tmp=kmem_alloc_wait(pte_map, size); + s=splhigh(); + if(osize) blkcpy(pmap->pm_pcb->P0BR, (void*)tmp,osize); + oaddr=(u_int)pmap->pm_pcb->P0BR; + mtpr(tmp,PR_P0BR); + mtpr(((size>>2)|astlvl),PR_P0LR); + mtpr(0,PR_TBIA); + pmap->pm_pcb->P0BR=(void*)tmp; + pmap->pm_pcb->P0LR=((size>>2)|astlvl); + splx(s); + if(osize) + kmem_free_wakeup(pte_map, (vm_offset_t)oaddr, osize); +} + +pmap_expandp1(pmap) + struct pmap *pmap; +{ + u_int tmp,s,size,osize,oaddr,*i,j; + + osize=0x800000-(pmap->pm_pcb->P1LR*4); + size=osize+PAGE_SIZE; + tmp=kmem_alloc_wait(pte_map, size); + s=splhigh(); + + if(osize) blkcpy((void*)pmap->pm_stack, (void*)tmp+PAGE_SIZE,osize); + oaddr=pmap->pm_stack; + pmap->pm_pcb->P1BR=(void*)(tmp+size-0x800000); + pmap->pm_pcb->P1LR=(0x800000-size)>>2; + pmap->pm_stack=tmp; + mtpr(pmap->pm_pcb->P1BR,PR_P1BR); + mtpr(pmap->pm_pcb->P1LR,PR_P1LR); + mtpr(0,PR_TBIA); + splx(s); + if (osize) + kmem_free_wakeup(pte_map, (vm_offset_t)oaddr, osize); +} diff --git a/sys/arch/vax/vax/random.s b/sys/arch/vax/vax/random.s new file mode 100644 index 00000000000..b6dc4db0bff --- /dev/null +++ b/sys/arch/vax/vax/random.s @@ -0,0 +1,83 @@ +/* $NetBSD: random.s,v 1.2 1994/10/26 08:03:24 cgd Exp $ */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * This implementation Copyright (c) 1994 Ludd, University of Lule}, Sweden + * All rights reserved. + * + * All bugs subject to removal without further notice. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ + + .data +randseed: + .long 1 + .text + .globl _random +_random: + .word 0x0 + movl $16807,r0 + + movl randseed,r1 # r2=16807*loword(randseed) + bicl3 $0xffff0000,r1,r2 + mull2 r0,r2 + ashl $-16,r1,r1 # r1=16807*hiword(randseed) + bicl2 $0xffff0000,r1 + mull2 r0,r1 + bicl3 $0xffff0000,r2,r0 + ashl $-16,r2,r2 # r1+=(r2>>16) + bicl2 $0xffff0000,r2 + addl2 r2,r1 + ashl $16,r1,r2 # r0|=r1<<16 + bisl2 r2,r0 + ashl $-16,r1,r1 # r1=r1>>16 + + ashl $1,r1,r1 + movl r0,r2 + rotl $1,r0,r0 + bicl2 $0xfffffffe,r0 + bisl2 r0,r1 + movl r2,r0 + bicl2 $0x80000000,r0 + addl2 r1,r0 + bgeq L1 + subl2 $0x7fffffff,r0 +L1: movl r0,randseed + ret diff --git a/sys/arch/vax/vax/rootfil.c b/sys/arch/vax/vax/rootfil.c new file mode 100644 index 00000000000..38ab448b58f --- /dev/null +++ b/sys/arch/vax/vax/rootfil.c @@ -0,0 +1,229 @@ +/* $NetBSD: rootfil.c,v 1.6 1995/04/12 15:35:04 ragge Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: machdep.c 1.63 91/04/24 + * + * @(#)machdep.c 7.16 (Berkeley) 6/3/91 + */ + /* All bugs are subject to removal without further notice */ + +#include "param.h" +#include "vax/include/sid.h" +#include "buf.h" +#include "mbuf.h" +#include "vax/include/pte.h" +#include "uda.h" +#include "uba.h" +#include "reboot.h" +#include "conf.h" +#include "vax/include/macros.h" +#include "vax/include/nexus.h" +#include "vax/uba/ubavar.h" + +#define DOSWAP /* Change swdevt, argdev, and dumpdev too */ +u_long bootdev; /* should be dev_t, but not until 32 bits */ +extern dev_t rootdev, dumpdev; + +static char devname[][2] = { + 'h','p', /* 0 = hp */ + 0,0, /* 1 = ht */ + 'u','p', /* 2 = up */ + 'r','k', /* 3 = hk */ + 0,0, /* 4 = sw */ + 0,0, /* 5 = tm */ + 0,0, /* 6 = ts */ + 0,0, /* 7 = mt */ + 0,0, /* 8 = tu */ + 'r','a', /* 9 = ra */ + 0,0, /* 10 = ut */ + 'r','b', /* 11 = rb */ + 0,0, /* 12 = uu */ + 0,0, /* 13 = rx */ + 'r','l', /* 14 = rl */ + 0,0, /* 15 = tmscp */ + 'k','r', /* 16 = ra on kdb50 */ +}; + +#define PARTITIONMASK 0x7 +#define PARTITIONSHIFT 3 + +/* + * Attempt to find the device from which we were booted. + * If we can do so, and not instructed not to do so, + * change rootdev to correspond to the load device. + */ +setroot() +{ + int majdev, mindev, unit, part, controller, adaptor; + dev_t temp, orootdev; +#if NUDA > 0 + extern struct uba_device ubdinit[]; +#endif + struct swdevt *swp; + extern int boothowto; + + if (boothowto & RB_DFLTROOT || + (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) + return; + majdev = B_TYPE(bootdev); + if (majdev >= sizeof(devname) / sizeof(devname[0])) + return; + adaptor = B_ADAPTOR(bootdev); + controller = B_CONTROLLER(bootdev); + part = B_PARTITION(bootdev); + unit = B_UNIT(bootdev); + if (majdev == 0) { /* MBA device */ +#if NMBA > 0 + register struct mba_device *mbap; + int mask; + +/* + * The MBA number used at boot time is not necessarily the same as the + * MBA number used by the kernel. In order to change the rootdev we need to + * convert the boot MBA number to the kernel MBA number. The address space + * for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number + * on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750. + * Therefore we can search the mba_hd table for the MBA that has the physical + * address corresponding to the boot MBA number. + */ +#define PHYSADRSHFT 13 +#define PHYSMBAMASK780 0x7 +#define PHYSMBAMASK750 0x3 + + switch (MACHID(cpu_type)) { + + case VAX_780: +/* case VAX_8600: */ + default: + mask = PHYSMBAMASK780; + break; + + case VAX_750: + mask = PHYSMBAMASK750; + break; + } + for (mbap = mbdinit; mbap->driver; mbap++) + if (mbap->alive && mbap->drive == unit && + (((long)mbap->hd->mh_physmba >> PHYSADRSHFT) + & mask) == adaptor) + break; + if (mbap->driver == 0) + return; + mindev = mbap->unit; +#else + return; +#endif +#if NUBA > 0 + } else { + register struct uba_device *ubap; + + for (ubap = ubdinit; ubap->ui_driver; ubap++){ + printf("ubap %x\n",ubap); + if (ubap->ui_alive && ubap->ui_slave == unit && + ubap->ui_ctlr == controller && + ubap->ui_ubanum == adaptor && + ubap->ui_driver->ud_dname[0] == devname[majdev][0] && + ubap->ui_driver->ud_dname[1] == devname[majdev][1]) + break; + } + if (ubap->ui_driver == 0) + return; + mindev = ubap->ui_unit; + printf("mindev %x, majdev %x\n",mindev,majdev); +#endif + } + mindev = (mindev << PARTITIONSHIFT) + part; + orootdev = rootdev; + rootdev = makedev(majdev, mindev); + /* + * If the original rootdev is the same as the one + * just calculated, don't need to adjust the swap configuration. + */ + if (rootdev == orootdev) + return; + + printf("Changing root device to %c%c%d%c\n", + devname[majdev][0], devname[majdev][1], + mindev >> PARTITIONSHIFT, part + 'a'); + +#ifdef DOSWAP + mindev &= ~PARTITIONMASK; + for (swp = swdevt; swp->sw_dev; swp++) { + if (majdev == major(swp->sw_dev) && + mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { + temp = swdevt[0].sw_dev; + swdevt[0].sw_dev = swp->sw_dev; + swp->sw_dev = temp; + break; + } + } + if (swp->sw_dev == 0) + return; + + /* + * If argdev and dumpdev were the same as the old primary swap + * device, move them to the new primary swap device. + */ + if (temp == dumpdev) + dumpdev = swdevt[0].sw_dev; + panic("autoconf.c: argdev\n"); +/* if (temp == argdev) + argdev = swdevt[0].sw_dev; */ +#endif +} + +/* + * Configure swap space and related parameters. + */ +swapconf() +{ + register struct swdevt *swp; + register int nblks; + + for (swp = swdevt; swp->sw_dev; swp++) + if (swp->sw_dev != NODEV &&bdevsw[major(swp->sw_dev)].d_psize){ + nblks = + (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); + if (nblks != -1 && + (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) + swp->sw_nblks = nblks; + } + dumpconf(); +} diff --git a/sys/arch/vax/vax/sbi.c b/sys/arch/vax/vax/sbi.c new file mode 100644 index 00000000000..5306145e1a0 --- /dev/null +++ b/sys/arch/vax/vax/sbi.c @@ -0,0 +1,178 @@ +/* $NetBSD: sbi.c,v 1.2 1995/02/23 17:54:03 ragge Exp $ */ +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + +#include "sys/types.h" +#include "sys/param.h" +#include "sys/device.h" +#include "vm/vm.h" +#include "vm/vm_kern.h" +#include "vm/vm_page.h" +#include "machine/nexus.h" +#include "machine/pmap.h" +#include "machine/sid.h" + +static int sbi_attached=0; + +struct bp_conf { + char *type; + int num; + int partyp; +}; + +int +sbi_print(aux, name) + void *aux; + char *name; +{ + struct sbi_attach_args *sa=(struct sbi_attach_args *)aux; + int unsupp=0; + extern int nmba; + + if(name){ + switch(sa->type){ + case NEX_MBA: + printf("mba%d at %s",nmba++, name); + unsupp++; + break; + default: + printf("unknown device 0x%x at %s",sa->type,name); + unsupp++; + } + } + printf(" tr%d",sa->nexnum); + return(unsupp?UNSUPP:UNCONF); +} + +int +sbi_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct bp_conf *bp=aux; + + if(strcmp(bp->type,"sbi")) + return 1; + return 0; +} + +void +sbi_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + void *nisse; + struct nexus *nexus; + u_int nextype, nexnum, maxnex; + struct sbi_attach_args sa; + + /* SBI space should be alloc'ed in SYSPT instead */ + kmem_suballoc(kernel_map, (void*)&nexus, (void*)&nisse, + (NNEXSBI*sizeof(struct nexus)), FALSE); + switch(cpunumber){ +#ifdef VAX730 + case VAX_730: + pmap_map((int)nexus, 0xf20000, 0xf40000, VM_PROT_READ|VM_PROT_WRITE); + maxnex = NNEX730; + printf(": BL[730\n"); + break; +#endif +#ifdef VAX750 + case VAX_750: + pmap_map((int)nexus, 0xf20000, 0xf40000, VM_PROT_READ|VM_PROT_WRITE); + maxnex = NNEX750; + printf(": CMI750\n"); + break; +#endif +#ifdef VAX630 + case VAX_78032: + switch (cpu_type) { + case VAX_630: + pmap_map((int)nexus, 0x20088000, 0x200a8000, + VM_PROT_READ|VM_PROT_WRITE); + maxnex = NNEX630; + printf(": Q22\n"); + break; + default: + panic("Microvax not supported"); + }; + break; +#endif + + case VAX_780: + case VAX_8600: + maxnex = NNEXSBI; + printf(": SBI780\n"); + } + +/* + * Now a problem: on different machines with SBI units identifies + * in different ways (if they identifies themselves at all). + * We have to fake identifying depending on different CPUs. + */ + for(nexnum=0;nexnum<maxnex;nexnum++){ + if(badaddr((caddr_t)&nexus[nexnum],4))continue; + + switch(cpunumber){ +#ifdef VAX750 + case VAX_750: + { extern int nexty750[]; + sa.type=nexty750[nexnum]; + break; + } +#endif +#ifdef VAX730 + case VAX_730: + { extern int nexty730[]; + sa.type=nexty730[nexnum]; + break; + } +#endif +#ifdef VAX630 + case VAX_78032: + sa.type = NEX_UBA0; + break; +#endif + default: + sa.type=nexus[nexnum].nexcsr.nex_type; + } + sa.nexnum=nexnum; + sa.nexaddr=nexus+nexnum; + config_found(self, (void*)&sa, sbi_print); + } +} + +struct cfdriver sbicd = + { NULL, "sbi", sbi_match, sbi_attach, DV_DULL, sizeof(struct device) }; + diff --git a/sys/arch/vax/vax/subr.s b/sys/arch/vax/vax/subr.s new file mode 100644 index 00000000000..a0d9d5d6b73 --- /dev/null +++ b/sys/arch/vax/vax/subr.s @@ -0,0 +1,279 @@ +/* $NetBSD: subr.s,v 1.11 1995/06/16 15:36:50 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "vax/include/mtpr.h" +#include "vax/include/param.h" +#include "vax/include/loconf.h" +#include "vax/include/vmparam.h" +#include "vax/include/pte.h" +#include "vax/include/nexus.h" +#include "sys/syscall.h" +#include "sys/errno.h" + + + .text + + .globl _sigcode,_esigcode +_sigcode: pushr $0x3f + subl2 $0xc,sp + movl 0x24(sp),r0 + calls $3,(r0) + popr $0x3f + chmk $SYS_sigreturn + halt + .align 2 +_esigcode: + + .globl _subyte +_subyte: .word 0x0 + movl 4(ap),r0 +# probew $3,$1,(r0) +# beql suerr + movb 8(ap),(r0) + clrl r0 + ret + +suerr: movl $-1,r0 + ret + + .globl _fubyte +_fubyte: .word 0x0 + movl 4(ap),r0 +# prober $3,$1,(r0) +# beql suerr + movzbl (r0),r0 + ret + + + + + + + + .globl _physcopypage +_physcopypage: .word 0x7 + movl 4(ap),r0 + ashl $-PGSHIFT,r0,r0 + bisl2 $(PG_V|PG_RO),r0 + + movl 8(ap),r1 + ashl $-PGSHIFT,r1,r1 + bisl2 $(PG_V|PG_KW),r1 + + movl r0,*(_pte_cmap) + movl r1,*$4+(_pte_cmap) + + movl _vmmap,r2 + addl3 $0x200,r2,r1 + mtpr r1,$PR_TBIS + mtpr r2,$PR_TBIS + + movl r1,r0 +1: movl (r2)+,(r1)+ + cmpl r0,r2 + bneq 1b + ret + + + .globl _badaddr +_badaddr: .word 0x0 + # Called with addr,b/w/l + mfpr $0x12,r0 + mtpr $0x1f,$0x12 + movl 4(ap),r2 # First argument, the address + movl 8(ap),r1 # Sec arg, b,w,l + pushl r0 # Save old IPL + clrl r3 + movl $4f,_memtest # Set the return adress + + caseb r1,$1,$4 # What is the size +1: .word 1f-1b + .word 2f-1b + .word 3f-1b # This is unused + .word 3f-1b + +1: movb (r2),r1 # Test a byte + brb 5f + +2: movw (r2),r1 # Test a word + brb 5f + +3: movl (r2),r1 # Test a long + brb 5f + +4: incl r3 # Got machine chk => addr bad +5: mtpr (sp)+,$0x12 + movl r3,r0 + ret + +# +# copyin(from, to, len) copies from userspace to kernelspace. +# + + .globl _locopyin +_locopyin:.word 0x1c + movl 16(ap),r0 # Get fault pointer flag + movl $ci,(r0) + + movl 4(ap),r0 # from + movl 8(ap),r1 # to + movl 12(ap),r2 # len + + movl r0,r4 + movl r2,r3 + + tstl r2 + beql 3f +2: movb (r0)+,(r1)+ # XXX Should be done in a faster way. + decl r2 + bneq 2b +3: movl 16(ap),r0 + clrl (r0) + clrl r0 +ci: ret + +# +# locopyout(from, to, len, addr) in the same manner as copyin() +# addr is iftrap addr for faulting. +# + + .globl _locopyout +_locopyout:.word 0x1c + movl 16(ap),r0 # Get fault pointer flag + movl $co,(r0) # and save ret addr + + movl 4(ap),r0 # from + movl 8(ap),r1 # to + movl 12(ap),r2 # len + + movl r1,r4 + movl r2,r3 + + tstl r2 + beql 3f +2: movb (r0)+,(r1)+ # XXX Should be done in a faster way. + decl r2 + bneq 2b +3: movl 16(ap),r0 + clrl (r0) + clrl r0 +co: ret + +# +# copystr(from, to, maxlen, *copied, addr) +# Only used in kernel mode, doesnt check accessability. +# + + .globl _copystr +_copystr: .word 0x7c + movl 4(ap),r4 # from + movl 8(ap),r5 # to + movl 12(ap),r2 # len + movl 16(ap),r3 # copied + +#if VAX630 + movl r4, r1 # (3) string address == r1 + movl r2, r0 # (2) string length == r0 + jeql Llocc_out # forget zero length strings +Llocc_loop: + tstb (r1) + jeql Llocc_out + incl r1 + sobgtr r0,Llocc_loop +Llocc_out: + tstl r0 # be sure of condition codes +#else + locc $0, r2, (r4) # check for null byte +#endif + beql 1f + + subl3 r0, r2, r6 # Len to copy. + incl r6 + tstl r3 + beql 7f + movl r6,(r3) +7: movc3 r6,(r4),(r5) + movl $0,r0 +cs: ret + +1: movc3 r2,(r4),(r5) + movl $ENAMETOOLONG, r0 + ret + + +_loswtch: .globl _loswtch,_rei + mtpr _curpcb,$PR_PCBB + svpctx + mtpr _nypcb,$PR_PCBB + ldpctx +_rei: rei + + .data + +mbanum: .long 0 + + +/*** DATA ********************************************************************/ + + + +_pte_cmap: .long 0 ; .globl _pte_cmap /* Address of PTE + corresponding to cmap */ + +_memtest: .long 0 ; .globl _memtest # Memory test in progress. + +#ifdef DDB +/* + * DDB is the only routine that uses setjmp/longjmp. + */ + .globl _setjmp, _longjmp +_setjmp:.word 0 + movl 4(ap), r0 + movl 8(fp), (r0) + movl 12(fp), 4(r0) + movl 16(fp), 8(r0) + addl3 fp,$28,12(r0) + clrl r0 + ret + +_longjmp:.word 0 + movl 4(ap), r1 + movl 8(ap), r0 + movl (r1), ap + movl 4(r1), fp + movl 12(r1), sp + jmp *8(r1) +#endif diff --git a/sys/arch/vax/vax/swapgeneric.c b/sys/arch/vax/vax/swapgeneric.c new file mode 100644 index 00000000000..00b5c1f1633 --- /dev/null +++ b/sys/arch/vax/vax/swapgeneric.c @@ -0,0 +1,212 @@ +/* $NetBSD: swapgeneric.c,v 1.5 1995/03/30 21:25:41 ragge Exp $ */ + +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)swapgeneric.c 7.11 (Berkeley) 5/9/91 + */ + +#include "mba.h" +#include "uda.h" + + +#include "sys/param.h" +#include "sys/conf.h" +#include "sys/buf.h" +#include "sys/systm.h" +#include "sys/reboot.h" + +#include "machine/pte.h" +#include "machine/mtpr.h" +#if NMBA > 0 +#include "../mba/mbareg.h" +#include "../mba/mbavar.h" +#endif +#include "../uba/ubareg.h" +#include "../uba/ubavar.h" + +/* + * Generic configuration; all in one + */ +dev_t rootdev = NODEV; +dev_t argdev = NODEV; +dev_t dumpdev = NODEV; +int nswap; +struct swdevt swdevt[] = { + { -1, 1, 0 }, + { -1, 1, 0 }, + { -1, 1, 0 }, + { 0, 0, 0 }, +}; +long dumplo; +int dmmin, dmmax, dmtext; + +extern int ffs_mountroot(); +int (*mountroot)() = ffs_mountroot; + +extern struct mba_driver hpdriver; +extern struct uba_driver scdriver; +extern struct uba_driver hkdriver; +extern struct uba_driver idcdriver; +extern struct uba_driver hldriver; +extern struct uba_driver udadriver; +extern struct uba_driver kdbdriver; + +struct genericconf { + caddr_t gc_driver; + char *gc_name; + dev_t gc_root; +} genericconf[] = { +/* { (caddr_t)&hpdriver, "hp", makedev(0, 0), }, + { (caddr_t)&scdriver, "up", makedev(2, 0), }, */ +#if NUDA > 0 + { (caddr_t)&udadriver, "ra", makedev(9, 0), }, +#endif +/* { (caddr_t)&idcdriver, "rb", makedev(11, 0), }, + { (caddr_t)&hldriver, "rl", makedev(14, 0), }, + { (caddr_t)&hkdriver, "hk", makedev(3, 0), }, + { (caddr_t)&hkdriver, "rk", makedev(3, 0), }, + { (caddr_t)&kdbdriver, "kra", makedev(16, 0), }, */ + { 0 }, +}; + +setconf() +{ +#if NMBA > 0 + register struct mba_device *mi; +#endif +#if NUDA > 0 + register struct uba_device *ui; +#endif + register struct genericconf *gc; + register char *cp, *gp; + int unit, swaponroot = 0; + + if (rootdev != NODEV) + goto doswap; + unit = 0; + if (boothowto & RB_ASKNAME) { + char name[128]; +retry: + printf("root device? "); + gets(name); + for (gc = genericconf; gc->gc_driver; gc++) + for (cp = name, gp = gc->gc_name; *cp == *gp; cp++) + if (*++gp == 0) + goto gotit; + printf( + "use hp%%d, up%%d, ra%%d, rb%%d, rl%%d, hk%%d or kra%%d\n"); + goto retry; +gotit: + if (*++cp < '0' || *cp > '9') { + printf("bad/missing unit number\n"); + goto retry; + } + while (*cp >= '0' && *cp <= '9') + unit = 10 * unit + *cp++ - '0'; + if (*cp == '*') + swaponroot++; + goto found; + } + for (gc = genericconf; gc->gc_driver; gc++) { +#if NMBA > 0 + for (mi = mbdinit; mi->mi_driver; mi++) { + if (mi->mi_alive == 0) + continue; + if (mi->mi_unit == unit && mi->mi_driver == + (struct mba_driver *)gc->gc_driver) { + printf("root on %s%d\n", + mi->mi_driver->md_dname, unit); + goto found; + } + } +#endif +#if NUDA > 0 + for (ui = ubdinit; ui->ui_driver; ui++) { + if (ui->ui_alive == 0) + continue; + if (ui->ui_unit == unit && ui->ui_driver == + (struct uba_driver *)gc->gc_driver) { + printf("root on %s%d\n", + ui->ui_driver->ud_dname, unit); + goto found; + } + } +#endif + } + + printf("no suitable root\n"); + asm("halt"); + +found: + gc->gc_root = makedev(major(gc->gc_root), unit*8); + rootdev = gc->gc_root; +doswap: + swdevt[0].sw_dev = argdev = dumpdev = + makedev(major(rootdev), minor(rootdev)+1); + /* swap size and dumplo set during autoconfigure */ + if (swaponroot) + rootdev = dumpdev; + +} + +gets(cp) + char *cp; +{ + register char *lp; + register c; + + lp = cp; + for (;;) { + cnputc(c = (cngetc()&0x7f)); + switch (c) { + case '\n': + case '\r': + *lp++ = '\0'; + return; + case '\b': + case '#': + case '\177': + lp--; + if (lp < cp) + lp = cp; + continue; + case '@': + case 'u'&037: + lp = cp; + cnputc('\n'); + continue; + default: + *lp++ = c; + } + } +} diff --git a/sys/arch/vax/vax/tmscpinf.h b/sys/arch/vax/vax/tmscpinf.h new file mode 100644 index 00000000000..5d6989995d6 --- /dev/null +++ b/sys/arch/vax/vax/tmscpinf.h @@ -0,0 +1,321 @@ +/* $NetBSD: tmscpinf.h,v 1.1 1995/02/23 17:54:06 ragge Exp $ */ + +/* @(#)tmscp.h 7.2 (Berkeley) 5/27/88 */ +/* + * @(#)tmscp.h 1.3 10/21/85 + * Definitions for the Tape Mass Storage Control Protocol + */ + +/**************************************************************** + * * + * Licensed from Digital Equipment Corporation * + * Copyright (c) * + * Digital Equipment Corporation * + * Maynard, Massachusetts * + * 1985, 1986 * + * All rights reserved. * + * * + * The Information in this software is subject to change * + * without notice and should not be construed as a commitment * + * by Digital Equipment Corporation. Digital makes no * + * representations about the suitability of this software for * + * any purpose. It is supplied "As Is" without expressed or * + * implied warranty. * + * * + * If the Regents of the University of California or its * + * licensees modify the software in a manner creating * + * diriviative copyright rights, appropriate copyright * + * legends may be placed on the drivative work in addition * + * to that set forth above. * + * * + **************************************************************** + * + * Modification history: /sys/vax/tmscp.h + * + * 18-Oct-85 - afd + * Added: defines for tape format (density) flag values. + * + * 18-Jul-85 - afd + * Added: #define M_UF_WBKNV 0000100 + * for write back (which enables cache). + ************************************************************************/ + +/* + * Control message opcodes + */ +#define M_OP_ABORT 0001 /* Abort command */ +#define M_OP_GTCMD 0002 /* Get command status command */ +#define M_OP_GTUNT 0003 /* Get unit status command */ +#define M_OP_STCON 0004 /* Set controller characteristics command */ +#define M_OP_AVAIL 0010 /* Available command */ +#define M_OP_ONLIN 0011 /* Online command */ +#define M_OP_STUNT 0012 /* Set unit characteristics command */ +#define M_OP_DTACP 0013 /* Determine access paths command */ +#define M_OP_ACCES 0020 /* Access command */ +#define M_OP_CMPCD 0021 /* Compare controller data command */ +#define M_OP_ERASE 0022 /* Erase command */ +#define M_OP_FLUSH 0023 /* Flush command */ +#define M_OP_ERGAP 0026 /* Erase gap command */ +#define M_OP_COMP 0040 /* Compare host data command */ +#define M_OP_READ 0041 /* Read command */ +#define M_OP_WRITE 0042 /* Write command */ +#define M_OP_WRITM 0044 /* Write tape mark command */ +#define M_OP_REPOS 0045 /* Reposition command */ +#define M_OP_AVATN 0100 /* Available attention message */ +#define M_OP_DUPUN 0101 /* Duplicate unit number attention message */ +#define M_OP_ACPTH 0102 /* Access path attention message */ +#define M_OP_END 0200 /* End message flag */ + + +/* + * Generic command modifiers + */ +#define M_MD_COMP 0040000 /* Compare */ +#define M_MD_CLSEX 0020000 /* Clear serious exception */ +#define M_MD_SECOR 0001000 /* Suppress error correction */ +#define M_MD_SEREC 0000400 /* Suppress error recovery */ +#define M_MD_STWRP 0000004 /* Set write protect */ +#define M_MD_ALLCD 0000002 /* All class drivers */ +#define M_MD_NXUNT 0000001 /* Next unit */ + +/* + * TMSCP command modifiers + */ +#define M_MD_DLEOT 0000200 /* Delete LEOT */ +#define M_MD_IMMED 0000100 /* Immediate completion */ +#define M_MD_EXCAC 0000040 /* Exclusive access */ +#define M_MD_UNLOD 0000020 /* Unload */ +#define M_MD_REVRS 0000010 /* reverse */ +#define M_MD_OBJCT 0000004 /* object count */ +#define M_MD_REWND 0000002 /* rewind */ + +/* + * End message flags + */ +#define M_EF_ERLOG 0040 /* Error log generated */ +#define M_EF_SEREX 0020 /* Serious exception */ +#define M_EF_EOT 0010 /* End of tape encountered */ +#define M_EF_PLS 0004 /* Position lost */ + + +/* + * Controller flags + */ +#define M_CF_ATTN 0200 /* Enable attention messages */ +#define M_CF_MISC 0100 /* Enable miscellaneous error log messages */ +#define M_CF_OTHER 0040 /* Enable other host's error log messages */ +#define M_CF_THIS 0020 /* Enable this host's error log messages */ + + +/* + * Unit flags + */ +#define M_UF_WRTPH 0020000 /* Write protect (hardware) */ +#define M_UF_WRTPS 0010000 /* Write protect (software or volume) */ +#define M_UF_WBKNV 0000100 /* Write back (enables cache) */ +#define M_UF_VSMSU 0000040 /* Variable speed mode suppression */ +#define M_UF_VARSP 0000020 /* Variable speed unit */ +#define M_UF_CMPWR 0000002 /* Compare writes */ +#define M_UF_CMPRD 0000001 /* Compare reads */ + + +/* + * Status codes + */ +#define M_ST_MASK 037 /* Status code mask */ +#define M_ST_SUCC 000 /* Success */ +#define M_ST_ICMD 001 /* Invalid command */ +#define M_ST_ABRTD 002 /* Command aborted */ +#define M_ST_OFFLN 003 /* Unit offline */ +#define M_ST_AVLBL 004 /* Unit available */ +#define M_ST_WRTPR 006 /* Write protected */ +#define M_ST_COMP 007 /* Compare error */ +#define M_ST_DATA 010 /* Data error */ +#define M_ST_HSTBF 011 /* Host buffer access error */ +#define M_ST_CNTLR 012 /* Controller error */ +#define M_ST_DRIVE 013 /* Drive error */ +#define M_ST_FMTER 014 /* Formatter error */ +#define M_ST_BOT 015 /* BOT encountered */ +#define M_ST_TAPEM 016 /* Tape mark encountered */ +#define M_ST_RDTRN 020 /* Record data truncated */ +#define M_ST_PLOST 021 /* Position lost */ +#define M_ST_SEX 022 /* Serious exception */ +#define M_ST_LED 023 /* LEOT detected */ +#define M_ST_DIAG 037 /* Message from an internal diagnostic */ + +/* + * An MSCP packet + */ + +struct mscp { + struct mscp_header mscp_header;/* device specific header */ + long mscp_cmdref; /* command reference number */ + short mscp_unit; /* unit number */ + short mscp_xxx1; /* unused */ + u_char mscp_opcode; /* opcode */ + u_char mscp_flags; /* end message flags */ + short mscp_modifier; /* modifiers */ + union { + struct { + long Mscp_bytecnt; /* byte count */ + long Mscp_buffer; /* buffer descriptor */ + long Mscp_mapbase; /* physical addr of map registers */ + long Mscp_xxx2; /* unused */ + long Mscp_lbn; /* logical block number */ + long Mscp_xxx4; /* unused */ + long *Mscp_dscptr; /* pointer to descriptor (software) */ + long Mscp_sftwds[17];/* software words, padding */ + } mscp_generic; + struct { + short Mscp_version; /* MSCP version */ + short Mscp_cntflgs; /* controller flags */ + short Mscp_hsttmo; /* host timeout */ + short Mscp_usefrac; /* use fraction */ + quad_t Mscp_time; /* time and date */ + long Mscp_cntdep; /* controller dependent parameters */ + } mscp_setcntchar; + struct { + short Mscp_multunt; /* multi-unit code */ + short Mscp_unitflgs; /* unit flags */ + long Mscp_hostid; /* host identifier */ + quad_t Mscp_unitid; /* unit identifier */ + long Mscp_mediaid; /* media type identifier */ + short Mscp_format; /* format (tape density) */ + short Mscp_speed; /* tape speed = (ips * bpi) /1000 */ + short Mscp_fmtmenu; /* format menu */ + short Mscp_group; /* group size */ + short Mscp_cylinder; /* cylinder size */ + short Mscp_xxx3; /* reserved */ + short Mscp_rctsize; /* RCT table size */ + char Mscp_rbns; /* RBNs / track */ + char Mscp_rctcpys; /* RCT copies */ + } mscp_getunitsts; + } mscp_un; + short mscp_fil1; + short mscp_fil2; + short mscp_fil3; +}; + +#define mscp_msglen (sizeof (struct mscp) - sizeof(struct mscp_header)) + +/* + * generic packet + */ + +#define mscp_bytecnt mscp_un.mscp_generic.Mscp_bytecnt +#define mscp_buffer mscp_un.mscp_generic.Mscp_buffer +#define mscp_mapbase mscp_un.mscp_generic.Mscp_mapbase +#define mscp_lbn mscp_un.mscp_generic.Mscp_lbn +#define mscp_dscptr mscp_un.mscp_generic.Mscp_dscptr +#define mscp_sftwds mscp_un.mscp_generic.Mscp_sftwds +#define mscp_status mscp_modifier + +/* + * Abort / Get Command Status packet + */ + +#define mscp_outref mscp_bytecnt + +/* + * Set Controller Characteristics packet + */ + +#define mscp_version mscp_un.mscp_setcntchar.Mscp_version +#define mscp_cntflgs mscp_un.mscp_setcntchar.Mscp_cntflgs +#define mscp_hsttmo mscp_un.mscp_setcntchar.Mscp_hsttmo +#define mscp_usefrac mscp_un.mscp_setcntchar.Mscp_usefrac +#define mscp_time mscp_un.mscp_setcntchar.Mscp_time +#define mscp_cntdep mscp_un.mscp_setcntchar.Mscp_cntdep + +/* + * Reposition command packet fields + */ + +#define mscp_reccnt mscp_bytecnt /* record/object count */ +#define mscp_tmkcnt mscp_buffer /* tape mark count */ + +/* + * Get Unit Status end packet + */ + +#define mscp_multunt mscp_un.mscp_getunitsts.Mscp_multunt +#define mscp_unitflgs mscp_un.mscp_getunitsts.Mscp_unitflgs +#define mscp_hostid mscp_un.mscp_getunitsts.Mscp_hostid +#define mscp_unitid mscp_un.mscp_getunitsts.Mscp_unitid +#define mscp_mediaid mscp_un.mscp_getunitsts.Mscp_mediaid +#define mscp_format mscp_un.mscp_getunitsts.Mscp_format /* density:0=high */ +#define mscp_speed mscp_un.mscp_getunitsts.Mscp_speed /* (ips*bpi)/1000 */ +#define mscp_fmtmenu mscp_un.mscp_getunitsts.Mscp_fmtmenu + +/* + * Online / Set Unit Characteristics end packet + */ + +#define mscp_maxwrt mscp_dscptr /* max write byte count */ +#define mscp_noiserec mscp_cylinder /* noise record */ + +/* + * Set Controller Characteristics end packet + */ + +#define mscp_cnttmo mscp_hsttmo /* controller timeout */ +#define mscp_cntcmdl mscp_usefrac /* controller soft & hardware version */ +#define mscp_cntid mscp_unitid /* controller id */ + + +/* + * Error Log message format codes + */ +#define M_FM_CNTERR 0 /* Controller error */ +#define M_FM_BUSADDR 1 /* Host memory access error */ +#define M_FM_TAPETRN 5 /* Tape transfer error */ +#define M_FM_STIERR 6 /* STI communication or command failure */ +#define M_FM_STIDEL 7 /* STI drive error log */ +#define M_FM_STIFEL 010 /* STI formatter error log */ + +/* + * Error Log message flags + */ +#define M_LF_SUCC 0200 /* Operation successful */ +#define M_LF_CONT 0100 /* Operation continuing */ +#define M_LF_SQNRS 0001 /* Sequence number reset */ + +/* + * Tape Format Flag Values + */ +#define M_TF_800 001 /* NRZI 800 bpi */ +#define M_TF_PE 002 /* Phase Encoded 1600 bpi */ +#define M_TF_GCR 004 /* Group Code Recording 6250 bpi */ +#define M_TF_BLK 010 /* Cartridge Block Mode */ + +/* + * MSCP Error Log packet + * + * NOTE: MSCP packet must be padded to this size. + */ + +struct mslg { + struct mscp_header mslg_header;/* device specific header */ + long mslg_cmdref; /* command reference number */ + short mslg_unit; /* unit number */ + short mslg_seqnum; /* sequence number */ + u_char mslg_format; /* format */ + u_char mslg_flags; /* error log message flags */ + short mslg_event; /* event code */ + quad_t mslg_cntid; /* controller id */ + u_char mslg_cntsvr; /* controller software version */ + u_char mslg_cnthvr; /* controller hardware version */ + short mslg_multunt; /* multi-unit code */ + quad_t mslg_unitid; /* unit id */ + u_char mslg_unitsvr; /* unit software version */ + u_char mslg_unithvr; /* unit hardware version */ + short mslg_group; /* group; retry + level */ + long mslg_position; /* position (object count) */ + u_char mslg_fmtsvr; /* formatter software version */ + u_char mslg_fmthvr; /* formatter hardware version */ + short mslg_xxx2; /* unused */ + char mslg_stiunsucc[62]; /* STI status information */ +}; + +#define mslg_sdecyl mslg_group + diff --git a/sys/arch/vax/vax/trap.c b/sys/arch/vax/vax/trap.c new file mode 100644 index 00000000000..3db706dee09 --- /dev/null +++ b/sys/arch/vax/vax/trap.c @@ -0,0 +1,468 @@ +/* $NetBSD: trap.c,v 1.13 1995/07/05 08:39:48 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + + + +#include "sys/types.h" +#include "sys/param.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/syscall.h" +#include "sys/systm.h" +#include "sys/signalvar.h" +#include "sys/exec.h" +#include "vm/vm.h" +#include "vm/vm_kern.h" +#include "vm/vm_page.h" +#include "vax/include/mtpr.h" +#include "vax/include/pte.h" +#include "vax/include/pcb.h" +#include "vax/include/trap.h" +#include "vax/include/pmap.h" +#include "kern/syscalls.c" + + +extern int want_resched,whichqs; +volatile int startsysc=0,ovalidstart=0,faultdebug=0,haltfault=0; + + +userret(p, pc, psl) + struct proc *p; + u_int pc, psl; +{ + int s,sig; + + while ((sig = CURSIG(p)) !=0) + postsig(sig); + p->p_priority = p->p_usrpri; + if (want_resched) { + /* + * Since we are curproc, clock will normally just change + * our priority without moving us from one queue to another + * (since the running process is not on a queue.) + * If that happened after we setrq ourselves but before we + * swtch()'ed, we might not be on the queue indicated by + * our priority. + */ + s=splstatclock(); + setrunqueue(curproc); + cpu_switch(); + splx(s); + while ((sig = CURSIG(curproc)) != 0) + postsig(sig); + } + + curpriority = curproc->p_priority; +} + +char *traptypes[]={ + "reserved addressing", + "privileged instruction", + "reserved operand", + "breakpoint instruction", + "Nothing", + "system call ", + "arithmetic trap", + "asynchronous system trap", + "page table length fault", + "translation violation fault", + "trace trap", + "compatibility mode fault", + "access violation fault", + "", + "", + "KSP invalid", + "", + "kernel debugger trap" +}; +int no_traps = 18; + +arithflt(frame) + struct trapframe *frame; +{ + u_int sig, type=frame->trap,trapsig=1,s; + u_int rv, addr,*i,j; + struct proc *p=curproc; + struct pmap *pm; + vm_map_t map; + vm_prot_t ftype; + extern vm_map_t pte_map; + + if((frame->psl & PSL_U) == PSL_U) { + type|=T_USER; + p->p_addr->u_pcb.framep = frame; + } + + type&=~(T_WRITE|T_PTEFETCH); + + + +if(frame->trap==7) goto fram; +if(faultdebug)printf("Trap: type %x, code %x, pc %x, psl %x\n", + frame->trap, frame->code, frame->pc, frame->psl); +fram: + switch(type){ + + default: +faulter: +#ifdef DDB + if (kdb_trap(frame)) + return; +#endif + panic("trap: adr %x",frame->code); + case T_KSPNOTVAL: + goto faulter; + + case T_TRANSFLT|T_USER: + case T_TRANSFLT: /* Translation invalid - may be simul page ref */ + if(frame->trap&T_PTEFETCH){ + u_int *ptep, *pte, *pte1; + + if(frame->code<0x40000000) + ptep=(u_int *)p->p_addr->u_pcb.P0BR; + else + ptep=(u_int *)p->p_addr->u_pcb.P1BR; + pte1=(u_int *)trunc_page(&ptep[(frame->code + &0x3fffffff)>>PG_SHIFT]); + pte=(u_int*)&Sysmap[((u_int)pte1&0x3fffffff)>>PG_SHIFT]; + if(*pte&PG_SREF){ /* Yes, simulated */ + s=splhigh(); + + *pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++; + *pte|=PG_REF|PG_V;*pte&=~PG_SREF; + mtpr(0,PR_TBIA); + splx(s); + goto uret; + } + } else { + u_int *ptep, *pte; + + frame->code=trunc_page(frame->code); + if(frame->code<0x40000000){ + ptep=(u_int *)p->p_addr->u_pcb.P0BR; + pte=&ptep[(frame->code>>PG_SHIFT)]; + } else if(frame->code>0x7fffffff){ + pte=(u_int *)&Sysmap[((u_int)frame->code& + 0x3fffffff)>>PG_SHIFT]; + } else { + ptep=(u_int *)p->p_addr->u_pcb.P1BR; + pte=&ptep[(frame->code&0x3fffffff)>>PG_SHIFT]; + } + if(*pte&PG_SREF){ + s=splhigh(); + *pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++; + *pte|=PG_REF|PG_V;*pte&=~PG_SREF; + /* mtpr(frame->code,PR_TBIS); */ + /* mtpr(frame->code+NBPG,PR_TBIS); */ + mtpr(0,PR_TBIA); + splx(s); + goto uret; + } + } + /* Fall into... */ + case T_ACCFLT: + case T_ACCFLT|T_USER: +if(faultdebug)printf("trap accflt type %x, code %x, pc %x, psl %x\n", + frame->trap, frame->code, frame->pc, frame->psl); + + if(!p) panic("trap: access fault without process"); + pm=&p->p_vmspace->vm_pmap; + if(frame->trap&T_PTEFETCH){ + u_int faultaddr,testaddr=(u_int)frame->code&0x3fffffff; + int P0=0,P1=0,SYS=0; + + if(frame->code==testaddr) P0++; + else if(frame->code>0x7fffffff) SYS++; + else P1++; + + if(P0){ + faultaddr=(u_int)pm->pm_pcb->P0BR+ + ((testaddr>>PG_SHIFT)<<2); + } else if(P1){ + faultaddr=(u_int)pm->pm_pcb->P1BR+ + ((testaddr>>PG_SHIFT)<<2); + } else panic("pageflt: PTE fault in SPT\n"); + + faultaddr&=~PAGE_MASK; + rv = vm_fault(pte_map, faultaddr, + VM_PROT_WRITE|VM_PROT_READ, FALSE); + if (rv != KERN_SUCCESS) { + + sig=SIGSEGV; + goto bad; + } else trapsig=0; +/* return; /* We don't know if it was a trap only for PTE*/ +/* break; */ + } + addr=(frame->code& ~PAGE_MASK); + if((frame->pc>(unsigned)0x80000000)&& + (frame->code>(unsigned)0x80000000)){ + map=kernel_map; + } else { + map= &p->p_vmspace->vm_map; + } + if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ; + else ftype = VM_PROT_READ; + + rv = vm_fault(map, addr, ftype, FALSE); + if (rv != KERN_SUCCESS) { + if(frame->pc>(u_int)0x80000000){ + if(p->p_addr->u_pcb.iftrap){ + frame->pc=(int)p->p_addr->u_pcb.iftrap; + return; + } + printf("Segv in kernel mode: rv %d\n",rv); + goto faulter; + } + sig=SIGSEGV; + } else trapsig=0; + break; + + case T_PTELEN: + case T_PTELEN|T_USER: /* Page table length exceeded */ + pm=&p->p_vmspace->vm_pmap; +if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n", + frame->trap, frame->code, frame->pc, frame->psl); + if(frame->code<0x40000000){ /* P0 */ + int i; + + if (p->p_vmspace == 0){ + printf("no vmspace in fault\n"); + goto faulter; + } + i = p->p_vmspace->vm_tsize + p->p_vmspace->vm_dsize; + if (i > (frame->code >> PAGE_SHIFT)){ + pmap_expandp0(pm, i << 1); + trapsig = 0; + } else { + sig = SIGSEGV; + } + } else if (frame->code > 0x7fffffff){ /* System, segv */ + sig = SIGSEGV; + } else { /* P1 */ + int i; + + i = (u_int)(p->p_vmspace->vm_maxsaddr); + if (frame->code < i){ + sig = SIGSEGV; + } else { + pmap_expandp1(pm); + trapsig = 0; + } + } + break; + + case T_BPTFLT|T_USER: + case T_TRCTRAP|T_USER: + sig = SIGTRAP; + frame->psl &= ~PSL_T; + break; + + case T_PRIVINFLT|T_USER: + case T_RESADFLT|T_USER: + case T_RESOPFLT|T_USER: + sig=SIGILL; + break; + + case T_ARITHFLT|T_USER: + sig=SIGFPE; + break; + + case T_ASTFLT|T_USER: + mtpr(AST_NO,PR_ASTLVL); + trapsig=0; + break; + } +bad: + if(trapsig) trapsignal(curproc, sig, frame->code); +uret: + userret(curproc, frame->pc, frame->psl); +}; + +showstate(p) + struct proc *p; +{ +if(p){ + printf("\npid %d, command %s\n",p->p_pid, p->p_comm); + printf("text size %x, data size %x, stack size %x\n", + p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace-> + vm_ssize); + printf("virt text %x, virt data %x, max stack %x\n", + p->p_vmspace->vm_taddr,p->p_vmspace->vm_daddr, + p->p_vmspace->vm_maxsaddr); + printf("kernel uarea %x, end uarea %x\n",p->p_addr, + (u_int)p->p_addr + USPACE); +} else { + printf("No process\n"); +} + printf("kernel stack: %x, interrupt stack %x\n", + mfpr(PR_KSP),mfpr(PR_ISP)); + printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n", + mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR)); +} + +void +setregs(p, pack, stack, retval) + struct proc *p; + struct exec_package *pack; + u_long stack; + register_t retval[2]; +{ + struct trapframe *exptr; + + exptr = p->p_addr->u_pcb.framep; + exptr->pc = pack->ep_entry + 2; + mtpr(stack, PR_USP); + retval[0] = retval[1] = 0; +} + +syscall(frame) + struct trapframe *frame; +{ + struct sysent *callp; + int nsys; + int err,rval[2],args[8],sig; + struct trapframe *exptr; + struct proc *p=curproc; + +if(startsysc)printf("trap syscall %s pc %x, psl %x, ap %x, pid %d, frame %x\n", + syscallnames[frame->code], frame->pc, frame->psl,frame->ap, + curproc->p_pid,frame); + + p->p_addr->u_pcb.framep = frame; + callp = p->p_emul->e_sysent; + nsys = p->p_emul->e_nsysent; + + if(frame->code == SYS___syscall){ + int g = *(int *)(frame->ap); + + frame->code=*(int *)(frame->ap+4); + frame->ap+=8; + *(int *)(frame->ap)=g-2; + } + + if(frame->code<0||frame->code>=nsys) + callp += p->p_emul->e_nosys; + else + callp += frame->code; + + rval[0]=0; + rval[1]=frame->r1; + if(callp->sy_narg) + copyin((char*)frame->ap+4, args, callp->sy_argsize); + + err=(*callp->sy_call)(curproc,args,rval); + exptr=curproc->p_addr->u_pcb.framep; + +if(startsysc) + printf("retur %s pc %x, psl %x, ap %x, pid %d, v{rde %d r0 %d, r1 %d, frame %x\n", + syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->ap, + curproc->p_pid,err,rval[0],rval[1],exptr); + + switch(err){ + case 0: + exptr->r1=rval[1]; + exptr->r0=rval[0]; + exptr->psl &= ~PSL_C; + break; + case EJUSTRETURN: + return; + case ERESTART: + exptr->pc=exptr->pc-2; + break; + default: + exptr->r0=err; + exptr->psl |= PSL_C; + break; + } + userret(curproc, exptr->pc, exptr->psl); +} + +stray(scb, vec){ + printf("stray interrupt scb %d, vec 0x%x\n", scb, vec); +} + +struct inta { + char pushr[2]; /* pushr $3f */ + char pushl[2]; /* pushl $? */ + char nop; /* nop, for foolish gcc */ + char calls[3]; /* $1,? */ + u_int hoppaddr; /* jump for calls */ + char popr[2]; /* popr $0x3f */ + char rei; /* rei */ +} intasm = {0xbb, 0x3f, 0xdd, 0, 1, 0xfb, 1, 0xef, 0, 0xba, 0x3f, 2}; + +u_int +settrap(plats, nyrut,arg) + u_int plats; /* Pointer to place to copy interrupt routine */ + u_int nyrut; /* Pointer to new routine to jump to */ + u_int arg; /* arg number to pass to routine. */ +{ + struct inta *introut; + + introut=(void *)((plats&0xfffffffc)+4); + bcopy(&intasm, introut, sizeof(struct inta)); + introut->pushl[1]=arg; + introut->hoppaddr=nyrut-(u_int)&introut->popr[0]; + return (u_int)introut; +} + +printstack(loaddr, highaddr) + u_int *loaddr, *highaddr; +{ + u_int *tmp; + + (u_int)tmp = 0xfffffffc & (u_int)loaddr; /* Easy align */ + + for (;tmp < highaddr;tmp += 4) + printf("%8x: %8x %8x %8x %8x\n", + tmp, *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3)); +} + +showregs(frame) + struct trapframe *frame; +{ + printf("P0BR %8x P1BR %8x P0LR %8x P1LR %8x\n", + mfpr(PR_P0BR), mfpr(PR_P1BR), mfpr(PR_P0LR), mfpr(PR_P1LR)); + printf("KSP %8x ISP %8x USP %8x\n", + mfpr(PR_KSP), mfpr(PR_ISP), mfpr(PR_USP)); + printf("R0 %8x R1 %8x R2 %8x R3 %8x\n", + frame->r0, frame->r1, frame->r2, frame->r3); + printf("R4 %8x R5 %8x R6 %8x R7 %8x\n", + frame->r4, frame->r5, frame->r6, frame->r7); + printf("R8 %8x R9 %8x R10 %8x R11 %8x\n", + frame->r8, frame->r9, frame->r10, frame->r11); + printf("FP %8x AP %8x PC %8x PSL %8x\n", + frame->fp, frame->ap, frame->pc, frame->psl); +} diff --git a/sys/arch/vax/vax/udiv.s b/sys/arch/vax/vax/udiv.s new file mode 100644 index 00000000000..99fb0fcab21 --- /dev/null +++ b/sys/arch/vax/vax/udiv.s @@ -0,0 +1,71 @@ +/* $NetBSD: udiv.s,v 1.2 1994/10/26 08:03:34 cgd Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udiv.s 5.6 (Berkeley) 4/15/91 + */ + +/* + * Unsigned division, PCC flavor. + * udiv() takes an ordinary dividend/divisor pair; + * audiv() takes a pointer to a dividend and an ordinary divisor. + */ + + +#define DIVIDEND 4(ap) +#define DIVISOR 8(ap) + + .globl udiv + .align 2 +udiv: .word 0x0 + movl DIVISOR,r2 + jlss Leasy # big divisor: settle by comparison + movl DIVIDEND,r0 + jlss Lhard # big dividend: extended division + divl2 r2,r0 # small divisor and dividend: signed division + ret +Lhard: + clrl r1 + ediv r2,r0,r0,r1 + ret +Leasy: + cmpl DIVIDEND,r2 + jgequ Lone # if dividend is as big or bigger, return 1 + clrl r0 # else return 0 + ret +Lone: + movl $1,r0 + ret diff --git a/sys/arch/vax/vax/urem.s b/sys/arch/vax/vax/urem.s new file mode 100644 index 00000000000..c0f0857df02 --- /dev/null +++ b/sys/arch/vax/vax/urem.s @@ -0,0 +1,69 @@ +/* $NetBSD: urem.s,v 1.2 1994/10/26 08:03:37 cgd Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Donn Seeley at UUNET Technologies, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)urem.s 5.6 (Berkeley) 4/15/91 + */ + +/* + * Unsigned modulus, PCC flavor. + * urem() takes an ordinary dividend/divisor pair; + */ + +#define DIVIDEND 4(ap) +#define DIVISOR 8(ap) + .globl urem + .align 2 +urem: .word 0x0 + + movl 8(ap),r2 + jlss Leasy # big divisor: settle by comparison + movl 4(ap),r0 + jlss Lhard # big dividend: need extended division + divl3 r2,r0,r1 # small divisor and dividend: signed modulus + mull2 r2,r1 + subl2 r1,r0 + ret +Lhard: + clrl r1 + ediv r2,r0,r1,r0 + ret +Leasy: + subl3 r2,DIVIDEND,r0 + jcc Ldifference # if divisor goes in once, return difference + movl DIVIDEND,r0 # if divisor is bigger, return dividend +Ldifference: + ret diff --git a/sys/arch/vax/vax/uvaxII.c b/sys/arch/vax/vax/uvaxII.c new file mode 100644 index 00000000000..3b617d2dc36 --- /dev/null +++ b/sys/arch/vax/vax/uvaxII.c @@ -0,0 +1,262 @@ +/* $NetBSD: uvaxII.c,v 1.2 1995/04/18 22:08:25 ragge Exp $ */ + +/*- + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ka630.c 7.8 (Berkeley) 5/9/91 + */ + +/* All bugs are subject to removal without further notice */ + +#if VAX630 || VAX410 + +#include "sys/param.h" +#include "sys/types.h" +#include "sys/device.h" +#include "machine/uvaxII.h" +#include "machine/nexus.h" +#include "machine/pte.h" +#include "machine/mtpr.h" +#include "machine/sid.h" +#include "vax/uba/ubavar.h" +#include "vax/uba/ubareg.h" + +#include "mba.h" +#include "uba.h" + +#include "vm/vm.h" +#include "vm/vm_kern.h" +#include "vax/include/pmap.h" + +struct nexus *nexus; +struct uvaxIIcpu *uvaxIIcpu_ptr; +#if VAX630 +struct ka630clock *ka630clk_ptr; +u_long ka630_clkread(); +void ka630_clkwrite(); +#endif +extern int cpu_type, nmba, numuba; + +int +uvaxII_conf() +{ + extern char cpu_model[]; + + switch (cpu_type) { + case VAX_630: + strcpy(cpu_model,"MicroVAXII"); + break; + case VAX_410: + strcpy(cpu_model,"MicroVAX 2000"); + break; + }; + config_rootfound("backplane",(void*)75); +} + +int +conf_uvaxII(){ + + printf(": UvaxII CPU (78032/78132)\n"); +} + +uvaxII_clock(){ + + mtpr(0x40,PR_ICCS); /* Start clock and enable interrupt */ + return 1; +} + +/* log crd errors */ +uvaxII_memerr() +{ + printf("memory err!\n"); +} + +#define NMC78032 10 +char *mc78032[] = { + 0, "immcr (fsd)", "immcr (ssd)", "fpu err 0", + "fpu err 7", "mmu st(tb)", "mmu st(m=0)", "pte in p0", + "pte in p1", "un intr id", +}; + +struct mc78032frame { + int mc63_bcnt; /* byte count == 0xc */ + int mc63_summary; /* summary parameter */ + int mc63_mrvaddr; /* most recent vad */ + int mc63_istate; /* internal state */ + int mc63_pc; /* trapped pc */ + int mc63_psl; /* trapped psl */ +}; + +uvaxII_mchk(cmcf) + caddr_t cmcf; +{ + register struct mc78032frame *mcf = (struct mc78032frame *)cmcf; + register u_int type = mcf->mc63_summary; + + printf("machine check %x", type); + if (type < NMC78032 && mc78032[type]) + printf(": %s", mc78032[type]); + printf("\n\tvap %x istate %x pc %x psl %x\n", + mcf->mc63_mrvaddr, mcf->mc63_istate, + mcf->mc63_pc, mcf->mc63_psl); + if (uvaxIIcpu_ptr && uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_MERR) { + printf("\tmser=0x%x ", uvaxIIcpu_ptr->uvaxII_mser); + if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_CPUE) + printf("page=%d", uvaxIIcpu_ptr->uvaxII_cear); + if (uvaxIIcpu_ptr->uvaxII_mser & UVAXIIMSER_DQPE) + printf("page=%d", uvaxIIcpu_ptr->uvaxII_dear); + printf("\n"); + } + return (-1); +} + +/* + * Handle the watch chip used by the ka630 and ka410 mother boards. + */ +u_long +uvaxII_gettodr(stopped_flag) + int *stopped_flag; +{ + register u_long year_secs; + + switch (cpu_type) { +#if VAX630 + case VAX_630: + year_secs = ka630_clkread(stopped_flag); + break; +#endif + default: + year_secs = 0; + *stopped_flag = 1; + }; + return (year_secs * 100); +} + +void +uvaxII_settodr(year_ticks) + u_long year_ticks; +{ + register u_long year_secs; + + year_secs = year_ticks / 100; + switch (cpu_type) { +#if VAX630 + case VAX_630: + ka630_clkwrite(year_secs); + break; +#endif + }; +} + +#if VAX630 +static short dayyr[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 }; +/* init system time from tod clock */ +/* ARGSUSED */ +u_long +ka630_clkread(stopped_flag) + int *stopped_flag; +{ + register struct ka630clock *claddr = ka630clk_ptr; + register int days, yr; + register u_long year_secs; + + *stopped_flag = 0; + claddr->csr1 = KA630CLK_SET; + while ((claddr->csr0 & KA630CLK_UIP) != 0) + ; + /* If the clock is valid, use it. */ + if ((claddr->csr3 & KA630CLK_VRT) != 0 && + (claddr->csr1 & KA630CLK_ENABLE) == KA630CLK_ENABLE) { + /* simple sanity checks */ + if (claddr->mon < 1 || claddr->mon > 12 || + claddr->day < 1 || claddr->day > 31) { + printf("WARNING: preposterous clock chip time.\n"); + year_secs = 0; + } else { + days = dayyr[claddr->mon - 1] + claddr->day - 1; + year_secs = days * DAYSEC + claddr->hr * HRSEC + + claddr->min * MINSEC + claddr->sec; + } + claddr->yr = 70; /* any non-leap year */ +#ifndef lint + { volatile int t = claddr->csr2; } /* ??? */ +#endif + claddr->csr0 = KA630CLK_RATE; + claddr->csr1 = KA630CLK_ENABLE; + + return (year_secs); + } + printf("WARNING: TOY clock invalid.\n"); + return (0); +} + +/* Set the time of day clock, called via. stime system call.. */ +void +ka630_clkwrite(year_secs) + u_long year_secs; +{ + register struct ka630clock *claddr = ka630clk_ptr; + register int t, t2; + int s; + + s = splhigh(); + claddr->csr1 = KA630CLK_SET; + while ((claddr->csr0 & KA630CLK_UIP) != 0) + ; + claddr->yr = 70; /* any non-leap year is ok */ + + /* t = month + day; separate */ + t = year_secs % YEARSEC; + for (t2 = 1; t2 < 12; t2++) + if (t < dayyr[t2]) + break; + + /* t2 is month */ + claddr->mon = t2; + claddr->day = t - dayyr[t2 - 1] + 1; + + /* the rest is easy */ + t = year_secs % DAYSEC; + claddr->hr = t / HRSEC; + t %= HRSEC; + claddr->min = t / MINSEC; + claddr->sec = t % MINSEC; +#ifndef lint + { int t = claddr->csr2; } /* ??? */ + { int t = claddr->csr3; } /* ??? */ +#endif + claddr->csr0 = KA630CLK_RATE; + claddr->csr1 = KA630CLK_ENABLE; + splx(s); +} +#endif +#endif diff --git a/sys/arch/vax/vax/vm_machdep.c b/sys/arch/vax/vax/vm_machdep.c new file mode 100644 index 00000000000..a33f58daa38 --- /dev/null +++ b/sys/arch/vax/vax/vm_machdep.c @@ -0,0 +1,521 @@ +/* $NetBSD: vm_machdep.c,v 1.16.2.1 1995/10/15 14:01:06 ragge Exp $ */ + +#undef SWDEBUG +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * 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 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 */ + +#include "sys/types.h" +#include "sys/param.h" +#include "sys/proc.h" +#include "sys/user.h" +#include "sys/exec.h" +#include "sys/vnode.h" +#include "sys/core.h" +#include "sys/mount.h" +#include "vm/vm.h" +#include "vm/vm_kern.h" +#include "vm/vm_page.h" +#include "machine/vmparam.h" +#include "machine/mtpr.h" +#include "machine/pmap.h" +#include "machine/pte.h" +#include "machine/macros.h" +#include "machine/trap.h" +#include "machine/pcb.h" + +#include <sys/syscallargs.h> + +volatile int whichqs; + +/* + * pagemove - moves pages at virtual address from to virtual address to, + * block moved of size size. Using fast insn bcopy for pte move. + */ +void +pagemove(from, to, size) + caddr_t from, to; + int size; +{ + u_int *fpte, *tpte,stor; + + fpte = kvtopte(from); + tpte = kvtopte(to); + + stor = (size/NBPG) * sizeof(struct pte); + bcopy(fpte,tpte,stor); + bzero(fpte,stor); + mtpr(0,PR_TBIA); +} + +#define VIRT2PHYS(x) \ + (((*(int *)((((((int)x)&0x7fffffff)>>9)*4)+ \ + (unsigned int)Sysmap))&0x1fffff)<<9) + +/* + * cpu_fork() copies parent process trapframe directly into child PCB + * so that when we swtch() to the child process it will go directly + * back to user mode without any need to jump back through kernel. + * We also take away mapping for the second page after pcb, so that + * we get something like a "red zone". + * No need for either double-map kernel stack or relocate it when + * forking. + */ +int +cpu_fork(p1, p2) + struct proc *p1, *p2; +{ + struct pcb *nyproc; + struct trapframe *tf; + struct pmap *pmap, *opmap; + u_int *p2pte; + extern vm_map_t pte_map; + + nyproc = &p2->p_addr->u_pcb; + tf = p1->p_addr->u_pcb.framep; + opmap = &p1->p_vmspace->vm_pmap; + pmap = &p2->p_vmspace->vm_pmap; + pmap->pm_pcb = nyproc; + +#ifdef notyet + /* Mark page invalid */ + p2pte = kvtopte((u_int *)p2->p_addr + 2 * NBPG); + *p2pte = 0; +#endif + +#ifdef notyet + /* Set up internal defs in PCB, and alloc PTEs. */ + nyproc->P0BR = kmem_alloc_wait(pte_map, + (opmap->pm_pcb->P0LR & ~AST_MASK) * 4); + nyproc->P1BR = kmem_alloc_wait(pte_map, + (0x800000 - (pmap->pm_pcb->P1LR * 4))) - 0x800000; + nyproc->P0LR = opmap->pm_pcb->P0LR; + nyproc->P1LR = opmap->pm_pcb->P1LR; +#else + nyproc->P0BR = (void *)0; + nyproc->P1BR = (void *)0x80000000; + nyproc->P0LR = AST_PCB; + nyproc->P1LR = 0x200000; +#endif + nyproc->USP = mfpr(PR_USP); + nyproc->iftrap = NULL; + nyproc->KSP = (u_int)p2->p_addr + USPACE; + + /* General registers as taken from userspace */ + /* trapframe should be synced with pcb */ + bcopy(&tf->r2,&nyproc->R[2],10*sizeof(int)); + nyproc->AP = tf->ap; + nyproc->FP = tf->fp; + nyproc->PC = tf->pc; + nyproc->PSL = tf->psl & ~PSL_C; + nyproc->R[0] = p1->p_pid; /* parent pid. (shouldn't be needed) */ + nyproc->R[1] = 1; + + return 0; /* Child is ready. Parent, return! */ + +} + +/* + * cpu_set_kpc() sets up pcb for the new kernel process so that it will + * start at the procedure pointed to by pc next time swtch() is called. + * When that procedure returns, it will pop off everything from the + * faked calls frame on the kernel stack, do an REI and go down to + * user mode. + */ +void +cpu_set_kpc(p, pc) + struct proc *p; + u_int pc; +{ + struct pcb *nyproc; + struct { + u_int chand; + u_int mask; + u_int ap; + u_int fp; + u_int pc; + u_int nargs; + u_int pp; + u_int rpc; + u_int rpsl; + } *kc; + extern int rei; + + kc = (void *)p->p_addr + USPACE - sizeof(*kc); + kc->chand = 0; + kc->mask = 0x20000000; + kc->pc = (u_int)&rei; + kc->nargs = 1; + kc->pp = (u_int)p; + kc->rpsl = 0x3c00000; + + nyproc = &p->p_addr->u_pcb; + nyproc->framep = (void *)p->p_addr + USPACE - sizeof(struct trapframe); + nyproc->AP = (u_int)&kc->nargs; + nyproc->FP = nyproc->KSP = (u_int)kc; + nyproc->PC = pc + 2; +} + +void +setrunqueue(p) + struct proc *p; +{ + struct prochd *q; + int knummer; + + if(p->p_back) + panic("sket sig i setrunqueue\n"); + knummer=(p->p_priority>>2); + bitset(knummer,whichqs); + q=&qs[knummer]; + + _insque(p,q); + + return; +} + +void +remrq(p) + struct proc *p; +{ + struct proc *qp; + int bitnr; + + bitnr=(p->p_priority>>2); + if(bitisclear(bitnr,whichqs)) + panic("remrq: Process not in queue\n"); + + _remque(p); + + qp=(struct proc *)&qs[bitnr]; + if(qp->p_forw==qp) + bitclear(bitnr,whichqs); +} + +volatile caddr_t curpcb,nypcb; + +cpu_switch(){ + int i,j,s; + struct proc *p; + volatile struct proc *q; + extern unsigned int want_resched,scratch; + +hej: + /* F|rst: Hitta en k|. */ + s=splhigh(); + if((i=ffs(whichqs)-1)<0) goto idle; + +found: + asm(".data;savpsl: .long 0;.text;movpsl savpsl"); + q=(struct proc *)&qs[i]; + if(q->p_forw==q) + panic("swtch: no process queued"); + + bitclear(i,whichqs); + p=q->p_forw; + _remque(p); + + if(q->p_forw!=q) bitset(i,whichqs); + if(curproc) (u_int)curpcb=VIRT2PHYS(&curproc->p_addr->u_pcb); + else (u_int)curpcb=scratch; + (u_int)nypcb=VIRT2PHYS(&p->p_addr->u_pcb); + + if(!p) panic("switch: null proc pointer\n"); + want_resched=0; + curproc=p; + if(curpcb==nypcb) return; + + asm("pushl savpsl"); + asm("jsb _loswtch"); + + return; /* New process! */ + +idle: + spl0(); + while(!whichqs); + goto hej; +} + +/* Should check that values is in bounds XXX */ +copyinstr(from, to, maxlen, lencopied) +void *from, *to; +u_int *lencopied,maxlen; +{ + u_int i; + void *addr=&curproc->p_addr->u_pcb.iftrap; + char *gfrom=from, *gto=to; + + asm("movl $Lstr,(%0)":: "r"(addr)); + for(i=0;i<maxlen;i++){ + *(gto+i)=*(gfrom+i); + if(!(*(gto+i))) goto ok; + } + + return(ENAMETOOLONG); +ok: + if(lencopied) *lencopied=i+1; + return(0); +} + +asm("Lstr: ret"); + +/* Should check that values is in bounds XXX */ +copyoutstr(from, to, maxlen, lencopied) +void *from, *to; +u_int *lencopied,maxlen; +{ + u_int i; + char *gfrom=from, *gto=to; + void *addr=&curproc->p_addr->u_pcb.iftrap; + + asm("movl $Lstr,(%0)":: "r"(addr)); + for(i=0;i<maxlen;i++){ + *(gto+i)=*(gfrom+i); + if(!(*(gto+i))) goto ok; + } + + return(ENAMETOOLONG); +ok: + if(lencopied) *lencopied=i+1; + return 0; +} + +cpu_exec_aout_makecmds(p, epp) + struct proc *p; + struct exec_package *epp; +{ + int error; + struct exec *ep; +/* + * Compatibility with reno programs. + */ + ep=epp->ep_hdr; + switch (ep->a_midmag) { + case 0x10b: /* ZMAGIC in 4.3BSD Reno programs */ + error = reno_zmagic(p, epp); + break; + case 0x108: +printf("Warning: reno_nmagic\n"); + error = exec_aout_prep_nmagic(p, epp); + break; + case 0x107: +printf("Warning: reno_omagic\n"); + error = exec_aout_prep_omagic(p, epp); + break; + default: + error = ENOEXEC; + } + return(error); +} + +int +sys_sysarch(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + + return (ENOSYS); +}; + +#ifdef COMPAT_ULTRIX +extern struct emul emul_ultrix; +#endif +/* + * 4.3BSD Reno programs have an 1K header first in the executable + * file, containing a.out header. Otherwise programs are identical. + * + * from: exec_aout.c,v 1.9 1994/01/28 23:46:59 jtc Exp $ + */ + +int +reno_zmagic(p, epp) + struct proc *p; + struct exec_package *epp; +{ + struct exec *execp = epp->ep_hdr; + + epp->ep_taddr = 0; + epp->ep_tsize = execp->a_text; + epp->ep_daddr = epp->ep_taddr + execp->a_text; + epp->ep_dsize = execp->a_data + execp->a_bss; + epp->ep_entry = execp->a_entry; + +#ifdef COMPAT_ULTRIX + epp->ep_emul = &emul_ultrix; +#endif + + /* + * check if vnode is in open for writing, because we want to + * demand-page out of it. if it is, don't do it, for various + * reasons + */ + if ((execp->a_text != 0 || execp->a_data != 0) && + epp->ep_vp->v_writecount != 0) { + return ETXTBSY; + } + epp->ep_vp->v_flag |= VTEXT; + + /* set up command for text segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text, + epp->ep_taddr, epp->ep_vp, 0x400, VM_PROT_READ|VM_PROT_EXECUTE); + + /* set up command for data segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data, + epp->ep_daddr, epp->ep_vp, execp->a_text+0x400, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + + /* set up command for bss segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss, + epp->ep_daddr + execp->a_data, NULLVP, 0, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + + return exec_aout_setup_stack(p, epp); +} + +void +cpu_exit(p) + struct proc *p; +{ + extern unsigned int scratch; + + if(!p) panic("cpu_exit from null process"); + vmspace_free(p->p_vmspace); + + (void) splimp(); + mtpr(scratch+NBPG,PR_KSP);/* Must change kernel stack before freeing */ + kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES)); + cpu_switch(); + /* NOTREACHED */ +} + +suword(ptr,val) + void *ptr; + int val; +{ + void *addr=&curproc->p_addr->u_pcb.iftrap; + + asm("movl $Lstr,(%0)":: "r"(addr)); + *(int *)ptr=val; + return 0; +} + +/* + * Dump the machine specific header information at the start of a core dump. + * First put all regs in PCB for debugging purposes. This is not an good + * way to do this, but good for my purposes so far. + */ +int +cpu_coredump(p, vp, cred, chdr) + struct proc *p; + struct vnode *vp; + struct ucred *cred; + struct core *chdr; +{ + struct trapframe *tf; + struct md_coredump state; + struct coreseg cseg; + int error; + + tf = p->p_addr->u_pcb.framep; + CORE_SETMAGIC(*chdr, COREMAGIC, MID_VAX, 0); + chdr->c_hdrsize = sizeof(struct core); + chdr->c_seghdrsize = sizeof(struct coreseg); + chdr->c_cpusize = sizeof(struct md_coredump); + + bcopy(tf, &state, sizeof(struct md_coredump)); + state.md_tf.code = mfpr(PR_USP); /* XXX */ + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_VAX, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = chdr->c_cpusize; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, + (off_t)chdr->c_hdrsize, UIO_SYSSPACE, + IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); + if (error) + return error; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&state, sizeof(state), + (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, + IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); + + if (!error) + chdr->c_nseg++; + + return error; +} + +copyout(from, to, len) + void *from, *to; +{ + void *addr=&curproc->p_addr->u_pcb.iftrap; + + return locopyout(from, to, len, addr); +} + +copyin(from, to, len) + void *from, *to; +{ + void *addr=&curproc->p_addr->u_pcb.iftrap; + + return locopyin(from, to, len, addr); +} + +/* + * cpu_swapin() is called just before a process shall be swapped in. + * Kernel stack and pcb must be mapped when we swtch() to this new + * process, to guarantee that we frob all pages here to ensure that + * they actually are in-core. Kernel stack red zone is also updated + * here. + */ +void +cpu_swapin(p) + struct proc *p; +{ + u_int uarea, i, *j, rv; + + uarea = (u_int)p->p_addr; + + for(i = uarea;i < uarea + USPACE;i += PAGE_SIZE) { + j = (u_int *)kvtopte(i); + if ((*j & PG_V) == 0) { + rv = vm_fault(kernel_map, i, + VM_PROT_WRITE|VM_PROT_READ, FALSE); + if (rv != KERN_SUCCESS) + panic("cpu_swapin: rv %d",rv); + } + } +#ifdef notyet + j = (u_int *)kvtopte(uarea + 2 * NBPG); + *j = 0; /* Set kernel stack red zone */ +#endif +} |