This commit is contained in:
Oliver Lehmann 1989-02-03 07:48:53 +00:00
parent a094055e97
commit 2adeef252b
16 changed files with 4724 additions and 0 deletions

121
WEGA/src/cmd/BOOT/bconf.c Normal file
View File

@ -0,0 +1,121 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul conf.c
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:07
Version: 1.1
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/inode.h>
#include <saio.h>
/*------------------------------------------ Funktionen ---------------------*/
/*---------------------------------------------------------------------------*/
/*
*devread
* Verzweigung zur speziellen Device - Treiber Routine strategy,
* (Block-Device) mit dem Parameter Read
* Verzweigung erfolgt ueber devsw am Ende dieses Moduls
*/
/*---------------------------------------------------------------------------*/
devread(io)
register struct iob *io;
{
return( (*devsw[io->i_ino.i_dev].dv_strategy)(io,READ) );
}
/*---------------------------------------------------------------------------*/
/*
*devwrite
* Verzweigung zur speziellen Device - Treiber Routine strategy,
* (Block-Device) mit dem Parameter Write
* Verzweigung erfolgt ueber devsw am Ende dieses Moduls
*/
/*---------------------------------------------------------------------------*/
devwrite(io)
register struct iob *io;
{
return( (*devsw[io->i_ino.i_dev].dv_strategy)(io, WRITE) );
}
/*---------------------------------------------------------------------------*/
/*
*devopen
* Verzweigung zur speziellen Device - Treiber Routine open,
* Verzweigung erfolgt ueber devsw am Ende dieses Moduls
*/
/*---------------------------------------------------------------------------*/
devopen(io)
register struct iob *io;
{
return( (*devsw[io->i_ino.i_dev].dv_open)(io) );
}
/*---------------------------------------------------------------------------*/
/*
*devclose
* Verzweigung zur speziellen Device - Treiber Routine close,
* Verzweigung erfolgt ueber devsw am Ende dieses Moduls
*/
/*---------------------------------------------------------------------------*/
devclose(io)
register struct iob *io;
{
return( (*devsw[io->i_ino.i_dev].dv_close)(io) );
}
/*---------------------------------------------------------------------------*/
/*
*nullsys
* null Device Treiber routine
*/
/*---------------------------------------------------------------------------*/
nullsys()
{ ; }
/*------------------------------------------ Variablen ----------------------*/
/*
* Device Switch Tabelle
* Die Tabelle ist ein Feld von n Elementen der Struktur devsw,
* welche aus jeweils 4 Elementen besteht.
* Ueber diese Tabelle erfolgt die Verzweigung zu den einzelnen
* Device Treibern
* Das 1. Element ist ein Pointer auf den Devicenamen. Dieser wird
* zB von open hier gesucht.
* Die folgenden Elemente sind Pointer auf die Device Routinen
* Das Ende der Tabelle wird mit 0 fuer alle 4 Elemente gekennzeichnet
* Die Tabelle ist Abhaengig von der Implenentation der Devices
*/
int mdstrategy();
int fdstrategy();
int rmstrat();
int rmopen();
int rmclose();
int udstrat();
int udopen();
int udclose();
int nullsys();
struct devsw devsw[] = {
"md", mdstrategy, nullsys, nullsys,
"zd", mdstrategy, nullsys, nullsys,
"fd", fdstrategy, nullsys, nullsys,
"ud", udstrat, udopen, udclose,
"rm", rmstrat, rmopen, rmclose,
0,0,0,0
};

59
WEGA/src/cmd/BOOT/bfd.c Normal file
View File

@ -0,0 +1,59 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1986
Standalone Modul fd.c
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:11
Version: 1.1
*******************************************************************************
Device Treiber fd fuer Floppydisk
Der physische Treiber befindet sich im Monitor
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/inode.h>
#include <saio.h>
extern long bsbase;
fdstrategy(io, func)
register struct iob *io;
{
register unsigned errcount;
register daddr_t bn;
register daddr_t addr;
register unsigned count;
unsigned size;
bn = io->i_bn;
count = io->i_cc;
addr = (daddr_t)io->i_ma + bsbase;
for (; count != 0; count -= size) {
errcount = 0;
size = min(0x200, count);
for (; fdisk(func, io->i_unit, bn, addr, size);) {
if (errcount == 0)
printf("fd: io error\n");
if (++errcount >= 10) {
printf ("fd: fatal error\n");
return(-1);
}
}
addr += size;
bn++;
}
return(io->i_cc);
}

606
WEGA/src/cmd/BOOT/bmch.s Normal file
View File

@ -0,0 +1,606 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul mch.s
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:11
Version: 1.1
*******************************************************************************
Boot Proceduren die nicht in C geschrieben werden
koennen.
*******************************************************************************
******************************************************************************!
mch_s module
$nonsegmented
external
_bsbase long
_currclk word
_isseg word
_manboot word
_serial long
_numterm word
_buffer array [%200 byte]
constant
SCR := %FFC1
SBR := %FFC9
NBR := %FFD1
LOFF := %FFB9
LON := %FFD9
constant
STACK_MMU := %00F6
DATA_MMU := %00FA
CODE_MMU := %00FC
constant
SEGMENT_00 := %0000
SEGMENT_03 := %0003
SEGMENT_62 := %003E
SEGMENT_63 := %003F
BREAK := %00
STACK := %F800
MEMBOOT:= %0300 !030000 Beginn boot im RAM!
constant !System Calls!
TTIN := %04
TTWR := %06
DISK := %1E
FDISK := %24
global
_codemmu word := CODE_MMU
_datammu word := DATA_MMU
_stakmmu word := STACK_MMU
_myseg word := SEGMENT_63 !Segm Nr boot Progr!
_srcseg word := SEGMENT_62
_hisseg word := SEGMENT_00 !Segm Nr fuer nichtseg Progr!
_ups long := 0 !User Programm Status 4 word!
_entry long := 0
internal
SYSADR array [11 word] := [
_exit _read _write _open _close _lseek
_loadit _getchar _putchar _getc _getw]
!*------------------------------------------ Proceduren ---------------------*!
!Programm Boot wird in Segment 0 geladen und dann nach Segment 63 umgeladen!
!Segment 0 ab Adresse %8000, Monitor liegt ab %0000!
global
start procedure
entry
jr start1
end start
!*---------------------------------------------------------------------------*!
!*
* System Entry Point
* Fuer unter boot laufende Anwenderprogramme koennen
* ueber einen call <SEGMENT_63>%8002 die Funktionen aus dem
* Modul sys.c benutzt werden.
* Anwenderprogramme muessen dann aber im nichtsegmentierten
* Mode laufen
* Input: in r1 Funktionsnummer, ab r7 abwaerts die Parameter
*!
!*---------------------------------------------------------------------------*!
!$segmented!
sysentry procedure
entry
ld r0,#%5800
ldctl FCW, r0
!$nonsegmented!
push @r15, r1
cpb rl1, #1 !read ?!
jr nz, sys0
push @r15, r6
lda r6, _buffer
jr sys4
sys0: cpb rl1, #2 !write ?!
jr nz, sys1
ld r4, r6 !quell adr!
lda r6, _buffer
jr sys2
sys1: cpb rl1, #3 !open ?!
jr nz, sys3
ld r4, r7
lda r7, _buffer
sys2: pushl @r15, rr6
push @r15, r5
push @r15, r3
push @r15, r1
ld r7, _myseg !Zielsegm!
ld r5, _hisseg !Quellsegm!
lda r6, _buffer !Quell offset!
ld r3, #%200 !laenge!
calr _scopy
pop r1, @r15
pop r3, @r15
pop r5, @r15
popl rr6, @r15
sys3: push @r15, r6
sys4: addb rl1, rl1
ldb rh1, #0
ld r1, SYSADR(r1)
call @r1 !call sys programm!
pop r6, @r15
pop r1, @r15
cpb rl1, #1 !read ?!
jr nz, sys5
ld r7, _hisseg !user segment nr!
ld r5, _myseg
lda r4, _buffer
ld r3, #%200 !laenge!
calr _scopy !move ins user segment!
sys5: ld r0, #%C000
ldctl FCW, r0
!$segmented!
ret
end sysentry
!*---------------------------------------------------------------------------*!
!*
* Start des Boot Programms, Initialisierung MMU's und Break Register
* Boot Programm von Segment 0 nach Segment 63 umladen
* Aufruf von main im Modul boot, Absprung zu einem geladenen
* Anwenderprogramm
*!
!*---------------------------------------------------------------------------*!
!$nonsegmented!
internal
start1 procedure
entry
ld r0, #%4000 !Nichtsegm. & System Mode!
ldctl FCW, r0 !setzen!
ld r15, #STACK !Stack offset setzen!
!init ports und MMU!
!Befehl 15: Set all cpu Inhibit Flags = alle Segmente fuer CPU gesperrt!
!fuer alle 3 MMU's!
soutb %1500+CODE_MMU, rl0
soutb %1500+DATA_MMU, rl0
soutb %1500+STACK_MMU, rl0
!Descriptor Counter Register = 0!
!= Zugriff auf hoeherwertiges Byte des Basisadr Feldes!
ldk r0, #%0
soutb %2000+CODE_MMU, rl0
soutb %2000+DATA_MMU, rl0
soutb %2000+STACK_MMU, rl0
ldb rl0, #BREAK
outb SBR, rl0
outb NBR, rl0
pushl @r15, rr6 !ZBOOT Parameter retten!
pushl @r15, rr4
!Aufbau von MMU init Daten im Stack!
push @r15, #%FF00 !FF+1 *256 = Laenge des Segmentes (64k)!
!00 = Attribute (Reset CPU Inhibit)!
push @r15, #%0000 !Basisadr = 000000!
ldk r6, #SEGMENT_00 !fuer Segment 0!
ld r5, r15 !Adr Daten im Stack!
calr init_mmus !Ausgabe an alle 3 MMU'S!
ld @r15, #MEMBOOT !Basisadr 030000, Laenge,Attribute wie vor!
!Beginn der echten MEM Adr fuer boot!
ld r6, #SEGMENT_63
ld r5, r15
calr init_mmus
inc r15, #%04
!Monitor und Boot programm von segment 0 nach 03!
ld r7, #SEGMENT_03
ldk r6, #%0
ld r5, r6
ld r4, r6
lda r3, _edata !Beginn bss!
calr _scopy !Transfer Boot!
popl rr4, @r15 !Rueckladen ZBOOT Parameter!
popl rr6, @r15
!MMU's scharf machen!
ldb rl0, #%D1 !Mode Register!
!Identification fuer Segmentrap AD8+1!
!untere 64 Segment Nummern!
!MMU Translate (Adressbildung) ein!
!MMU aktiv!
!MMU nur im System Mode (MST=1, NMS=0)!
!aktiv, N/S pin wird aber fuer Chipselekt!
!benutzt!
soutb CODE_MMU, rl0
inc r0, #%01
soutb DATA_MMU, rl0 !daten D2!
!Identifier AD8+2 sonst wie vor!
inc r0, #%01
soutb STACK_MMU, rl0 !daten D3!
!Identifier AD8+3 sonst wie vor!
ldb rl0, #%03
outb SCR, rl0
!Sprung ins Segment 63, (ehemals Segment 3)!
ld r2, #SEGMENT_63 !segment nr 63!
exb rh2, rl2
lda r3, start2
ld r0, #%C000
ldctl FCW, r0 !segmented & system mode!
!$segmented!
ld r14, r2 !system r14 Stackpointer segmentnr auf 63!
ldctl PSAPSEG, r2 !segm nr PSA Pointer auf 63!
jp @r2 !Sprung zu start2 Segment 63!
! jp @rr2 segmentiert!
!$nonsegmented!
!Programm wird ab hier in Segment 63 abgearbeitet!
!in PSA Segmentnummern von 0 auf 63 aendern!
start2:
ld r0, #%4000
ldctl FCW, r0
ldctl r1, PSAP
ld r0, #SEGMENT_63
exb rl0, rh0
ldb rl2, #6
inc r1, #12
start3:
ld @r1, r0
inc r1, #8
dbjnz rl2, start3
ldb rl2, #128
start4:
ld @r1, r0
inc r1, #4
dbjnz rl2, start4
ld r0, #%5800
ldctl FCW, r0 !Nichtsegm & System mode !
!interrupts ei!
!init bss RAM mit %0!
lda r1, _edata
lda r2, %02(r1)
lda r0, _end
sub r0, r1
resflg c
rrc r0, #%01
clr @r1
dec r0, #%01
ldir @r2, @r1, r0
ldl _serial, rr6 !Monitor Parameter speichern!
ld _numterm, r5
ld _manboot, r4 !0=autom. boot!
ldk r0, #%0
ld r1, #MEMBOOT
slll rr0, #%08 !*256 030000 = Beginn boot!
ldl _bsbase, rr0
end start1 !Programm lauft nach __ret weiter!
!*---------------------------------------------------------------------------*!
!*
* Rueckkehr aus User Programm (ueber exit in sys.c)
*!
!*---------------------------------------------------------------------------*!
global
__ret procedure
entry
ld r15, #STACK !Systemstack!
ldk r0, #0 !Basis Adr fuer MMU's init!
!ab dieser (echten) Adresse wird ein
User Programm geladen, currclk wird dann
um die Laenge des Programms erhoeht!
ld _currclk, r0
call _main !Kommandoeingabe!
!+ Programm laden zB Kern!
xor r0, r0
ld r1, r0
test _isseg !0=nonsegmented 1=segmented!
tcc nz, r1
rr r1, #%01
or r1, #%5800 !fcw =system mode + entsp segm mode!
ld r4, #SEGMENT_63 !Segment Nr fuer ldps Befehl!
exb rh4, rl4
lda r5, _ups
ldl @r5, rr0 !fuer user Programm (geladenes Prog)
fcw setzen in _ups!
!fuer Return zu boot den Programmstatus in den Stack!
push @r15, #__ret !Return Adr!
push @r15, r4 !Return Segment Nr!
push @r15, #%5800 !fcw fuer Return!
push @r15, #0 !unbenutzt im Prog Status!
ld r3, #-1
wait: djnz r3, wait !Warten auf letzten Interrupt!
ldl rr8, rr4
ldl rr6, _serial !Rueckladen ZBOOT Parameter!
ld r5, _numterm
ld r4, _manboot
ld r3, _currclk !Laenge des Programms in clicks!
ld r2, #0 !kein FPP!
ld r0, #%C000
ldctl FCW, r0 !segment. & system mode!
!$segmented!
ldps @r8
! ldps @rr8 segmented!
!Sprung ins geladene Programm
durch laden Programm Status Register
in r8 boot Segm Nr, in r9 Adr
von User Programm Status array!
end __ret
!*---------------------------------------------------------------------------*!
!*
* Ausgabe an alle 3 MMU's
* (fuer Initialisierung)
*!
!*---------------------------------------------------------------------------*!
!$nonsegmented!
internal
init_mmus procedure
entry
ld r8, r5
ldb rl7, #CODE_MMU
calr _loadsd
ldb rl7, #DATA_MMU
ld r5, r8
calr _loadsd
ldb rl7, #STACK_MMU
ld r5, r8
calr _loadsd
ret
end init_mmus
global
!*---------------------------------------------------------------------------*!
!*
* Programmierung einer MMU
*!
!*---------------------------------------------------------------------------*!
_loadsd procedure
entry
ldb rh7, #%01 !Ausgabe Segmentadr Register!
dec r15, #2
ld r1, r15
ldb @r1, rl6 !Daten in Stack!
soutib @r7, @r1, r0
inc r15, #2
ldb rh7, #%0B !Ausgabe Segmentdescriptor 4 Byte!
ldk r2, #%04 !4 Byte ausgeben!
sotirb @r7, @r5, r2
ret
end _loadsd
!*---------------------------------------------------------------------------*!
!*
* Copy (LDIR) von einem Segment in ein anderes
*!
!*---------------------------------------------------------------------------*!
_scopy procedure
entry
exb rh7, rl7
exb rh5, rl5
ex r7, r6
ex r5, r4
resflg c
rrc r3, #%01
ldctl r0, FCW !FCW retten!
ld r1, #%C000
ldctl FCW, r1 !segment & system mode!
!$segmented!
ldir @r6, @r4, r3
! ldir @rr6, @rr4, r3 segmentiert!
ldctl FCW, r0 !nichtsegm & system mode!
!$nonsegmented!
ret
end _scopy
!*---------------------------------------------------------------------------*!
!*
* Entry fuer printf (in misc.c)
* Parameter in Stack bringen
*!
!*---------------------------------------------------------------------------*!
_printf procedure
entry
ex r2, @r15
push @r15, r3
push @r15, r4
push @r15, r5
push @r15, r6
ld r6, r15
push @r15, r2
call _printfv
ld r2, @r15
inc r15, #%0C !Korrektur Stack!
jp @r2 !return!
end _printf
!*---------------------------------------------------------------------------*!
!*
* Ausgabe ein Zeichen (in rl7) an Console
* ueber Systemcall an Monitor- Programm
*!
!*---------------------------------------------------------------------------*!
_putchar procedure !Ausgabe rl7 auf Console!
entry
push @r15, r0
push @r15, r3
ld r2, r7
cpb rl7, #%0A
jr nz, PUTCHAR1
ldk r0, #%0D
sc #TTWR !bei LF CRLF ausgeben!
PUTCHAR1:
ld r0, r2
sc #TTWR
pop r3, @r15
pop r0, @r15
ret
end _putchar
!*---------------------------------------------------------------------------*!
!*
* Eingabe ein Zeichen (nach r2) von Console
* durch Systemcall an Monitor-Programm
*!
!*---------------------------------------------------------------------------*!
_getchar procedure
entry
push @r15, r0
push @r15, r3
outb LOFF, rl0 !lbolt off!
sc #TTIN
outb LON, rl0 !lbolt on!
ld r0, r3
and r0, #%7F !Zeichen eingelesen, reset bit 7!
cp r0, #%0D
jr nz, GETCHAR1
ldk r0, #%0A
GETCHAR1:
ld r2, r0
ld r7, r2
calr _putchar
pop r3, @r15
pop r0, @r15
ret
end _getchar
!*---------------------------------------------------------------------------*!
!*
* Realisierung von in und out Befehlen fuer C
*!
!*---------------------------------------------------------------------------*!
_otirb !@r7 @r6 r5! procedure
entry
otirb @r7, @r6, r5
ret
end _otirb
_outb !@r7 rl6! procedure
entry
outb @r7, rl6
ret
end _outb !@r7 rl6!
_inb !rl2 @r7! procedure
entry
inb rl2, @r7
xorb rh2, rh2
ret
end _inb !rl2 @r7!
!*---------------------------------------------------------------------------*!
!*
* Aufruf Disk Treiber im Monitor mit System Call
* vorher Register umladen
*!
!*---------------------------------------------------------------------------*!
_disk procedure
entry
dec r15, #6
ldm @r15, r8, #3
ld r2, _myseg !Ersetzen physische Adresse durch!
exb rl2, rh2 !Segmentnummer, da kein DMA!
ldl rr8, rr2
ld r10, 8(r15) !Laenge!
sc #DISK
ldm r8, @r15, #3
inc r15, #6
ret
end _disk
!*---------------------------------------------------------------------------*!
!*
* Aufruf Floppydisk Treiber im Monitor mit System Call
* vorher Register umladen
*!
!*---------------------------------------------------------------------------*!
_fdisk procedure
entry
dec r15, #6
ldm @r15, r8, #3
ld r2, _myseg !Ersetzen physische Adresse durch!
exb rl2, rh2 !Segmentnummer, da kein DMA!
ldl rr8, rr2
ld r10, 8(r15) !Laenge!
orb rl6, #%60 !Drivenr. + Typ 6!
sc #FDISK
ldm r8, @r15, #3
inc r15, #6
ret
end _fdisk
end mch_s

