new
This commit is contained in:
parent
a094055e97
commit
2adeef252b
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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";
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue