summaryrefslogtreecommitdiff
path: root/system/shard-x86-at/7/src
diff options
context:
space:
mode:
Diffstat (limited to 'system/shard-x86-at/7/src')
-rw-r--r--system/shard-x86-at/7/src/ATSHARD.ASM156
-rw-r--r--system/shard-x86-at/7/src/BLOCKERR.ASM82
-rw-r--r--system/shard-x86-at/7/src/BOOT.ASM426
-rw-r--r--system/shard-x86-at/7/src/CLOCK.ASM56
-rw-r--r--system/shard-x86-at/7/src/DEVICE.ASM92
-rw-r--r--system/shard-x86-at/7/src/EUCONECT.ASM80
-rw-r--r--system/shard-x86-at/7/src/FDISK.ASM839
-rw-r--r--system/shard-x86-at/7/src/FIXDISK.ASM307
-rw-r--r--system/shard-x86-at/7/src/FLOPPY.ASM454
-rw-r--r--system/shard-x86-at/7/src/FSHARD.ASM223
-rw-r--r--system/shard-x86-at/7/src/HARDWARE.ASM17
-rw-r--r--system/shard-x86-at/7/src/HDISK.ASM482
-rw-r--r--system/shard-x86-at/7/src/HSHARD.ASM242
-rw-r--r--system/shard-x86-at/7/src/I8250.ASM437
-rw-r--r--system/shard-x86-at/7/src/MAC286.ASM23
-rw-r--r--system/shard-x86-at/7/src/MACROS.ASM80
-rw-r--r--system/shard-x86-at/7/src/NILCHAN.ASM54
-rw-r--r--system/shard-x86-at/7/src/PATCH.ELA500
-rw-r--r--system/shard-x86-at/7/src/PATCHARE.ASM17
-rw-r--r--system/shard-x86-at/7/src/PCPAR.ASM226
-rw-r--r--system/shard-x86-at/7/src/PCPLOT.ASM430
-rw-r--r--system/shard-x86-at/7/src/PCSCREEN.ASM438
-rw-r--r--system/shard-x86-at/7/src/PCSYS.ASM131
-rw-r--r--system/shard-x86-at/7/src/SHMAIN.ASM241
-rw-r--r--system/shard-x86-at/7/src/STREAM.ASM290
-rw-r--r--system/shard-x86-at/7/src/WAIT.ASM176
26 files changed, 6499 insertions, 0 deletions
diff --git a/system/shard-x86-at/7/src/ATSHARD.ASM b/system/shard-x86-at/7/src/ATSHARD.ASM
new file mode 100644
index 0000000..f2f198c
--- /dev/null
+++ b/system/shard-x86-at/7/src/ATSHARD.ASM
@@ -0,0 +1,156 @@
+ page 80,132
+title AT-SHard, Copyright (C) 1985, 86 Martin Schoenbeck, Spenge
+;******************************************************************************
+;* *
+;* S H A R D - M O D U L *
+;* *
+;* fuer EUMEL auf 80286 Systemen *
+;* *
+;* SHard Version 7-PC/AT *
+;* *
+;* Copyright (C) 1985, 86 Martin Schoenbeck, Spenge *
+;* *
+;******************************************************************************
+
+at equ 1
+gensys equ 0
+ramsys equ 0
+pcxt equ 0
+pcd equ 0
+kompatible equ 0
+romharddisk equ 0
+romfloppy equ 0
+limited_to_360 equ 0
+boot_size equ 0
+
+hdsystem equ 1
+withhd equ 1
+
+setup_channel equ 28
+dos_channel equ 29
+
+shard group code
+code segment word public 'code'
+ assume cs:shard, ds:shard, es:nothing, ss:nothing
+
+shstart:
+ jmp los_gehts
+
+ even
+
+ include MACROS.ASM
+ include MAC286.ASM
+ include DEVICE.ASM
+ include EUCONECT.ASM
+ org 0a0h ;bei wort 80 beginnen
+ include PATCHARE.ASM
+
+ include SHMAIN.ASM
+
+IBMat equ 0fch
+com1base equ 03f8h
+com1irq equ 4
+com2base equ 02f8h
+com2irq equ 3
+com3base equ 03e8h
+com3irq equ 3
+com4base equ 82f8h
+com4irq equ 7
+com4_1base equ 02c0h
+com4_1irq equ 3
+com4_2base equ 02c8h
+com4_2irq equ 3 Šcom4_3base equ 02d0h
+com4_3irq equ 3
+com4_4base equ 02d8h
+com4_4irq equ 3
+com8_1base equ 02e0h
+com8_1irq equ 3
+com8_2base equ 02e8h
+com8_2irq equ 3
+com8_3base equ 02f0h
+com8_3irq equ 3
+com8_4base equ 02f8h
+com8_4irq equ 3
+para1base equ 3bch
+para1irq equ 7
+
+int_ctlr equ 20h
+first_ictlr_int equ 8
+
+channel macro number,dev,ccb
+channels = channels+1
+selectentry = 5
+ db number
+ dw offset ccb
+ if2
+ dwb paramstart_,%&dev
+ else
+ dw 0 ;;weil in pass eins device evtl. unbekannt
+ endif
+ endm
+
+selecttable:
+ db channels ;anzahl kanaele hier setzen
+channels = -1 ;nilchannel vorab abziehen
+ channel 32,shardchannel,0
+ channel 0,fixdisk,hgccb0
+alterable_channels:
+ channel 1,pc,0
+ channel 2,i8250,com1ccb
+ channel 3,i8250,com2ccb
+ channel 4,i8250,com4_1ccb
+ channel 5,i8250,com4_2ccb
+ channel 6,i8250,com4_3ccb
+ channel 7,i8250,com4_4ccb
+ channel 8,i8250,com8_1ccb
+ channel 9,i8250,com8_2ccb
+ channel 10,i8250,com8_3ccb
+ channel 12,parallel,para1ccb
+ channel 28,fixdisk,hgccb1
+ channel 29,fixdisk,hgccb2
+ channel 31,archive,archive_0
+ channel 30,archive,archive_1
+ channel -1,nilchannel,0
+ Š include I8250.ASM
+ include PCPAR.ASM
+ include STREAM.ASM
+ include NILCHAN.ASM
+ include PCSCREEN.ASM
+ include PCPLOT.ASM
+ include PCSYS.ASM
+ include FIXDISK.ASM
+ include FLOPPY.ASM
+ include CLOCK.ASM
+ include WAIT.ASM
+ include HARDWARE.ASM
+ include BLOCKERR.ASM
+
+ i8250_ccb com1,2
+ i8250_ccb com2,3
+ i8250_ccb com4_1,4
+ i8250_ccb com4_2,5
+ i8250_ccb com4_3,6
+ i8250_ccb com4_4,7
+ i8250_ccb com8_1,8
+ i8250_ccb com8_2,9
+ i8250_ccb com8_3,10
+ para_ccb para1,12
+ ;erlaubt drivetypen: highdensity, drive720
+ archive_ccb 0,highdensity
+ archive_ccb 1,0
+ fix_ccb 0
+ fix_ccb 1
+ fix_ccb 2
+
+sysmove:
+ rep movsw
+ jmp systemstart
+
+ include BOOT.ASM
+
+code ends
+
+ end los_gehts
+
+
+
diff --git a/system/shard-x86-at/7/src/BLOCKERR.ASM b/system/shard-x86-at/7/src/BLOCKERR.ASM
new file mode 100644
index 0000000..fb17016
--- /dev/null
+++ b/system/shard-x86-at/7/src/BLOCKERR.ASM
@@ -0,0 +1,82 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Dieses Modul enthaelt Routinen zur Uebergabe von Fehlermeldungen *
+;* nach Blockin/Blockout *
+;* *
+;* blockerr erwartet dabei folgende codes in ah: *
+sense_fail equ 0ffh ; sense operation
+blnrhigh equ 0feh ; block number to high
+write_fault equ 0cch ;
+not_rdy equ 0aah ; drive not ready
+undef_err equ 0bbf ; undefined error occurred
+time_out equ 80h ; attachment failed to respond
+bad_seek equ 40h ; seek operation failed
+bad_cntlr equ 20h ; controller has failed
+data_corrected equ 11h ; ecc corrected data error
+bad_ecc equ 10h ; bad ecc on disk read
+bad_crc equ 10h ; crc error on sector
+bad_track equ 0bh ; bad track flag detected
+bad_sect equ 0ah ; sector marked bad
+dma_boundary equ 9 ; attempt to dma across 64k
+bad_dma equ 8 ; dma failed
+init_fail equ 7 ; drive parameter activity failed
+bad_reset equ 5 ; reset failed
+record_not_fnd equ 4 ; requested sector not found
+write_protect equ 3 ; disk write protected
+bad_addr_mark equ 2 ; address mark not found
+bad_cmd equ 1 ; bad command passed to disk i/o
+;* *
+;****************************************************************************
+
+blockerr:
+ pop bp ;return adresse holen
+ pop dx ;ds:bx vom stack putzen
+ pop dx
+ mov bx,offset messagetable ;tabelle mit meldungen holen
+ mov dh,0 ;laengenangaben sind nur ein byte
+err_loop:
+ mov al,byte ptr [bx] ;fehlerschluessel holen
+ inc bx
+ cmp al,ah ;war das der gesuchte
+ jz err_found ;ja
+ inc al ;oder ende der tabelle
+ jz err_found ;ja
+ inc bx ;auf laengenbyte
+ mov dl,byte ptr [bx] ;laenge holen
+ add bx,dx ;adresse des naechsten textes
+ inc bx ;und ueber laengenbyte rueber
+ jmp err_loop
+
+err_found:
+ mov cl,byte ptr [bx]
+ mov ch,0 ;nur ein byte fehlercodes
+ inc bx ;auf textlaenge gehen
+ push cs ;adresse fehlermeldung drauf
+ push bx
+ jmp bp
+
+highblock:
+ mov ah,blnrhigh ;meldung blocknummer zu hoch
+ jmp blockerr
+
+err_mess macro code,eucode,mess
+local m_end
+ db code,eucode,m_end-$-1,mess
+m_end:
+ endm
+
+messagetable:
+ err_mess blnrhigh,3,'blocknummer zu hoch'
+ err_mess not_rdy,1,'not ready'
+ err_mess bad_crc,2,'crc err'
+ err_mess bad_sect,2,'bad sect'
+ err_mess record_not_fnd,2,'rec not fnd'
+ err_mess dma_boundary,1,'dma boundary'
+ err_mess time_out,2,'timeout'
+ err_mess 0ffh,2,'undef_err_code'
+
+
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/BOOT.ASM b/system/shard-x86-at/7/src/BOOT.ASM
new file mode 100644
index 0000000..e13c805
--- /dev/null
+++ b/system/shard-x86-at/7/src/BOOT.ASM
@@ -0,0 +1,426 @@
+;*****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ===================*
+;* *
+;* Laden des EUMEL - Restsystems vom Archiv oder HG *
+;* *
+;*****************************************************************************
+
+; Versionsschluessel:
+;2.2 enthaelt mehrere Partition, Floppy size = 0 bei start und fehler
+;2.3 enhaelt Floppy mit Block 0 lesen immer erlaubt
+;2.4 Drucker geht ueber rom, wenn adresse nicht ibmlike
+; mehrere Drucker moeglich
+; busy Abfrage kann verzoegert werden (Problem LQ1000)
+; es werden nur die vorhandenen Schnittstellen angezeigt
+; Lesezugriffe bis Block 6 auf Floppy werden immer erlaubt
+;2.5 Hercules Karte wird unterstuetzt
+; Bei AT werden schlechte sectoren statt spuren behandelt
+;2.6 Fehler in PlattengrӇe bei behoben (meldete immer al <> 0)
+;2.7 Floppylogik fuer 1.7.3 restauriert, Floppy steht jetzt immer
+; auf 360k, wenn keine Floppy erkannt wird, und der Urlader die
+; HG-Version 1742 hat.
+; die Schnittstellen der Addonics-Karte sind jetzt immer mit drin,
+; wenn COM4 generiert sind.
+; Die Druckerkan„le liegen auf 15,14,16
+; Die Baudrateabfrage verneint auch 0
+
+los_gehts:
+ cli
+; achtung: es und si muessen bis zum einstellen der Festplatte
+; unveraendert bleiben !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ mov ax,cs
+ mov ds,ax
+; cs in vorlaeufige EUMEL Tabelle eintragen
+ mov bx,offset systemstart+2
+ mov cx,eumel_cs_init_length
+self_cs_init_loop:
+ mov word ptr [bx],ax
+ add bx,4
+ loop self_cs_init_loop
+; cs in SHard - Tabelle eintragen
+ mov bx,offset first_shard_cs_to_alter
+ mov cx,shard_cs_alter_length
+shard_cs_init_loop:
+ mov word ptr [bx],cs ;put in my code segment
+ add bx,4
+ loop shard_cs_init_loop
+; berechnen, wohin der EUMEL spaeter soll
+ mov bx,offset lastbootbyte ;relativen paragraph ausrechnen
+ mov cl,4
+ shr bx,cl
+ inc bx
+ add ax,bx ;hier soll spaeter der EUMEL hin
+ mov ss,ax
+ mov sp,0
+ push si ;werte fuer plattensetup merken
+ push es
+; warte routine fuer Platten und Floppytreiber eintragen
+ call device_init ;int 15 eintragen
+; alle Kanaele initialisieren
+ mov dh,33
+ mov al,0
+inilop:
+ mov cx,-2
+ push ax
+ call control32
+ pop ax
+ cli
+ inc al
+ dec dh
+ jnz inilop
+ sti ;interrupts sind erlaubt
+ mov bx,offset signon ;sag ihm, wer wir sind
+ call print
+; alle kanaele fuer festplatte einstellen (falls vorhanden)
+ pop es
+ pop si ;zeiger auf partitiontabelle wiederholen
+ call setup_fix_disk
+; EUMEL 0 laden
+getagain:
+ ife gensys
+ mov al,31 ;zuerst von kanal 31 versuchen
+ mov bx,offset archtext
+ call geteumel
+ endif
+ mov al,0
+ mov bx,offset hgtext
+ call geteumel
+ mov bx,offset noeutext
+ call print
+ call waitchar
+ jmp getagain
+
+geteumel: ;EUMEL 0 laden und bei Erfolg starten
+ push ax
+ mov cx,5 ;size
+ call cs:iocontrol
+ pop ax
+ push bx ;text fuer medium merken
+ mov cx,ss ;ausrechnen, wohin der urlader muss (ss:0)
+ add cx,31 ;damit wir nicht rueckwaerts gehen
+ and cx,0ffe0h ;auf 512 byte boundary
+ mov ds,cx ;segment nach ds
+ mov bx,0 ;bei 0 im segment laden wir zuerst
+ mov cx,0 ;auftrag
+ mov dx,10 ;erster urlader block ist 10
+ mov ah,1 ;nur ein versuch
+ cmp al,0
+ ifz <mov ah,3> ;hintergrund muss lesbar sein
+ push bx
+ push ds
+ call getblock
+ pop ds
+ pop bx
+ or cx,cx ;fehlerfrei?
+ jz firstok
+ pop bx ;text fuer medium vergessen
+ ret
+firstok:
+ push ax
+ mov cx,5 ;text EUMEL hat 5 buchstaben
+ mov si,offset eutext ;text EUMEL
+ mov di,bx ;puffer
+textloop:
+ lods byte ptr cs:[si]
+ cmp al,byte ptr ds:[di]
+ jz charok
+ pop ax ;stack saeubern
+ pop bx
+ ret ;nicht gleich, kein eumel urlader
+charok:
+ inc di
+ loop textloop
+ pop ax ;kanal fuer urlader wiederholen
+ pop bx ;text fuer medium holen
+ call print ;ausgeben
+ mov bx,0 ;bx ist zerstoert, aber wir wissen, wohin
+ mov ah,8 ;ab hier mit acht versuchen
+euloop:
+ mov cx,0
+ inc dx
+ add bx,512 ;auf naechsten block schalten
+ push bx
+ push ds
+ call getblock
+ or cx,cx
+ jnz booterr
+ pop ds
+ pop bx
+ cmp dx,10+100 ;schon kompletten urlader gelesen
+ jnz euloop
+; Sprungleiste vom EUMEL abholen
+ push cs
+ pop es ;ziel ist codesegment
+ mov si,0
+ mov di,offset eumel0id
+ mov cx,eumel_leisten_laenge
+ cli
+ cld
+ rep movsb
+ mov ax,ds ;eumel codesegment nach ax
+ push cs ;datensegment wieder auf shard
+ pop ds
+; und passendes cs eintragen
+ mov bx,offset systemstart+2
+ mov cx,eumel_cs_init_length
+eumel_cs_init_loop:
+ mov word ptr [bx],ax
+ add bx,4
+ loop eumel_cs_init_loop
+ call paragraphs
+ sub dx,ax ;rest fuer eumel ausrechnen
+ if ramsys
+ urram equ 1000h
+
+ sub dx,urram ;64k fuer urlader und paging
+ mov M3SIZE,dx
+ mov M0SIZE,urram
+ mov M0START,ax
+ add ax,urram
+ mov M3START,ax
+ else
+ mov M0SIZE,dx
+ mov M0START,ax ;eumel codesegment eintragen
+ endif
+ mov ax,31 ;allen floppies die chance geben
+i173lop: ;sich auf 173 einzustellen
+ mov cx,-173
+ push ax
+ call control32
+ pop ax
+ dec al
+ jnz i173lop
+ mov bx,offset SHard_leiste
+ jmp systemstart
+
+
+booterr:
+ push ds
+ push bx
+ mov bx,offset booterrtext
+ call print
+ pop bx
+ pop ds
+ call dsprint
+ jmp $
+
+getblock:
+ push ax ;original ax merken
+getloop:
+ push bx
+ push ds
+ push ax ;ax mit retry zaehler
+ mov cx,0
+ call cs:blockin
+ pop ax
+ or cx,cx
+ jnz geterr
+ pop ds
+ pop bx
+ pop ax
+ ret
+geterr:
+ dec ah ;genuegend retries
+ jnz getcontinue
+ pop ax ;kill ds
+ pop ax ;kill bx
+ pop ax ;altes ax holen
+ ret
+getcontinue:
+ pop ds
+ pop bx
+ jmp getloop
+
+waitchar:
+ sti
+ mov byte ptr cs:waschar,0
+waitcloop:
+ cmp byte ptr cs:waschar,0
+ jz waitcloop
+ ret
+
+iint proc far
+ cmp al,1 ;nur kanal 1 ist interessant
+ ifnz <ret>
+ mov byte ptr cs:waschar,1
+ ret
+iint endp
+
+waschar db 0
+
+print:
+ push ds
+ push cs
+ pop ds
+ call dsprint
+ pop ds
+ ret
+
+dsprint:
+ push cx
+ push ax
+ mov cl,byte ptr [bx] ;laenge holen
+ inc bx ;auf text schalten
+ mov ch,0
+ mov al,1 ;auf terminal 1
+ call cs:output
+ pop ax
+ pop cx
+ ret
+
+setup_fix_disk:
+ if hdsystem
+ mov di,si ;si retten
+ mov dl,4
+eumel_partition_search_loop:
+ test byte ptr es:[si],80h ;aktivierte Partition
+ jnz eu_found
+ add si,10h
+ dec dl
+ jnz eumel_partition_search_loop
+; keine EUMEL Partition, Sauerei
+no_eu_part:
+ mov bx,offset no_eumel_partition_text
+ call print
+ sti
+ jmp $
+
+eu_found:
+ cmp byte ptr es:[si+4],'E' ;EUMEL partition
+ jc no_eu_part
+ mov dx,es:[si+8] ;low word partition start holen
+ mov bx,es:[si+10] ;high word partition start holen
+ add dx,68 ;50k fuer shard etc. frei lassen
+ adc bl,0
+ mov cx,-101 ;partition start einstellen
+ mov al,0 ;fuer HG
+ call control32
+ mov cx,-100 ;dasselbe als groesse fuer Setup Kanal
+ mov al,setup_channel
+ call control32
+ mov dx,es:[si+12] ;low word partition size holen
+ mov bx,es:[si+14] ;high word partition size holen
+
+ if at
+ sub dx,68 ;platz fuer SHard
+ sbb bl,0
+ sub dx,[bb_anz] ;platz fuer schlechte sectoren lassen
+ sbb bl,0
+ else
+ sub dx,68+(2*68) ;das, was wir fuers SHard lassen, abziehen
+ ;und das, was fuer schlechte spuren bleiben muss
+ sbb bl,0
+ endif
+
+ mov cx,-100 ;size einstellen
+ mov al,0 ;fuer hg
+ call control32
+; DOS partition suchen
+ mov si,di ;si wieder holen
+ mov dl,4
+dos_partition_search_loop:
+ cmp byte ptr es:[si+4],1 ;DOS partition
+ jz dos_found
+ add si,10h
+ dec dl
+ jnz dos_partition_search_loop
+ xor dx,dx
+ mov bx,dx ;DOS Partition existiert nicht
+ jmp short dos_size
+dos_found:
+ mov dx,es:[si+8] ;low word partition start holen
+ mov bx,es:[si+10] ;high word partition start holen
+ mov cx,-101 ;partition start einstellen
+ mov al,dos_channel ;fuer DOS
+ call control32
+ mov dx,es:[si+12] ;low word partition size holen
+ mov bx,es:[si+14] ;high word partition size holen
+dos_size:
+ mov cx,-100 ;size einstellen
+ mov al,dos_channel ;fuer DOS
+ call control32
+ endif
+ ret
+
+ if 0
+ mov ax,0
+ mov cx,5
+ call cs:iocontrol ;get size of harddisk
+ if mit_msdos
+ mov bx,17068
+ else
+ mov bx,100 ;50k freilassen
+ endif
+ sub cx,bx ;von size abziehen
+ cmp cx,0fd00h shr 1 ;bei mehr legt sich eumel auf den bauch
+ ifnc <mov cx,0fcfeh shr 1> ;dann nur soviel, wie er kann
+ mov dx,cx ;in dx melden
+ mov cx,-100 ;set size
+ call control32
+ ret
+ endif
+
+eutext:
+ db 'EUMEL'
+
+signon:
+ db booterrtext-$-1
+ if pcd
+ db 1bh,5bh,'H',1bh,5bh,'2J'
+ db 13,10,10
+ db 'Demo - SHard f',129,'r EUMEL auf Siemens PC-D, V 2.1'
+ db 13,10
+ db 'Copyright (C) 1985,86 Martin Sch',148,'nbeck, Spenge'
+ db 13,10
+ else
+ if gensys
+ db 13,10,10
+ db 'Setup - SHard f',129,'r EUMEL'
+ db ' auf IBM PC,AT,XT und Kompatiblen V 2.7'
+ db 13,10
+ db 'Copyright (C) 1985,86 Martin Sch',148,'nbeck, Spenge'
+ db 13,10
+ else
+ if at
+ db 13,10,10
+ db 'SHard f',129,'r EUMEL auf IBM PC/AT, V 2.7'
+ db 13,10
+ db 'Copyright (C) 1985,86 Martin Sch',148,'nbeck, Spenge'
+ db 13,10
+ else
+ db 13,10,10
+ db 'ModSoft - SHard f',129,'r EUMEL'
+ db ' auf IBM-PC und Kompatiblen, Version 2.7'
+ db 13,10
+ db 'Copyright (C) 1985,86 ModSoft, Martin Sch',148,'nbeck'
+ db 13,10
+ endif
+ endif
+ endif
+
+booterrtext:
+ db archtext-$-1
+ db 'Fehler beim Laden des Systems: '
+ db 7
+archtext:
+ db hgtext-$-1
+ db 'EUMEL wird vom Archiv geladen'
+ db 13,10
+hgtext:
+ db noeutext-$-1
+ db 'EUMEL wird vom Hintergrund geladen'
+ db 13,10
+noeutext:
+ db no_eumel_partition_text-$-1
+ db 'Kein EUMEL - System gefunden'
+ db 13,10
+ db 'Bitte einlegen und Taste dr',129,'cken! '
+no_eumel_partition_text:
+ db endtext-$-1
+ db 'Keine EUMEL Partition auf der Platte'
+ db 13,10
+ db 'Bitte benutzen Sie Ihre Setup-Floppy zum Anlegen'
+endtext:
+
+lastbootbyte:
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/CLOCK.ASM b/system/shard-x86-at/7/src/CLOCK.ASM
new file mode 100644
index 0000000..b70f18e
--- /dev/null
+++ b/system/shard-x86-at/7/src/CLOCK.ASM
@@ -0,0 +1,56 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Lesen der Echtzeituhr des IBM PC-AT *
+;* Schreiben dummy routine *
+;* Aufruf: blockin/blockout mit code -4 ueber kanal 32 *
+;* Puffer: ROW 7 INT VAR *
+;* *
+;****************************************************************************
+
+clockread:
+ call hardware
+ cmp al,IBMat ;haben wir den IBM PC-AT
+ jnz no_clock
+ mov ah,4 ;read date
+ int 1ah
+ jc no_clock
+ mov al,ch ;jahrhundert
+ call putbcd ;ueber bx wegschreiben
+ mov al,cl ;jahr
+ call putbcd
+ mov al,dh ;monat
+ call putbcd
+ mov al,dl ;tag
+ call putbcd
+ mov ah,2 ;read time
+ int 1ah
+ jc no_clock
+ mov al,ch ;stunden
+ call putbcd
+ mov al,cl ;minuten
+ call putbcd
+ mov al,dh ;sekunden
+ call putbcd
+ mov cx,0 ;keine fehler
+ ret
+
+no_clock:
+ mov cx,-1 ;geht nicht
+ ret
+
+clockwrite:
+ mov cx,-1
+ ret
+
+putbcd:
+ mov ah,al
+ and ah,0fh ;in al niedrige nibble behalten
+ ib shr al,4 ;rueberschieben
+ or ax,3030h ;ziffern draus machen
+ mov word ptr es:[bx],ax ;eintragen
+ inc bx
+ inc bx ;zum naechsten
+ ret
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/DEVICE.ASM b/system/shard-x86-at/7/src/DEVICE.ASM
new file mode 100644
index 0000000..0800a67
--- /dev/null
+++ b/system/shard-x86-at/7/src/DEVICE.ASM
@@ -0,0 +1,92 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Macros zur Definition von devicetypecontrolblocks und *
+;* bestimmten channelcontrolblock Eintraegen *
+;* *
+;***************************************************************************
+ .xlist
+
+actualdevice = 0
+
+device macro type
+ if1
+ ifdef type
+ .printx * device type doppelt definiert *
+ endif
+ endif
+actualdevice = actualdevice+1
+type = actualdevice
+
+ endm
+
+routine macro code,execut
+ db code
+ dw offset execut
+ endm
+
+dtcbroutines macro type
+ ifidn <type>,<blockin>
+ buildlabel blockin_,%actualdevice
+ else
+ ifidn <type>,<blockout>
+ buildlabel blockout_,%actualdevice
+ else
+ ifidn <type>,<iocontrol>
+ buildlabel iocontrol_,%actualdevice
+ else
+ ifidn <type>,<control32>
+ buildlabel control32_,%actualdevice
+ else
+ .printx * unbekannter routinentyp: '&type' in dctbroutine *
+ endif
+ endif
+ endif
+ endif
+ endm
+
+dtcbparams macro output,typ
+ buildlabel paramstart_,%actualdevice
+ dw offset output
+ dbbp blockin_,%actualdevice
+ dbbp blockout_,%actualdevice
+ dbbp iocontrol_,%actualdevice
+ dbbp control32_,%actualdevice
+dtcbentry devtype
+ db typ
+ endm
+
+dtcbentry macro entry
+ xequat entry,%actualdevice
+ endm
+
+dwb macro first,second
+ dw offset first&second
+ endm
+
+dbbp macro first,second
+ db first&second-paramstart_&second
+ endm
+
+xequat macro entry,dev
+entry = $-paramstart_&dev
+ endm
+
+buildlabel macro first,second
+first&second:
+ endm
+
+startccb macro name,kanal
+name:
+actccb = $
+ccbentry channel_no
+ db kanal
+ endm
+
+ccbentry macro entry
+entry = $-actccb
+ endm
+
+ .list
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/EUCONECT.ASM b/system/shard-x86-at/7/src/EUCONECT.ASM
new file mode 100644
index 0000000..9d1133c
--- /dev/null
+++ b/system/shard-x86-at/7/src/EUCONECT.ASM
@@ -0,0 +1,80 @@
+;======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =============
+;---------------------------------------------------------------------
+ even
+
+eumel0id db 'EUMEL '
+eumel0blocks dw 100
+hgver dw 1742
+cputype dw 3 ; 8086
+urver dw 100
+ dw 0
+shdvermin dw 7
+shdvermax dw 7
+ dw 0
+systemstart dd dummy_ret
+inputinterrupt dd iint
+timerinterrupt dd dummy_ret
+warte dd dummy_ret
+grab dd dummy_ret
+free dd dummy_ret
+shutup dd dummy_ret
+info dd dummy_ret
+eumel_cs_init_length equ ($-systemstart)/4
+eumel_leisten_laenge equ $-eumel0id
+
+;---------------------------------------------------------------------
+;
+; SHard-Leiste
+;
+;---------------------------------------------------------------------
+
+SHard_leiste:
+SHDID db 'SHard Schoenbeck'
+SHDVER dw 7
+ if withhd or at
+MODE dw 0
+ else
+MODE dw 1 ;freieumel0
+ endif
+ID4 dw 4711
+ID5 dw 4712
+ID6 dw 0
+ID7 dw 0
+ dw 0
+ dw 0
+output label dword
+ dw offset i_output
+first_shard_cs_to_alter:
+ dw 0
+blockin label dword
+ dw offset i_blockin
+ dw 0
+blockout label dword
+ dw offset i_blockout
+ dw 0
+iocontrol label dword
+ dw offset i_iocontrol
+ dw 0
+sysend label dword
+ dw offset i_sysend
+ dw 0
+ dd 0
+ dd 0
+ dd 0
+shard_cs_alter_length equ ($-first_shard_cs_to_alter)/4
+M0START dw 0
+M0SIZE dw 0
+M1START dw 0
+M1SIZE dw 0
+M2START dw 0
+M2SIZE dw 0
+M3START dw 0
+M3SIZE dw 0
+
+shdveclen equ offset shdid-offset m3size+2
+
+dummy_ret proc far
+ sti
+ ret
+dummy_ret endp
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/FDISK.ASM b/system/shard-x86-at/7/src/FDISK.ASM
new file mode 100644
index 0000000..1ada045
--- /dev/null
+++ b/system/shard-x86-at/7/src/FDISK.ASM
@@ -0,0 +1,839 @@
+;-----------------------------------------------------------------------
+; Disketten I/O
+; Input:
+; (ah)=0 Reset Diskette System
+; hard reset to nec, prepare command, recal rquired
+; on all drives
+; (ah)=1 read the status of the system into (al)
+; diskette_status from last operation is used
+;
+; Registers for read/write/verify/format
+; (dl) drive number (0-3 allowed, vlue checked)
+; (dh) head number (0-1 allowed, not value checked)
+; (ch) track number (0-39, not value checked)
+; (cl) sektor number (1-8, not value checked,
+; not used for format)
+; (al) number of sektors ( max = 8, not value checked,
+; not used for format
+; (es:bx) address of buffer (not required for verify)
+; (ah)=2 read the desired sektors into memory
+; =3 write
+; =4 verify
+; =5 format
+; for the format operation, the buffer pointer (es,bx)
+; must point to the collektion of desired address fields
+; for the track. Each field is composed of 4 Bytes,
+; (c,h,r,n) where c = track number, h=head number,
+; r = sektor number, n = number of bytes per sektor
+; (00=128, 01=256, 02=512, 03=1024). There must be one
+; entry for every sektor on the track. This information
+; is used to find the requested sektor during read/write
+; access.
+;
+; Data Variable -- disk_pointer
+; double word pointer to the current set of diskette parameters
+; Output
+; ah = status of Operation
+; Status bits are defined in the equates for
+; Diskette_status variable in the data segment of this
+; module.
+; cy = 0 successful operation (ah = 0 on return)
+; cy = 1 failed operation (ah has error reason)
+; for read/write/verify
+; ds,bx,dx,ch,cl reserved
+; al = number of sektors actually read
+; ***** al may not be correkt if time out error occurs
+; note: if an error is reported by the diskette code, the
+; appropriate action is to reset the diskette, then retry
+; the operation, on read access, no motor start delay
+; is taken, so that three retries are required on reads
+; to ensure that the problem is not due to motor
+; start-up.
+;-----------------------------------------------------------------------
+
+ data segment at 40h
+ org 3eh
+seek_status db ?
+int_flag equ 80h
+motor_status db ?
+motor_count db ?
+motor_wait equ 37
+diskette_status db ?
+nec_status db 7 dup(?)
+
+ data ends
+
+ assume ds:data
+
+ ife withhd
+dma equ 0 ; dma address
+dma_high equ 82h ; port for high 4 bits of dma
+ endif
+
+
+diskette_io proc near
+ sti
+ push bx
+ push cx
+ push ds
+ push si
+ push di
+ push bp
+ push dx
+ mov bp,sp ; set up pointer to head parm
+ mov si,data
+ mov ds,si
+ call j1 ; call the rest to ensure ds restored
+ mov bx,4 ; get the motor wait parameter
+ call get_parm
+ mov motor_count,ah ; set the timer count for the motor
+ mov ah,diskette_status ; get status of operation
+ cmp ah,1 ; set the carry flag to indicate
+ cmc ; success or failure
+ pop dx
+ pop bp
+ pop di
+ pop si
+ pop ds
+ pop cx
+ pop bx
+ ret
+diskette_io endp
+
+j1 proc near
+ mov dh,al
+ and motor_status,07fh
+ or ah,ah
+ jz disk_reset
+ dec ah
+ jz fdisk_status
+ mov diskette_status,0
+ cmp dl,4
+ jae j3
+ dec ah
+ jz fdisk_read
+ dec ah
+ jnz j2
+ jmp fdisk_write
+j2:
+ dec ah
+ jz disk_verf
+ dec ah
+ jz disk_format
+j3:
+ mov diskette_status,bad_cmd
+ ret
+j1 endp
+
+;----- reset the diskette system
+
+disk_reset proc near
+ mov dx,03f2h
+ cli
+ mov al,motor_status
+ mov cl,4
+ sal al,cl
+ test al,20h
+ jnz j5
+ test al,40h
+ jnz j4
+ test al,80h
+ jz j6
+ inc al
+j4:
+ inc al
+j5:
+ inc al
+j6:
+ or al,8
+ out dx,al
+ mov seek_status,0
+ mov diskette_status,0
+ or al,4
+ out dx,al
+ sti
+ call chk_stat_2
+
+ mov al,nec_status
+ cmp al,0c0h
+ jz j7
+ or diskette_status,bad_cntlr
+ ret
+
+;----- send specific command to nec
+
+j7:
+ mov ah,3
+ call nec_output
+ mov bx,1
+ call get_parm
+ mov bx,3
+ call get_parm
+j8:
+ ret
+disk_reset endp
+
+
+;-----diskette status routine
+
+fdisk_status proc near
+ mov al,diskette_status
+ ret
+fdisk_status endp
+
+
+;-----diskette read
+
+fdisk_read proc near
+ mov al,046h
+j9:
+ call dma_setup
+ mov ah,0e6h
+ jmp short rw_opn
+fdisk_read endp
+
+
+;----- diskette verify
+
+disk_verf proc near
+ mov al,042h
+ jmp j9
+disk_verf endp
+
+
+;----- diskette format
+
+disk_format proc near
+ or motor_status,80h
+ mov al,04ah
+ call dma_setup
+ mov ah,04dh
+ jmp short rw_opn
+j10:
+ mov bx,7
+ call get_parm
+ mov bx,9
+ call get_parm
+ mov bx,15
+ call get_parm
+ mov bx,17
+ jmp j16
+disk_format endp
+
+
+;-----diskette write routine
+
+fdisk_write proc near
+ or motor_status,80h
+ mov al,04ah
+ call dma_setup
+ mov ah,0c5h
+fdisk_write endp
+
+;-----allow write routine to fall into rw_opn
+
+;-----------------------------------------------------------------------
+; rw_opn
+; this routine performs the read/write/verify operation
+;-----------------------------------------------------------------------
+
+rw_opn proc near
+ jnc j11
+ mov diskette_status,dma_boundary
+ mov al,0
+ ret
+j11:
+ push ax
+
+;----- turn on the motor and select the drive
+
+ push cx
+ mov cl,dl
+ mov al,1
+ sal al,cl
+ cli
+
+ mov motor_count,0ffh
+ test al,motor_status
+ jnz j14
+ and motor_status,0f0h
+ or motor_status,al
+ sti
+ mov al,10h
+ sal al,cl
+ or al,dl
+ or al,0ch
+ push dx
+ mov dx,03f2h
+ out dx,al
+ pop dx
+
+;----- wait for motor if write operation
+
+ test motor_status,80h
+ jz j14
+
+ clc
+ mov ax,090fdh
+ int 15h
+ jc j14
+
+
+ mov bx,20
+ call get_parm
+ or ah,ah
+j12:
+ jz j14
+ sub cx,cx
+j13:
+ loop j13
+ dec ah
+ jmp j12
+j14:
+ sti
+ pop cx
+
+;----- do the seek operation
+
+ call seek
+ pop ax
+ mov bh,ah
+ mov dh,0
+ jc j17
+ mov si,offset j17
+ push si
+
+;----- send out the parameters to the controller
+
+ call nec_output
+ mov ah,[bp+1]
+ sal ah,1
+ sal ah,1
+ and ah,4
+ or ah,dl
+ call nec_output
+
+;----- test for format command
+
+ cmp bh,04dh
+ jne j15
+ jmp j10
+j15:
+ mov ah,ch
+ call nec_output
+ mov ah,[bp+1]
+ call nec_output
+ mov ah,cl
+ call nec_output
+ mov bx,7
+ call get_parm
+ mov bx,9
+ call get_parm
+ mov bx,11
+ call get_parm
+ mov bx,13
+j16:
+ call get_parm
+ pop si
+
+;----- let the operation happen
+
+ call wait_int
+j17:
+ jc j21
+ call results
+ jc j20
+
+;----- check the results returned by the controller
+
+ cld
+ mov si,offset nec_status
+ lods nec_status
+ and al,0c0h
+ jz j22
+ cmp al,040h
+ jnz j18
+
+;----- abnormal termination, find out wy
+
+ lods nec_status
+ sal al,1
+ mov ah,record_not_fnd
+ jc j19
+ sal al,1
+ sal al,1
+ mov ah,bad_crc
+ jc j19
+ sal al,1
+ mov ah,bad_dma
+ jc j19
+ sal al,1
+ sal al,1
+ mov ah,record_not_fnd
+ jc j19
+ sal al,1
+ mov ah,write_protect
+ jc j19
+ sal al,1
+ mov ah,bad_addr_mark
+ jc j19
+
+;----- nec must have failed
+
+j18:
+ mov ah,bad_cntlr
+j19:
+ or diskette_status,ah
+ call num_trans ; how many were really transferred
+j20:
+ ret
+j21:
+ call results
+ ret
+
+;----- operation was successfull
+
+j22:
+ call num_trans
+ xor ah,ah
+ ret
+rw_opn endp
+
+;-----------------------------------------------------------------------
+; nec_output
+; This routine sends a byte to the nec controller after testing
+; for correct direction and controller ready. This routine will
+; time out if the byte is not accepted within a reasonable
+; amount of time, setting the diskette status on completion.
+; Input
+; (ah) byte to be output
+; Output
+; cy=0 success
+; cy=1 failure -- diskette status updated
+; If a failure has occured, the return is made one level
+; higher than the caller of nec_output. (!Schweinkram)
+; This removes the requirement of testing after every
+; call of nec_output
+; (al) destroyed
+;-----------------------------------------------------------------------
+
+nec_output proc near
+ push dx
+ push cx
+ mov dx,03f4h
+ xor cx,cx
+j23:
+ in al,dx
+ test al,040h
+ jz j25
+ loop j23
+j24:
+ or diskette_status,time_out
+ pop cx
+ pop dx
+ pop ax ; discard the return address
+ stc
+ ret
+j25:
+ xor cx,cx
+j26:
+ in al,dx
+ test al,080h
+ jnz j27
+ loop j26
+ jmp j24
+j27:
+ mov al,ah
+ mov dl,0f5h
+ out dx,al
+ pop cx
+ pop dx
+ ret
+nec_output endp
+
+;-----------------------------------------------------------------------
+; get_parm
+; This routine fetches the indext pointer from the disk_bas
+; block pointed at by the data variable disk_pointer. A byte from
+; that table is then moved into ah, the index of that byte being
+; the parm in bx
+; Input:
+; bx index of byte to be fetched *2
+; if the low bit of bx is on, the byte is immediately output
+; to the nec controller
+; Exit
+; am that byte from block
+;-----------------------------------------------------------------------
+
+disk_pointer equ 1eh * 4
+
+get_parm proc near
+ push ds
+ push si
+ sub ax,ax
+ mov ds,ax
+
+ lds si,dword ptr ds:disk_pointer
+ shr bx,1
+
+ mov ah,[si+bx]
+ pop si
+ pop ds
+ jc nec_output
+ ret
+get_parm endp
+
+;-----------------------------------------------------------------------
+; seek
+; Thi routine will move the head on the named drive to the
+; named track. If the drive has not been accessed since the
+; drive reset command was issued, the drive will be recalibrated.
+; Input:
+; (dl) = Drive to seek on
+; (ch) = track t seek to
+; Output:
+; cy = 0 success
+; cy = 1 failure -- diskette_status set accordingly
+; (ax) destroyed
+;-----------------------------------------------------------------------
+
+seek proc near
+ mov al,1
+ push cx
+ mov cl,dl
+ rol al,cl
+ pop cx
+ test al,seek_status
+ jnz j28
+ or seek_status,al
+ mov ah,07h
+ call nec_output
+ mov ah,dl
+ call nec_output
+ call chk_stat_2
+ jc j32
+
+;----- drive is in synch with controller, seek to track
+
+j28:
+ mov ah,0fh
+ call nec_output
+ mov ah,dl
+ call nec_output
+ mov ah,ch
+ call nec_output
+ call chk_stat_2
+
+;----- wait for head settle
+
+ pushf
+ mov bx,18
+ call get_parm
+ push cx
+j29:
+ mov cx,550
+ or ah,ah
+ jz j31
+j30:
+ loop j30
+ dec ah
+ jmp j29
+j31:
+ pop cx
+ popf
+j32:
+ ret
+seek endp
+
+;-----------------------------------------------------------------------
+; dma_setup
+; this routine sets up the dma for read/write/verify operations
+; input:
+; (al) = mode byte for the dma
+; (es:bx) - address to read/write the data
+; output:
+; (ax) destroyed
+;-----------------------------------------------------------------------
+
+dma_setup proc near
+ push cx
+ cli
+ out dma+12,al
+ push ax
+ pop ax
+ out dma+11,al
+ mov ax,es
+ mov cl,4
+ rol ax,cl
+ mov ch,al
+ and al,0f0h
+ add ax,bx
+ jnc jj33
+ inc ch
+jj33:
+ push ax
+ out dma+4,al
+ mov al,ah
+ out dma+4,al
+ mov al,ch
+ and al,0fh
+ out 081h,al
+
+;----- determine count
+
+ mov ah,dh
+ sub al,al
+ shr ax,1
+ push ax
+ mov bx,6
+ call get_parm
+ mov cl,ah
+ pop ax
+ shl ax,cl
+ dec ax
+ push ax
+ out dma+5,al
+ mov al,ah
+ out dma+5,al
+ sti
+ pop cx
+ pop ax
+ add ax,cx
+ pop cx
+ mov al,2
+ out dma+10,al
+ ret
+dma_setup endp
+
+;-----------------------------------------------------------------------
+; chk_stat_2
+; This routine handles the interrupt received after a
+; recalibrate, seek, or reset to the adapter.
+; The interrupt is waited for, the interrupt sensed,
+; and the result returned to the caller.
+; input:
+; none
+; output:
+; cy = 0 success
+; cy = 1 failure -- error is in diskette_status
+; (ax) destroyed
+;-----------------------------------------------------------------------
+
+chk_stat_2 proc near
+ call wait_int
+ jc j34
+ mov ah,08h
+ call nec_output
+ call results
+ jc j34
+ mov al,nec_status
+ and al,060h
+ cmp al,060h
+ jz j35
+ clc
+j34:
+ ret
+j35:
+ or diskette_status,bad_seek
+ stc
+ ret
+chk_stat_2 endp
+
+;-----------------------------------------------------------------------
+; wait_int
+; This routine waits for an interrupt to occur. A time out
+; routine takes place during the wait, so that an error may be
+; returned if the drive is not ready.
+; input:
+; none
+; output:
+; cy = 0 success
+; cy = 1 failure -- diskette_status is set accordingly
+; (ax) destroyed
+;-----------------------------------------------------------------------
+
+wait_int proc near
+ sti
+ push ax
+ push bx
+ push cx
+ clc
+ mov ax,09001h
+ int 15h
+ sti
+ jc j36a
+;
+ mov bl,2
+ xor cx,cx
+j36:
+ test seek_status,int_flag
+ jnz j37
+; push cx
+; push bx
+; push ds
+; push es
+; push ax
+; push dx
+; push si
+; push di
+; push bp
+; call cs:warte
+; pop bp
+; pop di
+; pop si
+; pop dx
+; pop ax
+; pop es
+; pop ds
+; pop bx
+; pop cx
+ loop j36
+ dec bl
+ jnz j36
+
+j36a: or diskette_status, time_out
+ stc
+j37:
+ pushf
+ and seek_status, not int_flag
+ popf
+ pop cx
+ pop bx
+ pop ax
+ ret
+wait_int endp
+
+;-----------------------------------------------------------------------
+; disk_int
+; This routine handles the diskette interrupt
+; Input
+; none
+; output:
+; The interrupt flag is set is seek_status
+;-----------------------------------------------------------------------
+
+;**************
+;org 0ef57h
+;**************
+disk_int proc far
+ sti
+ push ds
+ push ax
+ push si
+ mov si,data
+ mov ds,si
+ or seek_status, int_flag
+ mov al,20h
+ out 20h,al
+ mov ax,09101h
+ int 15h
+ pop si
+ pop ax
+ pop ds
+ iret
+disk_int endp
+
+;-----------------------------------------------------------------------
+; results
+; This routine will read anything that the nec controller has
+; to say following an interrupt.
+; input:
+; none
+; output:
+; cy = 0 successful transfer
+; cy = 1 failure -- time out in waiting for status
+; nec_status area has status byte loaded into it
+; (ah) destroyed
+;-----------------------------------------------------------------------
+
+results proc near
+ cld
+ mov di,offset nec_status
+ push cx
+ push dx
+ push bx
+ mov bl,7
+
+;-----wait for request for master
+
+j38:
+ xor cx,cx
+ mov dx,03f4h
+j39:
+ in al,dx
+ test al,80h
+ jnz j40a
+ loop j39
+ or diskette_status, time_out
+j40:
+ stc
+ pop bx
+ pop dx
+ pop cx
+ ret
+
+;----- test the direction bit
+
+j40a:
+ in al,dx
+ test al,40h
+ jnz j42
+j41:
+ or diskette_status,bad_cntlr
+ jmp j40
+
+;-----read in the status
+
+j42:
+ inc dx
+ in al,dx
+ mov [di],al
+ inc di
+ mov cx,10
+j43: loop j43
+ dec dx
+ in al,dx
+ test al,10h
+ jz j44
+ dec bl
+ jnz j38
+ jmp j41
+
+;----- result operation is done
+
+j44:
+ pop bx
+ pop dx
+ pop cx
+ ret
+
+;-----------------------------------------------------------------------
+; num_trans
+; This routine calculates the number of sectors that were
+; actually transferred to/from the diskette
+; input
+; (ch) = cylinder of operation
+; (cl) = start sector of operation
+; output
+; (al) = number actually transferred
+; no other registers modified
+;-----------------------------------------------------------------------
+
+num_trans proc near
+ mov al,nec_status+3
+ cmp al,ch
+ mov al,nec_status+5
+ jz j45
+ mov bx,8
+ call get_parm
+ mov al,ah
+ inc al
+j45:
+ sub al,cl
+ ret
+num_trans endp
+results endp
+
+ assume ds:shard
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/FIXDISK.ASM b/system/shard-x86-at/7/src/FIXDISK.ASM
new file mode 100644
index 0000000..520976a
--- /dev/null
+++ b/system/shard-x86-at/7/src/FIXDISK.ASM
@@ -0,0 +1,307 @@
+;************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==============*
+;* *
+;* Harddisk routinen *
+;* *
+;************************************************************************
+
+ device fixdisk
+
+ dtcbroutines iocontrol
+ routine 5,fixed_size
+ routine -10,fixed_tracks
+ routine -11,fixed_sects
+ routine -12,fixed_heads
+ routine 1,devicetype
+ routine -1,unknowncontrol
+ dtcbroutines control32
+ routine -2,fixed_init
+ routine -100,fixed_size_set
+ routine -101,fixed_start_set
+ routine -102,fixed_landing_zone
+ routine -1,no_channel_setup
+ dtcbroutines blockin
+ routine -1,fixed_read
+ dtcbroutines blockout
+ routine -1,fixed_write
+ dtcbparams nil_output,0ch ;kein output, blockio device
+
+
+heads equ 4
+sects equ 17
+
+ if pcxt
+ if at
+ bitte nicht at und pcxt gleichzeitig
+ endif
+ endif
+
+ if pcd
+romhd equ 1
+ else
+ if at
+romhd equ 1
+ else
+romhd equ romharddisk
+ endif
+ endif
+
+fix_ccb macro kanal
+startccb hgccb&kanal,kanal
+ccbentry fix_size
+ dw 0
+ db 0
+ccbentry fix_firstblock
+ dw 0
+ db 0
+ccbentry fix_sects
+ db 0
+ccbentry fix_cylsize
+ dw 0
+ endm
+
+fixed_size_set:
+ mov [di+fix_size],dx
+ mov [di+fix_size+2],bl
+ ret
+
+fixed_start_set:
+ mov [di+fix_firstblock],dx
+ mov [di+fix_firstblock+2],bl
+ ret
+
+fixed_init:
+ mov ax,0801h ;return drive type
+ mov dl,80h ;drive 0
+ int 13h
+ mov al,cl ;anzahl sects holen
+ and al,3fh ;nur sector anzahl
+ mov [di+fix_sects],al ;eintragen
+ inc dh ;anzahl koepfe (statt hoechste nummer)
+ mul dh ;sects pro cylinder
+ mov [di+fix_cylsize],ax ;eintragen
+ mov dl,cl ;cylinder anzahl nach dx packen
+ shl dx,1
+ shl dx,1
+ and dh,3 ;nur unterste zwei bits behalten
+ mov dl,ch ;rest cylindernummer holen
+ inc dx ;anzahl draus machen
+ mul dx ;anzahl bloecke ausrechnen
+ mov [di+fix_size],ax
+ mov [di+fix_size+2],dl
+ ret
+
+fixed_tracks:
+ call fix_drive
+ rol cl,1 ;trackzahl in cx melden
+ rol cl,1
+ and cl,3 ;nur zwei bits sind noch track
+ xchg cl,ch
+ inc cx ;meldet hoechste nummer, anzahl draus
+ ret
+
+fixed_sects:
+ call fix_drive
+ and cl,03fh ;nur sectorenzahl behalten
+ mov ch,0 ;high byte 0
+ ret
+
+fixed_heads:
+ call fix_drive
+ mov cl,dh
+ mov ch,0
+ inc cx ;hoechsten head -> anzahl umrechnen
+ ret
+
+fix_drive:
+ mov ax,0801h ;return drive type
+ mov dl,80h ;drive 0
+ int 13h
+ ret
+
+fixed_landing_zone:
+ mov bx,0
+ call device_free ;auf freigabe warten
+ call hardware ;pruefen, ob at
+ cmp al,IBMat
+ jz fixed_at_landing
+ call fix_drive
+ mov ax,0c01h ;seek
+ mov dl,80h ;immer auf erstem drive
+ inc ch ;auf naechste spur
+ ifz <add cl,40h> ;hoeherwertigen bits auch zaehlen
+ int 13h
+ ret
+
+fixed_at_landing:
+ sub ax,ax
+ mov ds,ax
+ les bx,dword ptr ds:[(41h*4)]
+ mov ax,es:[bx+12] ;landing zone
+ mov ch,al ;unterste byte der cylinder number
+ and ax,0300h ;obersten zwei bits
+ shr ax,1
+ shr ax,1
+ or al,1 ;immer sector 1
+ mov cl,al
+ mov dx,80h ;drive und head 0
+ mov ax,0c01h ;seek
+ int 13h
+ ret ;device nicht wieder freigeben
+ ;aendern, wenn zwei laufwerke
+
+fix_highblock:
+ pop bx
+ jmp highblock
+
+fixed_write:
+ push bx
+ if romhd
+ mov bl,3
+ else
+ mov bl,0 ;auftrag schreiben nach bl
+ endif
+ jmp short fixed_rw
+fixed_read:
+ push bx
+ if romhd
+ mov bl,2 ;lesen nach bl
+ else
+ mov bl,1
+ endif
+fixed_rw:
+ cmp ch,0 ;wirklich read oder write
+ ifnz <jmp unknowncontrol>
+ cmp cl,[di+fix_size+2]
+ ifz <cmp dx,[di+fix_size]> ;blocknummer zu hoch?
+ jnc fix_highblock
+ push bx
+ mov bx,0
+ call device_free
+
+ pop bx
+ mov ax,dx ;blocknummer nach ax
+ add ax,[di+fix_firstblock] ;offset fuer ersten block dazu
+ adc cl,[di+fix_firstblock+2]
+ mov dx,cx ;high byte muss nach dx
+
+ if at ;translate bad blocks if at
+; jetzt erstmal schlechte sectoren suchen
+ push es
+ push ds
+ pop es
+ push di
+ mov di,offset bb_table
+ cld
+ mov cx,[bb_anz] ;anzahl schlechte sectoren
+fix_search_bb:
+ jcxz fix_no_translate
+ repnz scasw ;sieh mal nach
+ jnz fix_no_translate
+ cmp dl,byte ptr [di+max_bb*2-2] ;obere byte ebenfalls pruefen
+ jnz fix_search_bb
+; schlechten sector gefunden
+ pop di
+ mov ax,[di+fix_firstblock] ;direkt hinter letzten block
+ mov dl,[di+fix_firstblock+2]
+ add ax,[di+fix_size]
+ adc dl,[di+fix_size+2]
+ add ax,cx
+ adc dl,0
+ push di
+fix_no_translate:
+ pop di
+ pop es
+ endif
+
+ div word ptr (di+fix_cylsize) ;dxax / sectoren pro zylinder
+ ;der rest passt immer in 32 bit
+ mov ch,al ;low byte tracknummer nach ch
+ ror ah,1
+ ror ah,1
+ mov cl,ah ;high bits der cylindernummer nach cl
+ mov ax,dx ;rest nach ax
+ div byte ptr (di+fix_sects)
+
+ if at
+ mov dh,al ;kopf nach dh
+ else
+; jetzt erstmal schlechte spuren suchen
+ or cl,al ;kopf zur spur dazu
+ push ax ;retten
+ mov ax,cx ;zum suchen da rueber
+ push di
+ push es
+ push ds
+ pop es
+ mov di,offset bt_table
+ mov cx,8 ;8 moegliche schlechte spuren
+ cld
+ repnz scasw ;sieh mal nach
+ ifz <mov ax,word ptr [di+14]> ersatzwert holen
+ pop es
+ pop di
+ mov cx,ax ;zurueckgeben
+ and cl,0c0h ;nur cylinderbits behalten
+ and al,03fh ;nur kopf bits
+ mov dh,al ;head nach dh
+ pop ax
+ endif
+
+ mov dl,080h ;drive nach dl
+ or cl,ah ;sector nach cl reinbasteln
+ mov al,1 ;einen sector
+ mov ah,bl ;auftrag nach ah
+ pop bx
+ if romhd
+ inc cl
+ push es
+ int 13h
+ pop es
+ jc diskerr
+ else
+ push bx
+ mov bx,0
+ call device_lock
+ pop bx
+ mov byte ptr [cmd_block+1],dh ;kopfnummer
+ mov byte ptr [cmd_block+2],cl ;cylinder + sect
+ mov byte ptr [cmd_block+3],ch ;cylinder
+ push es
+ call hard_dsk
+ pop es
+ xor bx,bx ;device 0 freigeben
+ call device_unlock
+ mov ah,byte ptr [disk_status] ;haben wir fehler
+ or ah,ah
+ jnz diskerr
+ endif
+ mov byte ptr fix_err,0 ;ein aufruf war ohne fehler
+ mov cx,0
+ ret
+
+diskerr:
+ inc byte ptr fix_err
+ cmp byte ptr fix_err,4 ;schon viermal hintereinander fehler
+ jnz fix_blockerr
+ mov byte ptr fix_err,0
+ push ax
+ mov ah,13 ;nur harddisk zuruecksetzen
+ mov dl,80h ;disk reset
+ int 13h
+ pop ax
+fix_blockerr:
+ jmp blockerr
+
+fixed_size:
+ mov al,[di+fix_size+2]
+ mov cx,[di+fix_size]
+ ret
+
+fix_err db 0
+
+
+ ife romhd
+ include HDISK.ASM
+ endif
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/FLOPPY.ASM b/system/shard-x86-at/7/src/FLOPPY.ASM
new file mode 100644
index 0000000..861d06f
--- /dev/null
+++ b/system/shard-x86-at/7/src/FLOPPY.ASM
@@ -0,0 +1,454 @@
+;************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==============*
+;* *
+;* Floppydisk archiv routinen *
+;* *
+;************************************************************************
+
+ device archive
+
+ dtcbroutines iocontrol
+ routine 5,archive_size
+ routine 1,devicetype
+ routine 7,archive_format
+ routine -1,unknowncontrol
+ dtcbroutines control32
+ ife pcd
+ routine -2,archive_init
+ endif
+ routine -173,set173size
+ routine -1,no_channel_setup
+ dtcbroutines blockin
+ routine 0,archive_read
+ dtcbroutines blockout
+ routine 0,archive_write
+ routine -1,unknowncontrol
+ if pcd
+ dtcbparams nil_output,0ch ;kein output, blockio device
+ else
+ dtcbparams nil_output,1ch ;kein output, blockio device, format erlaubt
+ endif
+
+IBM equ 0
+OLI equ 1
+IBM_BIG equ 2
+IBMsize equ 360*2
+OLIsize equ 400*2
+IBM_BIGsize equ 15*80*2
+
+if pcd
+romfd equ 1
+ else
+ if at
+romfd equ 1
+ else
+romfd equ romfloppy
+ endif
+ endif
+
+floppyio macro
+ if romfd
+ if withhd
+ int 40h
+ else
+ int 13h ;disketten routine aufrufen
+ endif
+ else
+ call diskette_io
+ endif
+ endm
+
+archive_ccb macro drive,drive_type
+ startccb archive_&drive,0 ;kanalnummer ist uninterressant
+ccbentry arch_typ
+ db IBM ;standardmaessig IBM annehmen
+ccbentry arch_size
+ dw 0
+ccbentry arch_drive
+ db drive
+ccbentry arch_drive_type
+ db drive_type
+ccbentry arch_default_format
+ if drive_type eq highdensity
+ db 3
+ else
+ if drive_type eq drive720
+ db 2
+ else
+ db 1
+ endif
+ endif
+ endm
+
+highdensity equ 1 ;bit 0 ist highdensity bit
+with_boot_on_it equ 2 ;bit 1 sagt, dass boot auf der floppy ist (fuer hg)
+drive720 equ 4 ;bit 2 sagt, dass 80 track double density
+eighty_tracks equ 8 ;bit 3 sagt, wir formatieren gerade 80 spuren
+no_floppy equ 16 ;bit 4 sagt, hier ist kein laufwerk
+
+diskvector equ 01eh*4
+diskinterrupt equ 0eh*4
+
+archive_init:
+ mov ax,0
+ mov es,ax ;auf int vektoren zeigen
+ mov word ptr es:[diskvector],offset nineblockvector
+ mov word ptr es:[diskvector+2],cs
+ ife romfd ;wenn nicht at
+ mov word ptr es:[diskinterrupt],offset disk_int
+ mov word ptr es:[diskinterrupt+2],cs
+ endif
+ ret
+
+oliinout:
+ mov ax,dx ;blocknummer nach ax
+ mov dl,20 ;20 sectoren pro cylinder
+ div dl ;ax/dl
+ mov ch,al ;track nach ch
+ mov al,ah ;rest nach al
+ mov ah,0 ;obere haelfte loeschen
+ mov dl,10 ;10 sects pro spur
+ div dl
+ mov dh,al ;head nach dh
+ mov dl,(di+arch_drive) ;drive nach dl
+ mov cl,ah ;sector nach cl
+ inc cl ;beginnt mit eins
+ mov al,1 ;einen sector
+ mov ah,bl ;auftrag nach ah
+ pop bx
+ push es
+ floppyio
+ pop es
+ jc archive_diskerr
+ mov cx,0
+ ret
+
+
+archive_write:
+ push bx
+ mov bl,3 ;auftrag schreiben nach bl
+ jmp short archive_rw
+
+archive_read:
+ push bx
+ mov bl,2 ;lesen nach bl
+
+archive_rw:
+ push bx
+ mov bx,1 ;floppy ist device 1
+ call device_free ;warten, bis frei
+ pop bx
+ test byte ptr (di+arch_drive_type),with_boot_on_it ;ist der boot mit drauf
+ ifnz <add dx,boot_size>
+ jc archive_highblock
+ cmp dx,word ptr (di+arch_size) ;blocknummer zu hoch
+ jnc archive_highblock
+ cmp byte ptr (di+arch_typ),OLI ;haben wir ein olivetti archiv
+ jz oliinout
+ mov ax,dx
+ mov dh,0 ;erste seite annehmen
+ mov cx,(di+arch_size) ;gesamtgroesse
+ shr cx,1 ;halbieren
+ cmp ax,cx ;schon zweite seite
+ jc notsecond
+ mov dh,1 ;zweiten kopf
+ sub ax,cx
+notsecond:
+ mov dl,9
+ cmp byte ptr (di+arch_typ),IBM_BIG
+ ifz <mov dl,15> ;15 sectoren pro spur
+ div dl ;9 sectoren pro spur
+ mov ch,al ;track nach ch
+ mov dl,(di+arch_drive) ;drive nach dl
+ mov cl,ah ;sector nach cl
+ inc cl ;beginnt mit eins
+ mov al,1 ;einen sector
+ mov ah,bl ;auftrag nach ah
+ pop bx
+ push es
+ floppyio
+ pop es
+ jc archive_diskerr
+ mov cx,0
+ ret
+
+archive_diskerr:
+ push ax
+ mov ah,0
+ floppyio ;reset disk system
+ pop ax
+ jmp blockerr
+archive_highblock:
+ pop bx
+ jmp highblock
+
+set173size:
+ cmp word ptr [hgver],1742
+ ifz <mov word ptr (di+arch_size),IBMsize>
+ ret
+
+;************************************************************************
+;* archive_size liefert die groesse einer aktuell eingelegten floppy
+;*
+;* und zwar wird unterschieden zwischen IBM-Format (9 Sectoren pro Spur)
+;* und Olivetti (M20) Format mit 10 Sectoren pro Spur sowie IBM Format mit
+;* 15 Sectoren pro Spur
+archive_size:
+ mov bx,1 ;floppy ist device 1
+ call device_free
+ mov word ptr (di+arch_size),0 ;annehmen, dass keine floppy da
+; falls noch version 1.7.3, dann in diesem Fall 360K annehmen
+ cmp word ptr [hgver],1742
+ ifz <mov word ptr (di+arch_size),IBMsize>
+ if pcd
+ and byte ptr (di+arch_drive),0ffh-20h ;96 tpi ausschalten
+ endif
+
+ mov dl,(di+arch_drive) ;drive nummer holen
+ mov dh,0 ;head 0
+ mov cx,1 ;track 0, sector 1
+ mov ax,0401h ;verify, ein sector
+ floppyio ;ist ueberhaupt ne floppy da
+ jnc arch_det_size
+ mov dl,(di+arch_drive) ;drive nummer holen
+ mov dh,0 ;head 0
+ mov cx,1 ;track 0, sector 1
+ mov ax,0401h ;verify, ein sector
+ floppyio ;ist ueberhaupt ne floppy da
+ jc arch_size_end ;fertig
+arch_det_size:
+ mov dl,(di+arch_drive) ;drive nummer holen
+ mov dh,0 ;head 0
+ mov cx,14 ;track 0, sector 14
+ mov ax,0401h ;verify, ein sector
+ floppyio
+ mov byte ptr (di+arch_typ),IBM_BIG
+ mov word ptr (di+arch_size),IBM_BIGsize
+ jnc arch_size_end ;wir sind fertig
+
+ mov dl,(di+arch_drive) ;drive nummer holen
+ mov dh,0 ;head 0
+ mov cx,10 ;track 0, sector 10
+ mov ax,0401h ;verify, ein sector
+ floppyio
+ mov byte ptr (di+arch_typ),OLI
+ mov word ptr (di+arch_size),OLIsize
+ jnc arch_is_oli
+ mov byte ptr (di+arch_typ),IBM ;konnten nicht finden, dann IBM Format
+ mov word ptr (di+arch_size),IBMsize
+arch_is_oli:
+ mov dl,(di+arch_drive) ;drive nummer holen
+ if pcd
+ or dl,20h ;96 tpi floppy?
+ endif
+ test byte ptr (di+arch_drive_type),highdensity ;high density laufwerk
+ jnz arch_test_720k
+ ife limited_to_360
+ mov dh,0 ;head 0
+ mov cx,2901h ;track 41, sector 1
+ mov ax,0401h ;verify, ein sector
+ floppyio
+ jc arch_size_end
+ mov bx,word ptr (di+arch_size)
+ add bx,bx ;doppelte kapazitaet
+ mov word ptr (di+arch_size),bx
+ if pcd
+ or byte ptr (di+arch_drive),20h ;96 tpi einstellen
+ endif
+ endif
+arch_size_end:
+ mov al,0
+ mov cx,word ptr (di+arch_size)
+ test byte ptr (di+arch_drive_type),with_boot_on_it ;ist der boot mit drauf
+ ifnz <sub cx,boot_size>
+ ret
+
+arch_test_720k:
+ mov dh,0 ;head 0
+ mov cx,0201h ;spur 2, sector 1
+ mov ax,0401h
+ floppyio
+ mov al,0 ;annehmen, muss nicht gewechselt werden
+ jnc arch_skip_flip ;erkannt, groesse setzen
+ mov dl,(di+arch_drive)
+ mov dh,0 ;zurueck auf spur 0
+ mov cx,1 ;spur 0, sector 1
+ mov ax,0401h
+ floppyio
+ mov al,20h ;muss gewechselt werden
+arch_skip_flip:
+ mov bx,40h ;auf datensegment gehen
+ mov es,bx
+ mov bx,90h
+ add bl,byte ptr (di+arch_drive)
+ xor byte ptr es:[bx],al ;ggf. flag flippen
+ test byte ptr es:[bx],20h ;wenn double step stimmt groesse
+ jnz arch_size_end
+ mov bx,word ptr (di+arch_size)
+ add bx,bx ;doppelte kapazitaet
+ mov word ptr (di+arch_size),bx
+ jmp arch_size_end
+
+
+arch_form_unallowed:
+ mov cx,3
+ ret
+
+;*********************************************************************
+; formatieren einer floppy mit 9 oder 15 sects pro spur
+archive_format:
+ mov bx,1 ;floppy ist device 1
+ call device_free
+ and byte ptr (di+arch_drive_type),0ffh-eighty_tracks
+ cmp dx,0
+ ifz <mov dl,byte ptr (di+arch_default_format)>
+ cmp dx,1
+ jz arch_form_1
+ or byte ptr (di+arch_drive_type),eighty_tracks
+ cmp dx,2
+ jz arch_form_2
+ cmp dx,3
+ jnz arch_form_unallowed
+;format 3
+ test byte ptr (di+arch_drive_type),highdensity ;high density laufwerk
+ jz arch_form_unallowed ;nur bei highdensity geht 3
+ mov ax,1703h ;1.2M in 1.2M laufwerk
+ mov dl,(di+arch_drive)
+ floppyio
+ mov dx,offset fifteenblockvector
+ mov bx,offset archive_format_buffer15
+ jmp short arch_form_go
+
+;format 2
+arch_form_2:
+ test byte ptr (di+arch_drive_type),drive720+highdensity ;kann es 720k
+ jz arch_form_unallowed ;weder highdensity noch 720k, da geht nur 1
+ test byte ptr (di+arch_drive_type),highdensity
+ jz arch_form_1 ;wie 1, 80 track bit steht schon
+ mov ax,1702h ;low density in high density drive
+ mov dl,(di+arch_drive)
+ floppyio
+ mov bx,40h ;auf datensegment gehen
+ mov es,bx
+ mov bx,90h ;zur state variablen
+ add bl,byte ptr (di+arch_drive)
+ and byte ptr es:[bx],0ffh-20h ;double step flag loeschen
+ jmp short arch_form_low_density
+
+;format 1
+arch_form_1:
+ mov ax,1701h ;normal drive
+ mov dl,(di+arch_drive)
+ floppyio
+ test byte ptr (di+arch_drive_type),highdensity
+ jz arch_form_low_density ;kein highdensity laufwerk, einstellung bleibt
+ mov ax,1702h ;low density in high density drive
+ mov dl,(di+arch_drive)
+ floppyio
+
+arch_form_low_density:
+ mov dx,offset nineblockvector
+ mov bx,offset archive_format_buffer
+arch_form_go:
+ push es
+ mov ax,0
+ mov es,ax ;auf int vektoren zeigen
+ mov word ptr es:[diskvector],dx
+ mov word ptr es:[diskvector+2],cs
+ pop es
+ mov dl,(di+arch_drive) ;drive nummer holen
+ mov ch,0 ;bei track 0 anfangen
+archive_form_track_loop:
+ mov dh,0
+archive_form_head_loop:
+ push cs
+ pop es ;buffer liegt in cs
+ mov al,15
+ mov bp,bx ;wir muessen was eintragen
+arch_track_set_loop:
+ mov byte ptr cs:[bp],ch ;track
+ inc bp
+ mov byte ptr cs:[bp],dh ;head
+ inc bp
+ inc bp
+ inc bp
+ dec al
+ jnz arch_track_set_loop
+ mov ax,0501h ;format
+ floppyio
+ jnc arch_form_cont
+ mov cx,2 ;fehler melden
+ ret
+arch_form_cont:
+ if romfd
+ push bx
+ push cx
+ push dx
+ push di
+ push si
+ call warte
+ call warte
+ pop si
+ pop di
+ pop dx
+ pop cx
+ pop bx
+ endif
+ inc dh ;naechste kopf
+ cmp dh,2 ;fertig
+ jnz archive_form_head_loop
+ inc ch ;naechste track
+ cmp ch,40
+ jc archive_form_track_loop
+ test byte ptr (di+arch_drive_type),eighty_tracks ;80 spuren ?
+ jz arch_form_end
+ cmp ch,80
+ jnz archive_form_track_loop
+arch_form_end:
+ mov cx,0 ;ok
+ ret
+
+archive_format_buffer:
+ irp x,<1,6,2,7,3,8,4,9,5,10>
+ db 0,0,x,2 ;;track und head wird per programm eingetragen
+ endm
+;;achtung: hier nichts einfuegen, da beim initialisieren vom ersten buffer
+;;auch ein teil vom zweiten initialisiert wird
+archive_format_buffer15:
+ irp x,<1,9,2,10,3,11,4,12,5,13,6,14,7,15,8>
+ db 0,0,x,2 ;;track und head wird per programm eingetragen
+ endm
+
+nineblockvector:
+ db 11011111b ;step rate und hut
+ db 2 ;hd load = 1
+ db 37 ;let motor run 37 seconds
+ db 2 ;512 byte per sector
+ db 9 ;last sector is 9
+ db 42 ;gap length
+ db 0ffh ;dtl
+ db 80 ;gap length format
+ db 0f6h ;fill byte fuer format
+ db 15 ;head settle time
+ db 2 ;motor start time
+
+fifteenblockvector:
+ db 11011111b ;step rate und hut
+ db 2 ;hd load = 1
+ db 37 ;let motor run 37 seconds
+ db 2 ;512 byte per sector
+ db 15 ;last sector is 15
+ db 01bh ;gap length
+ db 0ffh ;dtl
+ db 054h ;gap length format
+ db 0f6h ;fill byte fuer format
+ db 15 ;head settle time
+ db 8 ;motor start time (1/8 sekunden)
+
+
+ ife romfd
+ include FDISK.ASM
+ endif
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/FSHARD.ASM b/system/shard-x86-at/7/src/FSHARD.ASM
new file mode 100644
index 0000000..da8f6a1
--- /dev/null
+++ b/system/shard-x86-at/7/src/FSHARD.ASM
@@ -0,0 +1,223 @@
+ page 80,132
+;******************************************************************************
+;* *
+;* S H A R D - M O D U L *
+;* *
+;* fuer EUMEL auf 8086/8088 Systemen *
+;* *
+;* SHard Version 6-PC/Floppy *
+;* *
+;* Copyright (C) Martin Schoenbeck, Spenge *
+;* *
+;******************************************************************************
+
+com2wrongirq equ 0
+add4 equ 0
+ast equ 0
+
+at equ 0
+pcxt equ 1
+pcd equ 0
+romfloppy equ 0
+ramsys equ 0
+limited_to_360 equ 0
+mit_msdos equ 0
+withhd equ 0
+hdsystem equ 0
+boot_size equ 0
+gensys equ 0
+
+shard group code
+code segment word public 'code'
+ assume cs:shard, ds:shard, es:nothing, ss:nothing
+ org 100h
+shstart:
+ jmp los_gehts
+
+ include MACROS.ASM
+ include MAC286.ASM
+ include DEVICE.ASM
+ include EUCONECT.ASM
+ include SHMAIN.ASM
+
+IBMat equ 0fch
+com1base equ 03f8h
+com1irq equ 4
+com2base equ 02f8h
+ if com2wrongirq
+ com2irq equ 5
+ else
+ com2irq equ 3
+ endif
+ if add4
+com4_1base equ 03e8h
+com4_1irq equ 3
+com4_2base equ 03e0h
+com4_2irq equ 3 Šcom4_3base equ 02f0h
+com4_3irq equ 3
+com4_4base equ 02e8h
+com4_4irq equ 3
+com8_1base equ 02e0h
+com8_1irq equ 3
+com8_2base equ 0260h
+com8_2irq equ 3
+com8_3base equ 02d8h
+com8_3irq equ 3
+ else
+com4_1base equ 02c0h
+com4_1irq equ 3
+com4_2base equ 02c8h
+com4_2irq equ 3 Šcom4_3base equ 02d0h
+com4_3irq equ 3
+com4_4base equ 02d8h
+com4_4irq equ 3
+com8_1base equ 02e0h
+com8_1irq equ 3
+com8_2base equ 02e8h
+com8_2irq equ 3
+com8_3base equ 02f0h
+com8_3irq equ 3
+com8_4base equ 02f8h
+com8_4irq equ 3
+add4_3base equ 03e8h
+add4_3irq equ 3
+add4_4base equ 03e0h
+add4_4irq equ 3 Šadd4_8base equ 0260h
+add4_8irq equ 3
+ endif
+ast0_1base equ 01a0h
+ast0_1irq equ 5
+ast0_2base equ 01a8h
+ast0_2irq equ 5
+ast0_3base equ 01b0h
+ast0_3irq equ 5
+ast0_4base equ 01b8h
+ast0_4irq equ 5
+ast1_1base equ 02a0h
+ast1_1irq equ 5
+ast1_2base equ 02a8h
+ast1_2irq equ 5
+ast1_3base equ 02b0h
+ast1_3irq equ 5
+ast1_4base equ 02b8h
+ast1_4irq equ 5
+
+
+int_ctlr equ 20h
+first_ictlr_int equ 8
+
+channel macro number,dev,ccb
+channels = channels+1
+selectentry = 5
+ db number
+ dw offset ccb
+ if2
+ dwb paramstart_,%&dev
+ else
+ dw 0 ;;weil in pass eins device evtl. unbekannt
+ endif
+ endm
+
+selecttable:
+ db channels ;anzahl kanaele hier setzen
+channels = -1 ;nilchannel vorab abziehen
+ channel 32,shardchannel,0
+ if at
+ channel 0,archive,archive_0
+ else
+ channel 0,archive,archive_1
+ endif
+alterable_channels:
+ channel 1,pc,0
+ channel 2,i8250,com1ccb
+ channel 3,i8250,com2ccb
+ if ast
+ channel 4,i8250,ast0_1ccb
+ channel 5,i8250,ast0_2ccb
+ channel 6,i8250,ast0_3ccb
+ channel 7,i8250,ast0_4ccb
+ channel 8,i8250,ast1_1ccb
+ channel 9,i8250,ast1_2ccb
+ channel 10,i8250,ast1_3ccb
+ channel 11,i8250,ast1_4ccb
+ else
+ channel 4,i8250,com4_1ccb
+ channel 5,i8250,com4_2ccb
+ channel 6,i8250,com4_3ccb
+ channel 7,i8250,com4_4ccb
+ channel 8,i8250,com8_1ccb
+ channel 9,i8250,com8_2ccb
+ channel 10,i8250,com8_3ccb
+ ife add4 ;wenn nicht extra fuer add4, trotzdem vorsehen
+ channel 11,i8250,add4_3ccb
+ channel 12,i8250,add4_4ccb
+ channel 13,i8250,add4_8ccb
+ endif
+ endif
+ channel 15,parallel,para0ccb
+ channel 14,parallel,para1ccb
+ channel 16,parallel,para2ccb
+ if at and not ramsys
+ channel 31,archive,archive_1
+ else
+ channel 31,archive,archive_0
+ endif
+ channel -1,nilchannel,0
+
+
+ include I8250.ASM
+ include PCPAR.ASM
+ include STREAM.ASM
+ include NILCHAN.ASM
+ include PCSCREEN.ASM
+ include PCPLOT.ASM
+ include PCSYS.ASM
+; include FIXDISK.ASM
+ include FLOPPY.ASM
+ include CLOCK.ASM
+ include WAIT.ASM
+ include HARDWARE.ASM
+ include BLOCKERR.ASM
+
+ i8250_ccb com1,2
+ i8250_ccb com2,3
+ if ast
+ i8250_ccb ast0_1,4
+ i8250_ccb ast0_2,5
+ i8250_ccb ast0_3,6
+ i8250_ccb ast0_4,7
+ i8250_ccb ast1_1,8
+ i8250_ccb ast1_2,9
+ i8250_ccb ast1_3,10
+ i8250_ccb ast1_4,11
+ else
+ i8250_ccb com4_1,4
+ i8250_ccb com4_2,5
+ i8250_ccb com4_3,6
+ i8250_ccb com4_4,7
+ i8250_ccb com8_1,8
+ i8250_ccb com8_2,9
+ i8250_ccb com8_3,10
+ ife add4 ;wenn nicht extra fuer add4, trotzdem vorsehen
+ i8250_ccb add4_3,11
+ i8250_ccb add4_4,12
+ i8250_ccb add4_8,13
+ endif
+ endif
+ para_ccb 0,15
+ para_ccb 1,14
+ para_ccb 2,16
+ archive_ccb 0,0
+ archive_ccb 1,0
+sysmove:
+ rep movsw
+ jmp systemstart
+
+ include BOOT.ASM
+
+code ends
+
+ end los_gehts
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/HARDWARE.ASM b/system/shard-x86-at/7/src/HARDWARE.ASM
new file mode 100644
index 0000000..df89fdf
--- /dev/null
+++ b/system/shard-x86-at/7/src/HARDWARE.ASM
@@ -0,0 +1,17 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Lesen des Hardware Kennzeichen-Bytes *
+;* *
+;****************************************************************************
+
+hardware:
+ push es
+ mov ax,0ffffh
+ mov es,ax
+ mov al,byte ptr es:14 ;hardware byte holen
+ pop es
+ ret
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/HDISK.ASM b/system/shard-x86-at/7/src/HDISK.ASM
new file mode 100644
index 0000000..67044d4
--- /dev/null
+++ b/system/shard-x86-at/7/src/HDISK.ASM
@@ -0,0 +1,482 @@
+;shard segment
+; assume cs: shard
+; assume ds: shard, es:nothing, ss:nothing
+
+;================================================================
+; modul hdisk.asm
+; hard - disk - treiber
+;
+; Status:
+; 0.0 13.11.84 erste Testversion
+;================================================================
+
+TIMEOUT1 equ 20h ; warten auf Disk-Interrupt
+ ; (20.0000h Tests)
+
+;-------------------------------------------------------;
+; Fehlercodes
+; Bem: 11h ist eigentlich k e i n Fehler !
+;-------------------------------------------------------;
+
+;sense_fail equ 0ffh ; sense operation
+;undef_err equ 0bbf ; undefined error occurred
+;time_out equ 80h ; attachment failed to respond
+;bad_seek equ 40h ; seek operation failed
+;bad_cntlr equ 20h ; controller has failed
+;data_corrected equ 11h ; ecc corrected data error
+;bad_ecc equ 10h ; bad ecc on disk read
+;bad_track equ 0bh ; bad track flag detected
+;dma_boundary equ 9 ; attempt to dma across 64k
+;init_fail equ 7 ; drive parameter activity failed
+;bad_reset equ 5 ; reset failed
+;record_not_fnd equ 4 ; requested sector not found
+;bad_addr_mark equ 2 ; address mark not found
+;bad_cmd equ 1 ; bad command passed to disk i/o
+
+;-------------------------------------------------------;
+; interrrupt and status area ;
+;-------------------------------------------------------;
+
+dummy segment at 0
+
+ org 0dh *4
+hdisk_int label dword
+
+ org 13h * 4
+org_vector label dword
+ org 19h *4
+hf_tbl_vec label dword
+dummy ends
+
+;-----------------------------------------------------------------------;
+; cmd_block
+;
+; +0 Kommando
+; +1 Kopfnummer Aufrufparameter 1
+; +2 2-Bit Zylinder & Rest Sektor Aufrufparameter 2
+; +3 Zylinder Aufrufparameter 3
+; +4 Block - Count (ist immer 1 )
+; +5 Control-Byte (Step - Option)
+;-----------------------------------------------------------------------;
+
+cmd_block label byte
+hd_error db 7 dup(?)
+disk_status db ?
+
+;-------------------------------------------------------;
+; hardware specific values ;
+; ;
+; - Controller i/o port ;
+; > when ready from: ;
+; hf_port+0 - read data (from controller to cpu ;
+; hf_port+1 - read controller hardware status ;
+; (controller to cpu) ;
+; hf_port+2 - read configuration switches ;
+; hf_port+3 - not used ;
+; < when written to: ;
+; hf_port+0 - write data (from cpu to controller) ;
+; hf_port+1 - controller reset ;
+; hf_port+2 - generate controller select pulse ;
+; hf_port+3 - write pattern to dma and interrupt ;
+; mask register ;
+;-------------------------------------------------------;
+
+hf_port equ 320h ; disk port
+r1_busy equ 00001000b ; disk port 1 busy bit
+r1_bus equ 00000100b ; command/data bit
+r1_iomode equ 00000010b ; mode bit
+r1_req equ 00000001b ; request bit
+
+dma_read equ 01000111b ; channel 3 (47h)
+dma_write equ 01001011b ; channel 3 (4bh)
+dma equ 0 ; dma address
+dma_high equ 82h ; port for high 4 bits of dma
+
+tst_rdy_cmd equ 0 ; cntrl ready (00h)
+recal_cmd equ 00000001b ; recal (01h)
+sense_cmd equ 00000011b ; sense (03h)
+fmtdrv_cmd equ 00000100b ; drive (04h)
+chk_trk_cmd equ 00000101b ; t chk (05h)
+fmttrk_cmd equ 00000110b ; track (06h)
+fmtbad_cmd equ 00000111b ; bad (07h)
+read_cmd equ 00001000b ; read (08h)
+write_cmd equ 00001010b ; write (0ah)
+seek_cmd equ 00001011b ; seek (0bh)
+init_drv_cmd equ 00001100b ; init (0ch)
+rd_ecc_cmd equ 00001101b ; burst (00h)
+rd_buff_cmd equ 00001110b ; buffr (0eh)
+wr_buff_cmd equ 00001111b ; buffr (0fh)
+ram_diag_cmd equ 11100000b ; ram (e0h)
+chk_drv_cmd equ 11100011b ; drv (e3h)
+cntrl_diag_cmd equ 11100100b ; cntlr (e4h)
+rd_long_cmd equ 11100101b ; rlong (e5h)
+wr_long_cmd equ 11100110b ; wlong (e6h)
+
+int_ctl_port equ 20h ; 8259 control port
+eoi equ 20h ; end of interrupt command
+
+ page
+
+;===============================================================;
+; MAIN - Routine
+; Input:
+; ah - 0 write disk
+; - 1 read disk
+; (es:bx) - Datenadresse
+; cmd_block
+; Output:
+; disk_status 0 - alles OK
+;===============================================================;
+
+hard_dsk proc
+; mov ax,0 ; interrupt initiieren
+; mov es,ax
+; mov word ptr es:[hdisk_int+2],cs
+; mov word ptr es:[hdisk_int],offset hd_int
+
+ sti ; enable interrupts
+ mov disk_status,0 ; noch alles ok !
+ mov cmd_block+5,5 ; 70 ysec steprate
+ cmp ah,0 ; ah = 0 --> write disk
+ jz a4 ; ah <> 0 --> read disk
+ call disk_read
+ jmp short dsbl
+a4: call disk_write
+
+;-------------------------------------------------------;
+; dsbl
+; make shure that all housekeeping is done
+; before exit
+;-------------------------------------------------------;
+
+dsbl:
+ mov dx,hf_port+3
+ sub al,al
+ out dx,al ; reset int/dma mask
+ mov al,7
+ out dma+10,al ; set dma - mode to disable
+ cli ; disable interrupts
+ in al,21h
+ or al,20h
+ out 21h,al ; disable interrupt 5
+ sti ; enable interrupts
+ ret
+
+hard_dsk endp
+
+;========================================================
+; disk read routine
+; Input:
+; (es:bx) - Datenadresse
+; cmd_block
+;========================================================
+
+disk_read proc near
+ mov al,dma_read ; mode byte for dma read
+ mov cmd_block+0,read_cmd
+ jmp do_io
+disk_read endp
+
+;========================================================
+; disk write routine
+; Input:
+; (es:bx) - Datenadresse
+; cmd_block
+;========================================================
+
+disk_write proc near
+ mov al,dma_write ; mode byte for dma write
+ mov cmd_block+0, write_cmd
+ jmp do_io
+disk_write endp
+ page
+;========================================================
+; do_io
+; gemeinsame Routine fuer alle Kommandos
+; Input:
+; (es:bx) - Datenadresse
+; al - mode (dma_read/dma_write)
+; cmd_block
+;========================================================
+
+do_io proc near
+
+ mov cmd_block+4,1 ; Blockzahl immer 1
+
+;-------------------------------------------------------;
+; DMA_SETUP
+; diese Routine dressiert den DMA
+;-------------------------------------------------------;
+
+ cli ; keine Interrupts mehr
+ out dma+12,al ; first/last ff setzen
+ push ax ; warten ?
+ pop ax
+ out dma+11,al ; mode setzen
+
+;-----phys. Adresse zum DMA ausgeben:
+
+ mov ax,es
+ mov cl,4
+ rol ax,cl ; h - nibble von es nach al
+ mov ch,al
+ and al,0f0h
+ add ax,bx
+ jnc j33
+ inc ch ; Uebertrag notieren
+j33: out dma+6,al ; a0 - a7 ausgeben
+ push ax ; fuer Ueberlauftest merken
+ mov al,ah
+ out dma+6,al ; a8 - a15 ausgeben
+ mov al,ch
+ and al,0fh
+ out dma_high,al ; a16 - a19 ausgeben
+
+;-----Blocklaenge zum DMA ausgeben:
+
+ mov ax,511 ; Blocklaenge
+ out dma+7,al ; Blocklaenge ausgeben
+ mov al,ah
+ out dma+7,al
+ sti ; Interrupts scharfmachen
+ pop ax
+ add ax,511 ; 64k Overflow testen
+ jnc gx ; wenn kein Overflow
+ mov disk_status, dma_boundary
+ ret
+
+gx: call command
+ jc error_chk ; wenn was schiefgelaufen ist
+
+ mov al,3 ; controller dma/interrupt register mask
+ out dma+10,al ; initialize the disk channel
+g3:
+ in al,21h
+ and al,0dfh
+ out 21h,al
+
+;-------------------------------------------------------;
+; wait_int
+; this routine waits for the fixed disk
+; controller to signal, that an interrupt
+; has occured
+;-------------------------------------------------------;
+
+ sti ; muss das nochmal sein ???
+ push es
+ push si
+
+;----- set timeout values
+ sub bh,bh
+ mov bl,TIMEOUT1 ; timout Zaehler setzen (high word)
+ sub cx,cx
+
+;----- wait for interrupt
+w1:
+ push ds
+ push bx
+ push cx
+ call cs:warte ; nicht dumm rumloopen, sondern
+ pop cx ; arbeiten !!
+ pop bx
+ pop ds
+
+ mov dx,hf_port+1
+ in al,dx
+ and al,20h
+ cmp al,20h
+ jz w2
+ loop w1
+ dec bx
+ jnz w1
+ mov disk_status,time_out
+
+w2: mov dx, hf_port
+ in al,dx
+ and al,2
+ or disk_status,al ; Fehler merken
+ mov dx,hf_port+3
+ xor al,al
+ out dx,al
+ pop si
+ pop es
+
+;-----------------------------------------------;
+; error_chk ;
+;-----------------------------------------------;
+
+error_chk:
+ ret ; zunaechst keine Fehler- Auswertung
+ mov al,disk_status
+ or al,al
+ jnz g21
+ ret
+
+;-----perform sense status
+
+g21: mov ax, shard
+ mov es,ax
+ sub ax,ax
+ mov di,ax
+ mov cmd_block+0, sense_cmd
+ sub al,al
+ call command
+ jc sense_abort
+ mov cx,4
+g22:
+ call hd_wait_req
+ jc g24
+ mov dx,hf_port
+ in al,dx
+ mov hd_error[di],al
+ inc di
+ mov dx,hf_port+1
+ loop g22
+ call hd_wait_req
+ jc g24
+ mov dx,hf_port
+ in al,dx
+ test al,2
+ jz stat_err
+sense_abort:
+ mov disk_status, sense_fail
+g24:
+ stc
+ ret
+do_io endp
+
+;========================================================
+; command
+; erklaert dem controller, was zu tun ist
+; input
+; cmd_block
+;========================================================
+
+command proc near
+
+ mov dx,hf_port+2
+ out dx,al ; controller select pulse ausgeben
+ mov dx,hf_port+3
+ mov al,3 ; controller dma/interrupt register mask
+ out dx,al ; DMA und Interrupt-Maske setzen
+
+; eigentlich ist es nicht normal, wenn der Controller an dieser
+; Stelle beschaeftigt ist, aber wer weiss ...
+
+ sub cx,cx ; timeout - Zaehler setzen
+ mov dx,hf_port+1
+wait_busy:
+ in al,dx ; status lesen
+ and al,0fh
+ cmp al,r1_busy or r1_bus or r1_req
+ je weiter_gehts ; weiter, wenn controller frei
+ loop wait_busy ; warten...
+ mov disk_status, time_out ; is nix
+ stc
+ ret
+
+weiter_gehts:
+ cld ; clear direction flag
+ mov cx,6 ; Blocklaenge fuer move
+ mov si, offset cmd_block
+
+cm3: mov dx,hf_port ; Command-Block ausgeben
+ lodsb ;
+ out dx,al
+ loop cm3
+
+ inc dx ; weiter nach hf_port+1
+ in al,dx ; status lesen
+ test al,r1_req
+ jz cm7 ; wenn alles ok
+ mov disk_status, bad_cntlr ; war nix
+ stc
+cm7:
+ ret
+command endp
+
+
+;================================================================
+; hd_int
+;================================================================
+
+hd_int proc near
+ push ax
+ mov al,eoi ; end of interrupt
+ out int_ctl_port,al
+ mov al,7 ; set dma mode to disable
+ out dma+10,al
+ in al,21h
+ or al,20h
+ out 21h,al
+ pop ax
+ iret
+hd_int endp
+
+
+t_0 dw type_0
+t_1 dw type_1
+t_2 dw type_2
+t_3 dw type_3
+
+
+stat_err:
+ mov bl,es:hd_error ; get error byte
+ mov al,bl
+ and al,0fh
+ and bl,00110000b
+ sub bh,bh
+ mov cl,3
+ shr bx,cl
+ jmp word ptr cs:[bx + offset t_0]
+
+type0_table label byte
+ db 0, bad_cntlr, bad_seek, bad_cntlr, time_out, 0, bad_cntlr
+ db 0, bad_seek
+type0_len equ $-type0_table
+
+type1_table label byte
+ db bad_ecc, bad_ecc, bad_addr_mark, 0, record_not_fnd
+ db bad_seek, 0, 0, data_corrected, bad_track
+type1_len equ $-type1_table
+
+type2_table label byte
+ db bad_cmd, bad_addr_mark
+type2_len equ $-type2_table
+
+type3_table label byte
+ db bad_cntlr, bad_cntlr, bad_ecc
+type3_len equ $-type3_table
+
+type_0:
+ ret
+type_1:
+ ret
+type_2:
+ ret
+type_3:
+ ret
+
+;================================================================
+; hd_wait_req
+;================================================================
+
+hd_wait_req proc near
+ push cx
+ sub cx,cx ; timeout - Zaehler setzen
+ mov dx,hf_port + 1
+l1:
+ in al,dx
+ test al,r1_req
+ jnz l2 ; wenn ok
+ loop l1
+ mov disk_status, time_out
+ stc
+l2:
+ pop cx
+ ret
+hd_wait_req endp
+
+
+; end
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/HSHARD.ASM b/system/shard-x86-at/7/src/HSHARD.ASM
new file mode 100644
index 0000000..c21b572
--- /dev/null
+++ b/system/shard-x86-at/7/src/HSHARD.ASM
@@ -0,0 +1,242 @@
+ page 80,132
+;******************************************************************************
+;* *
+;* S H A R D - M O D U L *
+;* *
+;* fuer EUMEL auf 80286, 8086, 8088 Systemen *
+;* *
+;* SHard Version 7-PC/XT, PC/AT *
+;* *
+;* Copyright (C) 1985, 86 Martin Schoenbeck, Spenge *
+;* *
+;******************************************************************************
+
+
+com2wrongirq equ 0
+add4 equ 0
+ast equ 0
+
+at equ 0
+gensys equ 0
+ramsys equ 0
+pcxt equ 1
+pcd equ 0
+romharddisk equ 0
+romfloppy equ 0
+limited_to_360 equ 0
+boot_size equ 0
+
+hdsystem equ 1
+withhd equ 1
+
+setup_channel equ 28
+dos_channel equ 29
+
+shard group code
+code segment word public 'code'
+ assume cs:shard, ds:shard, es:nothing, ss:nothing
+
+shstart:
+ jmp los_gehts
+
+ even
+
+ include MACROS.ASM
+ include MAC286.ASM
+ include DEVICE.ASM
+ include EUCONECT.ASM
+ org 0a0h ;bei wort 80 beginnen
+ include PATCHARE.ASM
+
+ include SHMAIN.ASM
+
+IBMat equ 0fch
+com1base equ 03f8h
+com1irq equ 4
+com2base equ 02f8h
+ if com2wrongirq
+ com2irq equ 5
+ else
+ com2irq equ 3
+ endif
+ if add4
+com4_1base equ 03e8h
+com4_1irq equ 3
+com4_2base equ 03e0h
+com4_2irq equ 3 Šcom4_3base equ 02f0h
+com4_3irq equ 3
+com4_4base equ 02e8h
+com4_4irq equ 3
+com8_1base equ 02e0h
+com8_1irq equ 3
+com8_2base equ 0260h
+com8_2irq equ 3
+com8_3base equ 02d8h
+com8_3irq equ 3
+ else
+com4_1base equ 02c0h
+com4_1irq equ 3
+com4_2base equ 02c8h
+com4_2irq equ 3 Šcom4_3base equ 02d0h
+com4_3irq equ 3
+com4_4base equ 02d8h
+com4_4irq equ 3
+com8_1base equ 02e0h
+com8_1irq equ 3
+com8_2base equ 02e8h
+com8_2irq equ 3
+com8_3base equ 02f0h
+com8_3irq equ 3
+com8_4base equ 02f8h
+com8_4irq equ 3
+add4_3base equ 03e8h
+add4_3irq equ 3
+add4_4base equ 03e0h
+add4_4irq equ 3 Šadd4_8base equ 0260h
+add4_8irq equ 3
+ endif
+ast0_1base equ 01a0h
+ast0_1irq equ 5
+ast0_2base equ 01a8h
+ast0_2irq equ 5
+ast0_3base equ 01b0h
+ast0_3irq equ 5
+ast0_4base equ 01b8h
+ast0_4irq equ 5
+ast1_1base equ 02a0h
+ast1_1irq equ 5
+ast1_2base equ 02a8h
+ast1_2irq equ 5
+ast1_3base equ 02b0h
+ast1_3irq equ 5
+ast1_4base equ 02b8h
+ast1_4irq equ 5
+
+int_ctlr equ 20h
+first_ictlr_int equ 8
+
+channel macro number,dev,ccb
+channels = channels+1
+selectentry = 5
+ db number
+ dw offset ccb
+ if2
+ dwb paramstart_,%&dev
+ else
+ dw 0 ;;weil in pass eins device evtl. unbekannt
+ endif
+ endm
+
+selecttable:
+ db channels ;anzahl kanaele hier setzen
+channels = -1 ;nilchannel vorab abziehen
+ channel 32,shardchannel,0
+ channel 0,fixdisk,hgccb0
+alterable_channels:
+ channel 1,pc,0
+ channel 2,i8250,com1ccb
+ channel 3,i8250,com2ccb
+ if ast
+ channel 4,i8250,ast0_1ccb
+ channel 5,i8250,ast0_2ccb
+ channel 6,i8250,ast0_3ccb
+ channel 7,i8250,ast0_4ccb
+ channel 8,i8250,ast1_1ccb
+ channel 9,i8250,ast1_2ccb
+ channel 10,i8250,ast1_3ccb
+ channel 11,i8250,ast1_4ccb
+ else
+ channel 4,i8250,com4_1ccb
+ channel 5,i8250,com4_2ccb
+ channel 6,i8250,com4_3ccb
+ channel 7,i8250,com4_4ccb
+ channel 8,i8250,com8_1ccb
+ channel 9,i8250,com8_2ccb
+ channel 10,i8250,com8_3ccb
+ ife add4 ;wenn nicht extra fuer add4, trotzdem vorsehen
+ channel 11,i8250,add4_3ccb
+ channel 12,i8250,add4_4ccb
+ channel 13,i8250,add4_8ccb
+ endif
+ endif
+; channel 4,i8250,com3ccb
+; channel 5,i8250,com4ccb
+ channel 15,parallel,para0ccb
+ channel 14,parallel,para1ccb
+ channel 16,parallel,para2ccb
+ channel 28,fixdisk,hgccb1
+ channel 29,fixdisk,hgccb2
+ if 0
+ channel 30,archive,archive_0
+ channel 31,archive,archive_1
+ else
+ channel 31,archive,archive_0
+ channel 30,archive,archive_1
+ endif
+ channel -1,nilchannel,0
+ Š include I8250.ASM
+ include PCPAR.ASM
+ include STREAM.ASM
+ include NILCHAN.ASM
+ include PCSCREEN.ASM
+ include PCPLOT.ASM
+ include PCSYS.ASM
+ include FIXDISK.ASM
+ include FLOPPY.ASM
+ include CLOCK.ASM
+ include WAIT.ASM
+ include HARDWARE.ASM
+ include BLOCKERR.ASM
+
+ i8250_ccb com1,2
+ i8250_ccb com2,3
+ if ast
+ i8250_ccb ast0_1,4
+ i8250_ccb ast0_2,5
+ i8250_ccb ast0_3,6
+ i8250_ccb ast0_4,7
+ i8250_ccb ast1_1,8
+ i8250_ccb ast1_2,9
+ i8250_ccb ast1_3,10
+ i8250_ccb ast1_4,11
+ else
+ i8250_ccb com4_1,4
+ i8250_ccb com4_2,5
+ i8250_ccb com4_3,6
+ i8250_ccb com4_4,7
+ i8250_ccb com8_1,8
+ i8250_ccb com8_2,9
+ i8250_ccb com8_3,10
+ ife add4 ;wenn nicht extra fuer add4, trotzdem vorsehen
+ i8250_ccb add4_3,11
+ i8250_ccb add4_4,12
+ i8250_ccb add4_8,13
+ endif
+ endif
+ para_ccb 0,15
+ para_ccb 1,14
+ para_ccb 2,16
+ ;erlaubt drivetypen: highdensity, drive720
+ if at
+ archive_ccb 0,highdensity
+ archive_ccb 1,0 ;drive720
+ else
+ archive_ccb 0,0
+ archive_ccb 1,0
+ endif
+ fix_ccb 0
+ fix_ccb 1
+ fix_ccb 2
+
+sysmove:
+ rep movsw
+ jmp systemstart
+
+ include BOOT.ASM
+
+code ends
+
+ end los_gehts
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/I8250.ASM b/system/shard-x86-at/7/src/I8250.ASM
new file mode 100644
index 0000000..19f584d
--- /dev/null
+++ b/system/shard-x86-at/7/src/I8250.ASM
@@ -0,0 +1,437 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Routinen fuer 8250 UART im EUMEL - System *
+;* *
+;* *
+;***************************************************************************
+
+i8250_data equ 0
+i8250_ier equ 1 ;interrupt enable register
+i8250_iir equ 2 ;interrupt indicator register
+i8250_lcr equ 3 ;line control register
+i8250_mcr equ 4 ;modem control register
+i8250_lsr equ 5 ;line status register
+i8250_msr equ 6 ;modem status register
+
+ device i8250
+
+ dtcbroutines iocontrol
+ routine 1,i8250_devicetype
+ routine 2,frout
+ routine 3,i8250_stop
+ routine 4,i8250_weiter
+ routine 5,nil_size
+ routine 6,priv_op_question
+ routine 8,priv_op_question
+ routine 9,priv_op_question
+ routine -2,frout
+ routine -3,i8250_status
+ routine -4,stream_in_count
+ routine -5,stream_out_count
+ routine -6,i8250_sendbreak
+ routine -10,i8250_i_stop
+ routine -11,i8250_i_weiter
+ routine -1,unknowncontrol
+
+ dtcbroutines control32
+ routine 6,i8250_flow
+ routine 8,i8250_baud
+ routine 9,i8250_bits
+ routine -2,i8250_init
+ routine -3,i8250_test
+ routine -1,no_channel_setup
+
+ dtcbroutines blockin
+ dtcbroutines blockout
+ routine -1,unknowncontrol
+
+ dtcbparams i8250_output,3 ;typ = nur stream io
+
+
+;******************************************************************
+;* der macro i8250_ccb muss fuer jeden 8250 im system einmal
+;* aufgerufen werden
+;*
+;* parameter:
+
+i8250_ccb macro i8250,kanal
+i8250&buf db 100 DUP (0ffh)
+ startccb i8250&ccb,kanal
+ stream 100,i8250&buf ;;die 8250 routinen benutzen stream routinen
+ccbentry i8250_stat
+ db 0
+ccbentry i8250_statusandmask
+ db 0 ;;keine statusleitungen abfragen
+ccbentry i8250_statusxormask
+ db 0
+ccbentry i8250_errmask
+ db 0 ;;keine fehler auswerten
+ccbentry i8250_errflags
+ db 0
+ccbentry i8250_irq_line
+ db i8250&irq
+ccbentry i8250_base
+ dw i8250&base
+ccbentry i8250_next_ccb
+ dw 0
+ccbentry i8250_int_entry
+ call i8250_interrupt
+ endm
+
+;*** bits in i8250_stat:
+i8250_rtscts equ 1
+i8250_exists equ 2
+
+i8250_baud_table:
+ dw 2304 ;50
+ dw 1536 ;75
+ dw 1047 ;110
+ dw 857 ;134.5
+ dw 768 ;150
+ dw 384 ;300
+ dw 192 ;600
+ dw 96 ;1200
+ dw 64 ;1800
+ dw 48 ;2400
+ dw 32 ;3600
+ dw 24 ;4800
+ dw 16 ;7200
+ dw 12 ;9600
+
+
+i8250_devicetype:
+ mov cx,0 ;erstmal 0 setzen
+ test byte ptr [di+i8250_stat],i8250_exists ;ist da einer
+ ifnz <mov cl,shard:(si+devtype)> ;type dazu
+ ret
+
+
+
+
+i8250_test:
+ cmp bh,0 ;abfrage
+ ifnz <int 0bh>
+ mov dx,(di+i8250_base)
+ add dx,i8250_iir ;auf interrupt indicator register
+ in al,(dx)
+ mov cl,al
+ mov ch,1
+ ret
+
+i8250_init:
+ mov ax,0
+ mov es,ax
+; pruefen, ob ueberhaupt vorhanden
+ mov dx,(di+i8250_base)
+ add dx,i8250_iir ;interrupt indicate register holen
+ jmp short $+2
+ in al,dx
+ nop ;der in befehl erwischt einen von diesen
+ nop ;codes, wenn auf der adresse kein port ist
+ nop
+ nop
+ nop
+ test al,0f8h ;alle bits weg, die nicht da sein koennen
+ ifnz <ret> ;keine schnittstelle da
+ or byte ptr [di+i8250_stat],i8250_exists ;da ist einer
+
+ mov bx,first_ictlr_int
+ add bl,(di+i8250_irq_line) ;an welchem pin des controllers haengt er
+ ;carry kann hier nicht auftreten
+ mov byte ptr i8250_initint,bl ;fuer passenden initialisierungsint basteln
+ add bx,bx ;*2 als wortadresse
+ mov dx,word ptr (i8250_i_tab-((3+first_ictlr_int)*2))[bx] ;letzten ccb holen
+ mov word ptr (i8250_i_tab-((3+first_ictlr_int)*2))[bx],di ;neuen eintragen
+ mov (di+i8250_next_ccb),dx ;alten selbst merken
+ add bx,bx ;*4
+ mov word ptr es:[bx+2],cs
+ mov dx,di ;adresse ccb holen
+ add dx,i8250_int_entry ;adresse interrupt routine errechnen
+ mov word ptr es:[bx],dx ;eintragen
+ mov cl,(di+i8250_irq_line) ;nochmal bit im controller
+ inc cl ;mindestens einmal shiften
+ stc
+ mov ch,0 ;mit nichts anfangen
+ rcl ch,cl
+ in al,int_ctlr+1 ;interrupt enable register holen
+ or al,ch ;bit fuer i8250 setzen
+ xor al,ch ;und freigeben
+ out int_ctlr+1,al
+ mov dx,(di+i8250_base)
+ add dx,i8250_ier ;auf interrupt enable register
+ mov al,0fh ;alle interrupts an
+ out dx,al ;interrupt enable
+ add dx,i8250_mcr-i8250_ier ;auf modem control register
+ mov al,0bh ;rts, dtr, int enable
+ out dx,al
+; ret
+i8250_initint = $+1
+ int 12
+ ret
+
+i8250_i_tab:
+ dw 0 ;int 3
+ dw 0 ;int 4
+ dw 0 ;int 5
+ dw 0 ;int 6
+ dw 0 ;int 7
+
+i8250_interrupt:
+ push ds
+ push cx
+ push di
+ push bx
+ push dx
+ push ax
+ mov ax,cs
+ mov ds,ax ;ds = cs setzen
+ mov bx,sp ;auf stack zeigen
+ mov di,ss:[bx+12] ;return adresse im ccb holen
+ sub di,i8250_int_entry+3 ;auf anfang ccb rechnen
+i8250_to_first_ccb:
+ push di ;ersten ccb merken
+ mov ah,1 ;bis jetzt keinen port gefunden
+i8250_check_same_int:
+ mov dx,(di+i8250_base)
+ add dx,i8250_iir ;interrupt indicate register lesen
+ in al,(dx)
+ test al,1 ;war interrupt auf diesem kanal
+ jnz i8250_int_end
+ mov ah,0 ;ax als index, gleichzeitig ah loeschen
+ push ax
+ mov bx,ax
+ call word ptr i8250_int_table[bx] ;passende service routine aufrufen
+ pop ax
+ jmp i8250_check_same_int
+
+i8250_int_end:
+ mov di,(di+i8250_next_ccb) ;naechsten port fuer diesen vektor holen
+ or di,di ;ende eintrag?
+ jnz i8250_check_same_int
+ pop di ;ersten ccb holen
+ or ah,ah ;haben wir im letzten durchlauf einen gefunden
+ jz i8250_to_first_ccb ;ja, dann weiter suchen
+ mov al,20h ;end of interrupt
+ out int_ctlr,al
+ pop ax
+ pop dx
+ pop bx
+ pop di
+ pop cx
+ pop ds
+ pop cs:[i8250_ret_dummy] ;return adresse im ccb vergessen
+ iret ;fertig
+
+i8250_ret_dummy dw 0
+
+i8250_int_table:
+ dw offset i8250_out_restart ;bei ext. status wechsel oder bei tx empty
+ dw offset i8250_out_restart ;nur output ggf. neu starten
+ dw offset i8250_rec_int
+ dw offset i8250_error_int
+
+
+i8250_baud:
+ cmp bh,15 ;negativer wert oder > 15
+ jnc i8250_not_ok
+ cmp bh,0
+ jz i8250_not_ok
+ test bl,1 ;abfage?
+ jnz i8250_ok ;ja, wir koennen alles
+ mov dx,(di+i8250_base)
+ add dx,i8250_lcr ;line control register
+ cli ;nichts dazwischen lassen
+ in al,dx ;alten wert holen
+ push ax
+ mov al,80h
+ out dx,al ;auf baudrate register schalten
+ sub dx,i8250_lcr ;wieder auf base
+ mov bl,bh ;baudrate schluessel nach bx ausdehnen
+ mov bh,0
+ sal bx,1 ;ein baudrate eintrag ist zwei byte
+ mov ax,word ptr i8250_baud_table-2[bx] ;passenden baudrate eintrag holen
+ out dx,al ;low byte raus
+ mov al,ah
+ inc dx
+ out dx,al ;high byte raus
+ pop ax
+ add dx,i8250_lcr-1 ;wieder auf lcr
+ out dx,al ;alte lcr wieder setzen
+ sti ;jetzt darf er wieder
+ jmp short i8250_ok ;alles klar
+ ret
+
+i8250_bits:
+ test bh,0a0h ;negativer wert oder 1.5 Stopbits
+ jnz i8250_not_ok
+ test bh,4 ;bitzahl >= 5
+ jz i8250_not_ok ;nein, muss aber
+ test bl,1 ;abfrage
+ jnz i8250_ok
+ mov al,bh ;anfoderung nach al
+ test al,10h ;gerade paritaet?
+ jz i8250_not_even
+ or al,8 ;dann paritaet auch enablen
+i8250_not_even:
+ test al,40h ;2 stopbits
+ jnz i8250_not_two ;nein, das bit steht schon
+ and al,0ffh-4 ;bit ausknipsen
+i8250_not_two:
+ and al,1fh ;alle unbenutzten loeschen
+ mov dx,(di+i8250_base)
+ add dx,i8250_lcr ;auf line control register
+ out dx,al
+ mov cl,bh ;anzahl bits nach cl
+ and cl,7 ;ausblenden
+ inc cl ;aus 0-7 1-8 machen
+ mov dx,0ffh ;von 0 bits ausgehen
+ shl dl,cl ;bits anzahl nullen reinziehen
+ xor dl,0ffh ;und 1 und 0 tauschen
+ call set_out_mask
+ call set_inp_mask
+ call set_inp_errmask
+i8250_ok:
+ mov cx,0
+ ret
+
+i8250_not_ok:
+ mov cx,1
+ ret
+
+i8250_flow:
+ test bh,80h ;negativer wert?
+ jnz i8250_not_ok
+ cmp bh,3
+ jnc i8250_not_ok ;oder > 2
+ test bl,1 ;abfrage
+ jnz i8250_ok ;ja
+ cli
+ mov byte ptr (di+i8250_statusxormask),0 ;beim status nichts abfragen
+ mov byte ptr (di+i8250_statusandmask),0
+ and byte ptr (di+i8250_stat),0ffh-i8250_rtscts ;handshake ausschalten
+ dec bh
+ jnz i8250_not_xonxoff
+ call enablexon
+ jmp i8250_flow_end
+i8250_not_xonxoff:
+ call disablexon
+ dec bh
+ jnz i8250_flow_end
+ mov byte ptr (di+i8250_statusandmask),10h ;cts abfragen
+ mov byte ptr (di+i8250_statusxormask),10h ;auf gesetzt
+ or byte ptr (di+i8250_stat),i8250_rtscts
+i8250_flow_end:
+ call i8250_out_restart ;immer probieren, ob jetzt output moeglich
+ sti
+ jmp i8250_ok
+
+i8250_output:
+ call fillbuffer
+ pushf
+ jz i8250_no_orest
+ call i8250_out_restart
+i8250_no_orest:
+ popf
+ ret
+
+;* out_restart kann jederzeit aufgerufen werden, da der status jedesmal
+;* abgefragt wird
+i8250_out_restart:
+ mov dx,(di+i8250_base) ;commandport laden
+ add dx,i8250_lsr ;adresse line status register
+ cli
+ in al,(dx) ;status holen
+ test al,20h ;tx buffer empty
+ lahf ;modem status register immer lesen
+ inc dx ;auf modem status register
+ in al,(dx) ;holen
+ sahf
+ jz i8250_stiret ;nein, sti und zurueck
+ and al,(di+i8250_statusandmask) ;gewuenschte bits ausblenden
+ xor al,(di+i8250_statusxormask)
+ jnz i8250_stiret
+ call getnextchar ;zeichen holen, xon/xoff etc. abhandeln
+ mov dx,(di+i8250_base) ;port holen
+ ifnz <out (dx),al> ;wenn was da, ausgeben
+i8250_stiret:
+ sti
+ ret ;fertig
+
+i8250_rec_int:
+ mov dx,(di+i8250_base)
+ in al,(dx) ;zeichen holen
+ call input ;zeichen uebergeben, xon/xoff etc. abhandeln
+ jz i8250_out_restart ;ggf. output neu starten
+ ret
+
+i8250_error_int:
+ mov dx,(di+i8250_base)
+ add dx,i8250_lsr ;line status register holen
+ in al,(dx)
+ or (di+i8250_errflags),al ;alte errorflags dazu
+ test al,10h ;break detected
+ jnz i8250_break
+ and al,(di+i8250_errmask) ;welche fehlerbits sollen behandelt werden
+ jz i8250_rec_int ;keine, normal einlesen
+ mov dx,(di+i8250_base)
+ in al,(dx) ;zeichen holen
+ call errorinput ;uebergeben
+ jz i8250_out_restart
+ ret
+
+i8250_break:
+ call breakinput ;break zeichen uebergeben
+ jz i8250_out_restart
+ ret
+
+i8250_stop:
+ call stream_stop
+ ifnz <call i8250_out_restart> ;output ggf neu starten
+ test byte ptr (di+i8250_stat),i8250_rtscts
+ jz i8250_stop_end
+i8250_i_stop:
+ mov dx,(di+i8250_base)
+ add dx,i8250_mcr ;auf modem control register
+ mov al,9 ;rts wegnehmen
+ out (dx),al
+i8250_stop_end:
+ ret
+
+i8250_weiter:
+ call stream_weiter
+ ifnz <call i8250_out_restart> ;output ggf. neu starten
+ test byte ptr (di+i8250_stat),i8250_rtscts
+ jz i8250_stop_end
+i8250_i_weiter:
+ mov dx,(di+i8250_base)
+ add dx,i8250_mcr ;auf modem control register
+ mov al,0bh ;rts wieder setzen
+ out (dx),al
+ ret
+
+i8250_status:
+ cli
+ mov cl,(di+i8250_errflags) ;fehler holen
+ mov byte ptr (di+i8250_errflags),0 ;loeschen
+ mov dx,(di+i8250_base)
+ add dx,i8250_lsr
+ in al,dx
+ mov ch,al
+ sti
+ ret
+
+i8250_sendbreak:
+ cli
+ mov dx,(di+i8250_base)
+ add dx,i8250_lcr
+ in al,dx
+ and al,10111111b ;switch breakbit off
+ and bl,1 ;nur ein bit behalten
+ ror bl,1
+ ror bl,1 ;auf bit 6 position
+ or al,bl ;send break or not
+ out dx,al
+ sti
+ ret
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/MAC286.ASM b/system/shard-x86-at/7/src/MAC286.ASM
new file mode 100644
index 0000000..3a1f164
--- /dev/null
+++ b/system/shard-x86-at/7/src/MAC286.ASM
@@ -0,0 +1,23 @@
+iw macro op,reg,count
+ local fbyte,cbyte
+fbyte:
+ op reg,1
+cbyte:
+ org cs:fbyte
+ db 0c1h
+ org cs:cbyte
+ db count
+ endm
+
+ib macro op,reg,count
+ local fbyte,cbyte
+fbyte:
+ op reg,1
+cbyte:
+ org cs:fbyte
+ db 0c0h
+ org cs:cbyte
+ db count
+ endm
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/MACROS.ASM b/system/shard-x86-at/7/src/MACROS.ASM
new file mode 100644
index 0000000..710ef4c
--- /dev/null
+++ b/system/shard-x86-at/7/src/MACROS.ASM
@@ -0,0 +1,80 @@
+;*************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ===============*
+;* *
+;* M A C R O s fuer E U M E L - U R L A D E R *
+;* *
+;*************************************************************************
+
+ .XLIST
+on equ 0ffh
+off equ 0
+
+test equ off
+
+deft macro text
+local textend
+ db (textend-$-1)
+ db &text
+textend label byte
+ endm
+
+ke macro text
+ local teend
+ call info
+ jmp teend
+ db '&text'
+teend:
+ endm
+
+trcpas macro name
+ local trcfield,endtrc
+ if trcswitch
+ push hl
+ ld hl,(trcfield)
+ inc hl
+ ld (trcfield),hl
+ pop hl
+ jr endtrc
+ db '&name'
+trcfield:
+ dw 0
+endtrc:
+ endif
+ endm
+
+
+ifz macro op
+local false
+ jnz false
+ op
+false:
+ endm
+
+ifnz macro op
+local false
+ jz false
+ op
+false:
+ endm
+
+ifc macro op
+local false
+ jnc false
+ op
+false:
+ endm
+
+ifnc macro op
+local false
+ jc false
+ op
+false:
+ endm
+
+popff macro
+ push cs
+ call x_iret
+ endm
+
+ .LIST
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/NILCHAN.ASM b/system/shard-x86-at/7/src/NILCHAN.ASM
new file mode 100644
index 0000000..70caad6
--- /dev/null
+++ b/system/shard-x86-at/7/src/NILCHAN.ASM
@@ -0,0 +1,54 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Dieses Modul definiert alle Routinen, die benoetigt werden, wenn *
+;* ein Kanal nicht existiert oder bestimmte Funktionen nicht durch- *
+;* fuehren kann. *
+;* *
+;***************************************************************************
+
+ device nilchannel
+
+ dtcbroutines iocontrol
+ routine 1,devicetype
+ routine 2,frout_ok
+ routine 5,nil_size
+ routine -1,unknowncontrol
+ dtcbroutines control32
+ routine -1,no_channel_setup
+ dtcbroutines blockin
+ dtcbroutines blockout
+ routine -1,no_blockinout
+ dtcbparams nil_output,0 ;output; niltype
+
+nil_size:
+ mov al,0
+ mov cx,0
+ ret
+
+unknowncontrol:
+no_blockinout:
+ mov cx,-1
+ ret
+
+frout_ok:
+ mov cx,200 ;200 bytes frei
+ stc ;puffer leer
+ ret
+
+no_baud:
+no_bits:
+no_flow:
+no_channel_setup:
+ mov cx,1
+ ret
+
+nil_output:
+ stc
+ ret ;alle zeichen uebernommen
+
+devicetype:
+ mov ch,0 ;hoeherwertige teil immer null
+ mov cl,shard:(si+devtype) ;type dazu
+ ret
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/PATCH.ELA b/system/shard-x86-at/7/src/PATCH.ELA
new file mode 100644
index 0000000..539a674
--- /dev/null
+++ b/system/shard-x86-at/7/src/PATCH.ELA
@@ -0,0 +1,500 @@
+(* SHard-Patcher fuer Schoenbeck AT-Shard V2.7:
+ - Vortest/Speichertest
+ - Keyboard Repeatfrequenz
+ - Baudrates 19200/38400 werden angeboten
+ - Refresh-Intervall „nderbar (bis zu 5% mehr Leistung)
+ - control (-3,,,r) liefert im Highbyte das Modemstatusregister (RI etc.)
+ - control (-5,8,,r) geht in ruc-Bios-Graphikmodus (mit Textausgabe:
+ Text mit 'out', 'put' etc. schreiben, cursor (x, y) mit y:1..43,
+ Codes ""4"", ""5"", Scroll l”schen jetzt vernnftig (Attribut von 7 auf
+ 0 ge„ndert),
+ Achtung: getcursor (x, y) im 'begin plot' einbauen.
+ cursor (x,y) im 'end plot' einbauen, wegen y<25 im Textmodus!)
+ - Kanal 30 (Archiv 1) jetzt fr MF-Laufwerke (5.25" bzw. 3.5"), Default-
+ Size ist 1.2MB (Achtung bei Formatieren von 3.5"-Floppys!)
+ - Mit control (-10/-11,...) ("stop", "weiter") wird an den RS232-Kan„len
+ jetzt nicht nur RTS active/inactive gesetzt sondern auch DTR (Modem).
+ - An Kanal 32:
+ Mit control (-3, x, mcr*32+kanal, r) (mcr ist Modemcontrolregister Wert,
+ x egal) k”nnen RTS, DTR explizit gesetzt werden.
+ - id (6) > 0 : SHard wurde gepatcht.
+
+ Michael Staubermann, Version 2: 09.10.87, Keyboardrepeat, Baudrates
+ Version 3: 04.11.87, Graphikcursor & Graphikmodi
+ Version 3.1: 20.11.87, >32MB Partitionen f. M+
+ Version 4: 04.12.87, TX-Interrupt restart
+ Version 4.1: 10.01.88, Refresh-Intervall „nderbar
+ Version 5: 21.02.88, Kanal 30 1.2MB-Format (3.5")
+ Version 5.1: 22.02.88,
+*)
+
+LET setup channel = 28 ;
+
+LET max partitions = 4 ,
+ patch version = 5 ,
+ shard bloecke = 18 ;
+
+
+patch shard ;
+
+ROW shard bloecke ROW 256 INT VAR block ;
+ROW shard bloecke BOOL VAR modified ;
+INT VAR old session := 0 ;
+REAL VAR partition size := 0.0, partition start 1 := 256.0 * 65536.0 -1.0 ;
+INT VAR i ;
+FOR i FROM 1 UPTO shard bloecke REP
+ modified (i) := FALSE
+PER ;
+
+ROW 256 INT VAR partition table ;
+
+
+INT OP & (TEXT CONST hex) :
+ INT VAR i, h := 0 ;
+ IF LENGTH hex > 4 THEN errorstop ("OP &: LENGTH > 4") FI ;
+ FOR i FROM 1 UPTO LENGTH hex REP
+ rotate (h, 4) ;
+ INT CONST c :: code (hex SUB i) ;
+ IF c >= 97 AND c <= 102
+ THEN h := h OR (c-87)
+ ELIF c >= 65 AND c <= 70
+ THEN h := h OR (c-55)
+ ELIF c >= 48 AND c <= 57
+ THEN h := h OR (c-48)
+ ELSE errorstop ("OP &: ungltiges Hexdigit ("+code(c)+")")
+ FI ;
+ PER ;
+ h
+ENDOP & ;
+
+TEXT OP % (INT CONST int) :
+ LET hex = "0123456789ABCDEF" ;
+ TEXT VAR t := "" ;
+ INT VAR i, r := int ;
+ FOR i FROM 1 UPTO 4 REP
+ rotate (r, 4) ;
+ t CAT (hex SUB ((r AND 15)+1)) ;
+ PER ;
+ t
+ENDOP % ;
+
+PROC poke (INT CONST shard adr, INT CONST byte) :
+ (* Der Shard beginnt bei 1280 d.h. 0500H, EUCONECT bei 504H (='EUMEL') *)
+ INT VAR block no, block offset ;
+ IF shard adr < 256
+ THEN errorstop ("poke: Adresse < 256") ;
+ LEAVE poke
+ FI ;
+ block offset := shard adr-256 ;
+ rotate (block offset, -1) ;
+ block offset := (block offset AND 255) + 1 ;
+ block no := shard adr - 256 ;
+ rotate (block no, -9) ;
+ block no := (block no AND 63) + 1 ;
+ IF block no < 1 OR block no > shard bloecke
+ THEN errorstop ("poke: falsche Adresse") ;
+ LEAVE poke
+ FI ;
+ TEXT VAR t := " " ;
+ replace (t, 1, block (block no)(block offset)) ;
+ replace (t, (shard adr AND 1) + 1, code (byte AND 255)) ;
+ modified (block no) := TRUE ;
+ block (block no)(block offset) := t ISUB 1 ;
+ENDPROC poke ;
+
+PROC poke2 (INT CONST shard adr, INT CONST word) :
+ INT VAR r := word ;
+ poke (shard adr, r) ;
+ rotate (r, 8) ;
+ poke (shard adr+1, r) ;
+ENDPROC poke2 ;
+
+PROC poken (INT CONST shard adr, TEXT CONST str) :
+ INT VAR i, adr := shard adr ;
+ i := 1 ;
+ WHILE i <= LENGTH str REP
+ IF (str SUB i+2) = " " OR (str SUB i+2) = ""
+ THEN poke (adr, &subtext (str, i, i+1)) ;
+ i INCR 3 ;
+ adr INCR 1
+ ELIF (str SUB i+4) = " " OR (str SUB i+4) = ""
+ THEN poke2 (adr, &subtext (str, i, i+3)) ;
+ i INCR 5 ;
+ adr INCR 2
+ ELSE errorstop ("poken: Zuviele zusammenh„ngende Bytes")
+ FI ;
+ PER ;
+ENDPROC poken ;
+
+INT PROC peek (INT CONST shard adr) :
+ INT VAR block no, block offset ;
+ block offset := shard adr ;
+ IF shard adr < 256
+ THEN errorstop ("peek: Adresse < 256") ;
+ LEAVE peek WITH 0
+ FI ;
+ block offset := shard adr-256 ;
+ rotate (block offset, -1) ;
+ block offset := (block offset AND 255) + 1 ;
+ block no := shard adr-256 ;
+ rotate (block no, -9) ;
+ block no := (block no AND 63) + 1 ;
+ IF block no < 1 OR block no > shard bloecke
+ THEN errorstop ("peek: falsche Adresse") ;
+ LEAVE peek WITH 0
+ FI ;
+ TEXT VAR t := " " ;
+ replace (t, 1, block (block no)(block offset)) ;
+ code (t SUB ((shard adr AND 1) + 1))
+ENDPROC peek ;
+
+
+INT PROC peek2 (INT CONST shard adr) :
+ INT VAR r := peek (shard adr + 1) ;
+ rotate (r, 8) ;
+ r + peek (shard adr)
+ENDPROC peek2 ;
+
+
+PROC get partition :
+ INT VAR partition, cyls, heads, secs ;
+ get media size (setup channel, cyls, heads, secs) ;
+ get partition table ;
+ get partition number from user ;
+ line ;
+ IF (partition size high AND -256) <> 0 OR
+ (partition start high AND -256) <> 0
+ THEN errorstop ("Sorry, Partitionsangaben zu hoch")
+ FI ;
+ line ;
+ partition start1 := real24 (partition start high, partition start low)-1.0;
+ partition size := real24 (partition size high, partition size low) ;
+ putline ("Platte hat " + text (cyls) + " Cylinder, " + text (heads) +
+ " Heads, " + text (secs) + " Sektoren = " +
+ text (real(cyls)*real(heads)*real(secs)/2048.0, 5, 1) + " MB") ;
+ putline ("Partionsanfang: " +
+ text ((partition start 1+1.0)/2.0, 6, 0) + " KB = Cylinder " +
+ text (int ((partition start 1+1.0)/real(secs)/real(heads)))) ;
+ putline ("Partionsgr”sse: " + text (partition size/2.0, 6, 0) + " KB = " +
+ text (int (partition size/real(secs)/real(heads))) + " Cylinder");
+ put ("Diese Partition ist") ;
+ IF NOT partition active
+ THEN put (""15"nicht"14"")
+ FI ;
+ putline ("aktiviert.") ;
+ line .
+
+get partition table :
+ blockin (setup channel, partition table, 0.0) .
+
+get partition number from user :
+ FOR partition FROM 1 UPTO max partitions REP
+ IF eumel partition CAND yes ("EUMEL-Partiton " +
+ text (partition type) + " patchen")
+ THEN LEAVE get partition number from user
+ FI
+ PER ;
+ partition := 0 ;
+ errorstop ("Keine EUMEL Partition gefunden") .
+
+
+eumel partition :
+ partition type >= 69 AND partition type <= 72 .
+
+entry : 216 + partition * 8 .
+partition active : bit (partition table (entry), 7) .
+partition type : partition table (entry + 2) AND 255 .
+partition start low : partition table (entry + 4) .
+partition start high: partition table (entry + 5) .
+partition size low : partition table (entry + 6) .
+partition size high: partition table (entry + 7) .
+
+ENDPROC get partition ;
+
+PROC read shard :
+ INT VAR i ;
+ old session := session ;
+ FOR i FROM 1 UPTO shard bloecke REP
+ cout (i) ;
+ modified (i) := FALSE ;
+ blockin (setup channel, block (i), partition start1 + real(i-1))
+ PER ;
+ENDPROC read shard ;
+
+
+PROC write shard :
+ INT VAR i ;
+ FOR i FROM 1 UPTO shard bloecke REP
+ IF modified (i)
+ THEN IF session <> old session
+ THEN errorstop ("RERUN w„hrend patch")
+ FI ;
+ blockout (setup channel, block (i), partition start1+real(i-1)) ;
+ modified (i) := FALSE
+ FI ;
+ cout (i)
+ PER
+ENDPROC write shard ;
+
+REAL PROC real24 (INT CONST high, low) :
+ real (high) * 65536.0 + low real .
+
+low real :
+ IF low < 0
+ THEN real (low) + 65536.0
+ ELSE real (low)
+ FI
+ENDPROC real24 ;
+
+PROC split real24 (REAL CONST r, INT VAR high, low) :
+ high := int (r/65536.0) ;
+ low := (code (int (r MOD 256.0)) +
+ code (int ((r MOD 65536.0)/256.0))) ISUB1
+ENDPROC split real24 ;
+
+PROC patch shard :
+ get partition ;
+ read shard ;
+ check if patch possible ;
+ patch baudrate ;
+ patch id and mode ;
+ patch typematic ;
+ patch refresh ;
+ patch modem status ;
+ patch cursor maxima ;
+ patch attribute bytes ;
+ patch out restart ;
+ patch dtr inactive ;
+ patch mcr set routine ;
+ patch archive 1 format ;
+ IF yes ("Žnderungen permanent machen")
+ THEN write shard ;
+ putline ("Žnderungen durchgefhrt, System neu booten.") ;
+ ELSE putline ("Keine Žnderungen durchgefhrt.") ;
+ FI .
+
+check if patch possible :
+ IF peek2 (&"0300") <> &"05EA"
+ THEN errorstop ("Partition enthaelt keinen SHard")
+ ELSE IF peek2 (shard ver) <> 7
+ THEN errorstop ("Dies ist die falsche SHard-Version")
+ ELIF peek2 (id6) = patch version
+ THEN putline ("Hinweis: Dieser SHard wurde bereits gepatcht")
+ ELIF peek2 (id6) <> 0
+ THEN putline ("Der SHard-Patch wird upgedated")
+ FI
+ FI .
+
+shard ver: &"0554" .
+mode: &"0556" .
+id 6: &"055C" .
+
+patch baudrate :
+ putline ("Baudrates 50, 75 entfernt, 19200, 38400 eingefgt.") ;
+ poke2 (&"07E8", 1047) ; (* 3: 110 *)
+ poke2 (&"07EA", 857) ; (* 4: 134.5 *)
+ poke2 (&"07EC", 768) ; (* 5: 150 *)
+ poke2 (&"07EE", 384) ; (* 6: 300 *)
+ poke2 (&"07F0", 192) ; (* 7: 600 *)
+ poke2 (&"07F2", 96) ; (* 8: 1200 *)
+ poke2 (&"07F4", 64) ; (* 9: 1800 *)
+ poke2 (&"07F6", 48) ; (* 10: 2400 *)
+ poke2 (&"07F8", 32) ; (* 11: 3600 *)
+ poke2 (&"07FA", 24) ; (* 12: 4800 *)
+ poke2 (&"07FC", 16) ; (* 13: 7200 *)
+ poke2 (&"07FE", 12) ; (* 14: 9600 *)
+ poke2 (&"0800", 6) ; (* 15: 19200 *)
+ poke2 (&"0802", 3) ; (* 16: 38400 *)
+
+ (* Korrektur der Adressoffsetberechnung auf Baudtable *)
+ (* Maschinencode nicht veraendern!
+ 08F4:
+ i8250_baud:
+ CMP BH,17
+ JNC i8250_not_ok
+ CMP BH,3
+ JC i8250_not_ok
+ ....
+ 0918:
+ MOV AX,WORD PTR i8250_baud_table-6[BX]
+*)
+ poken (&"08F4", "17 73 75 80 FF 03 72 70") ;
+ poken (&"0918", "87 E2") .
+
+patch id and mode :
+ poke2 (id6, patch version) ; (* Update Patch Version *)
+ IF yes ("Soll ein Vortest durchgefhrt werden")
+ THEN IF yes ("Soll ein Speichertest durchgefuehrt werden")
+ THEN poke2 (mode, 0)
+ ELSE poke2 (mode, 256)
+ FI
+ ELSE poke2 (mode, 512)
+ FI .
+
+patch modem status:
+ poke (&"0A5D", 6) . (* Modem Status Register Offset = 6 *)
+
+patch typematic: (* Nur mit ruc-Bios *)
+ INT VAR typematic ;
+ IF yes ("Schneller Keyboardrepeat")
+ THEN typematic := 4 (* Fast *)
+ ELSE typematic := 2 * 256 + 12 (* Standard *)
+ FI ;
+ (* Maschinencode, nicht veraendern!
+ 0E20:
+ XOR AX,AX ; Set Default Video Mode
+ INT 10H
+ MOV AX,0342 ; Set Typematic + Marwin
+ MOV BX,typematic ; BH = Delay (0..3), BL = Rate (0..31)
+ INT 16H
+ 0E2C:
+ MOV AL,54H ; Ab hier in 'patch refresh'
+ OUT [43H],AL ;
+ JMP $+2 ;
+ MOV AL,interval ; interval = 1.19 * us
+ OUT [41H],AL ;
+ RET ; End pc_init
+*)
+ poken (&"0E20", "33 C0 CD 10 B8 42 03 BB " + %typematic + " CD 16 C3") .
+ (* RET wird ueberschrieben von Refresh *)
+
+patch refresh:
+ INT VAR refresh ;
+ TEXT VAR ref := "15.126" ;
+ line ;
+ putline ("215us Refresh-Intervall bringen 5% mehr RAM-Performance.") ;
+ putline ("Achtung: Nicht bei allen RAMs moeglich (z.B. 120ns Toshiba nicht).") ;
+ put ("RAM-Refresh Intervall (in us):") ;
+ editget (ref) ; line ;
+ refresh := int (1.19 * real (ref) + 0.5) ;
+ IF refresh < 1
+ THEN refresh := 1
+ ELIF refresh > 255
+ THEN refresh := 256
+ FI ;
+ put (real (refresh) / 1.19) ;
+ putline ("us Refresh-Intervall eingestellt.") ;
+ IF refresh = 256 THEN refresh := 0 FI ;
+ poken (&"0E2C", "B0 54 E6 43 EB 00 B0 " + subtext (%refresh, 3, 4) +
+ " E6 41 C3") .
+
+patch cursor maxima:
+(* Es werden nur die Maxima bei CURSOR(,) veraendert, CLEOL, CLEOP,SCROLL
+ etc. arbeiten weiter mit 24 Zeilen, 80 Spalten *)
+ (* CURSOR y:0..43, x:0..89 EUMEL l„sst allerdings nur 0..79 zu *)
+ poke (&"0EFF", 43) ;
+ poke (&"0F16", 89) .
+
+patch attribute bytes:
+ poke (&"0FD4", 0) ; poke (&"0FE8", 0) ; (* CLEOP *)
+ poke (&"1002", 0) ; (* CLREOL *)
+ poke (&"1027", 0) . (* SCROLL *)
+
+patch out restart :
+ poke (&"09BA", 0) . (* out_restart immer: JP $+0 *)
+
+patch dtr inactive :
+ poke (&"0A30", 8) . (* RTS + DTR inaktiv, OUT2 muss an bleiben *)
+
+patch mcr set routine :
+ (*
+ 0812: 20 Bytes zur Verfgung
+ MOV DX,(DI+i8250_base)
+ ADD DX,i8250_mcr
+ MOV AL,BH ; Highbyte 2. IOCONTROL Parameter
+ OUT [DX],AL
+ MOV CX,0
+ RET
+ *)
+ poken (&"0812", "8B 95 1B 00 83 C2 04 88 F8 EE B9 00 00 C3") .
+
+patch archive 1 format :
+ line ;
+ putline ("Archiv-Kanal 30-Laufwerk (bitte Typnummer angeben):") ;
+ putline (" 0: Nicht vorhanden") ;
+ putline (" 1: 360K (Standard/Doublestep)") ;
+ putline (" 2: 720K (Standard/Singlestep)") ;
+ putline (" 3: 1.2MB (Multifunction)") ;
+ putline ("ESC: Nichts ver„ndern") ;
+ put ("Typ:") ;
+ TEXT VAR t ;
+ REP inchar (t) UNTIL t >= "0" AND t <= "3" OR t = ""27"" PER ;
+ putline (t) ;
+ line ;
+ IF t = "0" OR t = "1"
+ THEN poken (&"21DE", "00 01")
+ ELIF t = "2"
+ THEN poken (&"21DE", "04 02")
+ ELIF t = "3"
+ THEN poken (&"21DE", "01 03")
+ FI .
+
+ENDPROC patch shard ;
+
+PROC blockin (INT CONST kanal, ROW 256 INT VAR block, REAL CONST blockno) :
+ INT VAR r, my channel :: channel, high, low ;
+ split real24 (blockno, high, low) ;
+ continue (kanal) ;
+ blockin (block, high AND 255, low, r) ;
+ continue (my channel) ;
+ SELECT r OF
+ CASE 0 :
+ CASE 1 : errorstop ("Harddisk kann nicht gelesen werden")
+ CASE 2 : errorstop ("Lesefehler bei Block " + text (blockno))
+ CASE 3 : errorstop ("Block " + text(blockno) + " zu hoch")
+ OTHERWISE errorstop ("unbekannter Lesefehler auf Harddisk")
+ ENDSELECT .
+
+ENDPROC blockin ;
+
+PROC blockout (INT CONST kanal, ROW 256 INT VAR block, REAL CONST blockno):
+ INT VAR r, my channel :: channel, high, low ;
+ split real24 (blockno, high, low) ;
+ continue (kanal) ;
+ blockout (block, high AND 255, low, r) ;
+ continue (my channel) ;
+ SELECT r OF
+ CASE 0 :
+ CASE 1 : errorstop ("Harddisk kann nicht beschrieben werden")
+ CASE 2 : errorstop ("Schreibfehler bei Block " + text (blockno))
+ CASE 3 : errorstop ("Block " + text (blockno) + " zu hoch")
+ OTHERWISE errorstop ("unbekannter Schreibfehler auf Harddisk")
+ ENDSELECT .
+
+ENDPROC blockout ;
+
+PROC get media size (INT CONST kanal, INT VAR cyls, heads, secs) :
+ INT CONST old channel :: channel ;
+ continue (kanal) ;
+ control (-10, 0, 0, cyls) ; cyls INCR 1 ;
+ control (-11, 0, 0, secs) ;
+ control (-12, 0, 0, heads) ;
+ continue (old channel)
+ENDPROC get media size ;
+(*
+PROC dump block (INT CONST adr) :
+TEXT VAR t ;
+FOR i FROM adr UPTO adr+511 REP
+ IF (i AND 15) = 0
+ THEN line ;
+ put (%i+":") ;
+ t := "" ;
+ FI ;
+ INT CONST j :: peek (i) ;
+ IF j < 32 OR j > 126 THEN t CAT "."
+ ELSE t CAT code (j) FI ;
+ outsubtext (%j, 3, 4) ;
+ out (" ") ;
+ IF (i AND 15) = 15
+ THEN out (t)
+ FI
+PER ;
+line
+ENDPROC dump block ;
+
+putline ("Partitionstabelle lesen...") ;
+get partition ;
+putline ("SHard lesen...") ;
+read shard ;
+put (%peek (1364)) ;
+*)
diff --git a/system/shard-x86-at/7/src/PATCHARE.ASM b/system/shard-x86-at/7/src/PATCHARE.ASM
new file mode 100644
index 0000000..eb837e0
--- /dev/null
+++ b/system/shard-x86-at/7/src/PATCHARE.ASM
@@ -0,0 +1,17 @@
+;********************************************************
+;*==== Copyright (C) 1985,86 Martin Schoenbeck, Spenge =*
+;* *
+;* Bereich, der vom setup-Programm gepatcht wird *
+;* *
+;********************************************************
+
+ if at
+bb_table dw 32 DUP (-1)
+ dw 32 DUP (-1)
+max_bb equ 32
+bb_anz dw 0
+ else
+bt_table dw 8 DUP (-1) ;diese kopf/spur Kombination ist unmoeglich
+bt_replace dw 8 DUP (-1) ;ersatz
+ endif
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/PCPAR.ASM b/system/shard-x86-at/7/src/PCPAR.ASM
new file mode 100644
index 0000000..9ac1ebf
--- /dev/null
+++ b/system/shard-x86-at/7/src/PCPAR.ASM
@@ -0,0 +1,226 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Routinen fuer IBM - PC Parallel - Schnittstelle im EUMEL - System *
+;* *
+;* *
+;***************************************************************************
+
+ device parallel
+
+ dtcbroutines iocontrol
+ routine 1,para_devicetype
+ routine 2,para_frout
+ routine 5,nil_size
+ routine -3,para_force_rom_output
+ routine -4,para_set_wait
+ routine -1,no_channel_setup
+
+ dtcbroutines control32
+ routine -2,para_init
+ routine -1,no_channel_setup
+
+ dtcbroutines blockin
+ dtcbroutines blockout
+ routine -1,unknowncontrol
+
+ dtcbparams para_output,3 ;typ = nur stream io
+
+
+;******************************************************************
+;* der macro para_ccb muss fuer jede parallelschnittstelle im system
+;* einmal aufgerufen werden
+;*
+;* parameter:
+
+para_ccb macro par,kanal
+ startccb para&par&ccb,kanal
+ccbentry para_number
+ dw par
+ccbentry para_stat
+ db 0
+ccbentry para_statusandmask
+ db 80h ;;busy abfragen
+ccbentry para_statusxormask
+ db 80h ;;active high
+ccbentry para_wait ;;wie lange vor busy warten
+ db 1
+ccbentry para_retry
+ db 30 ;;> 100 usec minimum
+ endm
+
+para_rom_mode equ 1
+
+para_devicetype:
+ mov cx,0 ;erstmal 0 setzen
+ call para_get_port
+ ifnz <mov cl,shard:(si+devtype)> ;type dazu
+ ret
+
+para_init:
+ call para_get_port
+ ifz <ret>
+ test dx,0fc03h ;ist die adresse ibm like
+ jnz para_rom_init
+ inc dx
+ inc dx ;auf status ausgabe zeigen
+ mov al,8 ;init leitung aktivieren
+ out (dx),al
+ mov ax,4000
+para_ini_loop:
+ dec ax
+ jnz para_ini_loop ;warte ein weilchen
+ mov al,0ch ;kein auto lf, init high
+ out (dx),al
+ ret
+
+para_rom_init:
+ mov ah,1
+ mov dx,[di+para_number]
+ int 17h
+ ;es passt noch
+ mov bx,dx ;nummer nach bx
+ mov byte ptr es:[078h+bx],1 ;timeout wert,falls er doch mal busy kriegt
+ ret
+
+para_set_wait:
+ inc dl
+ mov [di+para_wait],dl
+ inc dh
+ mov [di+para_retry],dh
+ ret
+
+para_force_rom_output:
+ or byte ptr [di+para_stat],para_rom_mode
+ ret
+
+para_output:
+ jcxz para_all
+ push es
+ push bx
+ call para_get_port
+ pop bx
+ pop es
+ jz para_all ;kein port, dann wegwerfen
+ test dx,0fc03h ;ist die adresse ibm like
+ jnz para_rom_output ;nein, ueber rom raus
+ test byte ptr [di+para_stat],para_rom_mode
+ jnz para_rom_output
+ push cx
+ inc dx ;auf status gehen
+para_out_loop:
+ push cx
+ mov cl,[di+para_wait]
+ sub ch,ch ;0 nach ch
+ loop $ ;pause fuer langsame drucker
+ mov cl,[di+para_retry]
+ ;ch ist 0
+para_ow_loop: ;warten, bis output erlaubt
+ in al,dx ;status holen
+ and al,(di+para_statusandmask) ;welche bits interessieren uns
+ xor al,(di+para_statusxormask) ;und wie sollen sie stehen
+ jz para_ready ;passt, ausgeben
+ loop para_ow_loop
+ pop dx ;restlaenge holen
+ pop cx ;gesamtlaenge holen
+ sub cx,dx ;uebernommene laenge melden
+ ;carry ist geloescht
+ ret
+
+para_ready:
+ pop cx ;zeichenzaehler zurueckholen
+ dec dx ;auf port direkt gehen
+ mov al,byte ptr es:[bx] ;zeichen holen
+ inc bx ;auf naechstes zeichen
+ out (dx),al ;zeichen ausgeben
+ inc dx
+ inc dx ;auf port fuer strobe zeigen
+ mov al,0dh ;strobe ist bit 0
+ out (dx),al
+ jmp short $+2
+ mov al,0ch ;und strobe zuruecknehmen
+ out (dx),al
+ dec dx ;auf status port gehen
+ loop para_out_loop ;naechstes ausgeben
+ pop cx ;alles ausgegeben
+para_all:
+ stc
+ ret
+
+para_rom_output:
+ push cx
+ mov dx,[di+para_number]
+para_rom_out_loop:
+ push cx
+ mov cl,[di+para_wait]
+ sub ch,ch
+ loop $ ;pause fuer langsame drucker
+ mov cl,[di+para_retry]
+ shr cl,1 ;durch 16
+ shr cl,1
+ shr cl,1
+ shr cl,1
+ inc cl ;aber nie 65000 mal
+para_rom_ow_loop: ;warten, bis output erlaubt
+ mov ah,2 ;status holen
+ int 17h
+ and ah,(di+para_statusandmask) ;welche bits interessieren uns
+ xor ah,(di+para_statusxormask) ;und wie sollen sie stehen
+ jz para_rom_ready ;passt, ausgeben
+ loop para_rom_ow_loop
+ pop dx ;restlaenge holen
+ pop cx ;gesamtlaenge holen
+ sub cx,dx ;uebernommene laenge melden
+ ;carry ist geloescht
+ ret
+
+para_rom_ready:
+ pop cx ;zeichenzaehler zurueckholen
+ mov al,byte ptr es:[bx] ;zeichen holen
+ inc bx ;auf naechstes zeichen
+ mov ah,0 ;zeichen ausgeben
+ int 17h
+ loop para_rom_out_loop ;naechstes ausgeben
+ pop cx ;alles ausgegeben
+ stc
+ ret
+
+para_frout:
+ call para_get_port
+ jz para_frout_ok
+ test dx,0fc03h ;ist die adresse ibm like
+ jnz para_rom_frout ;nein, ueber rom fragen
+ test byte ptr [di+para_stat],para_rom_mode
+ jnz para_rom_frout
+ inc dx ;auf status gehen
+ in al,dx ;status holen
+ and al,(di+para_statusandmask) ;welche bits interessieren uns
+ xor al,(di+para_statusxormask) ;und wie sollen sie stehen
+ jnz para_frout_not_ok ;passt nicht, melden
+para_frout_ok:
+ mov cx,50 ;kann ausgeben
+ stc ;puffer leer
+ ret
+
+para_rom_frout:
+ mov dx,[di+para_number]
+ mov ah,2 ;status holen
+ int 17h
+ and ah,(di+para_statusandmask) ;welche bits interessieren uns
+ xor ah,(di+para_statusxormask) ;und wie sollen sie stehen
+ jz para_frout_ok ;passt, melden
+para_frout_not_ok:
+ mov cx,0 ;nichts passt
+ clc ;puffer nicht leer
+ ret
+
+para_get_port:
+ ;setzt zero flag, wenn port = 0
+ mov ax,40h ;ins pc datensegment
+ mov es,ax
+ mov bx,[di+para_number] ;welcher printer
+ shl bx,1 ;fuer basis adresse passend
+ mov dx,es:[8+bx] ;printer basis adresse holen
+ or dx,dx ;0?
+ ret
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/PCPLOT.ASM b/system/shard-x86-at/7/src/PCPLOT.ASM
new file mode 100644
index 0000000..6718e12
--- /dev/null
+++ b/system/shard-x86-at/7/src/PCPLOT.ASM
@@ -0,0 +1,430 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Graphikroutinen fuer IBM - PC *
+;* *
+;* *
+;****************************************************************************
+
+gr_base dw 03d0h ;default grahpic adress
+
+gr_pointer equ 4 ;pointer register of 6845
+gr_data equ 5 ;data register of 6845
+gr_msr equ 8 ;mode select register
+gr_csr equ 9 ;color select register
+gr_status equ 10 ;status register
+gr_xmsr equ 10 ;extended mode select register
+gr_cfgswitch equ 15 ;hercules config switch
+
+switch_mode:
+ cmp dh,1
+ jz gm_switch ;tecmar graphics master
+ cmp dh,2 ;hercules
+ jz herc_switch
+ push dx
+ push ax
+ mov dx,[gr_base]
+ add dx,gr_xmsr ;tecmar auf normal mode setzen
+ mov al,0
+ out (dx),al
+ jmp short $+2 ;io pause machen
+ add dx,gr_cfgswitch-gr_xmsr ;hercules configswitch
+ out (dx),al
+ pop ax
+ pop dx
+ mov byte ptr [plot_mode],0 ;kein mode, den wir direkt auswerten
+ mov al,dl
+ mov ah,0
+ int 10h ;auf gewuenschten mode schalten
+ mov cx,0
+ jnc mode_ok
+unallowed_mode:
+ mov cx,-1
+mode_ok:
+ ret
+
+herc_switch:
+ mov word ptr [gr_base],03b0h
+ cmp dl,1 ;mode 0 ist erlaubt
+ jnc unallowed_mode
+ add dl,6 ;da steht der erste herculesmode
+ jmp short all_allowed
+gm_switch: ;tecmar graphics master
+ cmp dl,6 ;werte 0 bis 5 erlaubt
+ jnc unallowed_mode
+ push dx
+ mov dx,[gr_base]
+ add dx,gr_status ;statusregister holen
+ in al,dx
+ pop dx
+ test al,80h ;schalter auf monochrom
+ jnz all_allowed ;nein, alle modi erlaubt
+ cmp dh,2 ;nur 0 und 1
+ jnc unallowed_mode
+all_allowed:
+ mov byte ptr [plot_mode],1 ;merken, dass in erweitertem mode
+ mov dh,0
+ mov ax,offset mod_tb_length ;laenge einer tabelle
+ mul dx ;auf passende tabelle zeigen
+ mov bx,ax
+ add bx,offset mod_tables ;auf erstes byte der tabelle
+;
+ mov ah,13 ;vierzehn register muessen ausgegeben werden
+ mov dx,[gr_base]
+ add dx,gr_msr ;da ist mode select register unserer graphik
+ mov al,0 ;disable screen output
+ out (dx),al
+ jmp short $+2
+ add dx,gr_cfgswitch-gr_msr ;hercules einschalten (wenn da)
+ mov al,3
+ out (dx),al
+ sub dx,gr_cfgswitch-gr_pointer
+
+set_6845:
+ mov al,ah
+ out (dx),al ;in dieses register wollen wir schreiben
+ inc dx ;und hier muss der wert hin
+ mov al,byte ptr [bx]
+ inc bx ;auf naechstes feld
+ out (dx),al
+ dec dx ;wieder auf zeiger_register
+ dec ah
+ jns set_6845 ;bis nummer negativ
+;
+ cld
+ mov cx,08000h ;fill 64k
+ mov ax,0a000h
+ mov es,ax
+ xor ax,ax ;fill with 0
+ xor di,di ;start at 0 in area
+ rep stosw
+ mov cx,08000h
+ mov ax,0b000h ;next 64k
+ mov es,ax
+ xor ax,ax ;fill with 0
+ xor di,di ;start at 0 in area
+ rep stosw
+;
+ mov al,byte ptr[bx] ;csr wert holen
+ inc bx
+ add dx,gr_csr-gr_pointer
+ out (dx),al
+;
+ inc dx ;to xmsr
+ mov al,byte ptr [bx]
+ inc bx
+ out (dx),al
+;
+ sub dx,gr_xmsr-gr_msr ;to msr
+ mov al,byte ptr [bx]
+ inc bx
+ out (dx),al
+;
+ mov ax,word ptr [bx] ;laenge einer graphik zeile
+ inc bx
+ inc bx
+ mov word ptr [gr_linelength],ax
+;
+ mov al,byte ptr [bx] ;maske, um ein pixel zu behalten
+ push ds
+ pop es
+ mov cx,16
+ mov di,offset color_tab
+ rep stosb ;farbtabelle auf 3 initalisieren
+ mov ah,0
+ inc bx
+ mov word ptr [gr_pixel_mask],ax
+ xor al,0ffh ;maske erzeugen, die ein pixel loescht
+ mov byte ptr [gr_pixel_inv_mask],al
+;
+ mov word ptr [first_shift],9090h ;ersten shift wegnoppen
+ test byte ptr [bx],1 ;vier segmente ?
+ ifnz <mov word ptr [first_shift],0ebd1h> ;shift wieder eintragen
+ inc bx
+;
+ mov al,byte ptr [bx] ;mask fuer pixel_pro_byte holen
+ inc bx
+ mov byte ptr [gr_pixel_per_byte_mask],al
+ mov word ptr [shift_count_shift],0c902h ;volles shift annehmen
+ mov word ptr [shift_count_shift+2],0c902h ;add cl,cl
+ mov ah,1 ;anzahl shifts, um byteoffset zu kriegen
+ shr al,1 ;bei mehr als zwei pixel ein shift weniger
+ jz shifts_nopped
+ inc ah
+ mov word ptr [shift_count_shift],09090h ;nops
+ shr al,1 ;bei acht pixel gar kein shift
+ jz shifts_nopped
+ inc ah
+ mov word ptr [shift_count_shift+2],09090h ;nops
+shifts_nopped:
+ mov byte ptr [gr_byte_calc_shift],ah
+;
+ mov si,bx
+ mov di,offset gr_segtable
+ mov cx,4
+ rep movsw ;segmentwerte uebertragen
+ add bx,8
+ mov cx,0
+ ret
+
+pen:
+ mov word ptr [maske],dx
+ mov byte ptr [linetype],bl
+ ret
+
+new_pen1:
+ mov cx,bx ;bx merken
+ mov bx,offset color_tab
+ call set4
+ mov cx,dx
+ call set4
+ ret
+
+new_pen2:
+ mov cx,bx ;bx merken
+ mov bx,offset color_tab+8 ;zweite haelfte der tabelle
+ call set4
+ mov cx,dx
+ call set4
+ ret
+
+set4:
+ call set2
+ mov cl,ch
+set2:
+ mov al,cl
+ and al,15 ;nur untersten 4 bits behalten
+ mov byte ptr [bx],al
+ inc bx
+ mov al,cl
+ mov cl,4
+ shr al,cl ;obersten 4 bits
+ mov byte ptr [bx],al
+ inc bx
+ ret
+
+mask_mode:
+ mov word ptr [jmp_or_not],9090h ;set mask mode
+ mov cx,word ptr [mask_count] ;alten mask_count zurueckliefern
+ mov word ptr [mask_count],bx
+ cmp dx,0 ;wirklich mask_mode gewuenscht
+ ifz <mov word ptr [jmp_or_not],07ebh> ;nein, sprung wieder einbauen
+ ret
+
+move:
+ mov word ptr [altx],dx ;neuen x wert
+ mov word ptr [alty],bx ;und y wert setzen
+ ret
+
+draw:
+ mov byte ptr [stepx],46h ;inc si
+ mov byte ptr [stepy],47h ;inc di
+ mov cx,dx ;in welche richtung wie weit gehen
+ sub cx,word ptr [altx]
+ jns positiv_x
+ neg cx ;negative richtung, positiv machen und
+ mov byte ptr [stepx],4eh ;dec si zum ausgleich
+positiv_x:
+ mov dx,bx ;y wert holen
+ sub dx,word ptr [alty] ;wie weit und welche richtung
+ jns positiv_y
+ neg dx ;negative richtung, positiv rechnen und
+ mov byte ptr [stepy],4fh ;dec di zur korrektur
+positiv_y:
+ cmp dx,cx ;hauptrichtung entlang des groesseren
+ ;offsets
+ jc direction_ok ;hauptrichtung war entlang si
+ mov bx,word ptr [stepy] ;richtungen tauschen
+ xchg bh,bl
+ mov word ptr [stepy],bx
+ xchg cx,dx ;und richtungslaengen tauschen
+ ;hauptrichtung ist jetzt entlang di
+direction_ok:
+ ;der wert fuer die hauptrichtung ist
+ ;in cx, fuer die nebenrichtung in dx
+ ;der fehlerwert der nebenrichtung in
+ ;1/abs(hauptrichtung) - einheiten ist in bx
+ mov bx,0 ;fehlerwert ist im moment 0
+ mov word ptr [delta_x],cx ;wert fuer hauptrichtung merken
+ mov si,word ptr [altx] ;alte werte holen
+ mov di,word ptr [alty]
+paint:
+ jcxz paint_done ;fertig, letzten punkt noch malen
+ sub bx,dx ;ist gerader fehler schon negativ
+ jns stepx ;nur hauptrichtung nehmen
+ mov ax,bx ;geraden fehler nach ax
+ add ax,ax ;
+ add ax,word ptr [delta_x] ;
+ jns stepx ;nur hauptrichtung
+ add bx,word ptr [delta_x]
+stepy:
+ inc di
+stepx:
+ inc si
+
+; errechneten punkt setzen
+
+ call punkt
+
+ loop paint
+
+paint_done:
+ call punkt ;letzten punkt setzen
+ mov word ptr [alty],di
+ mov word ptr [altx],si
+ ret
+
+
+punkt:
+ test byte ptr [plot_mode],0ffh
+ jnz new_punkt
+ push cx
+ push dx
+ mov dx,di
+ mov cx,si
+ ror word ptr maske,1
+linetype equ $+1
+ mov ax,0c01h ;write dot
+ and al,byte ptr [maske] ;linie einbauen
+ int 10h
+ pop dx
+ pop cx
+ ret
+
+new_punkt:
+ push ax
+ push bx
+ push cx
+ push dx
+ push es
+ mov bx,di
+ and bx,3
+ add bx,bx ; *2
+ mov es,[bx+gr_segtable] ;in diesem segment liegt unser punkt
+gr_linelength equ $+1
+ mov ax,720/4 ;bytes pro zeile horizontal
+ mov bx,di ;y wert wieder holen
+first_shift: ;dieser shift faellt bei zwei segmenten aus
+ shr bx,1
+ shr bx,1 ;di / 4
+ mul bx ;mal anzahl bytes pro graphikzeile
+ mov bx,si ;byte in zeile ausrechnen
+gr_byte_calc_shift equ $+1
+ mov cl,2 ;so oft si shiften, fuer byte in zeile
+ shr bx,cl
+ add bx,ax ;dies byte enthaelt unseren punkt
+ mov cx,si ;untersten bits geben shiftfaktor an
+ inc cx ;einmal mehr shiften (oder gar nicht)
+gr_pixel_per_byte_mask equ $+2
+ and cl,3 ;vier pixel pro byte (15 fuer zwei pixel etc
+shift_count_shift:
+ add cl,cl ;shiftfaktor verdoppeln
+ add cl,cl ;oder vervierfachen
+ mov al,byte ptr es:[bx] ;byte holen
+ rol al,cl ;pixel nach 0 holen
+ mov bp,ax ;evtl. wird pixelwert als index benutzt
+gr_pixel_mask equ $+2
+ and bp,3 ;die pixel bits behalten
+jmp_or_not:
+ jmp short punkt_no_mask
+mask_count equ $+1 ;zaehler fuer maske
+ mov bp,0
+ and bp,15 ;maskenzaehler MOD 16 nehmen
+punkt_no_mask:
+gr_pixel_inv_mask equ $+1
+ and al,0fch ;rest behalten
+ or al,byte ptr ds:[bp+color_tab] ;pixel setzen
+ ror al,cl ;zurueckdrehen
+ mov byte ptr es:[bx],al ;wieder eintragen
+ inc word ptr ds:[mask_count]
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+ even
+
+maske dw 0ffffh
+altx dw 0
+alty dw 0
+delta_x dw 0
+;gr_pixel_mask dw 3 ;maske, welche bits zum pixel gehoeren
+;mask_count dw 0 ;zaehler fuer maskiertes schreiben
+
+gr_segtable dw 0a000h ;tabelle der graphik segmente
+ dw 0a800h
+ dw 0b000h
+ dw 0b800h
+
+
+;gr_linelength dw 720/4 ;laenge einer graphikzeile
+;mask_mod db 0 ;nicht 0, wenn mit maske
+color_tab db 16 DUP (3) ;farbtabelle
+
+plot_mode db 0
+
+;gr_pixel_inv_mask db 0fch ;invertiert, nur byte
+
+
+
+mod_tables equ $
+;mode 0
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,3,2,88,86,1,91,14,90,90,109, 0, 191, 11
+ dw 720/4 ;laenge einer graphikzeile
+ db 3 ;maske, um ein pixel zu behalten
+ db 1 ;1 = 4 segmente, 0 = 2 segmente
+ db 3 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente
+mod_tb_length equ $-mod_tables
+;mode 1
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,3,3,88,86,1,91,14,90,90,109, 0, 191, 11
+ dw 720/4 ;laenge einer graphikzeile
+ db 3 ;maske, um ein pixel zu behalten
+ db 1 ;1 = 4 segmente, 0 = 2 segmente
+ db 3 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente
+;mode 2
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,1,2,112,100,6,127,15,184,160,227, 0, 31, 24
+ dw 640/2 ;laenge einer graphikzeile
+ db 15 ;maske, um ein pixel zu behalten
+ db 0 ;1 = 4 segmente, 0 = 2 segmente
+ db 1 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0a000h,0a800h ;die vier segmente
+;mode 3
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,3,3,56,50,1,64,15,184,160,227, 0, 31, 24
+ dw 640/2 ;laenge einer graphikzeile
+ db 15 ;maske, um ein pixel zu behalten
+ db 1 ;1 = 4 segmente, 0 = 2 segmente
+ db 1 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente
+;mode 4
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,1,2,112,100,7,127,15,98,90,128, 0, 63, 11
+ dw 720/4 ;laenge einer graphikzeile
+ db 3 ;maske, um ein pixel zu behalten
+ db 0 ;1 = 4 segmente, 0 = 2 segmente
+ db 3 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0a000h,0a800h ;die vier segmente
+;mode 5
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,32,3,3,56,50,3,64,15,98,90,128, 0, 63, 11
+ dw 720/4 ;laenge einer graphikzeile
+ db 3 ;maske, um ein pixel zu behalten
+ db 1 ;1 = 4 segmente, 0 = 2 segmente
+ db 3 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente
+;mode 6 (hercules)
+; 6845 regs 13 - 0,csr,xmsr,msr
+ db 0,0,0,0,3,2,87,87,2,91,7,46,45,53, 0, 0, 10
+ dw 720/8 ;laenge einer graphikzeile
+ db 1 ;maske, um ein pixel zu behalten
+ db 1 ;1 = 4 segmente, 0 = 2 segmente
+ db 7 ;maske, um si MOD pixel_pro_byte zu machen
+ dw 0b000h,0b200h,0b400h,0b600h ;die vier segmente
+  \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/PCSCREEN.ASM b/system/shard-x86-at/7/src/PCSCREEN.ASM
new file mode 100644
index 0000000..9fe7d9e
--- /dev/null
+++ b/system/shard-x86-at/7/src/PCSCREEN.ASM
@@ -0,0 +1,438 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Behandlung des PC Bildschirms und der Tastatur *
+;* *
+;***************************************************************************
+
+ device pc
+
+ dtcbroutines iocontrol
+ routine 1,devicetype
+ routine 2,frout_ok
+ routine 5,nil_size
+ routine 6,priv_op_question
+ routine 8,priv_op_question
+ routine 9,priv_op_question
+ routine -3,set_attribute
+ routine -4,set_palette
+ routine -5,switch_mode
+ routine -6,draw
+ routine -7,move
+ routine -8,pen
+ routine -9,new_pen1
+ routine -10,new_pen2
+ routine -11,mask_mode
+
+ routine -1,unknowncontrol
+
+ dtcbroutines control32
+ routine -2,pc_init
+ routine -1,no_channel_setup
+
+ dtcbroutines blockin
+ dtcbroutines blockout
+ routine -1,unknowncontrol
+
+ dtcbparams pc_output,3 ;typ = nur stream io
+
+
+;***************************************************************************
+
+pc_init:
+breakaddress equ 01bh*4 ;tastatur break adresse
+ mov bx,0
+ mov es,bx ;in die interrupt vektoren zeigen
+ mov word ptr es:[breakaddress+2],cs
+ mov word ptr es:[breakaddress],offset breakint
+ mov dx,0 ;cursor in die obere ecke
+ mov bh,0
+ mov ah,2 ;cursor setzen
+ int 10h
+ mov ax,0600h ;clear entire window
+ mov cx,0 ;von oben
+ mov dx,25*256+80 ;bis unten
+ mov bh,7 ;attribut
+ int 10h
+ ret
+
+;
+breakint:
+ push cx
+ push ax
+ push ds
+ push cs
+ pop ds
+; mov al,1
+; mov ch,'i'
+; call inputinterrupt
+ mov al,1
+ mov ch,2 ;sv
+ call inputinterrupt
+ pop ds
+ pop ax
+ pop cx
+ iret
+;
+;
+;
+REVERS EQU 01110000B ;ATTRIBUT FUER REVERS-VIDEO
+NORMAL EQU 00000111B ;ATTRIBUT FUER NORMAL-VIDEO
+HOME EQU 1
+RECHTS EQU 2
+OBEN EQU 3
+CLEOP EQU 4 ;CLEAR TO END OF PAGE
+CLEOL EQU 5 ;CLEAR TO END OF LINE
+CPOS EQU 6 ;CURSOR-POSITIONIERUNG
+; ES FOLGEN X- UND Y-KOORDINATE
+BELL EQU 7
+LINKS EQU 8
+UNTEN EQU 10
+RETURN EQU 13
+BEGMARK EQU 15
+ENDMARK EQU 14
+MAXCOLS EQU 79
+MAXLINES EQU 23
+ATTRIBUT DB NORMAL
+CURFLAG DB 0
+YPOS DB 0
+;
+;***********************************************************************
+;* output auf bildschirm des pc
+;*
+pc_output:
+ PUSH CX ;RETTE ORIGINALLAENGE DES STRINGS
+ CLD ;DIRECTION FLAG : INCREM. SI
+ MOV SI,BX
+OUT: mov al,es:[si] ;HOLE ZEICHEN
+ inc si
+ MOV AH,CURFLAG
+ CMP AH,0
+ JNZ s0
+ CMP AL,HOME
+ JZ s1 ;CURSOR HOME VERLANGT ?
+ CMP AL,RECHTS
+ JZ s2 ;CURSOR NACH RECHTS ?
+ CMP AL,OBEN
+ JZ s3 ;CURSOR NACH OBEN ?
+ CMP AL,CLEOP
+ JZ s4 ;LOESCHEN BIS BILDSCHIRMENDE ?
+ CMP AL,CLEOL
+ JZ s5 ;LOESCHEN BIS ZEILENENDE ?
+ CMP AL,CPOS
+ JZ s6 ;CURSOR POSITIONIEREN ?
+ CMP AL,LINKS
+ JZ s7 ;CURSOR NACH LINKS?
+ CMP AL,UNTEN
+ JZ s8 ;CURSOR NACH UNTEN ?
+ CMP AL,RETURN
+ JZ s9 ;CURSOR AN DEN ANFANG DER AKT. ZEILE ?
+ CMP AL,BEGMARK
+ JZ s10 ;AB JETZT REVERS ?
+ CMP AL,ENDMARK
+ JZ s11 ;WIEDER NORMALE VIDEO-DARSTELLUNG ?
+ CMP AL,BELL
+ JZ s12 ;KLINGELN ?
+;
+ PUSH CX
+ PUSH BX
+ PUSH SI
+ PUSH AX ;AKTUELLES ATTRIBUT
+ MOV AL,ATTRIBUT
+ MOV BL,AL
+ POP AX
+ MOV AH,9 ;SCHREIBEN MIT ATTRIBUT
+ MOV BH,0 ;PAGE #
+ MOV CX,1
+ INT 010H ;CALL BIOS
+ MOV AH,3 ;GET CURRENT CURSOR-POSITION
+ MOV BH,0 ;PAGE #
+ INT 010H ;CALL BIOS
+ INC DL ;COL = COL + 1
+ CMP DL,MAXCOLS+1
+ JNZ SAME_LINE
+ MOV DL,0
+ CMP DH,MAXLINES
+ JZ SCROLL_UP
+ INC DH
+SAME_LINE: MOV AH,2
+ mov bh,0 ;page number
+ INT 010H
+ POP SI
+ POP BX
+ POP CX
+ JMP DONE
+;
+SCROLL_UP: CALL SCROLL
+ JMP SAME_LINE
+;
+DONE: DEC CX ;ANZAHL ZEICHEN = ANZAHL ZEICHEN - 1
+ JNZ OUT ;WEITER ?
+ POP CX ;ANZAHL UEBERNOMMENE ZEICHEN (S.O.)
+ RET
+;
+s0: JMP CUR1
+s1: JMP CURHOME
+s2: JMP RIGHT
+s3: JMP UP
+s4: JMP CLEAREOP
+s5: JMP CLEAREOL
+s6: JMP CURPOS
+s7: JMP LEFT
+s8: JMP DOWN
+s9: JMP ENTER
+s10: JMP MARK
+s11: JMP UNMARK
+s12: JMP KLINGELN
+;
+;
+CURPOS:MOV AL,2
+ MOV CURFLAG,AL
+ JMP DONE
+;
+CUR1: CMP AH,1
+ JZ CURX
+ cmp al,maxlines
+ jc cur1ok
+ mov al,maxlines
+cur1ok:
+ MOV YPOS,AL
+ DEC CURFLAG
+ JMP DONE
+
+CURX: DEC CURFLAG
+ MOV DH,YPOS;Y-KOORDINATE
+ cmp al,maxcols
+ jc curxok
+ mov al,maxcols
+curxok:
+ MOV DL,AL ;X-KOORDINATE
+ PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV BH,0 ;PAGE #
+ MOV AH,2 ;SET CURSOR POSITION
+ INT 010H ;CALL BIOS
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+CURHOME: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV BH,0 ;PAGE #
+ MOV DX,0000H ;POSITION (0,0)
+ MOV AH,2
+ INT 010H ;CALL BIOS
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+RIGHT: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,3 ;GET CURRENT CURSOR-POSITION
+ MOV BH,0 ;PAGE #
+ INT 010H ;CALL BIOS
+ CMP DL,MAXCOLS ;X-POSITION DES CURSOR ZU GROSS?
+ JZ RUNTER
+ INC DL ;COL = COL + 1
+ MOV AH,2
+ INT 010H
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+RUNTER:MOV DL,0
+ MOV BH,0
+ mov ah,2
+ INT 010H
+ JMP down1
+;
+LEFT: PUSH BX ;KOMMENTARE : S.O.
+ PUSH CX
+ PUSH SI
+ MOV AH,3
+ MOV BH,0
+ INT 010H
+ DEC DL
+ MOV AH,2
+ INT 010H
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+UP: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,3
+ MOV BH,0
+ INT 010H
+ DEC DH
+ MOV AH,2
+ INT 010H
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+DOWN: PUSH BX
+ PUSH CX
+ PUSH SI
+down1: MOV AH,3
+ MOV BH,0
+ INT 010H
+ CMP DH,MAXLINES
+ JZ SCRL
+ INC DH
+ MOV AH,2
+ INT 010H
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+SCRL: CALL SCROLL
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+;
+ENTER: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,3
+ MOV BH,0
+ INT 010H
+ MOV DL,0
+ MOV AH,2
+ INT 010H
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+;
+CLEAREOP: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,3 ;GET CURRENT CURSOR-POSITION
+ MOV BH,0 ;PAGE #
+ INT 010H ;CALL BIOS
+ MOV CX,DX ;CURRENT CURS.POS = UPPER LEFT CORNER
+ MOV DL,maxcols ;END OF LINE
+ MOV AX,600H;AH=6 : SCROLL AL=0 : BLANK WINDOW
+ MOV BH,7 ;ATTRIBUTE FOR CLS
+ INT 010H ;CLEAR TO END OF LINE
+ MOV CL,0
+ CMP DH,MAXLINES
+ JZ FERTIG
+ INC CH
+ MOV DH,MAXLINES ;NEW LOWER RIGHT CORNER
+ MOV DL,MAXCOLS
+ MOV AX,600H
+ MOV BH,7 ;ATTRIBUTE FOR CLS
+ INT 010H
+FERTIG:POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+CLEAREOL: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,3 ;GET CURRENT CURSOR-POSITION
+ MOV BH,0 ;PAGE #
+ INT 010H ;CALL BIOS
+ MOV CX,DX ;CURRENT CURS.POS = UPPER LEFT CORNER
+ MOV DL,maxcols ;END OF LINE
+ MOV AX,600H;AH=6 : SCROLL AL=0 : BLANK WINDOW
+ MOV BH,7 ;ATTRIBUTE FOR CLS
+ INT 010H ;CLEAR TO END OF LINE
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+MARK:
+ MOV ATTRIBUT,revers
+ JMP DONE
+;
+UNMARK:
+ MOV ATTRIBUT,normal
+ JMP DONE
+;
+SCROLL:MOV AH,6
+ MOV AL,1 ;SCROLL WINDOW ONE LINE UP
+ MOV CX,0000H ;UPPER LEFT CORNER : (0,0)
+ MOV DH,MAXLINES
+ MOV DL,MAXCOLS
+ mov bh,7 ;attribute for scroll
+ INT 010H
+ MOV DH,MAXLINES
+ MOV DL,0
+ MOV BH,0 ;PAGE #
+ RET
+;
+;
+KLINGELN: PUSH BX
+ PUSH CX
+ PUSH SI
+ MOV AH,14
+ MOV BH,0
+ INT 010H ;PIEEPS
+ POP SI
+ POP CX
+ POP BX
+ JMP DONE
+;
+set_attribute:
+ mov attribut,dl
+ ret
+
+set_palette:
+ mov ah,11 ;set color palette
+ int 10h
+ ret
+
+;
+;
+;
+;**********************************************************************
+;*
+;* checkkey prueft ob ein zeichen auf der tastatur eingegeben wurde
+;* und uebergibt dies ggf. dem EUMEL;
+;* muss regelmaessig (z.B. aus timerinterrupt aufgerufen werden
+;
+checkkey:
+ push ax
+checkagain:
+ MOV AH,1 ;Z-FLAG GESETZT : ZEICHEN !
+ cli
+ INT 016H ;INPUT FROM KEYBOARD
+ JZ NO_KEY ;NEIN,KEINE TASTE GEDRUECKT
+ MOV AH,0
+ INT 016H ;JA, ZEICHEN ABHOLEN
+ cmp ax,0 ;kommt von 'break'
+ jz no_key
+ cmp al,0 ;extended code
+ jnz normal_key
+ mov al,ah ;mit bit acht kennzeichnen
+ or al,80h
+normal_key:
+ push cx
+ MOV CH,AL
+ MOV AL,1 ;KANAL-NUMMER
+ CALL inputinterrupt
+ pop cx
+ sti
+ jmp checkagain
+NO_KEY:
+ sti
+ pop ax
+ ret
+;
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/PCSYS.ASM b/system/shard-x86-at/7/src/PCSYS.ASM
new file mode 100644
index 0000000..6bc457f
--- /dev/null
+++ b/system/shard-x86-at/7/src/PCSYS.ASM
@@ -0,0 +1,131 @@
+;**************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ================*
+;* *
+;* PC spezifische, deviceunabhaengige routinen *
+;* *
+;**************************************************************************
+
+limit:
+ mov dx,0FFFh
+ push ax
+ push cx
+ int 12h ;Speichergroesse abholen
+ mov cl,6h
+ shl ax,cl
+ dec ax
+ mov dx,ax
+ mov ax,cs
+ sub dx,ax ;must be relativ to cs
+ pop cx
+ pop ax
+ ret
+
+paragraphs:
+ mov dx,0FFFh
+ push ax
+ push cx
+ int 12h ;Speichergroesse abholen
+ mov cl,6h
+ shl ax,cl
+ dec ax
+ mov dx,ax
+ pop cx
+ pop ax
+ ret
+
+
+;**************************************************************************
+timerint equ 08*4
+timercont equ 018h*4 ;resident basic ist ueberfluessig
+timer_init:
+ mov ax,0
+ mov es,ax
+ mov bx,word ptr es:[timerint+2]
+ mov word ptr es:[timercont+2],bx
+ mov bx,word ptr es:[timerint]
+ mov word ptr es:[timercont],bx
+ mov word ptr es:[timerint+2],cs
+ mov word ptr es:[timerint],offset timer_tick
+ ret
+;
+timer_tick:
+ int 18h
+ push ax
+ push ds
+ push cs ;ds := cs
+ pop ds
+ sti
+ call checkkey ;keybord abfragen
+ if pcd
+ mov al,50
+ else
+ mov al,55 ;ungefaehr 55 millisekunden
+ endif
+ cli
+ call timerinterrupt
+ inc tickcount
+ cmp tickcount,1000/55 ;schon eine sekunde um
+ jnc sec_tick
+ pop ds
+ pop ax
+ iret
+;
+;**************************************************************************
+;*
+;* Die Initialisierung der einzelnen Kanaele kann in der Zelle sec_entry
+;* eine Routine eintragen, die im Sekundentack (ungefaehr) aufgerufen
+;* werden soll. Diese Routine muss dann die vorher dort eingetragene
+;* Routine aufrufen. Ebenfalls kann ein di und si registerinhalt
+;* eingetragen werden, der beim aufruf gegeben sein soll. Dann ist dafuer
+;* Sorge zu tragen, dass die nachfolgenden Routine den jeweils vorher
+;* dort eingetragenen Wert erhaelt. Alle Register ausser di, si und !!ds!!
+;* duerfen beliebig zerstoert werden.
+;* ds ist immer auf das datensegment (momentan = cs) gesetzt.
+sec_tick:
+ mov tickcount,0 ;wieder vorn anfangen zu zaehlen
+ push si
+ push di
+ push bp
+ push bx
+ push cx
+ push dx
+ push es
+ mov di,word ptr sec_di
+ mov si,word ptr sec_si
+ jmp word ptr sec_entry
+sec_cont:
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop bp
+ pop di
+ pop si
+ pop ds
+ pop ax
+ iret
+
+sec_entry dw offset sec_cont
+sec_di dw 0 ;hier koennen routinen das di und das si
+sec_si dw 0 ;ablegen, mit dem sie aufgerufen werden wollen
+
+tickcount db 0
+
+;****************************************************************************
+;* neuen bootvorgang einleiten
+reboot:
+ if hdsystem
+ mov ax,0401h ;sector verify
+ mov cx,1 ;spur 0, sector 1
+ mov dx,80h ;drive 0, head 0
+ int 13h
+ endif
+ mov ax,40h
+ mov ds,ax ;auf datensegment
+ mov word ptr ds:[0072h],1234h ;reset flag
+ db 0eah ;jmp 0ffffh:0
+ dw 0
+ dw 0ffffh
+
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/SHMAIN.ASM b/system/shard-x86-at/7/src/SHMAIN.ASM
new file mode 100644
index 0000000..b7b618f
--- /dev/null
+++ b/system/shard-x86-at/7/src/SHMAIN.ASM
@@ -0,0 +1,241 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Routinen zur Verteilung der Auftraege auf verschiedene Kanaele *
+;* und Kanal 32 *
+;* *
+;****************************************************************************
+
+;******************************************************************************
+; routinen, die das restsystem vom SHard erwartet
+;******************************************************************************
+; routinen im restsystem, die SHard benutzen kann
+;systemstart = cs:1e10h
+;inputinterrupt = cs:1e13h
+;timerinterrupt = cs:1e16h
+;warte = cs:1e19h
+;freieumel0 = cs:1e1ch
+;info = cs:1e1fh
+;
+;******************************************************************************
+;******************************************************************************
+; kanalspezifische funktionen
+i_output proc far
+ push bp
+ push si
+ push di
+ push bx
+ push dx
+ push ax
+ push es
+ push ds ;bis hierhin nach funktion restaurieren
+ mov si,ds ;wir brauchen den alten wert von ds in es
+ mov es,si
+ mov si,cs ;wir brauchen ds = cs
+ mov ds,si
+ push bx ;fuer versorgung der funktion sichern
+ call select
+ pop bx
+ call shard:[si] ;routine anspringen
+ pop ds ;register wieder herstellen
+ pop es
+ pop ax
+ pop dx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+i_output endp
+
+i_blockin label far
+ push bp
+ mov bp,2 ;kennung blockin
+ jmp short dispatch
+
+i_blockout label far
+ push bp
+ mov bp,3 ;kennung blockout
+ jmp short dispatch
+
+i_iocontrol label far
+ push bp
+ mov bp,4 ;kennung iocontrol
+ jmp short dispatch
+
+control32: ;spezialaufrufe indirekt ueber kanal 32 gekommen
+ push cs
+ call i_control32
+ ret
+
+i_control32:
+ push bp
+ mov bp,5 ;kennung control32
+ jmp short dispatch
+
+;******************************************************************************
+; dispatch routine um aufrufe auf die kanalspezifischen treiber zu verteilen
+;
+; in: al = kanal
+; bp auf dem stack
+; bp = 2 bei blockin
+; 3 bei blockout
+; 4 bei iocontrol
+; 5 bei control ueber kanal 32
+; aufruf mit jmp dispatch
+;
+; funktion: aufruf der entsprechenden funktion des kanaltreibers mit
+; si = devicetypecontrolblock
+; di = channelcontrolblock
+; auf dem stack: bp, si, di, dx, es, ds, bx, returnadresse
+;
+; die routinen muessen deshalb keine register sichern.
+; soll in ds:bx etwas zurueckgeliefert werden, so ist dies ueber den
+; stack zu tun.
+;
+; out: die gewuenschte funktion wurde ausgefuehrt
+; bp, si, di, dx, bx unveraendert, ausnahme: bx in bestimmten faellen wo dies
+; ausdruecklich verlangt wird. flags, cx (ggf. bx) wie von der funktion geliefert.
+dispatch proc far
+ push si ;register sichern um sie nach ende der Funktion
+ push di
+ push dx ;zu restaurieren
+ push es
+ push ds
+ push bx
+ mov si,ds ;wir brauchen den alten wert von ds in es
+ mov es,si
+ mov si,cs ;wir brauchen ds = cs
+ mov ds,si
+ call dispexecute ;fuehre dispatch aus
+ pop bx ;register wieder herstellen
+ pop ds
+ pop es
+ pop dx
+ pop di
+ pop si
+ pop bp
+ ret ;fertig, funktion ausgefuehrt
+dispatch endp
+
+dispexecute:
+ push bx ;sichern, um versorgung der funktion durchfuehren
+ push dx ;zu koennen
+ call select ;adressen fuer diesen kanal laden
+ add bp,si ;adresse fuer offset der funktionstabelle in dtcb ausrechnen
+ mov bl,shard:[bp] ;offset nach bl
+ mov bh,0ffh ;maximal 255 byte grosse tabelle
+;bx enthaelt jetzt negativen offset
+ add bx,si ;start der tabelle fuer funktionswerte ausrechnen
+;
+; als funktionswert wird derzeit nur der bereich von -128 bis +127 akzeptiert.
+; -1 dient dabei als tabellenendekennzeichnung und wird fuer alle undefinierten
+; funktionswerte aufgerufen
+;
+; die tabelle besteht aus jeweils einem byte funktionsschluessel
+; im bereich -128 - +127 und zwei byte funktionsadresse.
+ mov dl,cl ;niederwertigen teil nach dl
+ mov al,ch ;hoeheren bits von cx muessen 0 oder 0ffh sein
+ or al,al ;ist es 0
+ jz dispfunctloop ;ja, ok
+ inc al ;oder -1
+ ifnz <mov dl,0ffh> ;nein, dann -1 als funktionswert
+dispfunctloop:
+ mov al,shard:[bx] ;aktuellen tabelleneintrag suchen
+ inc bx ;und auf dazugehoerige adresse
+ cmp al,dl ;gefunden
+ jz dispfuncfound ;ja
+ inc al ;oder -1
+ jz dispfuncfound
+ inc bx ;adresse ueberspringen
+ inc bx
+ jmp dispfunctloop
+dispfuncfound:
+ mov bp,bx ;adresse der routine nach bp
+ pop dx ;dx wieder herstellen
+ pop bx ;bx wiederherstellen
+ jmp shard:[bp] ;jmp funktion
+
+;***************************************************************************
+; select routine, um die tabellen eines bestimmten kanals zu adressieren
+;
+; in: al = kanalnummer
+;
+; out: si = dtcb adresse
+; di = ccb adresse
+; bx, dx zerstoert
+select:
+ push cx
+ mov dx,offset selectentry ;laenge eines eintrags in selecttabelle
+ mov bx,offset selecttable
+ mov cl,shard:[bx] ;anzahl kanaele laden
+ mov ch,0
+ inc bx ;auf eigentliche tabelle
+selectloop:
+ cmp al,shard:[bx] ;kanal gefunden
+ jz selectfound
+ add bx,dx ;auf naechsten kanal
+ loop selectloop
+; hier haben wir einen unbekannten kanal
+; bx zeigt jetzt auf den 'nilkanal'
+selectfound:
+; hier wurde der passende kanal gefunden
+ mov di,shard:[bx]+1 ;adresse channelcontrolblock
+ mov si,shard:[bx]+3 ;adresse devicetypecontrolblock
+ pop cx
+ ret
+
+;********************************************************************************
+;* definition des typs 'shardkanal' fuer operation ueber kanal 32
+ device shardchannel
+
+ dtcbroutines iocontrol
+ routine 1,devicetype
+ routine 2,frout_ok
+ routine 5,nil_size
+ routine 6,priv_operation
+ routine 8,priv_operation
+ routine 9,priv_operation
+ routine -3,priv_operation
+ routine -4,priv_operation
+ routine -5,reboot_request
+ routine -1,unknowncontrol
+ dtcbroutines control32
+ routine -2,timer_init
+ routine -1,no_channel_setup
+ dtcbroutines blockin
+ routine -4,clockread
+ dtcbroutines blockout
+ routine -4,clockwrite
+ routine -1,no_blockinout
+ dtcbparams nil_output,0 ;output,no in_out
+
+priv_operation:
+ mov al,bl ;kanalnummer nach al
+ mov bl,0 ;vermerken: privilegiert
+ jmp control32
+
+priv_op_question:
+ mov al,bl ;kanalnummer nach al
+ mov bl,1 ;vermerken: abfrage
+ jmp control32
+
+reboot_request:
+ mov byte ptr reboot_byte,1
+ ret
+
+reboot_byte db 0
+
+longmove:
+ rep movsw
+ ret
+
+i_sysend proc far
+ cmp byte ptr cs:reboot_byte,1
+ ifz <jmp reboot>
+ mov al,0
+ mov cx,-102
+ call control32 ;laufwerk parken, wenn implementiert
+ ret
+i_sysend endp
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/STREAM.ASM b/system/shard-x86-at/7/src/STREAM.ASM
new file mode 100644
index 0000000..3bc1797
--- /dev/null
+++ b/system/shard-x86-at/7/src/STREAM.ASM
@@ -0,0 +1,290 @@
+;***************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge =================*
+;* *
+;* Pufferverwaltung fuer Stream-I/O-Kanaele *
+;* und allgemeine Stream-I/O-Routinen *
+;* *
+;***************************************************************************
+
+;******************************************************************************
+; macro zur definition der fuer 'stream' notwendigen daten im ccb
+stream macro bufsiz,bufadr
+ccbentry stream_stat
+;;definition der bits in stream_stat
+outrestart = 1 ;;output war fertig, muss neu gestartet werden
+wasxon = 2 ;;es wurde bereits xon empfangen
+out_xon_xoff = 4 ;;ausgabeseitig findet xon/xoff handshake statt
+in_xon_xoff = 8 ;;eingabeseitig findet xon/xoff handshake statt
+sendxon_xoff = 10h ;;xon oder xoff muss gesendet werden
+sendxon = 20h ;;xon senden (in verbindung mit sendxon_xoff verwendet)
+in_xoff_send = 40h ;;xoff wurde ausgesendet -> nur dann xon senden
+ db outrestart + wasxon + in_xoff_send
+ccbentry buffersize
+ db bufsiz
+ccbentry content
+ db 0 ;;puffer ist anfangs leer
+ccbentry inpointer
+ db 0 ;;wir fuellen den puffer vom anfang an
+ccbentry outpointer
+ db 0 ;;und leeren ihn auch von da
+ccbentry buffer
+ dw offset bufadr ;;pufferadresse
+ccbentry andmask
+ db 0ffh ;;high bit loeschen
+ccbentry xormask
+ db 0 ;;keine bits kippen
+ccbentry errorandmask
+ db 0ffh ;;high bit loeschen
+ccbentry errorxormask
+ db 0 ;;keine bits kippen
+ccbentry outandmask
+ db 0ffh ;;high bit loeschen
+ccbentry outxormask
+ db 0 ;;keine bits kippen
+ccbentry breakchar
+ db '?' ;;nach ? umsetzen
+ccbentry xoffchar
+ db 'S'-40h ;;ctrl-s ist xoff
+ccbentry xonchar
+ db 'Q'-40h ;;ctrl-q ist xon
+ccbentry stream_icount
+ dw 0
+ccbentry stream_ocount
+ dw 0
+ endm
+
+
+fillbuffer:
+; di zeigt auf ccb
+; das z-flag ist rueckgesetzt, wenn der output neu gestartet werden muss
+ or cx,cx ;falls laenge null: alles uebernommen melden
+ jnz fillit
+ stc ;'alles uebernommen' setzen
+ ret ;war null, nichts zu tun
+fillit:
+ push cx ;gewuenschte laenge merken fuer rueckmeldung
+fillagain:
+ mov al,shard:(di+buffersize) ;puffergroesse holen
+ sub al,shard:(di+content) ;belegte abziehen
+ jz bufferfull ;nichts mehr frei
+ push cx ;noch zu uebernehmende merken
+ or ch,ch ;nachsehen, ob laenge > 255
+ ifnz <mov cl,0ffh> ;nein, dann bis zu 255 byte uebernehmen
+ cmp al,cl ;kleinere von freien und gewuenschten nehmen
+ ifc <mov cl,al> ;anzahl freie ist kleiner
+ mov al,shard:(di+buffersize) ;groesse holen
+ sub al,shard:(di+inpointer) ;zeiger abziehen -> abstand vom pufferende
+ jnz takeminimum
+ mov byte ptr shard:(di+inpointer),0 ;ist am ende, vorne anfangen
+ mov al,cl ;von daher volle groesse
+takeminimum: ;minimum (abstand vom ende, max moegliche) -> c
+ cmp al,cl ;welches ist groesser
+ ifc <mov cl,al> ;a ist kleiner, nehmen wir das
+ mov ch,0 ;laenge fuer movsb
+ push cx ;merken
+ mov dx,shard:(di+buffer)
+ add dl,shard:(di+inpointer)
+ ifc <inc dh> ;zielstartadresse nach dx
+;es:bx enthaelt quellenstart
+;ds:dx enthaelt zieladresse
+ push es
+ push ds
+ pop es ;es / ds vertauschen
+ pop ds
+ xchg bx,si ;bx als source
+ xchg dx,di ;dx als destination
+ cld
+ rep movsb ;uebertragen
+ xchg bx,si ;register zuruecktauschen
+ xchg dx,di
+ push es
+ push ds
+ pop es
+ pop ds
+ pop cx ;uebernommene laenge nach cx
+ add shard:(di+inpointer),cl ;neuen inpointer errechnen
+ add shard:(di+content),cl ;neuen inhalt
+ pop bp ;gewuenschte laenge nach bp
+ sub bp,cx ;restlaenge ausrechnen
+ mov cx,bp ;restlaenge nach cx
+ jnz fillagain ;ok, fertig
+ pop cx ;alles uebernommen
+ test byte ptr shard:(di+stream_stat),outrestart ;output neu starten?
+ stc ;carry setzen
+ ret
+
+bufferfull: ;nicht alles uebernommen
+ pop bx ;gewuenschte laenge vom stack holen
+ sub bx,cx ;uebernommene laenge errechnen
+ mov cx,bx ;uebernommene nach bc
+ test byte ptr shard:(di+stream_stat),outrestart ;output neu starten?
+ ret ;carry ist geloescht
+
+frout:
+;* meldet anzahl freie im puffer und carry, wenn puffer leer
+ mov al,shard:(di+buffersize) ;groesse
+ mov ch,al ;merken
+ sub al,shard:(di+content) ;minus inhalt gibt freie
+ cmp al,ch ;volle puffergroesse?
+ cmc ;carry ist genau dann gesetzt, wenn bl>al
+ mov ch,0
+ mov cl,al ;laenge melden
+ ret
+
+getnextchar:
+;* diese routine muss im disable interrupt aufgerufen werden und wird so verlassen
+;* z-flag -> kein zeichen mehr gefunden
+;* dx,ax,f werden zerstoert
+ test byte ptr (di+stream_stat),sendxon_xoff ;muessen wir xon/xoff senden
+ jnz getxon_xoff
+ test byte ptr shard:(di+stream_stat),wasxon ;war schon xon
+ jz getret ;nein, z sagt: kein zeichen mehr da
+ or byte ptr shard:(di+stream_stat),outrestart ;puffer leer, neustart erforderlich
+ cmp byte ptr shard:(di+content),0 ;noch was im puffer
+ jz getret ;ja
+ and byte ptr shard:(di+stream_stat),not outrestart ;kein neustart erforderlich
+ dec byte ptr shard:(di+content) ;einen vom inhalt abziehen
+ mov dx,shard:(di+buffer) ;buffer adresse + outpointer nach cx
+ mov al,shard:(di+outpointer)
+ cmp al,shard:(di+buffersize) ;sind wir am ende angelangt
+ ifz <mov al,0> ;ja, dann auf den anfang setzen
+ inc al ;auf naechstes zeigen
+ mov shard:(di+outpointer),al ;neuen outpointer setzen
+ dec al ;alten outpointer wiederherstellen
+ xor ah,ah ;ah loeschen
+ add dx,ax ;byte im puffer errechnen
+ xchg bx,dx
+ mov al,shard:[bx] ;zeichen holen
+ xchg bx,dx
+ and al,(di+outandmask) ;unerwuenschte bits blenden
+ xor al,(di+outxormask) ;andere evtl. kippen
+ inc word ptr (di+stream_ocount) ;zeichen zaehlen
+ inc dx ;puffer steht nie auf 0
+ ;nz => zeigt an, dass zeichen da
+getret:
+ ret
+
+getxon_xoff:
+ and byte ptr (di+stream_stat),not sendxon_xoff ;jetzt senden wirs
+ test byte ptr (di+stream_stat),sendxon ;sollen wir xon senden
+ jz getxoff ;nein, dann wars xoff
+ and byte ptr (di+stream_stat),not sendxon ;muss jetzt auch weg
+ or al,1 ;nz => zeichen da
+ mov al,(di+xonchar) ;xon holen
+ ret
+
+getxoff:
+ or al,1 ;nz => zeichen
+ mov al,(di+xoffchar) ;xoff holen
+ ret
+
+xonfound:
+ test byte ptr shard:(di+stream_stat),wasxon ;warten wir auf xon
+ lahf
+ or byte ptr shard:(di+stream_stat),wasxon ;jetzt war auf jeden fall eins da
+ sahf
+ ret ;z => output wieder starten
+
+xofffound:
+ and byte ptr shard:(di+stream_stat),not wasxon ;ab sofort auf xon warten
+ ret ;nz => output nicht wieder starten
+
+input:
+ and al,shard:(di+andmask) ;evtl. bits ausblenden
+ xor al,shard:(di+xormask) ;oder kippen
+allinput:
+ test byte ptr shard:(di+stream_stat),out_xon_xoff
+ jz directinput
+ cmp al,shard:(di+xonchar)
+ jz xonfound
+ cmp al,shard:(di+xoffchar)
+ jz xofffound
+directinput: ;input ohne xon/xoff
+ mov ch,al ;zeichen nach ch
+ mov al,shard:(di+channel_no) ;kanal nach al
+ inc word ptr shard:(di+stream_icount) ;zeichen zaehlen
+ call inputinterrupt
+ or al,1 ;nz => kein output restart
+ ret
+
+errorinput:
+ and al,shard:(di+errorandmask) ;evtl. bits ausblenden
+ xor al,shard:(di+errorxormask) ;oder kippen
+ jmp allinput
+
+breakinput:
+ mov al,shard:(di+breakchar)
+ jmp allinput
+
+stream_weiter:
+ cli
+ mov al,(di+stream_stat) ;aktuellen status holen
+ test al,in_xon_xoff ;ueberhaupt xon_xoff handshake
+ jz stream_weiter_end ;nein, ei und zurueck
+ test al,in_xoff_send ;habe ich ein xoff gesendet
+ jz stream_weiter_end ;nichts liefern
+ or al,sendxon+sendxon_xoff ;bitte schick ein xon
+ and al,0ffh-in_xoff_send ;das xoff ist erledigt
+ mov (di+stream_stat),al ;neuen status setzen
+ test byte ptr (di+stream_stat),outrestart ;nz => output neu starten
+stream_weiter_end:
+ sti
+ ret
+
+stream_stop:
+ cli
+ mov al,(di+stream_stat) ;aktuellen status holen
+ test al,in_xon_xoff ;ueberhaupt xon_xoff handshake
+ jz stream_stop_end ;nein, ei und zurueck
+ or al,in_xoff_send+sendxon_xoff ;bitte schick ein xoff und merk dirs
+ and al,0ffh-sendxon ;auf keinen fall mehr xon schicken
+ mov (di+stream_stat),al ;neuen status setzen
+ test byte ptr (di+stream_stat),outrestart ;nz => output neu starten
+stream_stop_end:
+ sti
+ ret
+
+enablexon:
+ or byte ptr shard:(di+stream_stat),in_xon_xoff ;ab sofort xon/xoff handshake
+enableoutxon:
+ or byte ptr (di+stream_stat),out_xon_xoff ;auch ausgabe seitig
+ ret
+
+
+disablexon:
+ and byte ptr (di+stream_stat),not in_xon_xoff ;ab sofort eingabe und
+disablexoff:
+ and byte ptr (di+stream_stat),not out_xon_xoff ;ausgabe wieder ohne xon/xoff
+ test byte ptr shard:(di+stream_stat),wasxon ;warten wir noch auf xon
+ lahf
+ or byte ptr shard:(di+stream_stat),wasxon ;dann haben wir jetzt eins
+ sahf
+ ret ;z => outputrestart
+
+set_out_mask:
+ mov (di+outandmask),dx
+ ret
+
+set_inp_mask:
+ mov (di+andmask),dx
+ ret
+
+set_inp_errmask:
+ mov (di+errorandmask),dx
+ ret
+
+stream_in_count:
+ cli
+ mov cx,(di+stream_icount)
+ mov word ptr (di+stream_icount),0
+ sti
+ ret
+
+stream_out_count:
+ cli
+ mov cx,(di+stream_ocount)
+ mov word ptr (di+stream_ocount),0
+ sti
+ ret
+
+ \ No newline at end of file
diff --git a/system/shard-x86-at/7/src/WAIT.ASM b/system/shard-x86-at/7/src/WAIT.ASM
new file mode 100644
index 0000000..28153aa
--- /dev/null
+++ b/system/shard-x86-at/7/src/WAIT.ASM
@@ -0,0 +1,176 @@
+;****************************************************************************
+;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================*
+;* *
+;* Support fuer die Wartelogik des IBM PC-AT ueber int 15h *
+;* *
+;* *
+;****************************************************************************
+
+int15 proc far
+ sti
+ push ax
+ cmp ah,90h ;hat ein treiber nichts zu tun
+ jz device_is_busy
+ cmp ah,91h ;oder ist er gerade fertig
+ jz device_ready
+not_for_me: ;hab ich nichts mit am hut
+ pop ax
+ jmp dword ptr cs:[int15_cont]
+
+device_ready:
+ cmp al,2 ;0 (platte) oder 1 (floppy)
+ jnc not_for_me
+ mov ah,0
+ push bx
+ mov bx,ax
+ mov byte ptr cs:device_busy[bx],2 ;device ist fertig geworden
+ pop bx
+ pop ax
+ iret
+
+device_is_busy:
+ mov ah,8 ;annahme: 6 sekunden fuer platte
+ cmp al,0 ;ist es platte
+ jz device_wait ;ja
+ mov ah,3 ;annahme: 2 sekunden fuer floppy
+ cmp al,1
+ jz device_wait ;ist floppy
+ cmp al,0fdh ;warten auf floppy_motor
+ jnz not_for_me ;mit allem anderen haben wir nichts am hut
+ mov ax,0301h ;zwei sekunden warten; device floppy
+device_wait:
+ push bx ;den ganzen ramsch sichern
+ push cx
+ push dx
+ push bp
+ push di
+ push si
+ push es
+ push ds
+ mov bl,al
+ mov bh,0
+ cli
+ mov byte ptr cs:device_table[bx],1 ;device busy setzen
+ mov byte ptr cs:device_timeout_table[bx],ah ;anzahl sekunden eintragen
+ sti
+device_wait_loop:
+ cmp byte ptr cs:device_busy[bx],0 ;noch kein interrupt gekommen
+ jnz device_wait_end
+ push bx
+ call cs:warte
+ pop bx
+ jmp device_wait_loop
+device_wait_end:
+ cmp byte ptr cs:device_busy[bx],2 ;normales ende
+ ifnz <stc> ;nicht normal, war timeout
+ mov byte ptr cs:device_table[bx],0 ;device ist wieder frei
+ mov byte ptr cs:device_busy[bx],0 ;device kann wieder auf int warten
+; jnc devcont
+; call cs:info
+; jmp short devcont
+; db ' timeout'
+devcont:
+ pop ds
+ pop es
+ pop si
+ pop di
+ pop bp
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret 2 ;kill flags on stack
+
+int15 endp
+
+device_timing:
+ mov bx,-1 ;mit 0 fangen wir an
+ mov cx,2 ;zwei durchlaeufe
+device_timing_loop:
+ inc bx
+ mov al,byte ptr device_timeout_table[bx] ;timeout zaehler holen
+ cmp al,0ffh ;schon fertig mit zaehlen
+ jz device_timing_end
+ dec al
+ mov byte ptr device_timeout_table[bx],al ;timeout zaehler neu setzen
+ jns device_timing_end
+ cmp byte ptr device_table[bx],1 ;noch aktiv?
+ ifz <cmp byte ptr device_busy[bx],0> ;und noch kein endeinterrupt
+ ifz <mov byte ptr device_busy[bx],3> ;timeout aufgetreten
+device_timing_end:
+ loop device_timing_loop
+ jmp word ptr device_cont
+
+;***********************************************************************
+;* warten, bis das in bx uebergebene device frei ist
+;* ds = cs ist bedingung, alle register (ausser flags) bleiben erhalten
+ db 'device free'
+device_free:
+ cmp byte ptr device_table[bx],0 ;ist das device frei
+ jnz device_not_free
+ mov byte ptr device_busy[bx],0 ;evtl. nachgeklapperte ints loeschen
+ ret ;device kann benutzt werden
+device_not_free:
+ push ax
+ push bx
+ push cx
+ push dx
+ push si
+ push di
+ push bp
+ push ds
+ push es
+ call warte
+ pop es
+ pop ds
+ pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ jmp device_free
+
+device_lock:
+ mov byte ptr device_table[bx],1 ;device sperren
+ ret
+
+device_unlock:
+ mov byte ptr device_table[bx],0 ;device freigeben
+ ret
+
+device_init:
+ mov ax,0
+ mov es,ax
+ mov bx,word ptr es:[15h*4] ;int routine holen
+ mov cx,word ptr es:[15h*4+2] ;int segment holen
+ mov word ptr es:[15h*4],offset int15
+ mov word ptr es:[15h*4+2],cs
+ mov word ptr [int15_cont],bx
+ mov word ptr [int15_cont+2],cx
+ mov ax,word ptr [sec_entry] ;alte adresse fuer sec_tick holen
+ mov word ptr [device_cont],ax ;eintragen fuer weitergabe
+ mov word ptr [sec_entry],offset device_timing ;unseren aufruf eintragen
+ ret
+
+int15_cont:
+ dw 0
+ dw 0
+
+device_cont:
+ dw 0
+
+device_table:
+ db 0
+ db 0
+
+device_busy:
+ db 0
+ db 0
+
+device_timeout_table:
+ db 0
+ db 0
+
+ \ No newline at end of file