59
WEGA/src/cmd/BOOT/bmd.c Normal file
View File

@ -0,0 +1,59 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul md.c
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:13
Version: 1.1
*******************************************************************************
Device Treiber md fuer Disk
Der physische Treiber befindet sich im Monitor
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/inode.h>
#include <saio.h>
extern long bsbase;
mdstrategy(io, func)
register struct iob *io;
{
register unsigned errcount;
register daddr_t bn;
register daddr_t addr;
register unsigned count;
unsigned size;
bn = io->i_bn;
count = io->i_cc;
addr = (daddr_t)io->i_ma + bsbase;
for (; count != 0; count -= size) {
errcount = 0;
size = min(0x200, count);
for (; disk(func, io->i_unit, bn, addr, size);) {
if (errcount == 0)
printf("md: io error\n");
if (++errcount >= 10) {
printf ("md: fatal error\n");
return(-1);
}
}
addr += size;
bn++;
}
return(io->i_cc);
}

270
WEGA/src/cmd/BOOT/bmisc.c Normal file
View File

@ -0,0 +1,270 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul misc.c
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:15
Version: 1.1
*******************************************************************************
Dieses Programm kann fuer alle Standalone Programme benutzt werden,
die unter dem Wega boot laufen.
Funktionen:
atol ASCII zu long integer
atoi ASCII zu integer
printfv
gets
*******************************************************************************
******************************************************************************/
/*------------------------------------------ Funktionen ---------------------*/
/*---------------------------------------------------------------------------*/
/*
*atol
* Konvertierung ASCII in long integer
*
* es werden Tabs und Space, falls vor Dezimalzahl vorhanden, uebergangen
* es wird auf ein optionales Vorzeichen getestet
* die Dezimalziffern werden so lange konvertiert bis ein
* Zeichen ungleich einer Dezimalzahl gefunden wird
*/
/*---------------------------------------------------------------------------*/
long atol(s)
register char *s;
{
register sign;
register long n;
for(sign=0;; s++) {
switch(*s) {
case '\t':
case ' ':
continue;
case '-':
sign++;
case '+':
s++;
}
break;
}
for (n = 0; *s >= '0' && *s <= '9'; s++)
n = 10 * n + *s - '0';
if (sign)
return(0-n);
return(n);
}
/*---------------------------------------------------------------------------*/
/*
*atoi
* Konvertierung ASCII string in integer
* es wird atol aufgerufen und long in int konvertiert
*/
/*---------------------------------------------------------------------------*/
atoi(s)
char *s;
{
return(atol(s));
}
/*---------------------------------------------------------------------------*/
/*
*ltol3
* Konvertierung long integer in 3 byte integer
*
* Konvertiert eine Liste von long integer (lp zeigt darauf)
* in eine Liste von 3 byte integer (cp zeigt darauf)
* n = Anzahl der Zahlen
*/
/*---------------------------------------------------------------------------*/
ltol3(cp, lp, n)
register unsigned char *cp;
register unsigned char *lp;
register n;
{
for(; n != 0; n--) {
lp++;
*(cp++) = *(lp++);
*(cp++) = *(lp++);
*(cp++) = *(lp++);
}
}
/*---------------------------------------------------------------------------*/
/*
*l3tol
* Konvertierung 3 byte integer in long integer
*
* Konvertiert eine Liste von 3 byte integer (cp zeigt darauf)
* in eine Liste von long integer (lp zeigt darauf)
* n = Anzahl der Zahlen
*/
/*---------------------------------------------------------------------------*/
l3tol(lp, cp, n)
register unsigned char *lp;
register unsigned char *cp;
register n;
{
for(; n != 0; n--) {
*(lp++) = 0;
*(lp++) = *(cp++);
*(lp++) = *(cp++);
*(lp++) = *(cp++);
}
}
/*---------------------------------------------------------------------------*/
/*
*lswap
* Vertauschen low und high von long integer
*/
/*---------------------------------------------------------------------------*/
long lswap(l)
long l;
{
return(l<<16 | l>>16);
}
/*---------------------------------------------------------------------------*/
/*
*printf
* Abgeruestete Version des C Library printf.
* Nur %s %u %d (==%u) %o %x %D %X sind realisiert.
* Ausgabe erfolgt auf Console.
* Sollte nicht fuer "chit-chat" benutzt werden.
*
* Der eigentliche Entry Point muss in Assembler
* geschrieben werden. Das Programm muss wie folgt
* aussehen:
* _printf procedure
* entry
* ex r2, @r15
* push @r15, r3
* push @r15, r4
* push @r15, r5
* push @r15, r6
* ld r6, r15
* push @r15, r2
* call _printfv
* ld r2, @r15
* inc r15, #12
* jp @r2
* end _printf
*/
/*---------------------------------------------------------------------------*/
printfv(fmt, x1)
register char *fmt;
register unsigned *x1;
{
register c;
register unsigned int *adx;
register char *s;
adx = x1;
loop:
while((c = *fmt++) != '%') {
if(c == '\0')
return;
putchar(c);
}
c = *fmt++;
if(c == 'd' || c == 'u' || c == 'o' || c == 'x')
printn((long)*adx, c=='o'? 8: (c=='x'? 16:10));
else if(c == 's') {
s = (char *)*adx;
while(c = *s++)
putchar(c);
} else if (c == 'D' || c == 'X' ) {
for(; adx-x1 < 5; adx++) {
if ((adx-x1)%2 == 0)
continue;
printn(lswap(*(long *)adx), c=='D' ? 10 : 16);
goto end;
}
printn(*(long *)adx, c=='D' ? 10 : 16 );
end:
adx += (sizeof(long) / sizeof(int)) - 1;
}
adx++;
goto loop;
}
/*---------------------------------------------------------------------------*/
/*
*printn
* Print ein unsigned integer zur Basis b
*/
/*---------------------------------------------------------------------------*/
printn(n, b)
register long n;
register b;
{
register long a;
if (n<0) { /* shouldn't happen */
putchar('-');
n = -n;
}
if(a = n/b)
printn(a, b);
putchar("0123456789ABCDEF"[(int)(n%b)]);
}
/*---------------------------------------------------------------------------*/
/*
*gets
* Eingabe einer Zeichenkette von der Console
*
* in einen vorgegebenen Puffer bis CR oder LF
* oder bis der Eingabepuffer gefuellt ist
* Das letzte Zeichen im Puffer ist 0x00. CR und LF werden
* nicht in den Puffer geschrieben
*/
/*---------------------------------------------------------------------------*/
char *gets(buf, buflen)
register char *buf;
register unsigned buflen;
{
register char *lp;
register c;
lp = buf;
for (;;) {
c = getchar() & 0177;
switch(c) {
case '\n':
case '\r':
*lp = '\0';
return(buf);
case '\b':
putchar(' ');
putchar('\b');
lp--;
if (lp < buf)
lp = buf;
continue;
case 0x18:
case 0x7f:
lp = buf;
putchar('\n');
continue;
default:
if (lp>=buf+buflen-1) {
*lp = '\0';
return(buf);
}
*lp++ = c;
}
}
}

404
WEGA/src/cmd/BOOT/boot.c Normal file
View File

