Skip to content

Latest commit

 

History

History
294 lines (293 loc) · 24.2 KB

pib1.pas

File metadata and controls

294 lines (293 loc) · 24.2 KB
 
Nov 18, 2000
Nov 18, 2000
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
290
291
292
293
INLINE(
$FB/ { STI ;Allow interrupts}
{;}
{; Begin major polling loop over pending interrupts.}
{;}
{; The polling loop is needed because the 8259 cannot handle another 8250}
{; interrupt while we service this interrupt. We keep polling here as long}
{; as an interrupt is received.}
{;}
$8B/$16/>ASYNC_UART_IIR/ {Poll: MOV DX,[>Async_Uart_IIR] ;Get Interrupt ident register}
$EC/ { IN AL,DX ;Pick up interrupt type}
{;}
$A8/$01/ { TEST AL,1 ;See if any interrupt signalled.}
$74/$03/ { JZ Polla ;Yes --- continue}
$E9/$7F/$01/ { JMP NEAR Back ;No --- return to invoker}
{;}
{; Determine type of interrupt.}
{; Possibilities:}
{;}
{; 0 = Modem status changed}
{; 2 = Transmit hold register empty (write char)}
{; 4 = Character received from port}
{; 6 = Line status changed}
{;}
$24/$06/ {Polla: AND AL,6 ;Strip unwanted bits from interrupt type}
$3C/$04/ { CMP AL,4 ;Check if interrupt >= 4}
$74/$03/ { JE Pollb ;}
$E9/$A1/$00/ { JMP NEAR Int2}
{;}
{; Write interrupts must be turned on if a higher-priority interrupt}
{; has been received, else the characters may not be sent (and a lockup}
{; may occur).}
{;}
$50/ {Pollb: PUSH AX ;Save interrupt type}
$E8/$65/$01/ { CALL EnabWI ;Enable write interrupts}
$58/ { POP AX ;Restore interrupt type}
{;}
{; --- Received a character ----}
{;}
$3C/$04/ {Int4: CMP AL,4 ;Check for received char interrupt}
$74/$03/ { JE Int4a ;Yes -- process it.}
$E9/$95/$00/ { JMP NEAR Int2 ;No -- skip.}
{;}
{; Read the character from the serial port.}
{;}
$8B/$16/>ASYNC_BASE/ {Int4a: MOV DX,[>Async_Base] ;Read character from port}
$EC/ { IN AL,DX}
{;}
{; Check if XON/XOFF honored. If so, check if incoming character is}
{; an XON or an XOFF.}
{;}
$90/$90/$90/$90/$90/ { NOP NOP NOP NOP NOP }
$EB/$25/ { JMP Int4d ;No -- skip XON/XOFF checks}
(* $F6/$06/>ASYNC_DO_XONXOFF/$01/ { TEST BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF}*)
(* $74/$25/ { JZ Int4d ;No -- skip XON/XOFF checks}*)
{;}
$3C/<XON/ { CMP AL,<XON ;See if XON found}
$74/$11/ { JE Int4b ;Skip if XON found}
$3C/<XOFF/ { CMP AL,<XOFF ;See if XOFF found}
$75/$1D/ { JNE Int4d ;Skip if XOFF not found}
{;}
{; XOFF received -- set flag indicating sending of chars isn't possible}
{;}
$C6/$06/>ASYNC_XOFF_RECEIVED/$01/ { MOV BYTE [<Async_XOFF_Received],1 ;Turn on received XOFF flag}
$C6/$06/>ASYNC_XOFF_REC_DISPLAY/$01/ { MOV BYTE [<Async_XOFF_Rec_Display],1 ;Turn on display flag}
$E9/$BE/$FF/ { JMP NEAR Poll}
{;}
{; XON received -- allow more characters to be sent.}
{;}
$C6/$06/>ASYNC_XOFF_RECEIVED/$00/ {Int4b: MOV BYTE [<Async_XOFF_Received],0 ;Turn off received XOFF flag}
$C6/$06/>ASYNC_XON_REC_DISPLAY/$01/ { MOV BYTE [<Async_XON_Rec_Display],1 ;Turn on display flag}
{;}
$E8/$2F/$01/ { CALL EnabWI ;Enable write interrupts}
$E9/$61/$00/ { JMP NEAR Int4z}
{;}
{; Not XON/XOFF -- handle other character.}
{;}
$90/$90/$90/$90/$90/ {Int4d: NOP NOP NOP NOP NOP }
$90/$90/ { NOP NOP }
(* $F6/$06/>ASYNC_LINE_STATUS/$02/ {Int4d: TEST BYTE [>Async_Line_Status],2 ;Check for buffer overrun}*)
(* $75/$5A/ { JNZ Int4z ;Yes --- don't store anything}*)
(* Commented out to prevent lockups. Needs better coding. *)
{;}
$8B/$1E/>ASYNC_BUFFER_HEAD/ { MOV BX,[>Async_Buffer_Head] ;Current position in input buffer}
$C4/$3E/>ASYNC_BUFFER_PTR/ { LES DI,[>Async_Buffer_Ptr] ;Pick up buffer address}
$01/$DF/ { ADD DI,BX ;Update position}
$26/$88/$05/ { ES: MOV [DI],AL ;Store received character in buffer}
$FF/$06/>ASYNC_BUFFER_USED/ { INC WORD [>Async_Buffer_Used] ;Increment count of chars in buffer}
{;}
$A1/>ASYNC_BUFFER_USED/ { MOV AX,[>Async_Buffer_Used] ;Pick up buffer usage count}
$3B/$06/>ASYNC_MAXBUFFERUSED/ { CMP AX,[>Async_MaxBufferUsed] ;See if greater usage than ever before}
$7E/$03/ { JLE Int4f ;Skip if not}
$A3/>ASYNC_MAXBUFFERUSED/ { MOV [>Async_MaxBufferUsed],AX ;This is greatest use thus far}
{;}
$43/ {Int4f: INC BX ;Increment buffer pointer}
$3B/$1E/>ASYNC_BUFFER_SIZE/ { CMP BX,[>Async_Buffer_Size] ;Check if past end of buffer}
$7E/$02/ { JLE Int4h}
$31/$DB/ { XOR BX,BX ;If so, wrap around to front}
{;}
$39/$1E/>ASYNC_BUFFER_TAIL/ {Int4h: CMP WORD [>Async_Buffer_Tail],BX ;Check for overflow}
$74/$29/ { JE Int4s ;Jump if head ran into tail}
{;}
$89/$1E/>ASYNC_BUFFER_HEAD/ { MOV [>Async_Buffer_Head],BX ;Update head pointer}
{;}
{; If XON/XOFF available, and buffer getting full, set up to send}
{; XOFF to remote system.}
{;}
{; This happens in two possible stages:}
{;}
{; (1) An XOFF is sent right when the buffer becomes 'Async_Buffer_High'}
{; characters full.}
{;}
{; (2) A second XOFF is sent right when the buffer becomes}
{; 'Async_Buffer_High_2' characters full; this case is likely the}
{; result of the remote not having seen our XOFF because it was}
{; lost in transmission.}
{;}
$90/$90/$90/$90/$90/ { NOP NOP NOP NOP NOP }
$EB/$23/ { JMP Int4z ;No -- skip XON/XOFF checks}
(* $F6/$06/>ASYNC_DO_XONXOFF/$01/ { TEST BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF}*)
(* $74/$23/ { JZ Int4z ;No -- skip XON/XOFF checks}*)
{;}
{; Check against first high-water mark.}
{;}
$3B/$06/>ASYNC_BUFFER_HIGH/ { CMP AX,[>Async_Buffer_High] ;AX still has Async_Buffer_Used}
$7C/$1D/ { JL Int4z ;Not very full, so keep going.}
{;}
{; Check if we've already sent XOFF.}
{;}
$F6/$06/>ASYNC_XOFF_SENT/$01/ { TEST BYTE [<Async_XOFF_Sent],1 ;Remember if we sent XOFF or not}
$74/$06/ { JZ Int4j ;No -- go send it now.}
{;}
{; Check against second high-water mark.}
{; If we are right at it, send an XOFF regardless of whether we've}
{; already sent one or not. (Perhaps the first got lost.)}
{;}
$3B/$06/>ASYNC_BUFFER_HIGH_2/ { CMP AX,[>Async_Buffer_High_2]}
$75/$10/ { JNE Int4z ;Not at 2nd mark -- skip}
{;}
$C6/$06/>ASYNC_SEND_XOFF/$01/ {Int4j: MOV BYTE [<Async_Send_XOFF],1 ;Indicate we need to send XOFF}
$E8/$D3/$00/ { CALL EnabWI ;Ensure write interrupts enabled}
$E9/$52/$FF/ { JMP NEAR Poll ;}
{;}
{; If we come here, then the input buffer has overflowed.}
{; Characters will be thrown away until the buffer empties at least one slot.}
{;}
$80/$0E/>ASYNC_LINE_STATUS/$02/ {Int4s: OR BYTE PTR [>Async_Line_Status],2 ;Flag overrun}
{;}
$E9/$4A/$FF/ {Int4z: JMP NEAR Poll}
{;}
{; --- Write a character ---}
{;}
$3C/$02/ {Int2: CMP AL,2 ;Check for THRE interrupt}
$74/$03/ { JE Int2a ;Yes -- process it.}
$E9/$97/$00/ { JMP NEAR Int6 ;No -- skip.}
{;}
{; Check first if we need to send an XOFF to remote system.}
{;}
$F6/$06/>ASYNC_SEND_XOFF/$01/ {Int2a: TEST BYTE [<Async_Send_Xoff],1 ;See if we are sending XOFF}
$74/$34/ { JZ Int2d ;No -- skip it}
{;}
{; Yes, we are to send XOFF to remote.}
{;}
{; First, check DSR and CTS as requested.}
{; If those status lines aren't ready, turn off write interrupts and}
{; try later, after a line status change.}
{;}
$F6/$06/>ASYNC_DO_DSR/$01/ { TEST BYTE [<Async_Do_DSR],1 ;See if DSR checking required}
$74/$09/ { JZ Int2b ;No -- skip it}
{;}
$8B/$16/>ASYNC_UART_MSR/ { MOV DX,[>Async_Uart_MSR] ;Get modem status register}
$EC/ { IN AL,DX}
$A8/<ASYNC_DSR/ { TEST AL,<Async_DSR ;Check for Data Set Ready}
$74/$2E/ { JZ Int2e ;If not DSR, turn off write interrupts}
{;}
$F6/$06/>ASYNC_DO_CTS/$01/ {Int2b: TEST BYTE [<Async_Do_CTS],1 ;See if CTS checking required}
$74/$09/ { JZ Int2c ;No -- skip it}
{;}
$8B/$16/>ASYNC_UART_MSR/ { MOV DX,[>Async_Uart_MSR] ;Get modem status register}
$EC/ { IN AL,DX}
$A8/<ASYNC_CTS/ { TEST AL,<Async_CTS ;Check for Clear To Send}
$74/$1E/ { JZ Int2e ;If not CTS, turn off write ints}
{;}
{; All status lines look OK.}
{; Send the XOFF.}
{;}
$B0/<XOFF/ {Int2c: MOV AL,<XOFF ;Get XOFF Character}
$8B/$16/>ASYNC_BASE/ { MOV DX,[>Async_Base] ;Get transmit hold register address}
$EE/ { OUT DX,AL ;Output the XOFF}
$C6/$06/>ASYNC_SEND_XOFF/$00/ { MOV BYTE [<Async_Send_XOFF],0 ;Turn off send XOFF flag}
$C6/$06/>ASYNC_XOFF_SENT/$01/ { MOV BYTE [<Async_XOFF_Sent],1 ;Turn on sent XOFF flag}
$E9/$08/$FF/ { JMP NEAR Poll ;Return}
{;}
{; Not sending XOFF -- see if any character in buffer to be sent.}
{;}
$8B/$1E/>ASYNC_OBUFFER_TAIL/ {Int2d: MOV BX,[>Async_OBuffer_Tail] ;Pick up output buffer pointers}
$3B/$1E/>ASYNC_OBUFFER_HEAD/ { CMP BX,[>Async_OBuffer_Head]}
$75/$0B/ { JNE Int2m ;Skip if not equal --> something to send}
{;}
{; If nothing to send, turn off write interrupts to avoid unnecessary}
{; time spent handling useless THRE interrupts.}
{;}
$8B/$16/>ASYNC_UART_IER/ {Int2e: MOV DX,[>Async_Uart_IER] ;If nothing -- or can't -- send ...}
$EC/ { IN AL,DX ;}
$24/$FD/ { AND AL,$FD ;}
$EE/ { OUT DX,AL ;... disable write interrupts}
$E9/$F3/$FE/ { JMP NEAR Poll ;}
{;}
{; If something to send, ensure that remote system didn't send us XOFF.}
{; If it did, we can't send anything, so turn off write interrupts and}
{; wait for later (after an XON has been received).}
{;}
$F6/$06/>ASYNC_XOFF_RECEIVED/$01/ {Int2m: TEST BYTE [<Async_XOFF_Received],1 ;See if we received XOFF}
$75/$EE/ { JNZ Int2e ;Yes -- can't send anything now}
{;}
{; If we can send character, check DSR and CTS as requested.}
{; If those status lines aren't ready, turn off write interrupts and}
{; try later, after a line status change.}
{;}
$8B/$16/>ASYNC_UART_MSR/ { MOV DX,[>Async_Uart_MSR] ;Otherwise get modem status}
$EC/ { IN AL,DX}
$A2/>ASYNC_MODEM_STATUS/ { MOV [>Async_Modem_Status],AL ;and save modem status for later}
{;}
$F6/$06/>ASYNC_DO_DSR/$01/ { TEST BYTE [<Async_Do_DSR],1 ;See if DSR checking required}
$74/$04/ { JZ Int2n ;No -- skip it}
{;}
$A8/<ASYNC_DSR/ { TEST AL,<Async_DSR ;Check for Data Set Ready}
$74/$DB/ { JZ Int2e ;If not DSR, turn off write ints}
{;}
$F6/$06/>ASYNC_DO_CTS/$01/ {Int2n: TEST BYTE [<Async_Do_CTS],1 ;See if CTS checking required}
$74/$04/ { JZ Int2o ;No -- skip it}
{;}
$A8/<ASYNC_CTS/ { TEST AL,<Async_CTS ;Check for Clear To Send}
$74/$D0/ { JZ Int2e ;If not CTS, turn off write ints}
{;}
{; Everything looks OK for sending, so send the character.}
{;}
$C4/$3E/>ASYNC_OBUFFER_PTR/ {Int2o: LES DI,[>Async_OBuffer_Ptr] ;Get output buffer pointer}
$01/$DF/ { ADD DI,BX ;Position to character to output}
$26/$8A/$05/ { ES: MOV AL,[DI] ;Get character to output}
$8B/$16/>ASYNC_BASE/ { MOV DX,[>Async_Base] ;Get transmit hold register address}
$EE/ { OUT DX,AL ;Output the character}
{;}
$FF/$0E/>ASYNC_OBUFFER_USED/ { DEC WORD [>Async_OBuffer_Used] ;Decrement count of chars in buffer}
$43/ { INC BX ;Increment tail pointer}
$3B/$1E/>ASYNC_OBUFFER_SIZE/ { CMP BX,[>Async_OBuffer_Size] ;See if past end of buffer}
$7E/$02/ { JLE Int2z}
$31/$DB/ { XOR BX,BX ;If so, wrap to front}
{;}
$89/$1E/>ASYNC_OBUFFER_TAIL/ {Int2z: MOV [>Async_OBuffer_Tail],BX ;Store updated buffer tail}
$E9/$AC/$FE/ { JMP NEAR Poll}
{;}
{; --- Line status change ---}
{;}
$3C/$06/ {Int6: CMP AL,6 ;Check for line status interrupt}
$75/$11/ { JNE Int0 ;No -- skip.}
{;}
$8B/$16/>ASYNC_UART_LSR/ { MOV DX,[>Async_Uart_LSR] ;Yes -- pick up line status register}
$EC/ { IN AL,DX ;and its contents}
$24/$1E/ { AND AL,$1E ;Strip unwanted bits}
$A2/>ASYNC_LINE_STATUS/ { MOV [>Async_Line_Status],AL ;Store for future reference}
$08/$06/>ASYNC_LINE_ERROR_FLAGS/ { OR [>Async_Line_Error_Flags],AL ;Add to any past transgressions}
$E9/$97/$FE/ { JMP NEAR Poll}
{;}
{; --- Modem status change ---}
{;}
$3C/$00/ {Int0: CMP AL,0 ;Check for modem status change}
$74/$03/ { JE Int0a ;Yes -- handle it}
$E9/$90/$FE/ { JMP NEAR Poll ;Else get next interrupt}
{;}
$8B/$16/>ASYNC_UART_MSR/ {Int0a: MOV DX,[>Async_Uart_MSR] ;Pick up modem status reg. address}
$EC/ { IN AL,DX ;and its contents}
$A2/>ASYNC_MODEM_STATUS/ { MOV [>Async_Modem_Status],AL ;Store for future reference}
$E8/$03/$00/ { CALL EnabWI ;Turn on write interrupts, in case}
{; ;status change resulted from CTS/DSR}
{; ;changing state.}
$E9/$82/$FE/ { JMP NEAR Poll}
{;}
{; Internal subroutine to enable write interrupts.}
{;}
{EnabWI: ;PROC NEAR}
$8B/$16/>ASYNC_UART_IER/ { MOV DX,[>Async_Uart_IER] ;Get interrupt enable register}
$EC/ { IN AL,DX ;Check contents of IER}
$A8/$02/ { TEST AL,2 ;See if write interrupt enabled}
$75/$03/ { JNZ EnabRet ;Skip if so}
$0C/$02/ { OR AL,2 ;Else enable write interrupts ...}
$EE/ { OUT DX,AL ;... by rewriting IER contents}
$C3/ {EnabRet: RET ;Return to caller}
{;}
{; Send non-specific EOI to 8259 controller.}
{;}
$B0/$20/ {Back: MOV AL,$20 ;EOI = $20}
$E6/$20); { OUT $20,AL}