3 \ Serial input/output words for IBM PC compatiables.
\r
5 \ Adjust the value of CONSTANT words IRQ and COMBASE for your system.
\r
7 \ SIO.F is a example of direct control of hardware.
\r
8 \ You should not or can not do this in a respectable OS.
\r
9 \ However, MS-DOS is not one of them :).
\r
11 \ There are two input and output buffers. Serial port output as well as input
\r
12 \ are driven by interrupts. High-level words simply take or put characters in
\r
13 \ the buffers. Then the interrupt service routine takes outgoing characters
\r
14 \ from the output buffer and puts incomming characters in the input buffer.
\r
20 \ Align 'IrptServ' according to new EXE structure.
\r
24 3 CONSTANT IRQ \ normally COM1 and COM3 use IRQ4,
\r
25 \ COM2 and COM4 use IRQ3
\r
26 02F8 CONSTANT COMBASE \ base address, 3F8 for COM1, 2F8 for COM2
\r
27 \ 3E8 for COM3, 2E8 for COM4
\r
41 20 CONSTANT CTRL8259_0 \ interrupt control register
\r
42 21 CONSTANT CTRL8259_1 \ interrupt mask register
\r
43 20 CONSTANT EOI \ end of interrupt
\r
45 COMBASE CONSTANT TXR \ transmission register (WRITE)
\r
46 COMBASE CONSTANT RXR \ receive register (READ)
\r
47 COMBASE 1 + CONSTANT IER \ interrupt enable
\r
48 COMBASE 2 + CONSTANT IIR \ interrupt ID
\r
49 COMBASE 3 + CONSTANT LCR \ line contril
\r
50 COMBASE 4 + CONSTANT MCR \ modem control
\r
51 COMBASE 5 + CONSTANT LSR \ line status
\r
52 COMBASE 6 + CONSTANT MSR \ modem status
\r
53 COMBASE CONSTANT DLL \ divisor latch low
\r
54 COMBASE 1 + CONSTANT DLH \ divisor latch high
\r
61 [ BINARY 00011000 INVERT HEX ] LITERAL AND
\r
64 : BITS ( n -- ) \ n = 5, 6, 7, or 8
\r
67 [ BINARY 00000011 INVERT HEX ] LITERAL AND
\r
70 : STOPBIT ( n -- ) \ n = 0 or 1
\r
73 [ BINARY 00000100 INVERT HEX ] LITERAL AND
\r
76 : BPS ( n -- ) \ set speed
\r
78 0FF LCR PC! \ set Divisor-Latch Access-Bit
\r
80 [ HEX ] ROT UM/MOD NIP \ calculate divisor
\r
83 LCR PC! ; \ restore original LCR
\r
100 IIR PC@ 00000001 AND
\r
105 [ 1 IRQ LSHIFT INVERT ] LITERAL AND \ clear mask bit
\r
108 LCR PC@ 01111111 AND LCR PC! \ clear divisor latch addr.
\r
110 00001111 IER PC! \ interrupts when data received
\r
112 MCR PC@ 00001000 OR MCR PC! \ allow modem to generate interrupts
\r
117 [ 1 IRQ LSHIFT ] LITERAL OR \ set mask bit
\r
120 00000000 IER PC! \ no interrupt allowed
\r
122 MCR PC@ 11110111 AND MCR PC! ;
\r
126 1 10 LSHIFT CONSTANT RxBufSize \ receive buffer size = 2 ^ 10 (1024)
\r
127 \ The buffer size should be power of 2.
\r
128 VARIABLE RxBuffer RxBufSize ALLOT
\r
132 VARIABLE RxOverflow
\r
134 1 8 LSHIFT CONSTANT TxBufSize \ transmit buffer size = 2 ^ 8 (256)
\r
135 \ The buffer size should be power of 2.
\r
136 CREATE TxBuffer TxBufSize CHARS ALLOT
\r
166 0 # #Tx ) WORD CMP,
\r
170 DX AL OUT, \ Disable TXR empty irpt
\r
174 TxBuffer [BX] AL MOV,
\r
178 TxBufSize 1- # BX AND,
\r
187 RxBufSize # #Rx ) CMP,
\r
189 -1 # RxOverflow ) MOV,
\r
193 AL RxBuffer [BX] MOV,
\r
195 RxBufSize 1- # BX AND,
\r
209 ' ModemServ , ' TxServ , ' RxServ , ' LineServ ,
\r
219 CHAR " PARSE model" ENVIRONMENT? DROP
\r
220 CHAR " PARSE ROM Model" COMPARE 0=
\r
221 CHAR " PARSE model" ENVIRONMENT? DROP
\r
222 CHAR " PARSE RAM Model" COMPARE 0= OR
\r
227 CHAR " PARSE model" ENVIRONMENT? DROP
\r
228 CHAR " PARSE EXE Model" COMPARE 0=
\r
231 1000 # AX ADD, \ data segment follows after 64KB code segment
\r
234 IIR # DX MOV, \ identify irpt
\r
240 IrptTable [BX] CALL,
\r
241 1 L: \ do end of interrupt
\r
243 CTRL8259_0 # AL OUT,
\r
258 CREATE OLD-VECTOR 2 CELLS ALLOT
\r
259 CODE ATTACH-IRPT ( -- )
\r
262 IRQ 8 + 3500 OR # AX MOV, \ AL = irpt number, AH = 35h
\r
263 21 INT, \ DOS get interrupt vector service
\r
264 BX OLD-VECTOR ) MOV, \ save old vector
\r
265 ES OLD-VECTOR CELL+ ) MOV,
\r
266 IRQ 8 + 2500 OR # AX MOV, \ AL = irpt number, AH = 25h
\r
268 DX DS MOV, \ irpt service roution in CS:IrptServ
\r
269 ' IrptServ # DX MOV,
\r
270 21 INT, \ DOS set irpt vector
\r
276 CODE DETACH-IRPT ( -- ) \ restore old vector
\r
279 IRQ 8 + 2500 OR # AX MOV, \ AL = irpt number, AH = 25h
\r
280 OLD-VECTOR ) DX MOV,
\r
281 OLD-VECTOR CELL+ ) DS MOV, \ DOS set irpt vector
\r
288 : SER-IN? ( -- f ) \ true if char received
\r
293 ELSE RxTail @ RxBuffer + C@
\r
294 RxTail @ 1+ [ RxBufSize 1 - ] LITERAL AND RxTail !
\r
299 : SER-OUT ( x -- error_code )
\r
301 IF TxHead @ TxBuffer + C!
\r
302 TxHead @ 1+ [ TxBufSize 1- ] LITERAL AND TxHead !
\r
310 19200 BPS NO PARITY 8 BITS 0 STOPBIT
\r
316 SER-IN? IF SER-IN EMIT THEN
\r
317 EKEY? IF KEY DUP 27 = IF DROP DISABLE-IRQ DETACH-IRPT EXIT THEN
\r
322 CHAR " PARSE FILE" ENVIRONMENT?
\r
324 0= [IF] << CON [THEN]
\r