@ -0,0 +1,404 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone boot.c (secundary boot)
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:20
Version: 1.1
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/filsys.h>
#include <sys/dir.h>
#include <sys/mmu.h>
#include <sys/s.out.h>
#include <sys/z.out.h>
#include <saio.h>
extern unsigned codemmu, datammu, stakmmu;
extern unsigned myseg, hisseg, srcseg;
extern union entry {
long lentry;
int ientry[2];
} entry;
extern char dfline[];
unsigned manboot;
unsigned currclk;
unsigned isseg;
int fd;
#define NCHAR 100
char line[NCHAR];
char buffer[0x200];
union header {
struct s_exec s_out;
struct z_exec z_out;
} header;
struct segt segtble[128];
/*---------------------------------------------------------------------------*/
/*
*main
* main Funktion von boot
*
* Meldung Boot Programm, Eingabe des zu ladenen Programms
* bei manuellem boot bzw interner Name des Programms
* - zd(x,yyyy)wega - bei automatischem boot. Open file,
* bei Fehler Wiederholung der Eingabe, wenn open ok
* laden des files durch loadit. Return in mch Module,
* dort erfolgt Start des geladenen Programms
*/
/*---------------------------------------------------------------------------*/
main()
{
printf("\n\n\nBoot\n");
do {
line[0] = 0;
printf(": ");
if (manboot)
gets(line, NCHAR);
if (line[0] == 0) {
printf(dfline);
putchar('\n');
fd = open(dfline, 0);
}else
fd = open(line, 0);
} while (fd < 0);
loadit(fd);
putchar('\n');
}
/*---------------------------------------------------------------------------*/
/*
*loadit
* Laden eines executable files in den RAM
* Folgende files koennen geladen werden:
* s.out, segmented, separate instruction & data (Magic E611)
* s.out, segmented, executable (Magic E607)
* s.out, nonsegmented, separate instruction & data (Magic E711)
* s.out, nonsegmented, executable (Magic E707)
* z.out, nonsegmented, separate instruction & data (Magic E811)
* z.out, nonsegmeted, executable (Magic E807)
*
* Segmentierte (standalone) Programme werden in die Segmente geladen
* fuer die sie gelinkt wurden (Segment 62 und 63 fuer boot reserviert)
* nichtsegmentierte Programme werden in Segment 0 geladen.
* Der BSS Bereich wird mit 0 initialisiert.
*/
/*---------------------------------------------------------------------------*/
loadit(io)
register io;
{
register unsigned sepid;
register unsigned nsegt;
register struct s_exec *psh = &header.s_out;
register struct z_exec *pzh = (struct z_exec *)psh;
register struct segt *psegt = segtble;
register unsigned csize;
unsigned dsize;
unsigned bsize;
isseg = 0; /* nonsegmented init */
sepid = 0; /* executable init */
fd = io;
lseek(fd, (off_t)0, 0);
psh->s_magic = getw(io);
switch(psh->s_magic) {
case 0xE611: /* s.out segmented seperate I&D */
sepid = 1;
case 0xE607: /* s.out segmented executable */
isseg++;
goto E707;
case 0xE711: /* s.out nonseg separate I&D */
sepid = 1;
case 0xE707: /* s.out nonseg executable */
E707: /* fuer alle s.out Formate */
getn(io, (char *)&header.s_out.s_imsize, sizeof(struct s_exec)-sizeof(int));
entry.lentry = psh->s_entry;
getn(io, (char *)psegt, psh->s_segt);
nsegt = psh->s_segt / sizeof(struct segt);
for (; nsegt != 0; nsegt--) {
if (psegt->sg_atr & (SG_OCODE | SG_ODATA | SG_OBSS)) {
close(io);
printf("Cannot load offset segs yet\n");
exit(1);
}
csize=0;
dsize=0;
bsize=0;
if (psegt->sg_atr & SG_CODE)
csize = psegt->sg_code;
if (psegt->sg_atr & SG_DATA)
dsize = psegt->sg_data;
if (psegt->sg_atr & SG_BSS)
bsize = psegt->sg_bss;
loadseg((unsigned char)psegt->sg_segno, csize, dsize, bsize, sepid);
psegt++;
}
break;
case 0xE811: /* z.out nonseg sep I&D */
sepid = 1;
case 0xE807: /*z.out nonseg executable */
getn(io, (char *)&header.z_out.z_code, sizeof(struct z_exec)-sizeof(int));
entry.ientry[1] = pzh->z_entry;
loadseg(hisseg, pzh->z_code, pzh->z_data, pzh->z_bss, sepid);
break;
default:
close(fd);
printf("Cannot load 0x%x files\n", psh->s_magic);
exit(1);
return;
}
close(io);
if (isseg == 0)
entry.ientry[0] = hisseg * 256;
}
/*---------------------------------------------------------------------------*/
/*
*getn
* Laden von n Bytes einer eroeffnetten file in einen Puffer
*/
/*---------------------------------------------------------------------------*/
getn(io, buf, n)
register io;
register char *buf;
register unsigned n;
{
for (; n != 0; n--)
*buf++ = getc(io);
}
/*---------------------------------------------------------------------------*/
/*
*getsh
* Laden des Headers einer s.out file
*
* (wird innerhalb des boot Programms nicht verwendet)
*/
/*---------------------------------------------------------------------------*/
struct s_exec *
getsh(io, magic)
{
header.s_magic = magic;
getn(io, (char *)&header.s_out.s_imsize, sizeof(struct s_exec)-sizeof(int));
return(&header.s_out);
}
/*---------------------------------------------------------------------------*/
/*
*getzh
* Laden des Headers einer z.out file
*
* (wird innerhalb des boot Programms nicht verwendet)
*/
/*---------------------------------------------------------------------------*/
struct z_exec *
getzh(io, magic)
{
header.z_out.z_magic = magic;
getn(io, (char *)&header.z_out.z_code, sizeof(struct z_exec)-sizeof(int));
return(&header.z_out);
}
/*---------------------------------------------------------------------------*/
/*
*getst
* Lader der Segment table einer s.out file
*
* (wird innerhalb des boot Programms nicht verwendet)
*/
/*---------------------------------------------------------------------------*/
struct segt *
getst(io, segt)
register io;
register unsigned segt;
{
getn(io, (char *)segtble, segt);
return(segtble);
}
/*---------------------------------------------------------------------------*/
/*
*loadseg
* Laden eines Segmentes des Programms
*
* Jedes im Programm vorhandene Segment ist in der Segment table
* beschrieben (siehe s.out.h)
* Die MMU's werden fuer dieses Segment gesetzt.
* Fuer executable Programme wird Code MMU = Data MMU gesetzt,
* Stack MMU wird = Data MMU gesetzt, bei nichtsegmentierten
* Programmen wird die Laenge fuer die Stack MMU auf 64K gesetzt
* (Stack liegt von F800 abwaerts).
*/
/*---------------------------------------------------------------------------*/
loadseg(segnr, csize, dsize, bsize, sepid)
register unsigned segnr, csize, dsize, bsize, sepid;
{
register unsigned tsize;
if (sepid == 0) {
dsize += csize;
csize = 0;
}
if (csize) {
tsize = ((unsigned long)csize+256)/256;
setmmu(codemmu, segnr, currclk, tsize-1, 0);
loadmem(currclk, csize);
currclk += tsize;
}
bsize += dsize;
if (isseg == 0 && bsize == 0)
bsize++;
if (bsize) {
bsize = ((unsigned long)bsize+256)/256;
tsize = bsize;
tsize--;
setmmu(datammu, segnr, currclk, tsize, 0);
if (sepid == 0 || isseg)
setmmu(codemmu, segnr, currclk, tsize, 0);
if (isseg == 0 && sepid == 0) {
bsize = 0x0100; /* nonseg size = 64k */
tsize = bsize;
tsize--;
setmmu(codemmu, segnr, currclk, tsize, 0);
}
setmmu(stakmmu, segnr, currclk, tsize, 0);
clrseg(currclk, bsize); /* data+bss = 0 */
if (dsize)
loadmem(currclk, dsize);
currclk += bsize;
}
}
/*---------------------------------------------------------------------------*/
/*
*loadmem
* Laden des Code oder Data Teil eines Segmentes in den RAM
* Dafuer wird Segment 62 der MMU's verwendet
*/
/*---------------------------------------------------------------------------*/
loadmem(addr, size)
register unsigned addr, size;
{
register char *bp;
register unsigned srcadr;
register unsigned smin, count;
register unsigned len = 0x100;
setmmu(codemmu, srcseg, addr, 0xFF, 0);
setmmu(datammu, srcseg, addr, 0xFF, 0);
setmmu(stakmmu, srcseg, addr, 0xFF, 0);
for (srcadr = 0; size != 0; size -= smin) {
smin = min(size, len);
for (bp = buffer, count = smin; count != 0; count--)
*bp++ = getc(fd);
if (smin < len)
zero(bp, len-smin);
scopy(srcseg, srcadr, myseg, buffer, len);
srcadr += len;
}
}
/*---------------------------------------------------------------------------*/
/*
*setmmu
* ein Segment einer MMU programmieren
*
* Die Daten fuer 1 Segment werden in den Stack gebracht
* und loadsd im Modul mch aufgerufen.
*/
/*---------------------------------------------------------------------------*/
setmmu(mmu, segnr, addr, size, attrib)
unsigned mmu, segnr, addr, size, attrib;
{
struct segd mmuout;
mmuout.sg_base = addr;
mmuout.sg_limit = size;
mmuout.sg_attr = attrib;
loadsd(mmu, segnr, &mmuout);
}
/*---------------------------------------------------------------------------*/
/*
*clrseg
* Speicherbereich mit 00 initialisieren
*
* Ein Puffer im boot Programm (0x100 Laenge) wird mit
* 00 beschrieben. Dieser wird entsprechend der vorgegebenen
* Laenge n mal in den physischen Speicherbereich kopiert
*/
/*---------------------------------------------------------------------------*/
clrseg(addr, size)
register unsigned addr, size;
{
register unsigned srcadr;
register unsigned len = 0x100;
setmmu(codemmu, srcseg, addr, size-1, 0);
setmmu(datammu, srcseg, addr, size-1, 0);
setmmu(stakmmu, srcseg, addr, size-1, 0);
srcadr = 0;
zero(buffer, len);
for (; size != 0; size--) {
scopy(srcseg, srcadr, myseg, buffer, len);
srcadr += len;
}
}
/*---------------------------------------------------------------------------*/
/*
*zero
* Puffer (im boot) mit 0 beschreiben
*/
/*---------------------------------------------------------------------------*/
zero(buf, n)
register char *buf;
register unsigned n;
{
for (; n != 0; n--)
*buf++ = 0;
}
/*---------------------------------------------------------------------------*/
/*
*min
* Ermittlung der kleineren von 2 Zahlen
*/
/*---------------------------------------------------------------------------*/
min(num1, num2)
unsigned num1, num2;
{
if (num1 < num2)
return(num1);
return(num2);
}

345
WEGA/src/cmd/BOOT/brm.s Normal file
View File

@ -0,0 +1,345 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Module rm.s
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:45
Version: 1.2
*******************************************************************************
Device Treiber zum Laden von Wega Procedure Dateien
von einem Local System wie GDS 6000 unter UDOS ueber
den Console TTY Kanal.
Der Modul liegt leider nur als PLZ/ASM Quelle vor.
Bei Aenderungen der Struktur iob in saio.h und
der inode in inode.h mussen die Referenzen zu dieser
Struktur per Hand geaendert werden.
*******************************************************************************
******************************************************************************!
rm_s module
constant
TTIN := %04
TTWR := %06
FLAG0 := %3F0 !relative Adresse zu Beginn Monitor RAM!
SOH := %01
ESC := %1B
ETX := %03
ACK := %06
CAN := %18
STX := %02
EOT := %04
NAK := %15
typ := %01 !binary file!
!Referenzen auf iob Struktur!
constant
iob_i_ino_i_number := 6 !in rm Pointer auf Filename!
iob_i_unit := 80
iob_i_ma := 98
iob_i_cc := 100
internal
rmflag1 word
rmflag2 word
MSG_OERR array [* byte] := 'rm: cannot open file on local system%l%00'
MSG_RERR array [* byte] := 'rm: read error from local system%l%00'
MSG_WERR array [* byte] := 'rm: cannot write to local system%l%00'
!*------------------------------------------ Proceduren ---------------------*!
global
!*----------------------------------------------------------------------------*
*
*rmopen
* Open Request
*
* Nur Open fuer Read moeglich
* rmopen sendet an das Local System den Filenamen, das Local
* System beginnt mit dem Senden des 1. Datenblocks, falls die
* Datei vorhanden ist.
* input r7: Pointer auf Struktur iob
*
*---------------------------------------------------------------------------*!
_rmopen procedure
entry
pushl @r15, rr8
ldctl r8, PSAP
sub r8, #(%400-FLAG0)
setb @r8, #0 !control S und esc abschalten!
ldk r8, #0
ld rmflag1, r8 !init rmflag!
ld rmflag2, r8
ld iob_i_unit(r7), #'r'!remote open drive nr setzen!
bitb @r7, #1 !bit 1 = 1 = open for write!
jp nz, rmwerror !write nicht moeglich!
ldk r0, #SOH !Kommando Send file an local!
sc #TTWR
ldb rl0, #ESC
sc #TTWR
ldb rl0, #'S'
sc #TTWR
sc #TTIN !acknowledge von local!
ldb rl0, #typ !file typ an local!
sc #TTWR
sc #TTIN !acknowledge von local!
!Ausgabe filename an local!
ld r2, iob_i_ino_i_number(r7) !file name Pointer!
ldb rh7, #10 !retries!
ld r5, r2
rmo0: ldb rl7, #0 !Checksumme init!
ld r2, r5
ldb rl0, #STX !Start of Text!
sc #TTWR
rmo1: ldb rl0 ,@r2 !Zeichen von filename!
inc r2, #1
cpb rl0, #0 !ende filename ?!
jr z, rmo2
xorb rl7, rl0 !Checksumme berechnen!
sc #TTWR
jr rmo1
rmo2: ldb rl0, #ETX !end of text!
sc #TTWR
exb rl0, rl7
sc #TTWR !Checksumme ausgeben!
sc #TTIN !Warten auf Quittung!
resb rl3, #7
cpb rl3, #ACK
ldk r2, #0 !kein Fehler!
jp z, rmclose4
cpb rl3, #CAN !Abbrechen ?!
jr z,rmoerr
dbjnz rh7, rmo0 !naechster Versuch!
rmoerr:
lda r7, MSG_OERR
jr rmerror
end _rmopen
!*----------------------------------------------------------------------------*
*rmclose
* Close Request
*
* rm beendet die Fileuebertragung mit dem Local System
*
*---------------------------------------------------------------------------*!
_rmclose procedure
entry
pushl @r15, rr8
ldctl r8, PSAP
sub r8, #(%400-FLAG0)
setb @r8, #0 !control S und esc abschalten!
test rmflag2
jr nz, rmclose3 !file war schon zu Ende!
ldb rl0, #CAN !file transfer abbrechen!
sc #TTWR
jr rmclose1
end _rmclose
!*----------------------------------------------------------------------------*
*
*rmstrategy
* Block Read Request (Write nicht moeglich)
*
* Einlesen eines Blocks der eroeffneten Datei vom Local System
* input r7: Pointer auf iob Struktur
*
*---------------------------------------------------------------------------*!
_rmstrat procedure
entry
pushl @r15, rr8
ldctl r8, PSAP
sub r8, #(%400-FLAG0)
setb @r8, #0 !control S und esc abschalten!
cp r6, #1 !Read!
jr nz,rmwerror !write nicht moeglich!
rmst1: test rmflag2
jr z,rmst2
ldk r2, #0 !file schon close!
jr rmclose3
rmst2: ld r8, iob_i_ma(r7) !Lade Adr!
ld r9, iob_i_cc(r7) !Laenge!
test r9
jr z, rmst3 !0 nicht zulaessig!
rmstloop:
push @r15, r7
calr rmread !64 byte von local!
pop r7, @r15
test r2
jr z,rmst4
rmst3: lda r7, MSG_RERR
jr rmerror !Read Error!
rmst4: ld r2, iob_i_cc(r7) !Laenge!
cpb rl3, #EOT
jr nz,rmst5
sub r9, r6 !file uebertragen!
jr c, rmclose1
sub r2, r9 !uebertragene Anzahl Byte!
jr rmclose1
rmst5: sub r9, r6
jr z, rmclose3 !1 Block fertig uebertragen!
jr c, rmclose3
jr rmstloop
end _rmstrat
!*----------------------------------------------------------------------------*
* Unterprogramme
*---------------------------------------------------------------------------*!
internal
rmread procedure !Lesen 1 Block von local System (64 Byte)!
entry
ldb rh7, #10 !retries!
ldk r2, #0 !kein Fehler!
ldk r6, #0 !init lenght!
test rmflag1
jr z, rmr0 !Sprung 1.Aufruf!
ldb rl0, #ACK !Ack fuer letzen Aufruf!
sc #TTWR
rmr0: ldb rl7, #0 !Checksumme init!
ld rmflag1, #-1
ld r5, r8 !Buffer Pointer retten!
sc #TTIN
resb rl3, #7
cpb rl3, #EOT
ret z !file fertig uebertragen!
cpb rl3, #CAN
jr z, rmrerr !local gibt Abbruch!
cpb rl3, #ESC
jr z, rmrerr !local gibt Abbruch!
cpb rl3, #STX !Start of text muss 1.Zeichen sein!
jr nz, rmr2 !warten auf ETX und Uebertragung wiederholen!
sc #TTIN
ldb rh4, rl3 !high count!
sc #TTIN
ldb rl4, rl3 !low count!
ld r6, r4
rmr1: sc #TTIN !Daten lesen!
ldb @r8, rl3 !in Buffer!
inc r8, #1
xorb rl7, rl3 !Checksumme berechnen!
djnz r4, rmr1
rmr2: sc #TTIN !warten auf ETX!
resb rl3, #7
cpb rl3, #ESC
jr z, rmrerr
cpb rl3, #CAN
jr z, rmrerr
cpb rl3, #ETX
jr nz, rmr2
sc #TTIN !Checksumme!
cpb rl3, rl7 !uebertragene = berechnete ?!
ldb rl3, #0 !falls zufaellig EOT!
ret z !ja!
decb rl7, #1
jr z, rmrerr !Abbruch!
ldb rl0, NAK !n mal wiederholen!
ld r8, r5 !Buffer Pointer auf Anfang zurueck!
sc #TTWR
jr rmr0
rmrerr: ld r2, #-1
ret
end rmread
rmerror procedure
entry
ldb rl0, #CAN !remote abbrechen!
sc #TTWR
sc #TTIN
jr rmerror1
end rmerror
rmwerror procedure
entry
lda r7, MSG_WERR
end rmwerror
rmerror1 procedure
entry
call _printf
ld r2, #-1
jr rmclose2
end rmerror1
rmclose1 procedure
entry
sc #TTIN
end rmclose1
rmclose2 procedure
entry
ld rmflag2, #-1 !remote close!
end rmclose2
rmclose3 procedure
entry
ldctl r8, PSAP
sub r8, #(%400-FLAG0)
resb @r8, #0 !FLAG0 im Monitor RAM ruecksetzen!
end rmclose3
rmclose4 procedure
entry
popl rr8, @r15
ret
end rmclose4
end rm_s

