diff --git a/WEGA/src/cmd/BOOT/bconf.c b/WEGA/src/cmd/BOOT/bconf.c new file mode 100644 index 0000000..b0be380 --- /dev/null +++ b/WEGA/src/cmd/BOOT/bconf.c @@ -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 +#include +#include + +/*------------------------------------------ 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 +}; diff --git a/WEGA/src/cmd/BOOT/bfd.c b/WEGA/src/cmd/BOOT/bfd.c new file mode 100644 index 0000000..00327bf --- /dev/null +++ b/WEGA/src/cmd/BOOT/bfd.c @@ -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 +#include +#include + +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); +} diff --git a/WEGA/src/cmd/BOOT/bmch.s b/WEGA/src/cmd/BOOT/bmch.s new file mode 100644 index 0000000..577f9aa --- /dev/null +++ b/WEGA/src/cmd/BOOT/bmch.s @@ -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 %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 diff --git a/WEGA/src/cmd/BOOT/bmd.c b/WEGA/src/cmd/BOOT/bmd.c new file mode 100644 index 0000000..a26575a --- /dev/null +++ b/WEGA/src/cmd/BOOT/bmd.c @@ -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 +#include +#include + +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); +} diff --git a/WEGA/src/cmd/BOOT/bmisc.c b/WEGA/src/cmd/BOOT/bmisc.c new file mode 100644 index 0000000..e14120a --- /dev/null +++ b/WEGA/src/cmd/BOOT/bmisc.c @@ -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; + } + } +} diff --git a/WEGA/src/cmd/BOOT/boot.c b/WEGA/src/cmd/BOOT/boot.c new file mode 100644 index 0000000..493cc73 --- /dev/null +++ b/WEGA/src/cmd/BOOT/boot.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 +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/WEGA/src/cmd/BOOT/brm.s b/WEGA/src/cmd/BOOT/brm.s new file mode 100644 index 0000000..ed726c7 --- /dev/null +++ b/WEGA/src/cmd/BOOT/brm.s @@ -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 diff --git a/WEGA/src/cmd/BOOT/bstart.c b/WEGA/src/cmd/BOOT/bstart.c new file mode 100644 index 0000000..86e3130 --- /dev/null +++ b/WEGA/src/cmd/BOOT/bstart.c @@ -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"; diff --git a/WEGA/src/cmd/BOOT/bsys.c b/WEGA/src/cmd/BOOT/bsys.c new file mode 100644 index 0000000..088f853 --- /dev/null +++ b/WEGA/src/cmd/BOOT/bsys.c @@ -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 +#include +#include +#include +#include +#include + +/*------------------------------------------ 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(); +} diff --git a/WEGA/src/cmd/BOOT/bud.s b/WEGA/src/cmd/BOOT/bud.s new file mode 100644 index 0000000..90ac665 --- /dev/null +++ b/WEGA/src/cmd/BOOT/bud.s @@ -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 diff --git a/WEGA/src/cmd/BOOT/create.boot b/WEGA/src/cmd/BOOT/create.boot new file mode 100755 index 0000000..a72247d --- /dev/null +++ b/WEGA/src/cmd/BOOT/create.boot @@ -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 diff --git a/WEGA/src/cmd/BOOT/sa.function.s b/WEGA/src/cmd/BOOT/sa.function.s new file mode 100644 index 0000000..af197c4 --- /dev/null +++ b/WEGA/src/cmd/BOOT/sa.function.s @@ -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 diff --git a/WEGA/src/cmd/BOOT0/boot0.fd.s b/WEGA/src/cmd/BOOT0/boot0.fd.s new file mode 100644 index 0000000..d1102dc --- /dev/null +++ b/WEGA/src/cmd/BOOT0/boot0.fd.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 diff --git a/WEGA/src/cmd/BOOT0/boot0.md.s b/WEGA/src/cmd/BOOT0/boot0.md.s new file mode 100644 index 0000000..0220e37 --- /dev/null +++ b/WEGA/src/cmd/BOOT0/boot0.md.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 diff --git a/WEGA/src/cmd/BOOT0/boot0.rm.s b/WEGA/src/cmd/BOOT0/boot0.rm.s new file mode 100644 index 0000000..94f057f --- /dev/null +++ b/WEGA/src/cmd/BOOT0/boot0.rm.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 diff --git a/WEGA/src/cmd/BOOT0/boot0.ud.s b/WEGA/src/cmd/BOOT0/boot0.ud.s new file mode 100644 index 0000000..4316b53 --- /dev/null +++ b/WEGA/src/cmd/BOOT0/boot0.ud.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