summaryrefslogtreecommitdiff
path: root/system/shard-x86-at/7/src/STREAM.ASM
blob: 87c3547ee0ebba65f2c8bcae8ea7e5f35779d460 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
;***************************************************************************
;*======= 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