View File

@ -0,0 +1,20 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1986
Standalone Modul bstart.c
Datum: 22.11.1986
Version: 3.2
*******************************************************************************
Der Modul enthaelt das Startkommando fuer den
normalen Start des Kerns.
*******************************************************************************
******************************************************************************/
char dfline[50] = "md(0,14000)wega";

674
WEGA/src/cmd/BOOT/bsys.c Normal file
View File

@ -0,0 +1,674 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul sys.c
Bearbeiter: P. Hoge
Datum: 04/01/87 11:15:32
Version: 1.2
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/filsys.h>
#include <sys/dir.h>
#include <saio.h>
/*------------------------------------------ Funktionen ---------------------*/
/*---------------------------------------------------------------------------*/
/*
*openi
* inode Block in Puffer einlesen, entsprechende inode
* auswaehlen, Uebertragen von Teilen der Disk inode (dinode),
* das sind inumber imode isize und die Pointer auf die
* Daten- und indirekten Pointerbloecke (mit Konvertierung
* 3 byte Integer in long integer), in den iob.
* Parameter: n = inumber
* io = Pointer auf iob
*/
/*---------------------------------------------------------------------------*/
static
openi(n,io)
register struct iob *io;
register n;
{
register struct dinode *dp;
io->i_offset = 0;
io->i_bn = (daddr_t)((n+15)/INOPB) + io->i_boff;
io->i_cc = 512;
io->i_ma = io->i_buf;
devread(io);
dp = (struct dinode *)io->i_buf;
dp = &dp[(n-1)%INOPB];
io->i_ino.i_number = n;
io->i_ino.i_mode = dp->di_mode;
io->i_ino.i_size = dp->di_size;
l3tol((char *)io->i_ino.i_addr,(char *)dp->di_addr,NADDR);
}
/*---------------------------------------------------------------------------*/
/*
*find
* Suchen einer file mit dem angegebenen path name in der (den)
* directories
* Parameter: path - Pointer auf pathname string
* file - Pointer auf iob
* Return: inumber der file wenn gefunden
* 0 wenn nicht gefunden
*/
/*---------------------------------------------------------------------------*/
static
find(path, file)
register char *path;
register struct iob *file;
{
register char *q;
register char c;
register n;
ino_t dlook();
if (path==0 || *path=='\0') {
printf("null path\n");
return(0);
}
openi((ino_t) 2, file);
while (*path) {
while (*path == '/')
path++;
q = path;
while(*q != '/' && *q != '\0')
q++;
c = *q;
*q = '\0';
if ((n=dlook(path, file))!=0) {
if (c=='\0')
break;
openi(n, file);
*q = c;
path = q;
continue;
} else {
printf("%s not found\n",path);
return(0);
}
}
return(n);
}
/*---------------------------------------------------------------------------*/
/*
*sbmap
* Ermittlung der Blocknummer im Filesystem fuer
* einen gewueschten logischen Datenblock
*
* Parameter: io - Pointer auf iob
* bn - Blocknummer (logische, n.Datenblock der file
* Return: Blocknummer im Filesystem
* 0 bei Fehler
*/
/*---------------------------------------------------------------------------*/
static daddr_t
sbmap(io, bn)
register struct iob *io;
register daddr_t bn;
{
register i;
register struct inode *ip;
register j, sh;
register daddr_t nb, *bap;
ip = &io->i_ino;;
if(bn < 0) {
printf("bn negative\n");
return((daddr_t)0);
}
/*
* blocks 0..NADDR-4 sind direct blocks
*/
if(bn < NADDR-3) {
i = bn;
nb = ip->i_addr[i];
return(nb);
}
/*
* Adressen NADDR-3, NADDR-2 und NADDR-1
* sind single, double, triple indirect blocks.
* der erste Schritt ist die Ermittlung
* des levels der indirection.
*/
sh = 0;
nb = 1;
bn -= NADDR-3;
for(j=3; j>0; j--) {
sh += NSHIFT;
nb <<= NSHIFT;
if(bn < nb)
break;
bn -= nb;
}
if(j == 0) {
printf("bn ovf %D\n",bn);
return((daddr_t)0);
}
/*
* fetch die Adresse von der inode
*/
nb = ip->i_addr[NADDR-j];
if(nb == 0) {
printf("bn void %D\n",bn);
return((daddr_t)0);
}
/*
* fetch durch die indirect blocks
*/
for(; j<=3; j++) {
if (blknos[j] != nb) {
io->i_bn = nb + io->i_boff;
io->i_ma = b[j];
io->i_cc = 512;
devread(io);
blknos[j] = nb;
}
bap = (daddr_t *)b[j];
sh -= NSHIFT;
i = (bn>>sh) & NMASK;
nb = bap[i];
if(nb == 0) {
printf("bn void %D\n",bn);
return((daddr_t)0);
}
}
return(nb);
}
/*---------------------------------------------------------------------------*/
/*
*dlook
* Lesen einer directory und Durchsuchen nach einer file
*
* Parameter: s - Pointer auf filename string
* io - Pointer auf iob
* Return: inumber falls file gefunden
* 0 wenn nicht gefunden bzw bei Fehler
*/
/*---------------------------------------------------------------------------*/
static ino_t
dlook(s, io)
register char *s;
register struct iob *io;
{
register struct direct *dp;
register struct inode *ip;
register daddr_t bn;
register n,dc;
if (s==0 || *s=='\0')
return(0);
ip = &io->i_ino;
if ((ip->i_mode&IFMT)!=IFDIR) {
printf("not a directory\n");
return(0);
}
n = ip->i_size/sizeof(struct direct);
if (n==0) {
printf("zero length directory\n");
return(0);
}
dc = 512;
bn = (daddr_t)0;
while(n--) {
if (++dc >= 512/sizeof(struct direct)) {
io->i_bn = sbmap(io, bn++) + io->i_boff;
io->i_ma = io->i_buf;
io->i_cc = 512;
devread(io);
dp = (struct direct *)io->i_buf;
dc = 0;
}
if (match(s, dp->d_name))
return(dp->d_ino);
dp++;
}
return(0);
}
/*---------------------------------------------------------------------------*/
/*
*match
* Vergleich zweier Strings (device filename)
*
* Parameter: s1, s2 - Pointer auf filename string
* Return: 1 - Strings sind gleich
* 0 - Strings sind ungleich
*/
/*---------------------------------------------------------------------------*/
static
match(s1,s2)
register char *s1,*s2;
{
register cc;
cc = DIRSIZ;
while (cc--) {
if (*s1 != *s2)
return(0);
if (*s1++ && *s2++)
continue; else
return(1);
}
return(1);
}
/*---------------------------------------------------------------------------*/
/*
*lseek
* Positionierung des Filepointers (in iob)
*
* Parameter: fdesc - Nummer des Filedescriptors
* addr - gewueschter Offset im file
* ptr - nur 0 = offset von Beginn der file zulaessig
* Return: 0 - ok
* -1 - bei Fehler
*/
/*---------------------------------------------------------------------------*/
lseek(fdesc, addr, ptr)
register fdesc;
register off_t addr;
register ptr;
{
register struct iob *io;
if (ptr != 0) {
printf("Seek not from beginning of file\n");
return(-1);
}
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
return(-1);
io->i_offset = addr;
io->i_bn = addr/512 + io->i_boff;
io->i_cc = 0;
return(0);
}
/*---------------------------------------------------------------------------*/
/*
*getc
* 1 Zeichen (Byte) der eroeffneten file holen, Filepointer
* incrementieren
* bei fdesc < 3 Zeichen von Console (getchar) einlesen
* open ist dafuer nicht moeglich bzw erforderlich
*
* Parameter: fdesc - Nummer Filedescriptor
* Return: Zeichen falls ok
* -1 bei Fehler
*/
/*---------------------------------------------------------------------------*/
getc(fdesc)
register fdesc;
{
register struct iob *io;
register char *p;
register c;
register off;
if (fdesc >= 0 && fdesc <= 2)
return(getchar());
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
return(-1);
p = io->i_ma;
if (io->i_cc <= 0) {
io->i_bn = io->i_offset/(off_t)512;
if (io->i_flgs&F_FILE)
io->i_bn = sbmap(io, io->i_bn) + io->i_boff;
io->i_ma = io->i_buf;
io->i_cc = 512;
devread(io);
if (io->i_flgs&F_FILE) {
off = io->i_offset % (off_t)512;
if (io->i_offset+(512-off) >= io->i_ino.i_size)
io->i_cc = io->i_ino.i_size - io->i_offset + off;
io->i_cc -= off;
if (io->i_cc <= 0)
return(-1);
} else
off = 0;
p = &io->i_buf[off];
}
io->i_cc--;
io->i_offset++;
c = (unsigned char)*p++;
io->i_ma = p;
return(c);
}
/*---------------------------------------------------------------------------*/
/*
*getw
* 1 Word der eroeffneten file holen, Filepointer
* incrementieren
* bei fdesc < 3 word von Console (getchar) einlesen
* open ist dafuer nicht moeglich bzw erforderlich
*
* Parameter: fdesc - Nummer Filedescriptor
* Return: word falls ok
* -1 bei Fehler
*/
/*---------------------------------------------------------------------------*/
getw(fdesc)
register fdesc;
{
register w,i;
register char *cp;
int val;
for (i = 0, val = 0, cp = (char *)&val; i < sizeof(val); i++) {
w = getc(fdesc);
if (w < 0) {
if (i == 0)
return(-1);
else
return(val);
}
*cp++ = w;
}
return(val);
}
/*---------------------------------------------------------------------------*/
/*
*read
* 1 Block (bzw eine Anzahl von Bytes) ab aktuellem Filepointer
* der eroeffneten file lesen,
* bei fdesc < 3 von Console (getchar) einlesen, open
* fuer diesen Fall nicht moeglich
*
* Parameter: fdesc - Nummer Filedescriptor
* buf - Pointer auf Puffer
* count - Anzahl zu lesender Bytes
* Return: Anzahl gelesener Bytes fall ok
* -1 bei Fehler
* 0 bei negativem count
*/
/*---------------------------------------------------------------------------*/
read(fdesc, buf, count)
register fdesc;
register char *buf;
register count;
{
register i;
register struct iob *file;
if (fdesc >= 0 & fdesc <= 2) {
i = count;
do {
*buf = getchar();
} while (--i && *buf++ != '\n');
return(count - i);
}
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
return(-1);
if ((file->i_flgs&F_READ) == 0)
return(-1);
if ((file->i_flgs&F_FILE) == 0) {
file->i_cc = count;
file->i_ma = buf;
i = devread(file);
file->i_bn++;
return(i);
}
else {
if (file->i_offset+count > file->i_ino.i_size)
count = file->i_ino.i_size - file->i_offset;
if ((i = count) <= 0)
return(0);
do {
*buf++ = getc(fdesc+3);
} while (--i);
return(count);
}
}
/*---------------------------------------------------------------------------*/
/*
*write
* 1 Block (bzw eine Anzahl von Bytes) ab aktuellem Filepointer
* der eroeffneten file schreiben,
* bei fdesc < 3 an Console (putchar) ausgeben, open
* fuer diesen Fall nicht moeglich
*
* Parameter: fdesc - Nummer Filedescriptor
* buf - Pointer auf Puffer
* count - Anzahl zu schreibender Bytes
* Return: Anzahl geschriebener Bytes fall ok
* -1 bei Fehler
*/
/*---------------------------------------------------------------------------*/
write(fdesc, buf, count)
register fdesc;
register char *buf;
register count;
{
register i;
register struct iob *file;
if (fdesc >= 0 && fdesc <= 2) {
i = count;
while (i--)
putchar(*buf++);
return(count);
}
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
return(-1);
if ((file->i_flgs&F_WRITE) == 0)
return(-1);
file->i_cc = count;
file->i_ma = buf;
i = devwrite(file);
file->i_bn++;
return(i);
}
/*---------------------------------------------------------------------------*/
/*
*open
* device / file eroeffnen
* 4 files / devices koennen gleichzeitig open sein
*
* Parameter: str - Pointer auf device / filename string
* zB zd(0,13200)wega
* zd - devicename
* 0 - Nummer des physischen drives
* 13200 - offset
* bei Disk: Beginn des logischen
* Filesystems
* bei Tape: n. file auf Tape
* (filename nicht moeglich)
wega - filename
* bei einem Disk-Device:
auch vollstaendiger pathname moeglich,
* nur Lesen einer file moeglich !
* ist kein filename angegeben,wird
* aber das device fuer Zugriffe
* auf Blockebene eroeffnet.
* bei rm device (Kopplung mit local
* System ueber V24):
* drivenummer und offset werden nicht
* benutzt, mueesen aber angegeben
* werden (zB 0), nur filename moeglich.
* how - 0 = open fuer read
* 1 = open fuer write (falls moeglich)
* Return: Nummer des filedescriptors wenn ok
* -1 bei Fehler
*/
/*---------------------------------------------------------------------------*/
open(str, how)
register char *str;
register how;
{
register char *cp;
register i;
register struct iob *file;
register struct devsw *dp;
register fdesc;
static first = 1;
long atol();
if (first) {
for (i = 0; i < NFILES; i++)
iob[i].i_flgs = 0;
first = 0;
}
for (fdesc = 0; fdesc < NFILES; fdesc++)
if (iob[fdesc].i_flgs == 0)
goto gotfile;
_stop("No more file slots");
gotfile:
(file = &iob[fdesc])->i_flgs |= F_ALLOC;
for (cp = str; *cp && *cp != '('; cp++)
;
if (*cp != '(') {
printf("Bad device\n");
file->i_flgs = 0;
return(-1);
}
*cp++ = '\0';
for (dp = devsw; dp->dv_name; dp++) {
if (match(str, dp->dv_name))
goto gotdev;
}
printf("Unknown device\n");
file->i_flgs = 0;
return(-1);
gotdev:
*(cp-1) = '(';
file->i_ino.i_dev = dp-devsw;
file->i_unit = *cp++ - '0';
if (file->i_unit < 0 || file->i_unit > 7) {
printf("Bad unit specifier\n");
file->i_flgs = 0;
return(-1);
}
if (*cp++ != ',') {
badoff:
printf("Missing offset specification\n");
file->i_flgs = 0;
return(-1);
}
file->i_boff = atol(cp);
for (;;) {
if (*cp == ')')
break;
if (*cp++)
continue;
goto badoff;
}
cp++;
file->i_ino.i_number = (unsigned)cp;
if (devopen(file) == -1) {
file->i_flgs = 0;
return(-1);
}
if (file->i_unit == 'r' || *cp == '\0') {
file->i_flgs |= how+1;
file->i_cc = 0;
file->i_offset = 0;
return(fdesc+3);
}
if ((i = find(cp, file)) == 0) {
file->i_flgs = 0;
return(-1);
}
if (how != 0) {
printf("Can't write files yet.. Sorry\n");
file->i_flgs = 0;
return(-1);
}
openi(i, file);
file->i_offset = 0;
file->i_cc = 0;
file->i_flgs |= F_FILE | (how+1);
return(fdesc+3);
}
/*---------------------------------------------------------------------------*/
/*
*close
* file schliessen und iob des files freigeben
*
* Parameter: fdesc - Nummer filedescriptor
* Return: 0 wenn ok
* -1 bei Fehler
*/
/*---------------------------------------------------------------------------*/
close(fdesc)
register fdesc;
{
register struct iob *file;
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
return(-1);
if ((file->i_flgs&F_FILE) == 0)
devclose(file);
file->i_flgs = 0;
return(0);
}
/*---------------------------------------------------------------------------*/
/*
*exit
* Beendigung des laufenden Programms, Wiedereintrit in
* boot Programm, schliessen aller offenen files
*/
/*---------------------------------------------------------------------------*/
exit()
{
register fdesc;
for (fdesc=3; fdesc < NFILES+3; fdesc++)
close(fdesc);
_stop("Exit called");
}
/*---------------------------------------------------------------------------*/
/*
*stop
* Return zu boot (von exit aus)
*/
/*---------------------------------------------------------------------------*/
_stop(s)
register char *s;
{
printf("%s\n", s);
_ret();
}

