|
|
1.1 root 1: .xlist
2: include mdef
3: .ilist
4: ;************************************************************************
5: ;* *
6: ;* rciol: direct 8250 communications interface for C *
7: ;* *
8: ;* prototypes: int rioini(int,int); initialize com,irq *
9: ;* int setbaud(int); set baud rate *
10: ;* *n/a int rioctl(int); remote i/o control *
11: ;* void dtr(char); set/reset dtr *
12: ;* int outcom(int); send character *
13: ;* int incom(void); receive character *
14: ;* *n/a int rioifc(int); local i/o redirection *
15: ;* *
16: ;************************************************************************
17:
18: ; this source file is lacking _rioctl and _rioifc
19:
20: biosda segment at 40h ;bios data area
21: biosda ends
22:
23: setmod %mm
24:
25: ; 8259 interrupt controller register equates
26:
27: icr1 equ 20h ;interrupt command register (master)
28: imr1 equ 21h ;interrupt mask register (master)
29: ivb1 equ 8 ;vector base 0-7: cannot be read, assumed
30: icr2 equ 0a0h ;interrupt command register (slave)
31: imr2 equ 0a1h ;interrupt mask register (slave)
32: ivb2 equ 70h ;vector base 8-f: cannot be read, assumed
33:
34: ; 8250 uart register equates
35:
36: iir equ 2 ;interrupt identification register
37: ier equ 1 ;interrupt enable register
38: ierd equ 0bh ;enable: rxd, thre, msr
39:
40: msr equ 6 ;modem status register
41: mcr equ 4 ;modem control register
42: mcrd equ 0bh ;irq enable, rts on, dtr on
43:
44: lsr equ 5 ;line status register
45: lcr equ 3 ;line control register
46: lcrd equ 3 ;N,8,1 mode
47:
48: ; buffer pointer structure
49:
50: dstruc bufp,0
51: dss 2,bcnt ;character count
52: dss 2,bput ;next character to buffer
53: dss 2,bget ;next character from buffer
54: dss 1,ovfl ;overflow flag
55: dss 1
56: dss 2,bofst ;buffer offset
57: dss 2,bsize ;buffer size
58: dstruc bufp
59: .xlist
60: .eopg
61: .data
62: public _plst
63:
64: align 2
65:
66: brdd dd 115200 ;baud rate dividend
67:
68: iv16h dd 0 ;saved interrupt vector for int 16h
69: iv29h dd 0 ;saved interrupt vector for int 29h
70: ivsio dd 0 ;saved serial i/o vector
71:
72: buart dw 0 ;uart base address
73: lsrad dw 0 ;line status register port address
74: irqn db 0 ;interrupt request line
75: ircr db 0 ;saved interrupt controller mask
76: siovn db 0 ;serial i/o vector number
77:
78: ic29h equ 1 ;int 29h is being intercepted
79: ic29d equ 3 ;int 29h is being diverted
80: ic16h equ 10h ;int 16h is being intercepted
81: intcp db 0 ;intercepted interrupt code
82:
83: opera db 0 ;operational (port defined, baud set)
84:
85: mode db 0 ;function enable (incl pause/abort cycles)
86: state db 0 ;operational state (must follow mode)
87: hold equ 2 ;stop transmission
88: abort equ 4 ;aborting
89: ctsck equ 10h ;check clear to send signal (mode only, fixed)
90:
91: txintp db 0 ;transmit interrupt pending
92: status db 0 ;communications status
93: rxlost equ 1 ;received characters lost
94:
95: align 2
96: txbmx equ 1024 ;receive buffer maximum size
97: rxbmx equ 1024 ;transmit buffer maximum size
98:
99: _plst label word
100:
101: dv rxbp bufp,0 ;receive buffer pointers
102: dv txbp bufp,0 ;transmit buffer pointers
103:
104: dv rxb rxbmx,0a8h ;receive buffer
105: dv txb txbmx,0a8h ;transmit buffer
106:
107: tst db 0
108: .xlist
109: .eopg
110: .code
111: public _rioini,_outcom,_incom,_dtr,_setbaud
112:
113: riods: dw -1 ;remote i/o routine data segment value
114:
115: ; initialize communications
116:
117: ; clear buffers, data, program uart, enable interrupts
118:
119: _rioini proc
120: push bp
121: mov bp,sp
122: push si
123: push di
124:
125: mov ax,pb[bp] ;com port or uart address
126: or ax,ax
127: mov ax,buart
128: jnz @f ;initialize
129: or ax,ax
130: jz cierr ;error, not initialized
131: jmp finis ;terminate
132:
133: @@: or ax,ax
134: jz cinit ;continue, not yet initialized
135: cierr: mov ax,-1
136: jmp ciex ;return error
137:
138: cinit: mov ax,ds
139: mov cs:riods,ax ;save data segment
140:
141: call ibfls ;clear input buffer
142: mov bofst[si],os rxb ;set receive buffer address
143: call obfls ;clear output buffer
144: mov bofst[si],os txb ;set transmit buffer address
145:
146: xor ax,ax
147: mov mode,ax ;clear mode and state
148: mov txintp,al ;clear int pending
149:
150: mov ax,seg biosda
151: mov es,ax
152: mov bx,pb[bp] ;com port or uart address
153: mov dx,bx
154: dec bx
155: cmp bx,4
156: jnc scport ;com port address specified
157:
158: and bx,3 ;com 0-3 for 1-4
159: add bx,bx ;offset (x 2)
160: mov dx,es:[bx]
161: or dx,dx
162: jnz scport ;port exists
163: jmp ciabt ;no such com port
164:
165: scport: mov buart,dx ;uart base address
166: add dx,lsr
167: mov lsrad,dx ;line status register
168:
169: ; mov al,pb[bp+4] ;hardware flow control
170: ; and al,1
171: ; jz girq
172: ; or mode,ctsck ;check cts
173:
174: girq: mov al,pb[bp+2] ;irq line
175: and al,7
176: jnz irqv ;valid
177: and al,1
178: add al,3 ;assume 4 for 1, 3 for 2
179: irqv: mov irqn,al
180: mov cl,al
181: mov al,1
182: shl al,cl ;mask for current irq line
183: ; mov irqm,al
184: mov ah,al
185: push ax ;save irq mask
186: in al,imr1
187: mov ircr,al ;save prior enable mask
188: or al,ah
189: out imr1,al ;inhibit interrupts
190: mov al,cl ;irq number
191: add al,ivb1 ;add vector base
192: mov siovn,al ;save sio vector
193: call gvect ;get prior vector in dx:bx
194: mov ivsio,bx
195: mov ivsio+2,dx ;save prior vector
196: push cs
197: pop dx
198: mov bx,os sioisr
199: call svect ;set service routine vector in dx:bx
200:
201: mov dx,buart
202: in ax,dx ;clear%
203: add dx,mcr
204: mov al,mcrd
205: out dx,al ;modem control register
206: dec dx
207: mov al,lcrd
208: out dx,al ;line control register
209: dec dx
210: dec dx
211: mov al,ierd
212: out dx,al ;interrupt enable register
213:
214: pop ax ;irq mask
215: in al,imr1
216: not ah
217: and al,ah
218: out imr1,al ;enable interrupts
219:
220: ; mov mw cs:mv2,1234h
221: ; xor ax,ax
222: ; mov si,os inims
223: ; call msout
224:
225: xor ax,ax ;return 0
226: jmp ciex ;exit
227:
228: ; terminate serial i/o operation
229:
230: finis: mov dx,buart
231: add dx,mcr
232: xor al,al
233: out dx,al ;dtr off, release irq line
234:
235: mov al,siovn ;serial i/o vector
236: mov bx,ivsio ;prior offset
237: mov dx,ivsio+2 ;prior segment
238: call svect ;replace original vector
239:
240: mov al,ircr
241: out imr1,al ;replace prior interrupt controller mask
242: xor bx,bx
243: jmp cterm ;return 0
244:
245: ciabt: mov bx,-1
246: cterm: xor ax,ax
247: mov buart,ax ;not initialized
248: mov opera,al ;not operational
249: mov ax,bx ;return code
250: ciex: pop di
251: pop si
252: pop bp
253: ret
254:
255: _rioini endp
256:
257:
258: ; get interrupt vector al in dx:bx
259:
260: gvect: push es
261: mov ah,35h
262: int 21h ;returns vector in es:bx
263: push es
264: pop dx ;segment
265: pop es
266: ret
267:
268: ; set interrupt vector al in dx:bx
269:
270: svect: push ds
271: push dx
272: mov ds,dx ;segment
273: mov dx,bx ;offset
274: mov ah,25h
275: int 21h ;takes vector in ds:dx
276: pop dx
277: pop ds
278: ret
279:
280:
281: ; flush buffers
282:
283: ibfls: mov si,os rxbp ;address input buffer pointers
284: mov bx,rxbmx ;set maximum size
285: jmp s xbfls
286: obfls: mov si,os txbp ;address output buffer pointers
287: mov bx,txbmx ;set maximum size
288:
289: ; si -> bufp structure, bx = maximum size
290:
291: xbfls: mov cx,os bofst/2 ;pointer list length
292: pushf
293: cli
294: push si
295: xor ax,ax
296: rep stosw ;clear pointers
297: pop si
298: mov bsize[si],bx
299: popf
300: ret
301:
302:
303: ; get character from buffer, ds:si -> pointers, saves cx, dx
304:
305: bgetc: mov ax,bcnt[si]
306: or ax,ax
307: jz bgnc ;buffer empty
308:
309: pushf
310: cli
311: mov bx,bofst[si] ;buffer offset from segment
312: mov di,bget[si] ;character offset from buffer
313: mov al,mb [bx+di] ;get character
314: inc di ;advance pointer
315: cmp di,bsize[si]
316: jc bggp ;pointer not past end of buffer
317: xor di,di ;reset to start
318: bggp: mov bget[si],di
319: dec bcnt[si] ;character count
320: popf ;re-enable interrupts if disabled
321: or al,al ;character in al, clear carry
322: ret
323:
324: bgnc: stc
325: ret
326:
327:
328: ; put character to buffer, ds:si -> pointers, al = char, saves ax, cx, dx
329:
330: bputc: mov bx,bcnt[si]
331: bputco: cmp bx,bsize[si]
332: jnc bgnc ;buffer full
333:
334: pushf
335: cli
336: mov bx,bofst[si] ;buffer offset from segment
337: mov di,bput[si] ;character offset from buffer
338: mov mb [bx+di],al ;put character
339: inc di ;advance pointer
340: cmp di,bsize[si]
341: jc bpgp ;pointer not past end of buffer
342: xor di,di ;reset to start
343: bpgp: mov bput[si],di
344: inc bcnt[si] ;character count
345: popf ;re-enable interrupts if disabled
346: clc ;character in al, clear carry
347: ret
348:
349:
350: ; sio input character
351:
352: _incom proc
353: push si
354: push di
355:
356: mov si,os rxbp ;address receive buffer pointers
357: call bgetc ;get character from receive buffer
358: mov ah,state
359: jnc icgc ;received character in al
360: or ah,1 ;no character available
361: xor al,al
362:
363: icgc: pop di
364: pop si
365: ret
366: _incom endp
367:
368:
369: ; sio output character
370:
371: _outcom proc
372: xor al,al
373: mov ah,state
374: test ah,abort
375: jnz ocabt ;aborting
376:
377: push bp
378: mov bp,sp
379: push si
380: push di
381:
382: mov al,pb[bp]
383: mov si,os txbp ;address transmit buffer pointers
384:
385: ocrep: mov bx,bcnt[si]
386: or bx,bx
387: jnz ocbuf ;buffer not empty
388:
389: test ah,hold
390: jnz ocbuf ;paused
391:
392: mov dx,lsrad ;address line status register
393: mov cl,al
394: in al,dx
395: and al,20h ;transmit hold register empty
396: mov al,cl
397: jz ocbuf ;interrupt pending
398:
399: mov dx,buart ;uart base (r/w data port)
400: out dx,al ;transmit character
401: jmp s ocex ;exit
402:
403: ocbuf: call bputco ;put character to transmit buffer
404: jnc ocex ;done
405:
406: ;check timer, exit if 2 min.
407:
408: jmp ocrep ;retry
409:
410: ocex: pop di
411: pop si
412: pop bp
413: ocabt: ret ;state in ah
414: _outcom endp
415:
416:
417: ; sio interrupt service routine
418:
419: sioisr proc
420: cli
421: push ax
422: push bx
423: push cx
424: push dx
425: push si
426: push di
427: push ds
428:
429: mov ax,cs:riods
430: mov ds,ax ;i/o data segment
431:
432: isrep: mov dx,lsrad ;line status register
433: in ax,dx ;lsr in al, msr in ah
434: mov mw cs:mv2,ax ;%
435: mov cx,ax ;save line status
436: sub dx,lsr ;address r/w data port
437: test al,1 ;received data available
438: jz txchk ;no character received
439:
440: test al,0ch ;overrun/parity/framing error
441: in al,dx ;read data
442: jnz txchk ;receive error, discard data
443:
444: mov bx,mode ;mode in bl, state in bh
445: test bh,abort
446: jnz intex ;aborting
447: test bl,abort
448: jz rcpau ;not checking for abort
449: cmp al,3 ;^C
450: jnz rcpau ;not abort character
451:
452: call ibfls ;flush input buffer
453: call obfls ;flush output buffer
454: mov state,abort ;aborting
455: jmp intex
456:
457: rxccs: mov state,hold ;set pause flag
458: jmp s txchk
459: rxccq: and state,not hold ;clear pause flag
460: jmp s txchk
461:
462: rcpau: test bl,hold
463: jz rxpch ;not checking pause
464: cmp al,13h ;^s
465: jz rxccs ;pause
466: cmp al,10h ;^q
467: jz rxccq ;resume
468:
469: rxpch: mov si,os rxbp ;address receive buffer
470: call bputc ;put character in buffer
471: jnc txchk ;done
472: or status,rxlost ;set receive characters lost flag
473:
474: txchk: test cl,20h ;transmit hold register empty
475: jz intex ;not ready to transmit
476:
477: mov si,os txbp ;address transmit buffer
478: call bgetc
479: jc intex ;buffer empty
480:
481: mov bx,mode ;mode in bl, state in bh
482: not ch
483: and ch,bl ;mode and not msr
484: test ch,ctsck ;cts checking and cts off
485: jnz intex ;hardware flow off, interrupt will resume
486:
487: test bh,hold
488: jnz intex ;paused
489:
490: out dx,al ;transmit character
491:
492: intex: mov dx,buart
493: add dx,iir
494: in al,dx ;reset int?
495: in al,dx
496: ; and al,1
497: ; jnz isrex ;more?
498: ; jmp isrep
499:
500: inc mw cs:mv1
501: mov ax,rxbp.bcnt
502: mov mw cs:mv3,ax
503: mov ax,txbp.bcnt
504: mov mw cs:mv4,ax
505: mov ax,800
506: mov si,os intmsg
507: call msout
508:
509: isrex: pop ds
510: pop di
511: pop si
512: pop dx
513: pop cx
514: pop bx
515: mov al,20h
516: out icr1,al ;non-specific eoi
517: pop ax
518: iret
519:
520: intmsg: db 'Interrupt �5, msr/lsr �4, rxbc �4, txbc �4 ',0
521:
522: sioisr endp
523:
524:
525: ; set baud rate
526:
527: _setbaud proc
528: mov dx,buart ;base port address
529: or dx,dx
530: jnz sbinit ;initialized
531: xor ax,ax
532: dec ax ;-1
533: ret ;return error
534:
535: sbinit: push bp
536: mov bp,sp
537: push si
538: mov cx,dx ;%
539: mov si,os brdd ;address baud rate dividend
540: mov dx,2[si]
541: mov ax,[si] ;dividend in dx:ax
542: div mw pb[bp] ;divide by parameter 1
543: mov dx,cx ;%
544: push ax ;actual rate divisor for uart
545: mov si,dx
546: add dx,lcr ;address line control register
547: in al,dx
548: or al,80h
549: out dx,al ;address baud rate divisor
550: xchg si,dx
551: pop ax
552: out dx,ax ;write baud rate divisor
553: xchg si,dx
554: in al,dx
555: and al,7fh
556: out dx,al ;address rx/tx registers, ier
557: xchg si,dx
558: in ax,dx ;clear%
559:
560: xor ax,ax ;no error
561: pop si
562: pop bp
563: ret
564: _setbaud endp
565: .xlist
566: .eopg
567: ; drop dtr
568:
569: ; n=0 (off), n=1 (on), or n>1 (off, wait n seconds for dcd off)
570:
571: _dtr proc
572:
573: push bp
574: mov bp,sp
575: mov ax,seg biosda
576: mov es,ax
577:
578: mov dx,buart ;uart base port
579: or dx,dx
580: jz dtrer ;not initialized
581:
582: add dx,4 ;address mcr
583: in al,dx
584: and al,0feh ;clear dtr bit
585: mov ah,pb[bp] ;parameter
586: and ah,0fh
587: cmp ah,2 ;0 off, 1 on
588: jnc wtdcd ;off, wait for dcd
589: or al,ah
590: out dx,al ;set as specified
591: xor al,al
592: jmp s dtrck
593:
594: wtdcd: out dx,al ;dtr off
595: inc dx
596: inc dx ;address msr
597:
598: twn: mov cx,18 ;55ms/s
599: tws: mov bl,es:[6ch] ;55ms counter
600: twt: in al,dx
601: and al,80h ;dcd
602: jz dtrck ;done
603: cmp bl,es:[6ch] ;55ms counter
604: jz twt ;wait 55ms
605: loop tws ;wait 990ms
606: dec ah
607: jnz twn ;wait 2-x seconds
608: dtrer: mov al,-1 ;timeout
609:
610: dtrck: mov ah,al
611: cmp mb pb[bp],1
612: jz dtrex ;dtr was set
613:
614: push ax ;dtr was reset, clear state and buffers
615: call ibfls
616: call obfls
617: xor al,al
618: mov state,al
619: mov status,al
620: pop ax
621:
622: dtrex: pop bp
623: ret
624: _dtr endp
625:
626: include mviow
627: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.