324
WEGA/src/cmd/BOOT/bud.s Normal file
View File

@ -0,0 +1,324 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1986
Standalone Module ud.s
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:50
Version: 1.2
*******************************************************************************
Device Treiber zum Laden von Wega Procedure Dateien
von Minidisketten unter P8000 UDOS
Der Modul liegt leider nur als PLZ/ASM Quelle vor.
Bei Aenderungen der Struktur iob in saio.h und
der inode in inode.h mussen die Referenzen zu dieser
Struktur per Hand geaendert werden.
*******************************************************************************
******************************************************************************!
ud_s module
constant
UDIN := %20
UDWR := %22
ESC := %1B
ETX := %03
ACK := %06
CAN := %18
STX := %02
EOT := %04
NAK := %15
typ := %01 !binary file!
!Referenzen auf iob Struktur!
constant
iob_i_ino_i_number := 6 !in ud Pointer auf Filename!
iob_i_unit := 80
iob_i_ma := 98
iob_i_cc := 100
internal
udflag1 word
udflag2 word
MSG_OERR array [* byte] := 'ud: cannot open file%l%00'
MSG_RERR array [* byte] := 'ud: read error%l%00'
MSG_WERR array [* byte] := 'ud: cannot write%l%00'
!*------------------------------------------ Proceduren ---------------------*!
global
!*----------------------------------------------------------------------------*
*
*udopen
* Open Request
*
* Nur Open fuer Read moeglich
* udopen sendet an das UDOS System den Filenamen, das Local
* System beginnt mit dem Senden des 1. Datenblocks, falls die
* Datei vorhanden ist.
* input r7: Pointer auf Struktur iob
*
*---------------------------------------------------------------------------*!
_udopen procedure
entry
pushl @r15, rr8
ldk r8, #0
ld udflag1, r8 !init udflag!
ld udflag2, r8
ld iob_i_unit(r7), #'r'!udos open drive nr setzen!
bitb @r7, #1 !bit 1 = 1 = open for write!
jp nz, udwerror !write nicht moeglich!
ldb rl0, #'S' !Kommando Send file an udos!
sc #UDWR
sc #UDIN !acknowledge von udos!
ldb rl0, #typ !file typ an udos!
sc #UDWR
sc #UDIN !acknowledge von udos!
!Ausgabe filename an udos!
ld r2, iob_i_ino_i_number(r7) !file name Pointer!
ldb rh7, #10 !retries!
ld r5, r2
udo0: ldb rl7, #0 !Checksumme init!
ld r2, r5
ldb rl0, #STX !Start of Text!
sc #UDWR
udo1: ldb rl0 ,@r2 !Zeichen von filename!
inc r2, #1
cpb rl0, #0 !ende filename ?!
jr z, udo2
xorb rl7, rl0 !Checksumme berechnen!
sc #UDWR
jr udo1
udo2: ldb rl0, #ETX !end of text!
sc #UDWR
exb rl0, rl7
sc #UDWR !Checksumme ausgeben!
sc #UDIN !Warten auf Quittung!
resb rl3, #7
cpb rl3, #ACK
ldk r2, #0 !kein Fehler!
jp z, udclose4
cpb rl3, #CAN !Abbrechen ?!
jr z,udoerr
dbjnz rh7, udo0 !naechster Versuch!
udoerr:
lda r7, MSG_OERR
jr uderror
end _udopen
!*----------------------------------------------------------------------------*
*udclose
* Close Request
*
* ud beendet die Fileuebertragung mit dem UDOS System
*
*---------------------------------------------------------------------------*!
_udclose procedure
entry
pushl @r15, rr8
test udflag2
jr nz, udclose3 !file war schon zu Ende!
ldb rl0, #CAN !file transfer abbrechen!
sc #UDWR
jr udclose1
end _udclose
!*----------------------------------------------------------------------------*
*
*udstrategy
* Block Read Request (Write nicht moeglich)
*
* Einlesen eines Blocks der eroeffneten Datei vom UDOS System
* input r7: Pointer auf iob Struktur
*
*---------------------------------------------------------------------------*!
_udstrat procedure
entry
pushl @r15, rr8
cp r6, #1 !Read!
jr nz,udwerror !write nicht moeglich!
udst1: test udflag2
jr z,udst2
ldk r2, #0 !file schon close!
jr udclose3
udst2: ld r8, iob_i_ma(r7) !Lade Adr!
ld r9, iob_i_cc(r7) !Laenge!
test r9
jr z, udst3 !0 nicht zulaessig!
udstloop:
push @r15, r7
calr udread !64 byte von udos!
pop r7, @r15
test r2
jr z,udst4
udst3: lda r7, MSG_RERR
jr uderror !Read Error!
udst4: ld r2, iob_i_cc(r7) !Laenge!
cpb rl3, #EOT
jr nz,udst5
sub r9, r6 !file uebertragen!
jr c, udclose1
sub r2, r9 !uebertragene Anzahl Byte!
jr udclose1
udst5: sub r9, r6
jr z, udclose3 !1 Block fertig uebertragen!
jr c, udclose3
jr udstloop
end _udstrat
!*----------------------------------------------------------------------------*
* Unterprogramme
*---------------------------------------------------------------------------*!
internal
udread procedure !Lesen 1 Block von udos System (64 Byte)!
entry
ldb rh7, #10 !retries!
ldk r2, #0 !kein Fehler!
ldk r6, #0 !init lenght!
test udflag1
jr z, udr0 !Sprung 1.Aufruf!
ldb rl0, #ACK !Ack fuer letzen Aufruf!
sc #UDWR
udr0: ldb rl7, #0 !Checksumme init!
ld udflag1, #-1
ld r5, r8 !Buffer Pointer retten!
sc #UDIN
resb rl3, #7
cpb rl3, #EOT
ret z !file fertig uebertragen!
cpb rl3, #CAN
jr z, udrerr !udos gibt Abbruch!
cpb rl3, #ESC
jr z, udrerr !udos gibt Abbruch!
cpb rl3, #STX !Start of text muss 1.Zeichen sein!
jr nz, udr2 !warten auf ETX und Uebertragung wiederholen!
sc #UDIN
ldb rh4, rl3 !high count!
sc #UDIN
ldb rl4, rl3 !low count!
ld r6, r4
udr1: sc #UDIN !Daten lesen!
ldb @r8, rl3 !in Buffer!
inc r8, #1
xorb rl7, rl3 !Checksumme berechnen!
djnz r4, udr1
udr2: sc #UDIN !warten auf ETX!
resb rl3, #7
cpb rl3, #ESC
jr z, udrerr
cpb rl3, #CAN
jr z, udrerr
cpb rl3, #ETX
jr nz, udr2
sc #UDIN !Checksumme!
cpb rl3, rl7 !uebertragene = berechnete ?!
ldb rl3, #0 !falls zufaellig EOT!
ret z !ja!
decb rl7, #1
jr z, udrerr !Abbruch!
ldb rl0, NAK !n mal wiederholen!
ld r8, r5 !Buffer Pointer auf Anfang zurueck!
sc #UDWR
jr udr0
udrerr: ld r2, #-1
ret
end udread
uderror procedure
entry
ldb rl0, #CAN !udos abbrechen!
sc #UDWR
sc #UDIN
jr uderror1
end uderror
udwerror procedure
entry
lda r7, MSG_WERR
end udwerror
uderror1 procedure
entry
call _printf
ld r2, #-1
jr udclose2
end uderror1
udclose1 procedure
entry
sc #UDIN
end udclose1
udclose2 procedure
entry
ld udflag2, #-1 !udos close!
end udclose2
udclose3 procedure
entry
end udclose3
udclose4 procedure
entry
popl rr8, @r15
ret
end udclose4
end ud_s

122
WEGA/src/cmd/BOOT/create.boot Executable file
View File

@ -0,0 +1,122 @@
all: pb.image boot0.fd boot0.ud boot0.rm boot libb.a sa.cat sa.format sa.verify sa.mkfs sa.install sa.timer
pb.image: boot0.md.s
@echo pb.image:
as -u -o boot0.md.o boot0.md.s
ld -s -o pb.image boot0.md.o
strip -h pb.image
chmod 400 pb.image
rm boot0.md.o
@echo
boot0.fd: boot0.fd.s
@echo boot0.fd:
as -u -o boot0.fd.o boot0.fd.s
ld -s -o boot0.fd boot0.fd.o
strip -h boot0.fd
chmod 400 boot0.fd
rm boot0.fd.o
@echo
boot0.ud: boot0.ud.s
@echo boot0.ud:
as -u -o boot0.ud.o boot0.ud.s
ld -s -o boot0.ud boot0.ud.o
strip -h boot0.ud
chmod 400 boot0.ud
rm boot0.ud.o
@echo
boot0.rm: boot0.rm.s
@echo boot0.rm:
as -u -o boot0.rm.o boot0.rm.s
ld -s -o boot0.rm boot0.rm.o
strip -h boot0.rm
chmod 400 boot0.rm
rm boot0.rm.o
@echo
boot: bstart.c BOOTLIB
@echo boot:
cc -c -O bstart.c
ld -s -e start -b 0x8000 -o boot bstart.o BOOTLIB
chmod 400 boot
rm bstart.o
@echo
BOOTLIB: bmch.s boot.c bsys.c bconf.c bmisc.c bmd.c bfd.c bud.s brm.s
@echo BOOTLIB:
as -u -o bmch.o bmch.s
cc -c -O boot.c
cc -c -O bsys.c
cc -c -O bconf.c
cc -c -O bmisc.c
cc -c -O bmd.c
cc -c -O bfd.c
as -u -o bud.o bud.s
as -u -o brm.o brm.s
rm -f BOOTLIB
ar qc BOOTLIB bmch.o boot.o bsys.o bconf.o bmisc.o bmd.o bfd.o bud.o brm.o
chmod 644 BOOTLIB
rm bmch.o boot.o bsys.o bconf.o bmisc.o bmd.o bfd.o bud.o brm.o
@echo
libb.a: sa.function.s bmisc.c
@echo libb.a:
as -u -o sa.function.o sa.function.s
cc -c -O bmisc.c
rm -f libb.a
ar qc libb.a sa.function.o bmisc.o
chmod 644 libb.a
rm sa.function.o bmisc.o
@echo
sa.mkfs: sa.mkfs.c libb.a
@echo sa.mkfs:
cc -c -O sa.mkfs.c
ld -s -o sa.mkfs sa.mkfs.o libb.a
chmod 400 sa.mkfs
rm sa.mkfs.o
@echo
sa.cat: sa.cat.c libb.a
@echo sa.cat:
cc -c -O sa.cat.c
ld -s -o sa.cat sa.cat.o libb.a
chmod 400 sa.cat
rm sa.cat.o
@echo
sa.timer: sa.timer.c libb.a
@echo sa.timer:
cc -c -O sa.timer.c
ld -s -o sa.timer sa.timer.o libb.a
chmod 400 sa.timer
rm sa.timer.o
@echo
sa.install: sa.install.c libb.a
@echo sa.install:
cc -c -O sa.install.c
ld -s -o sa.install sa.install.o libb.a
chmod 400 sa.install
rm sa.install.o
@echo
sa.format: sa.format.c sa.wdc.s libb.a
@echo sa.format:
cc -c -O sa.format.c
as -u -o sa.wdc.o sa.wdc.s
ld -s -o sa.format sa.format.o sa.wdc.o libb.a
chmod 400 sa.format
rm sa.format.o sa.wdc.o
@echo
sa.verify: sa.verify.c sa.disk.s libb.a
@echo sa.verify:
cc -c -O sa.verify.c
as -u -o sa.wdc.o sa.wdc.s
ld -s -o sa.verify sa.verify.o sa.wdc.o libb.a
chmod 400 sa.verify
rm sa.verify.o sa.wdc.o
@echo

View File

@ -0,0 +1,170 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Modul sa.function.s
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:56
Version: 1.1
*******************************************************************************
Dieser Modul gestattet die Benutzung der Boot Systemfunktionen
von einem User Programm aus. Dieser Modul wird zusammen mit
dem Modul misc.c zur libb.a
*******************************************************************************
******************************************************************************!
sa_function_s module
$nonsegmented
external
_printfv procedure
global
_printf procedure
entry
ex r2, @r15
push @r15, r3
push @r15, r4
push @r15, r5
push @r15, r6
ld r6, r15
push @r15, r2
call _printfv
ld r2, @r15
inc r15, #12
jp @r2
end _printf
_exit procedure
entry
ldb rl1, #0
jr system
end _exit
_read procedure !read nach Segment 0!
entry
ldb rl1, #1
jr system
end _read
_write procedure !von Segment 0!
entry
ldb rl1, #2
jr system
end _write
_open procedure
entry
ldb rl1, #3
jr system
end _open
_close procedure
entry
ldb rl1, #4
jr system
end _close
_lseek procedure
entry
ldb rl1, #5
jr system
end _lseek
_loadit procedure
entry
ldb rl1, #6
jr system
end _loadit
_getchar procedure
entry
ldb rl1, #7
jr system
end _getchar
_putchar procedure
entry
ldb rl1, #8
jr system
end _putchar
_getc procedure
entry
ldb rl1, #9
jr system
end _getc
_getw procedure
entry
ldb rl1, #10
end _getw
internal
system procedure
entry
ld r0, #%C000
ldctl FCW, r0
!$segmented!
wval %5F00 !call <3F>%8002!
wval %BF00
wval %8002
ld r0, #%5800
ldctl FCW, r0
!nonsegmented!
ret
end system
!*--------------------------------------------------------*!
!*
* Realisierung von in und out Befehlen fuer C
*!
!*--------------------------------------------------------*!
global
_otirb !@r7, @r6, r5! procedure
entry
otirb @r7, @r6, r5
ret
end _otirb
_outb !@r7, rl6! procedure
entry
outb @r7, rl6
ret
end _outb
_inb !rl2, @r7! procedure
entry
inb rl2, @r7
xorb rh2, rh2
ret
end _inb
_out !@r7, r6! procedure
entry
out @r7, r6
ret
end _out
_in !r2, @r7! procedure
entry
in r2, @r7
ret
end _in
end sa_function_s

View File

@ -0,0 +1,379 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Module boot0.fd.s (primary bootstrapper)
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:20
Version: 1.1
*******************************************************************************
fuer einen Systemstart von der Floppydisk (WEGA-Format)
*******************************************************************************
******************************************************************************!
boot0_fd_s module
$SECTION boot0
constant
DISK_BUFFER := %FA00 !array [%200 byte]!
BLOCK_POINTER := %FC00 !array [%228 byte]!
PATH_NAME := %FE28 !n * 14 byte fuer pathname!
MOVE_ADR := %F800
LOAD_ADR := %8000
TTIN := %04
TTWR := %06
FDISK := %24
global
!*---------------------------------------------------------------------------*!
!*
* eigentliches Programm von 8000 auf F800 moven
*!
!*---------------------------------------------------------------------------*!
START procedure
entry
ld r2, #%5800 !nonsegmented Systemmode!
ldctl FCW, r2 !fcw setzen!
ldb rh2, #(MOVE_ADR shr 8)
ldar r1, MAIN !Quelladr!
ld r15, r2
ld r14, #(DISK_BUFFER - MOVE_ADR)
ldirb @r2, @r1, r14
jp @r15
end START
!Dieses Programm ist voll relativ!
!Es wird auf MOVE_ADR gemoved!
!*---------------------------------------------------------------------------*!
!*
* Main Procedure
* Eingabe filename (pathname) bei manuellem boot
* bzw Standardname fuer secundary boot bei automatischem boot
* Suchen des files in der directory (bzw den derectories)
* Laden ab 8000 hex, Segment 0
* Starten des Programms
*!
!*---------------------------------------------------------------------------*!
MAIN procedure
entry
pushl @r15, rr6 !Monitor Parameter retten!
pushl @r15, rr4
test r4 !0=automatischer Boot!
jr nz, MAIN_LOOP !manueller Boot r14 ist 0!
ldar r14, MSG_BOOT !autom.:boot Kommando laden!
MAIN_LOOP:
ldar r8, MSG_PROMPT
calr PRINT_MSG !Meldung zur Eingabeanforderung!
ld r10, #PATH_NAME
ld r11, r10 !r11 Anf adr Puffer!
MAIN3:
ld r12, r11 !r12 aktueller Puffer Pointer!
MAIN4:
calr GETA
cpb rl0, #%0A !lf = Ende der Eingabe!
jr z, MAIN6
cpb rl0, #'/' !Name fuer directory file!
jr z, MAIN5
ldb @r12, rl0 !Zeichen in Puffer!
inc r12, #%01 !Pointer inc!
jr MAIN4 !naechstes Zeichen!
MAIN5:
cp r12, r11 !1. eingegebenes Zeichen ?!
jr z, MAIN4 !name eingeben!
calr CLEAR !Namensfeld bis Ende mit 00 beschreiben!
jr MAIN3 !naechsten Namen eingeben!
MAIN6: !Ende der Eingabe!
calr CLEAR !Rest vom Namensfeld mit 00 fuellen!
clrb @r11 !erstes Zeichen vom naechsten Namensfeld = 0!
!directories nach file durchsuchen!
ldk r11, #%02 !inumber der root directory!
MAIN7:
calr READ_INODE !inode lesen!
jr nz, MAIN16 !Floppydisk Error!
testb @r10 !<> 0 directory einlesen!
!0 = gewuenschten file einlesen!
jr z, MAIN11 !Sprung Procedure file einlesen!
MAIN8:
!directory lesen!
test r13 !directory ende ?!
jr z, MAIN14 !Ja, file nicht gefunden!
calr READ_BLOCK !naechsten Block der directory einlesen!
jr nz, MAIN16 !Floppydisk Error!
MAIN9:
pop r11, @r9 !inumber in directory!
test r11 !0=keine Datei auf diesem Platz eingetragen!
jr z, MAIN10 !naechster Platz in directory!
!Abstand 10 Hex Bytes 2 byte inumber 14 byte Name!
ldk r0, #14 !Laenge filename!
ld r1, r9
ld r2, r10 !filename in directory Block suchen!
cpsirb @r10, @r1, r0, nz
jr nz, MAIN7 !Name gefunden!
!in r11 ist inumber fuer gesuchte file!
ld r10, r2
MAIN10:
inc r9, #14
cp r9, #DISK_BUFFER+%200 !Ende Floppydisk Puffer!
jr ge, MAIN8 !Name nicht gefunden, naechsten Block lesen!
jr MAIN9 !nicht gefunden, weiter im gleichen Block suchen!
!Procedure file einlesen!
MAIN11:
test r13 !file leer ?!
jr z, MAIN14
calr READ_BLOCK !1. Block der file lesen!
jr nz, MAIN16 !Floppydisk Error!
cp @r9, #%E707 !Magic Nr!
!=nonsegmented, executable!
jr nz, MAIN14 !Fehler falsche Magic!
ld r11, %10(r9) !Entry Point des Programms!
ld r0, #%18 !size header!
add r0, %0A(r9) !size segment table!
add r9, r0 !Anfangsadr Programmcode!
ld r10, #LOAD_ADR !Ladeadr im Segment 0!
neg r0
add r0, #%200 !%200-header-segtable!
MAIN12:
ldirb @r10, @r9, r0 !Move Puffer auf echte Adr!
test r13 !noch Datenbloecke einzulesen ?!
jr z, MAIN13 !file eingelesen!
calr READ_BLOCK !alle weiteren Bloecke lesen!
jr nz, MAIN16 !Floppydisk Error!
ld r0, #%0200 !RL!
jr MAIN12
!Programm starten!
MAIN13:
ld r15, #MOVE_ADR - 8 !Stackpointer fuer Parameter neu setzen!
popl rr4, @r15 !Rueckladen der Monitor Parameter!
popl rr6, @r15
jp @r11 !Sprung zum geladenen Programm!
!Fehlerbehandlung!
MAIN14:
ldar r8, MSG_ERROR
MAIN15:
calr PRINT_MSG
ldk r14, #0 !manuel boot setzen!
jr MAIN_LOOP
MAIN16: ldar r8, MSG_DERROR
jr MAIN15
end MAIN
internal
!*---------------------------------------------------------------------------*!
!*
* Inode Block fuer vorgegebene inumber lesen
* richtige inode ermitteln
*!
!*---------------------------------------------------------------------------*!
READ_INODE procedure
entry
inc r11, #%0F !aus inumber inode Block berechnen!
ld r5, r11
srl r5, #%03 !/8 ;8 inodes je Block!
xor r4, r4
calr READ_DISK !inode Block in DISK_BUFFER lesen!
ret nz !Floppydisk Error!
and r11, #%07
sll r11, #%06
add r11, #DISK_BUFFER+8
popl rr12, @r11 !Laenge file aus inode!
addl rr12, #%01FF
srll rr12, #9 !in r13 nun Anzahl Bloecke der file!
ld r12, #BLOCK_POINTER
ld r9, r12 !array der Blockpointer!
ldk r1, #10 !10 direkte Pointer!
READ_INODE1:
clrb @r9 !direkte Pointer einlesen!
inc r9, #%01
ldk r0, #%03
ldirb @r9, @r11, r0 !move in Pointer array!
dec r1, #%01
jr nz, READ_INODE1
cp r13, #%0A !file < 10 Bloecke ?!
jr le, READ_INODE2 !ja=fertig!
xorb rh4, rh4 !Pointer zu einfach indirekt laden!
ldb rl4, @r11
inc r11, #%01
ldb rh5, @r11
inc r11, #%01
ldb rl5, @r11
calr READ_DISK !einfach indirekt Pointer Block lesen!
ret nz !Floppydisk Error!
ld r1, #DISK_BUFFER
ld r0, #%0200 !RL!
ldirb @r9, @r1, r0 !in Pointerarray an die 10 direkten Pointer moven!
READ_INODE2:
setflg z
ret
end READ_INODE
!*---------------------------------------------------------------------------*!
!*
* 1 Block von Floppydisk einlesen
*!
!*---------------------------------------------------------------------------*!
READ_BLOCK procedure
entry
popl rr4, @r12 !naechste Blocknummer!
calr READ_DISK
ret nz !Floppydisk Error!
ld r9, #DISK_BUFFER
dec r13, #%01 !Anzahl Bloecke dec!
setflg z
ret
end READ_BLOCK
!*---------------------------------------------------------------------------*!
!*
* Programme zur Ein- Ausgabe an Console und zur
* Aufbereitung der Eingaben
*!
!*---------------------------------------------------------------------------*!
CLEAR procedure
entry
inc r11, #%0E !Pointer auf nachstes Namensfeld im PATH_NAME Puffer!
CLEAR1:
cp r12, r11
ret ge
clrb @r12 !Rest vom alten Namensfeld mit 00 beschreiben!
inc r12, #%01
jr CLEAR1
end CLEAR
PRINT_MSG procedure
entry
ldb rl0, @r8
testb rl0 !Ausgabe bis 00!
ret z
calr PRINT_CHAR
inc r8, #%01
jr PRINT_MSG
end PRINT_MSG
SET_BOOT procedure
entry
ldar r14, MSG_BOOT
end SET_BOOT !laeuft in GETA weiter!
GETA procedure
entry
test r14
jr z, GETA1
ldb rl0, @r14 !Zeichen nicht ueber CON!
!sondern aus Message holen!
inc r14, #%01
jr GETA2
!Zeichen von CON holen!
GETA1:
sc #TTIN
ld r0, r3
GETA2:
resb rl0, #%07 !reset bit 7!
cpb rl0, #%0D
jr nz, PRINT_CHAR !Zeichen ausgeben!
ldk r0, #%0A !cr in lf!
end GETA !laueft in PRINT_CHAR weiter!
PRINT_CHAR procedure
entry
cpb rl0, #%0A !Zeichen = LF ?!
jr nz, PUTA !nein normal Ausgeben!
cp r12, r10 !r12=r10=kein Zeichen eingegeben!
jr z, SET_BOOT !Boot Kommando laden!
ldk r14, #%00 !Kommando ueber CON eingeben setzen!
ldk r0, #%0D !cr lf ausgeben!
calr PUTA
ldk r0, #%0A
end PRINT_CHAR
PUTA procedure
entry
sc #TTWR
ret
end PUTA
!*---------------------------------------------------------------------------*!
!*
* Lesen 1 Block von Floppydisk in Puffer
* Es wird der Floppydisktreiber im Monitor benutzt
*!
!*---------------------------------------------------------------------------*!
READ_DISK procedure
entry
ldk r8, #10 !retries!
LOOP:
dec r15, #6
ldm @r15, r8, #3
ldk r7, #1 !read!
ld r6, #%0060 !drive 0 typ 6!
!in rr4 Blocknummer!
ldk r8, #0 !obere 16 bit der pysischen RAM Adr!
lda r9, DISK_BUFFER !Ladeadr untere 16 bit!
ld r10, #%200 !Laenge!
sc #FDISK
ldm r8, @r15, #3
inc r15, #6
test r2 !<> 0 ist Fehler!
ret z
djnz r8, LOOP !10 Versuche!
test r2 !z flag!
ret
end READ_DISK
internal
MSG_PROMPT array [* byte] := '> %00'
MSG_BOOT array [* byte] := 'boot%l'
MSG_ERROR array [* byte] := '?%l%00'
MSG_DERROR array [* byte] := 'DISK ERROR%l%00'
end boot0_fd_s

View File

@ -0,0 +1,392 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Module boot0.md.s (primary bootstrapper)
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:26
Version: 1.1
*******************************************************************************
boot0 disk fuer einen Systemstart von der Harddisk
(primary bootstrapper)
bei autonatischem boot bzw Eingabe von CR bei manuellem
boot nach der Meldung mit > wird das Programm boot
(secundary bootstrapper) von der Harddisk
(vom ersten Filesystem)
in den Speicher des U8000 Systems
(Segment 0, ab Adresse %8000) geladen.
Bei manuellem boot kann nach der Meldung mit > auch
ein anderer filename (pathname) eingegeben werden.
Es wird das Filesystem md(0,0) - nicht das root File-
system benutzt.
boot0 benutzt den U8000 Monitor.
*******************************************************************************
******************************************************************************!
boot0_md_s module
$SECTION boot0
constant
DISK_BUFFER := %FA00 !array [%200 byte]!
BLOCK_POINTER := %FC00 !array [%228 byte]!
PATH_NAME := %FE28 !n * 14 byte fuer pathname!
MOVE_ADR := %F800
LOAD_ADR := %8000
TTIN := %04
TTWR := %06
DISK := %1E
global
!*---------------------------------------------------------------------------*!
!*
* eigentliches Programm von 8000 auf F800 moven
*!
!*---------------------------------------------------------------------------*!
START procedure
entry
ld r2, #%5800 !nonsegmented Systemmode!
ldctl FCW, r2 !fcw setzen!
ldb rh2, #(MOVE_ADR shr 8)
ldar r1, MAIN !Quelladr!
ld r15, r2
ld r14, #(DISK_BUFFER - MOVE_ADR)
ldirb @r2, @r1, r14
jp @r15
end START
!Dieses Programm ist voll relativ!
!Es wird auf MOVE_ADR gemoved!
!*---------------------------------------------------------------------------*!
!*
* Main Procedure
* Eingabe filename (pathname) bei manuellem boot
* bzw Standardname fuer secundary boot bei automatischem boot
* Suchen des files in der directory (bzw den derectories)
* Laden ab 8000 hex, Segment 0
* Starten des Programms
*!
!*---------------------------------------------------------------------------*!
MAIN procedure
entry
pushl @r15, rr6 !Monitor Parameter retten!
pushl @r15, rr4
test r4 !0=automatischer Boot!
jr nz, MAIN_LOOP !manueller Boot r14 ist 0!
ldar r14, MSG_BOOT !autom.:boot Kommando laden!
MAIN_LOOP:
ldar r8, MSG_PROMPT
calr PRINT_MSG !Meldung zur Eingabeanforderung!
ld r10, #PATH_NAME
ld r11, r10 !r11 Anf adr Puffer!
MAIN3:
ld r12, r11 !r12 aktueller Puffer Pointer!
MAIN4:
calr GETA
cpb rl0, #%0A !lf = Ende der Eingabe!
jr z, MAIN6
cpb rl0, #'/' !Name fuer directory file!
jr z, MAIN5
ldb @r12, rl0 !Zeichen in Puffer!
inc r12, #%01 !Pointer inc!
jr MAIN4 !naechstes Zeichen!
MAIN5:
cp r12, r11 !1. eingegebenes Zeichen ?!
jr z, MAIN4 !name eingeben!
calr CLEAR !Namensfeld bis Ende mit 00 beschreiben!
jr MAIN3 !naechsten Namen eingeben!
MAIN6: !Ende der Eingabe!
calr CLEAR !Rest vom Namensfeld mit 00 fuellen!
clrb @r11 !erstes Zeichen vom naechsten Namensfeld = 0!
!directories nach file durchsuchen!
ldk r11, #%02 !inumber der root directory!
MAIN7:
calr READ_INODE !inode lesen!
jr nz, MAIN16 !Disk Error!
testb @r10 !<> 0 directory einlesen!
!0 = gewuenschten file einlesen!
jr z, MAIN11 !Sprung Procedure file einlesen!
MAIN8:
!directory lesen!
test r13 !directory ende ?!
jr z, MAIN14 !Ja, file nicht gefunden!
calr READ_BLOCK !naechsten Block der directory einlesen!
jr nz, MAIN16 !Disk Error!
MAIN9:
pop r11, @r9 !inumber in directory!
test r11 !0=keine Datei auf diesem Platz eingetragen!
jr z, MAIN10 !naechster Platz in directory!
!Abstand 10 Hex Bytes 2 byte inumber 14 byte Name!
ldk r0, #14 !Laenge filename!
ld r1, r9
ld r2, r10 !filename in directory Block suchen!
cpsirb @r10, @r1, r0, nz
jr nz, MAIN7 !Name gefunden!
!in r11 ist inumber fuer gesuchte file!
ld r10, r2
MAIN10:
inc r9, #14
cp r9, #DISK_BUFFER+%200 !Ende Disk Puffer!
jr ge, MAIN8 !Name nicht gefunden, naechsten Block lesen!
jr MAIN9 !nicht gefunden, weiter im gleichen Block suchen!
!Procedure file einlesen!
MAIN11:
test r13 !file leer ?!
jr z, MAIN14
calr READ_BLOCK !1. Block der file lesen!
jr nz, MAIN16 !Disk Error!
cp @r9, #%E707 !Magic Nr!
!=nonsegmented, executable!
jr nz, MAIN14 !Fehler falsche Magic!
ld r11, %10(r9) !Entry Point des Programms!
ld r0, #%18 !size header!
add r0, %0A(r9) !size segment table!
add r9, r0 !Anfangsadr Programmcode!
ld r10, #LOAD_ADR !Ladeadr im Segment 0!
neg r0
add r0, #%200 !%200-header-segtable!
MAIN12:
ldirb @r10, @r9, r0 !Move Puffer auf echte Adr!
test r13 !noch Datenbloecke einzulesen ?!
jr z, MAIN13 !file eingelesen!
calr READ_BLOCK !alle weiteren Bloecke lesen!
jr nz, MAIN16 !Disk Error!
ld r0, #%0200 !RL!
jr MAIN12
!Programm starten!
MAIN13:
ld r15, #MOVE_ADR - 8 !Stackpointer fuer Parameter neu setzen!
popl rr4, @r15 !Rueckladen der Monitor Parameter!
popl rr6, @r15
jp @r11 !Sprung zum geladenen Programm!
!Fehlerbehandlung!
MAIN14:
ldar r8, MSG_ERROR
MAIN15:
calr PRINT_MSG
ldk r14, #0 !manuel boot setzen!
jr MAIN_LOOP
MAIN16: ldar r8, MSG_DERROR
jr MAIN15
end MAIN
internal
!*---------------------------------------------------------------------------*!
!*
* Inode Block fuer vorgegebene inumber lesen
* richtige inode ermitteln
*!
!*---------------------------------------------------------------------------*!
READ_INODE procedure
entry
inc r11, #%0F !aus inumber inode Block berechnen!
ld r5, r11
srl r5, #%03 !/8 ;8 inodes je Block!
xor r4, r4
calr READ_DISK !inode Block in DISK_BUFFER lesen!
ret nz !Disk Error!
and r11, #%07
sll r11, #%06
add r11, #DISK_BUFFER+8
popl rr12, @r11 !Laenge file aus inode!
addl rr12, #%01FF
srll rr12, #9 !in r13 nun Anzahl Bloecke der file!
ld r12, #BLOCK_POINTER
ld r9, r12 !array der Blockpointer!
ldk r1, #10 !10 direkte Pointer!
READ_INODE1:
clrb @r9 !direkte Pointer einlesen!
inc r9, #%01
ldk r0, #%03
ldirb @r9, @r11, r0 !move in Pointer array!
dec r1, #%01
jr nz, READ_INODE1
cp r13, #%0A !file < 10 Bloecke ?!
jr le, READ_INODE2 !ja=fertig!
xorb rh4, rh4 !Pointer zu einfach indirekt laden!
ldb rl4, @r11
inc r11, #%01
ldb rh5, @r11
inc r11, #%01
ldb rl5, @r11
calr READ_DISK !einfach indirekt Pointer Block lesen!
ret nz !Disk Error!
ld r1, #DISK_BUFFER
ld r0, #%0200 !RL!
ldirb @r9, @r1, r0 !in Pointerarray an die 10 direkten Pointer moven!
READ_INODE2:
setflg z
ret
end READ_INODE
!*---------------------------------------------------------------------------*!
!*
* 1 Block von Disk einlesen
*!
!*---------------------------------------------------------------------------*!
READ_BLOCK procedure
entry
popl rr4, @r12 !naechste Blocknummer!
calr READ_DISK
ret nz !Disk Error!
ld r9, #DISK_BUFFER
dec r13, #%01 !Anzahl Bloecke dec!
setflg z
ret
end READ_BLOCK
!*---------------------------------------------------------------------------*!
!*
* Programme zur Ein- Ausgabe an Console und zur
* Aufbereitung der Eingaben
*!
!*---------------------------------------------------------------------------*!
CLEAR procedure
entry
inc r11, #%0E !Pointer auf nachstes Namensfeld im PATH_NAME Puffer!
CLEAR1:
cp r12, r11
ret ge
clrb @r12 !Rest vom alten Namensfeld mit 00 beschreiben!
inc r12, #%01
jr CLEAR1
end CLEAR
PRINT_MSG procedure
entry
ldb rl0, @r8
testb rl0 !Ausgabe bis 00!
ret z
calr PRINT_CHAR
inc r8, #%01
jr PRINT_MSG
end PRINT_MSG
SET_BOOT procedure
entry
ldar r14, MSG_BOOT
end SET_BOOT !laeuft in GETA weiter!
GETA procedure
entry
test r14
jr z, GETA1
ldb rl0, @r14 !Zeichen nicht ueber CON!
!sondern aus Message holen!
inc r14, #%01
jr GETA2
!Zeichen von CON holen!
GETA1:
sc #TTIN
ld r0, r3
GETA2:
resb rl0, #%07 !reset bit 7!
cpb rl0, #%0D
jr nz, PRINT_CHAR !Zeichen ausgeben!
ldk r0, #%0A !cr in lf!
end GETA !laueft in PRINT_CHAR weiter!
PRINT_CHAR procedure
entry
cpb rl0, #%0A !Zeichen = LF ?!
jr nz, PUTA !nein normal Ausgeben!
cp r12, r10 !r12=r10=kein Zeichen eingegeben!
jr z, SET_BOOT !Boot Kommando laden!
ldk r14, #%00 !Kommando ueber CON eingeben setzen!
ldk r0, #%0D !cr lf ausgeben!
calr PUTA
ldk r0, #%0A
end PRINT_CHAR
PUTA procedure
entry
sc #TTWR
ret
end PUTA
!*---------------------------------------------------------------------------*!
!*
* Lesen 1 Block von Disk in Puffer
* Es wird der Disktreiber im Monitor benutzt
*!
!*---------------------------------------------------------------------------*!
READ_DISK procedure
entry
ldk r8, #10 !retries!
LOOP:
dec r15, #6
ldm @r15, r8, #3
ldk r7, #1 !read!
ldk r6, #0 !drive 0!
!in rr4 Blocknummer!
ldk r8, #0 !obere 16 bit der pysischen RAM Adr!
lda r9, DISK_BUFFER !Ladeadr untere 16 bit!
ld r10, #%200 !Laenge!
sc #DISK
ldm r8, @r15, #3
inc r15, #6
test r2 !<> 0 ist Fehler!
ret z
djnz r8, LOOP !10 Versuche!
test r2 !z flag!
ret
end READ_DISK
internal
MSG_PROMPT array [* byte] := '> %00'
MSG_BOOT array [* byte] := 'boot%l'
MSG_ERROR array [* byte] := '?%l%00'
MSG_DERROR array [* byte] := 'DISK ERROR%l%00'
end boot0_md_s

View File

@ -0,0 +1,396 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Module boot0.rm.s (primary bootstrapper)
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:33
Version: 1.1
*******************************************************************************
boot0 remote fuer einen Systemstart von einem Local System
unter dem Betriebssystem UDOS
(primary bootstrapper)
bei autonatischem boot bzw Eingabe von CR bei manuellem
boot nach der Meldung mit > wird das Programm boot
(secundary bootstrapper) von der Diskette des Local Systems
uber den Terminal-Kanal in den Speicher des U8000 Systems
(Segment 0, ab Adresse %8000) geladen.
Bei manuellem boot kann nach der Meldung mit > auch
ein anderer filename eingegeben werden.
boot0 benutzt den U8000 Monitor.
*******************************************************************************
******************************************************************************!
boot0_rm_s module
$SECTION boot0
constant
MOVE_ADR := %F800
LOAD_ADR := %8000
TTIN := %04
TTWR := %06
FLAG0 := %3F0 !relative Adresse zu Beginn Monitor RAM!
SOH := %01
ESC := %1B
ETX := %03
ACK := %06
CAN := %18
STX := %02
EOT := %04
NAK := %15
typ := %01 !binary file!
global
!*---------------------------------------------------------------------------*!
!*
* eigentliches Programm von 8000 auf F800 moven
*!
!*---------------------------------------------------------------------------*!
START procedure
entry
ld r2, #%5800 !nonsegmented Systemmode!
ldctl FCW, r2 !fcw setzen!
ldb rh2, #(MOVE_ADR shr 8)
ldar r1, MAIN !Quelladr!
ld r15, r2
ld r14, #%200
ldirb @r2, @r1, r14
jp @r15
end START
!Dieses Programm ist voll relativ!
!Es wird auf MOVE_ADR gemoved!
!*---------------------------------------------------------------------------*!
!*
* Main Procedure
* Eingabe filename bei manuellem boot
* (bzw Standardname fuer secundary boot bei automatischem boot)
* Uebertragung filename an Local System, warten auf Bestaetigung
* dass file vorhanden, Start der blockweisen Fileuebertragung
* Laden ab Adr 8000 hex, Segment 0
* Starten des Programms
*!
!*---------------------------------------------------------------------------*!
MAIN procedure
entry
pushl @r15, rr6 !Monitor Parameter retten!
pushl @r15, rr4
test r4 !0=automatischer Boot!
jr nz, MAIN_LOOP !manueller Boot r14 ist 0!
ldar r14, MSG_BOOT !autom.:boot Kommando laden!
MAIN_LOOP:
ldar r8, MSG_PROMPT
calr PRINT_MSG
ldar r10, CON_BUFFER
ld r11, r10 !r11 Anf adr Puffer!
inc r11, #%0E !Ende Puffer!
MAIN3:
ld r12, r10 !r12 aktueller Puffer Pointer!
MAIN4:
calr GETA
cpb rl0, #%0A !lf = Ende der Eingabe!
jr z, MAIN5
cpb rl0, #'/' !Eingabe loeschen!
jr z, MAIN3 !Eingabe wiederholen!
ldb @r12, rl0 !Zeichen in Puffer!
inc r12, #%01 !Pointer inc!
cp r12, r11
jr ge, MAIN3 !Eingabe zu lang neu anfangen!
jr MAIN4 !naechstes Zeichen!
MAIN5: !Ende der Eingabe!
clrb @r12 !letztes Byte im Puffer = 0!
!boot file open!
ld r2, r10
calr rmopen
test r1
jr nz, MAIN9
!boot file lesen!
lda r2, LOAD_ADR
ld r9, r2
calr rmread !1. Block der file lesen!
test r1
jr nz, MAIN9 !Fehler!
cp @r9, #%E707 !Magic Nr!
!=nonsegmented, executable!
jr nz, MAIN7 !Fehler falsche Magic!
ld r11, %10(r9) !Entry Point des Programms!
ld r0, #%18 !size header!
add r0, %0A(r9) !size segment table!
ld r10, r9 !LOAD_ADR!
add r9, r0 !Anfangsadr Programmcode!
neg r0
add r0, r6 !%200-header-segmtable!
ldirb @r10, @r9, r0 !Move Code auf LOAD_ADR!
ld r2, r10
calr rmread !alle weiteren Bloecke lesen!
test r1
jr nz, MAIN9 !Fehler!
!Ok!
ld r15, #MOVE_ADR - 8 !Stackpointer fuer Parameter neu setzen!
popl rr4, @r15 !Rueckladen der Monitor Parameter!
popl rr6, @r15
jp @r11 !Sprung zum geladenen Programm!
MAIN7:
calr rmerror
ldar r8, MSG_ERROR !Fehler, neue Kommandoeingabe!
MAIN8:
calr PRINT_MSG
ldk r14, #0 !nanuel boot setzen!
jr MAIN_LOOP
MAIN9:
ldar r8, MSG_NO_LOAD
jr MAIN8 !Fehler!
end MAIN
internal
!*---------------------------------------------------------------------------*!
!*
* Ein- Ausgaben an Local System im Terminalmode
* Fileuebertragung von Local System in Transfer Mode
*!
!*---------------------------------------------------------------------------*!
PRINT_MSG procedure
entry
ldb rl0, @r8
testb rl0
ret z !Ausgabe message bis 00!
calr PRINT_CHAR
inc r8, #%01
jr PRINT_MSG
end PRINT_MSG
SET_BOOT procedure
entry
ldar r14, MSG_BOOT
end SET_BOOT !laeuft in GETA weiter!
GETA procedure
entry
test r14
jr z, GETA1
ldb rl0, @r14 !Zeichen nicht ueber CON!
!sondern aus Message holen!
inc r14, #%01
jr GETA2
!Zeichen von CON holen!
GETA1:
push @r15, r3
sc #TTIN
ld r0, r3
pop r3, @r15
GETA2:
resb rl0, #%07 !reset bit 7!
cpb rl0, #%0D
jr nz, PRINT_CHAR !Zeichen ausgeben!
ldk r0, #%0A !cr in lf!
end GETA !laueft in PRINT_CHAR weiter!
PRINT_CHAR procedure
entry
cpb rl0, #%0A !Zeichen = LF ?!
jr nz, PUTA !nein normal Ausgeben!
cp r12, r10 !r12=r10=kein Zeichen eingegeben!
jr z, SET_BOOT !Boot Kommando laden!
ldk r14, #%00 !Kommando ueber CON eingeben setzen!
ldk r0, #%0D !cr lf ausgeben!
calr PUTA
ldk r0, #%0A
end PRINT_CHAR
PUTA procedure
entry
push @r15, r3
sc #TTWR
pop r3, @r15
ret
end PUTA
!*---------------------------------------------------------------------------*!
!*
* Fileuebertragung mit Local System
*!
!*---------------------------------------------------------------------------*!
!input r2 Pointer zu filename string!
rmopen procedure
entry
ldk r5, #0
ldr rmflag, r5 !init rmflag!
ldctl r5, PSAP
sub r5, #(%400-FLAG0)
setb @r5, #0 !FLAG0 im Monitor RAM setzen!
ldk r0, #SOH !Kommando Send file an local!
sc #TTWR
ldb rl0, #ESC
sc #TTWR
ldb rl0, #'S'
sc #TTWR
sc #TTIN !acknowledge von local!
ldb rl0, #typ !file typ an local!
sc #TTWR
sc #TTIN !acknowledge von local!
!Ausgabe filename an local!
ldb rh7, #10 !retries!
ld r5, r2
rmo0: ldb rl7, #0 !Checksumme init!
ld r2, r5
ldb rl0, #STX !Start of Text!
sc #TTWR
rmo1: ldb rl0 ,@r2 !Zeichen von filename!
inc r2, #1
cpb rl0, #0 !ende filename ?!
jr z, rmo2
xorb rl7, rl0 !Checksumme berechnen!
sc #TTWR
jr rmo1
rmo2: ldb rl0, #ETX !end of text!
sc #TTWR
exb rl0, rl7
sc #TTWR !Checksumme ausgeben!
sc #TTIN !Warten auf Quittung!
resb rl3, #7
cpb rl3, #ACK
ldk r1, #0 !kein Fehler!
ret z !filename richtig uebertragen, file vorhanden!
cpb rl3, #CAN !Abbrechen ?!
jr z, rmerror
dbjnz rh7, rmo0 !naechster Versuch!
end rmopen
rmerror procedure
entry
ldb rl0, #CAN !Abbruch zurueck senden!
sc #TTWR
ld r1, #-1 !Error setzen!
end rmerror
rmclose procedure
entry
sc #TTIN
ldctl r3, PSAP
sub r3, #(%400-FLAG0)
resb @r3, #0 !FLAG0 im Monitor RAM ruecksetzen!
ret
end rmclose
rmread procedure
entry
ldb rh7, #10 !retries!
ldk r1, #0 !kein Fehler!
ldr r0, rmflag
test r0
jr z, rmr0 !Sprung 1.Aufruf!
ldb rl0, #ACK !Ack fuer letzen Aufruf!
sc #TTWR
rmr0: ldb rl7, #0 !Checksumme init!
ld r5, r2 !Buffer Pointer retten!
sc #TTIN
resb rl3, #7
cpb rl3, #EOT
jr z, rmclose !file fertig uebertragen!
cpb rl3, #CAN
jr z, rmerror !local gibt Abbruch!
cpb rl3, #ESC
jr z, rmerror
cpb rl3, #STX !Start of text muss 1.Zeichen sein!
jr nz, rmr2 !warten auf ETX und Uebertragung wiederholen!
sc #TTIN
ldb rh4, rl3 !high count!
sc #TTIN
ldb rl4, rl3 !low count!
ld r6, r4
rmr1: sc #TTIN !Daten lesen!
ldb @r2, rl3 !in Buffer!
inc r2, #1
xorb rl7, rl3 !Checksumme berechnen!
djnz r4, rmr1
rmr2: sc #TTIN !warten auf ETX!
resb rl3, #7
cpb rl3, #ESC
jr z, rmerror
cpb rl3, #CAN
jr z, rmerror
cpb rl3, #ETX
jr nz, rmr2
sc #TTIN !Checksumme!
cpb rl3, rl7 !uebertragene = berechnete ?!
jr nz, rmr3
ldr r0, rmflag
test r0
ldr rmflag, r7 !r7 ist ungleich 0!
jr nz, rmread !naechsten Block!
ret !nur nach 1. Block!
rmr3: decb rh7, #1
jr z, rmerror !Abbruch!
ldb rl0, NAK !n mal wiederholen!
ld r2, r5 !Buffer Pointer auf Anfang zurueck!
sc #TTWR
jr rmr0
end rmread
MSG_PROMPT array [* byte] := '> %00'
MSG_BOOT array [* byte] := 'boot%l'
MSG_ERROR array [* byte] := 'invalid file%l%00'
MSG_NO_LOAD array [* byte] := 'cannot load boot file%l%00'
rmflag word
CON_BUFFER array [%0F byte]
end boot0_rm_s

View File

@ -0,0 +1,383 @@
!******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone Module boot0.ud.s (primary bootstrapper)
Bearbeiter: P. Hoge
Datum: 04/01/87 11:20:40
Version: 1.1
*******************************************************************************
boot0 udos fuer einen Systemstart von den P8000-UDOS
Minidisketten
(primary bootstrapper)
bei automatischem boot bzw Eingabe von CR bei manuellem
boot nach der Meldung mit > wird das Programm boot
(secundary bootstrapper) von der Diskette des UDOS Systems
uber den Koppel-Kanal in den Speicher des U8000 Systems
(Segment 0, ab Adresse %8000) geladen.
Bei manuellem boot kann nach der Meldung mit > auch
ein anderer filename eingegeben werden.
boot0 benutzt den U8000 Monitor.
*******************************************************************************
******************************************************************************!
boot0_ud_s module
$SECTION boot0
constant
MOVE_ADR := %F800
LOAD_ADR := %8000
TTIN := %04
TTWR := %06
UDIN := %20
UDWR := %22
ESC := %1B
ETX := %03
ACK := %06
CAN := %18
STX := %02
EOT := %04
NAK := %15
typ := %01 !binary file!
global
!*---------------------------------------------------------------------------*!
!*
* eigentliches Programm von 8000 auf F800 moven
*!
!*---------------------------------------------------------------------------*!
START procedure
entry
ld r2, #%5800 !nonsegmented Systemmode!
ldctl FCW, r2 !fcw setzen!
ldb rh2, #(MOVE_ADR shr 8)
ldar r1, MAIN !Quelladr!
ld r15, r2
ld r14, #%200
ldirb @r2, @r1, r14
jp @r15
end START
!Dieses Programm ist voll relativ!
!Es wird auf MOVE_ADR gemoved!
!*---------------------------------------------------------------------------*!
!*
* Main Procedure
* Eingabe filename bei manuellem boot
* (bzw Standardname fuer secundary boot bei automatischem boot)
* Uebertragung filename an UDOS System, warten auf Bestaetigung
* dass file vorhanden, Start der blockweisen Fileuebertragung
* Laden ab Adr 8000 hex, Segment 0
* Starten des Programms
*!
!*---------------------------------------------------------------------------*!
MAIN procedure
entry
pushl @r15, rr6 !Monitor Parameter retten!
pushl @r15, rr4
test r4 !0=automatischer Boot!
jr nz, MAIN_LOOP !manueller Boot r14 ist 0!
ldar r14, MSG_BOOT !autom.:boot Kommando laden!
MAIN_LOOP:
ldar r8, MSG_PROMPT
calr PRINT_MSG
ldar r10, CON_BUFFER
ld r11, r10 !r11 Anf adr Puffer!
inc r11, #%0E !Ende Puffer!
MAIN3:
ld r12, r10 !r12 aktueller Puffer Pointer!
MAIN4:
calr GETA
cpb rl0, #%0A !lf = Ende der Eingabe!
jr z, MAIN5
cpb rl0, #'/' !Eingabe loeschen!
jr z, MAIN3 !Eingabe wiederholen!
ldb @r12, rl0 !Zeichen in Puffer!
inc r12, #%01 !Pointer inc!
cp r12, r11
jr ge, MAIN3 !Eingabe zu lang neu anfangen!
jr MAIN4 !naechstes Zeichen!
MAIN5: !Ende der Eingabe!
clrb @r12 !letztes Byte im Puffer = 0!
!boot file open!
ld r2, r10
calr udopen
test r1
jr nz, MAIN9
!boot file lesen!
lda r2, LOAD_ADR
ld r9, r2
calr udread !1. Block der file lesen!
test r1
jr nz, MAIN9 !Fehler!
cp @r9, #%E707 !Magic Nr!
!=nonsegmented, executable!
jr nz, MAIN7 !Fehler falsche Magic!
ld r11, %10(r9) !Entry Point des Programms!
ld r0, #%18 !size header!
add r0, %0A(r9) !size segment table!
ld r10, r9 !LOAD_ADR!
add r9, r0 !Anfangsadr Programmcode!
neg r0
add r0, r6 !%200-header-segmtable!
ldirb @r10, @r9, r0 !Move Code auf LOAD_ADR!
ld r2, r10
calr udread !alle weiteren Bloecke lesen!
test r1
jr nz, MAIN9 !Fehler!
!Ok!
ld r15, #MOVE_ADR - 8 !Stackpointer fuer Parameter neu setzen!
popl rr4, @r15 !Rueckladen der Monitor Parameter!
popl rr6, @r15
jp @r11 !Sprung zum geladenen Programm!
MAIN7:
calr uderror
ldar r8, MSG_ERROR !Fehler, neue Kommandoeingabe!
MAIN8:
calr PRINT_MSG
ldk r14, #0 !nanuel boot setzen!
jr MAIN_LOOP
MAIN9:
ldar r8, MSG_NO_LOAD
jr MAIN8 !Fehler!
end MAIN
internal
!*---------------------------------------------------------------------------*!
!*
* Ein- Ausgaben an UDOS System
*!
!*---------------------------------------------------------------------------*!
PRINT_MSG procedure
entry
ldb rl0, @r8
testb rl0
ret z !Ausgabe message bis 00!
calr PRINT_CHAR
inc r8, #%01
jr PRINT_MSG
end PRINT_MSG
SET_BOOT procedure
entry
ldar r14, MSG_BOOT
end SET_BOOT !laeuft in GETA weiter!
GETA procedure
entry
test r14
jr z, GETA1
ldb rl0, @r14 !Zeichen nicht ueber CON!
!sondern aus Message holen!
inc r14, #%01
jr GETA2
!Zeichen von CON holen!
GETA1:
push @r15, r3
sc #TTIN
ld r0, r3
pop r3, @r15
GETA2:
resb rl0, #%07 !reset bit 7!
cpb rl0, #%0D
jr nz, PRINT_CHAR !Zeichen ausgeben!
ldk r0, #%0A !cr in lf!
end GETA !laueft in PRINT_CHAR weiter!
PRINT_CHAR procedure
entry
cpb rl0, #%0A !Zeichen = LF ?!
jr nz, PUTA !nein noudal Ausgeben!
cp r12, r10 !r12=r10=kein Zeichen eingegeben!
jr z, SET_BOOT !Boot Kommando laden!
ldk r14, #%00 !Kommando ueber CON eingeben setzen!
ldk r0, #%0D !cr lf ausgeben!
calr PUTA
ldk r0, #%0A
end PRINT_CHAR
PUTA procedure
entry
push @r15, r3
sc #TTWR
pop r3, @r15
ret
end PUTA
!*---------------------------------------------------------------------------*!
!*
* Fileuebertragung mit UDOS System
*!
!*---------------------------------------------------------------------------*!
!input r2 Pointer zu filename string!
udopen procedure
entry
ldk r5, #0
ldr udflag, r5 !init udflag!
ldb rl0, #'S' !Kommando Send!
sc #UDWR
sc #UDIN !acknowledge von udos!
ldb rl0, #typ !file typ an udos!
sc #UDWR
sc #UDIN !acknowledge von udos!
!Ausgabe filename an udos!
ldb rh7, #10 !retries!
ld r5, r2
udo0: ldb rl7, #0 !Checksumme init!
ld r2, r5
ldb rl0, #STX !Start of Text!
sc #UDWR
udo1: ldb rl0 ,@r2 !Zeichen von filename!
inc r2, #1
cpb rl0, #0 !ende filename ?!
jr z, udo2
xorb rl7, rl0 !Checksumme berechnen!
sc #UDWR
jr udo1
udo2: ldb rl0, #ETX !end of text!
sc #UDWR
exb rl0, rl7
sc #UDWR !Checksumme ausgeben!
sc #UDIN !Warten auf Quittung!
resb rl3, #7
cpb rl3, #ACK
ldk r1, #0 !kein Fehler!
ret z !filename richtig uebertragen, file vorhanden!
cpb rl3, #CAN !Abbrechen ?!
jr z, uderror
dbjnz rh7, udo0 !naechster Versuch!
end udopen
uderror procedure
entry
ldb rl0, #CAN !Abbruch zurueck senden!
sc #UDWR
ld r1, #-1 !Error setzen!
end uderror
udclose procedure
entry
sc #UDIN
ret
end udclose
udread procedure
entry
ldb rh7, #10 !retries!
ldk r1, #0 !kein Fehler!
ldr r0, udflag
test r0
jr z, udr0 !Sprung 1.Aufruf!
ldb rl0, #ACK !Ack fuer letzen Aufruf!
sc #UDWR
udr0: ldb rl7, #0 !Checksumme init!
ld r5, r2 !Buffer Pointer retten!
sc #UDIN
resb rl3, #7
cpb rl3, #EOT
jr z, udclose !file fertig uebertragen!
cpb rl3, #CAN
jr z, uderror !udos gibt Abbruch!
cpb rl3, #ESC
jr z, uderror
cpb rl3, #STX !Start of text muss 1.Zeichen sein!
jr nz, udr2 !warten auf ETX und Uebertragung wiederholen!
sc #UDIN
ldb rh4, rl3 !high count!
sc #UDIN
ldb rl4, rl3 !low count!
ld r6, r4
udr1: sc #UDIN !Daten lesen!
ldb @r2, rl3 !in Buffer!
inc r2, #1
xorb rl7, rl3 !Checksumme berechnen!
djnz r4, udr1
udr2: sc #UDIN !warten auf ETX!
resb rl3, #7
cpb rl3, #ESC
jr z, uderror
cpb rl3, #CAN
jr z, uderror
cpb rl3, #ETX
jr nz, udr2
sc #UDIN !Checksumme!
cpb rl3, rl7 !uebertragene = berechnete ?!
jr nz, udr3
ldr r0, udflag
test r0
ldr udflag, r7 !r7 ist ungleich 0!
jr nz, udread !naechsten Block!
ret !nur nach 1. Block!
udr3: decb rh7, #1
jr z, uderror !Abbruch!
ldb rl0, NAK !n mal wiederholen!
ld r2, r5 !Buffer Pointer auf Anfang zurueck!
sc #UDWR
jr udr0
end udread
MSG_PROMPT array [* byte] := '> %00'
MSG_BOOT array [* byte] := 'boot%l'
MSG_ERROR array [* byte] := 'invalid file%l%00'
MSG_NO_LOAD array [* byte] := 'cannot load boot file%l%00'
udflag word
CON_BUFFER array [%0F byte]
end boot0_ud_s