]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/ascii.180
Initial XON/XOFF input control (Holm. T)
[z180-stamp-cpm3.git] / cbios / ascii.180
1
2 ; Interrupt drivers for ASCI0 and ASCI1
3
4 global as0_dev,as1_dev
5
6 extrn @ctbl,f_cpu
7 extrn ff_empty,ff_get,ff_full,ff_put
8 extrn ff_puth,ff_cnt,ff_gech
9 extrn bufinit
10 extrn isv_sw,ijphl,add_hla,div32_r
11 extrn b_st_a,b_ld_a
12
13
14
15 maclib z180reg.inc
16 maclib config.inc
17 maclib ioctl.inc
18 maclib modebaud.inc
19
20
21 m2b mbxon_bit,mb$xon$xoff
22
23 ;-----------------------------------------------------
24
25 dseg
26
27 dw asci0_out
28 dw asci0_osta
29 dw asci0_inp
30 dw asci0_ista
31 dw asci_ioctl
32 as0_dev:
33 db 0 ;absolute device #
34 db 0 ;relative device
35 db 0 ;iflags
36 db M_CREAD+M_CRTS_IFLOW+M_CCTS_OFLOW ;fflags
37 db M_CS8 ;cflags
38 o.absdev equ 0
39 o.reldev equ 1
40 o.iflags equ 2
41 o.fflags equ 3
42 o.cflags equ 4
43
44 db 0
45 db 0
46 oint.iflags equ as0_dev+o.iflags-s0.inbuf
47 oint.fflags equ as0_dev+o.fflags-s0.inbuf
48 mkbuf s0.rx_id, s0.inbuf, s0.rx_len
49 mkbuf s0.tx_id, s0.outbuf,s0.tx_len
50
51
52 dw asci1_out
53 dw asci1_osta
54 dw asci1_inp
55 dw asci1_ista
56 dw asci_ioctl
57 as1_dev:
58 db 0 ;absolute device #
59 db 1 ;relative device
60 db 0 ;iflags
61 db M_CREAD+M_IXOFF ;fflags
62 db M_CS8 ;cflags
63
64 db 0
65 db 0
66 mkbuf s1.rx_id, s1.inbuf, s1.rx_len
67 mkbuf s1.tx_id, s1.outbuf,s1.tx_len
68
69
70
71 dseg
72
73
74 ioctl_ftab:
75 dw func_tcinit ;(00h) CP/M 3 DEVINI function
76 dw func_tcgeta ;(01h) Get the current serial port settings.
77 dw func_tcseta ;(02h) Set the current serial port settings.
78 dw func_tcsetaw ;(03h) Allow the output buffer to drain
79 dw func_tcsetaf ;(04h) Allow the output buffer to drain, discard pending input
80 dw func_tcsbrk ;(05h) Sending a break (250ms .. 500ms)
81 dw func_tcsbrkp ;(06h) arg is timeinterval in 0.1sec
82 dw func_tiocsbrk ;(07h) Turn break on
83 dw func_tioccbrk ;(08h) Turn break off
84 dw func_tcxonc ;(09h) Software flow control (TCOOFF, TCOON, TCIOFF, TCION)
85 dw func_tcflsh ;(0Ah) Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)
86 dw func_fionread ;(0Bh) Get the number of bytes in the input buffer.
87 dw func_tiocoutq ;(0Ch) Get the number of bytes in the output buffer.
88 dw func_tiocmget ;(0Dh) get the status of modem bits.
89 dw func_tiocmbis ;(0Eh) set the indicated modem bits.
90 dw func_tiocmbic ;(0Fh) clear the indicated modem bits.
91 dw func_tiocmset ;(10h) set the status of modem bits.
92 dw func_tiocgsoftcar ;(11h) Get the status of the CLOCAL flag in the c_cflag field
93 dw func_tiocssoftcar ;(12h) Set the CLOCAL flag when *argp is nonzero, and clear it otherwise.
94
95 IOCTL_MAX equ ($-ioctl_ftab)/2
96 dw nofunc
97
98
99 ;--------------------------------------------------------------
100 ;
101 ; b: device number
102 ; c: command
103 ; de: ioctl arg pointer
104 ; hl: ptr to driver local data
105 ;
106
107 asci_ioctl:
108 ld a,b
109 cp 1
110 jr nz,asioc_1
111 ld a,(inidone)
112 cp inidoneval
113 ret z
114 asioc_1:
115 push hl
116 ex (sp),ix
117 ld (ix+o.absdev),b
118 ld hl,ioctl_ftab
119 ld a,IOCTL_MAX
120 cp c
121 jr c,$+3
122 ld a,c
123 add a,a
124 call add_hla
125 ld a,(hl)
126 inc hl
127 ld h,(hl)
128 ld l,a
129 call ijphl
130 pop ix
131 nofunc:
132 or a
133 ret
134
135 ;--------------------------------------------------------------
136 ; CP/M 3 DEVINI function
137 ; Init Serial I/O for input and output (ASCI 0/1)
138
139 func_tcinit:
140 call asci_stop
141
142 init_st:
143 ld c,asext0 ;Enable baud rate generator
144 ld a,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS +M_BREAKEN
145 bit CCTS_OFLOW,(ix+o.fflags)
146 jr nz,$+4
147 or M_CTS0DIS
148 call out_asci_reg
149
150 ld b,(ix+o.absdev)
151 ld c,8 ;
152 mlt bc ;
153 ld hl,@ctbl+7 ;
154 add hl,bc ;
155 ld a,(hl) ;get baudrate index
156 call as_br_div
157 ld c,astc0l
158 call out_asci_reg_hl
159
160 ld c,cntlb0
161 ld a,M_MPBT ;No MP Mode, X16
162 bit PARODD,(ix+o.iflags)
163 jr z,$+4
164 or M_PEO
165 call out_asci_reg
166
167 ld c,cntla0
168 ld a,(ix+o.cflags)
169 srlan CS8
170 ld hl,mod_tab
171 call add_hla
172 ld a,(hl)
173 or a,M_RE+M_TE+M_RTS0+M_EFR ;Rx/Tx enable
174 call out_asci_reg
175
176 bit 0,(ix+o.reldev)
177 push ix
178 jr nz,init_1
179 ld hl,rtxisvjmp0 ;rx/tx int vector
180 ld (ivtab + IV$ASCI0),hl ;
181 ld ix,s0.outbuf
182 call bufinit
183 ld ix,s0.inbuf
184 jr init_2
185 init_1:
186 ld hl,rtxisvjmp1 ;rx/tx int vector
187 ld (ivtab + IV$ASCI1),hl ;
188 ld ix,s1.outbuf
189 call bufinit
190 ld ix,s1.inbuf
191 init_2:
192 call bufinit
193 pop ix
194 call asci_start
195 ret
196
197 ;--------------------------------------------------------------
198
199 mod_tab:
200 db 000B ; 7N1
201 db 100B ; 8N1
202 db 001B ; 7N2
203 db 101B ; 8N2
204 db 010B ; 7P1
205 db 110B ; 8P1
206 db 011B ; 7P2
207 db 111B ; 8P2
208
209
210 ;--------------------------------------------------------------
211 ; Get the current serial port settings.
212
213 func_tcgeta:
214 call chk_ptr
215
216 ld a,(ix+o.iflags)
217 call b_st_a
218 inc de
219 ld a,(ix+o.fflags)
220 call b_st_a
221 inc de
222
223 ld b,(ix+o.absdev)
224 ld c,8 ;
225 mlt bc ;
226 ld hl,@ctbl+7 ;
227 add hl,bc ;
228 ld a,(hl) ;get baudrate index
229 and M_CBAUD
230 ld b,a
231 ld a,(ix+o.cflags)
232 and ~M_CBAUD
233 or b
234 call b_st_a
235 dec de
236 dec de
237 xor a
238 ret
239
240 ;--------------------------------------------------------------
241 ; Set the current serial port settings.
242
243 func_tcseta:
244 call chk_ptr
245
246 call asci_stop
247
248 call b_ld_a
249 ld (ix+o.iflags),a
250 inc de
251 call b_ld_a
252 ld (ix+o.fflags),a
253 inc de
254
255 ld b,(ix+o.absdev)
256 ld c,8 ;
257 mlt bc ;
258 ld hl,@ctbl+7 ;
259 add hl,bc ;
260 call b_ld_a
261 ld (ix+o.cflags),a
262 and M_CBAUD
263 ld (hl),a ;set baudrate index
264 dec de
265 dec de
266 push de
267 call init_st
268 pop de
269 xor a
270 ret
271
272 ;--------------------------------------------------------------
273 ; Allow the output buffer to drain
274
275 func_tcsetaw:
276
277 ;--------------------------------------------------------------
278 ; Allow the output buffer to drain, discard pending input
279
280 func_tcsetaf:
281
282 ;--------------------------------------------------------------
283 ; Sending a break (250ms .. 500ms)
284
285 func_tcsbrk:
286
287 ;--------------------------------------------------------------
288 ; arg is timeinterval in 0.1sec
289
290 func_tcsbrkp:
291
292 ;--------------------------------------------------------------
293 ; Turn break on
294
295 func_tiocsbrk:
296
297 ;--------------------------------------------------------------
298 ; Turn break off
299
300 func_tioccbrk:
301
302 ;--------------------------------------------------------------
303 ; Software flow control (TCOOFF, TCOON, TCIOFF, TCION)
304
305 func_tcxonc:
306
307 ;--------------------------------------------------------------
308 ; Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)
309
310 func_tcflsh:
311
312 ;--------------------------------------------------------------
313 ; Get the number of bytes in the input buffer.
314
315 func_fionread:
316
317 ;--------------------------------------------------------------
318 ; Get the number of bytes in the output buffer.
319
320 func_tiocoutq:
321
322 ;--------------------------------------------------------------
323 ; get the status of modem bits.
324
325 func_tiocmget:
326
327 ;--------------------------------------------------------------
328 ; set the indicated modem bits.
329
330 func_tiocmbis:
331
332 ;--------------------------------------------------------------
333 ; clear the indicated modem bits.
334
335 func_tiocmbic:
336
337 ;--------------------------------------------------------------
338 ; set the status of modem bits.
339
340 func_tiocmset:
341
342 ;--------------------------------------------------------------
343 ; Get the status of the CLOCAL flag in the c_cflag field
344
345 func_tiocgsoftcar:
346
347 ;--------------------------------------------------------------
348 ; Set the CLOCAL flag when *argp is nonzero, and clear it otherwise.
349
350 func_tiocssoftcar:
351
352 or 0ffh
353 ret
354
355 ;--------------------------------------------------------------
356
357 chk_ptr:
358 ld a,e
359 or d
360 ret nz
361 cpl
362 pop hl
363 ret
364
365 ;--------------------------------------------------------------
366
367 asci_stop:
368 ld c,stat0 ;Disable rx/tx interrupts
369 xor a ;
370 call out_asci_reg
371
372 ld c,cntla0 ;Disable receiver and transmitter
373 ld a,M_RTS0+M_EFR ;RTS/CKA1
374 jr out_asci_reg
375
376 ;--------------------------------------------------------------
377
378 asci_start:
379 bit 0,(ix+o.reldev)
380 jr nz,asci_st1
381 in0 a,cntla0 ;asci0
382 and ~M_RTS0 ;Activate RTS
383 or M_EFR
384 out0 (cntla0),a
385 asci_st1:
386 ld c,stat0 ;
387 ld a,M_RIE
388 jr out_asci_reg
389
390 ;--------------------------------------------------------------
391 ; output to asci0/1 register
392 ;
393 ; c: register address
394 ; a: value
395 ;
396
397 out_asci_reg:
398 push bc
399 bit 0,(ix+o.reldev)
400 jr z,$+3
401 inc c
402 ld b,0
403 out (c),a
404 pop bc
405 ret
406
407 ;--------------------------------------------------------------
408 ; output 16 bit value to asci0/1 register
409 ;
410 ; c: register address
411 ; hl: value
412 ; a destroyed
413
414 out_asci_reg_hl:
415 ld a,b ;save b
416 bit 0,(ix+o.reldev)
417 jr z,$+4
418 inc c
419 inc c
420 ld b,0
421 out (c),l
422 inc c
423 out (c),h
424 ld b,a
425 ret
426
427 ;--------------------------------------------------------------
428 ; baud rate divider
429 ;
430 ; a: index
431 ; return
432 ; hl: divider
433
434 as_br_div:
435 push de
436 push bc
437 and 0fh
438 add a,a ;get factor
439 ld hl,bd150_tab
440 call add_hla
441 ld c,(hl)
442 inc hl
443 ld b,(hl)
444 ld hl,(f_cpu)
445 ld de,(f_cpu+2)
446 call div32_r
447 ld bc,32*150
448 call div32_r
449 ld de,2
450 or a
451 sbc hl,de
452 pop bc
453 pop de
454 ret nc
455 ld hl,0
456 ret
457
458 bd150_tab:
459 ; factor index baudrate orig. cp/m
460 dw 19200/150 ; 0 19200 -
461 dw 28800/150 ; 1 28800 50
462 dw 38400/150 ; 2 38400 75
463 dw 57600/150 ; 3 57600 110
464 dw 11520/15 ; 4 115200 134.5
465 dw 150/150 ; 5 150
466 dw 300/150 ; 6 300
467 dw 600/150 ; 7 600
468 dw 1200/150 ; 8 1200
469 dw 1800/150 ; 9 1800
470 dw 2400/150 ;10 2400
471 dw 3600/150 ;11 3600
472 dw 4800/150 ;12 4800
473 dw 7200/150 ;13 7200
474 dw 9600/150 ;14 9600
475 dw 19200/150 ;15 19200
476
477
478 ;--------------------------------------------------------------
479
480 if 0
481
482 initab0:
483 db 1,stat0,0 ;Disable rx/tx interrupts
484 ;Enable baud rate generator
485 db 1,asext0,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS
486 db 2,astc0l
487 init_br_off equ $ - initab0
488 dw 28
489 db 1,cntlb0,M_MPBT ;No MP Mode, X16
490 db 1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1
491 db 0
492
493 initab1:
494 db 1,stat1,0 ;Disable rx/tx ints, disable CTS1
495 db 1,asext1,M_BRGMOD ;Enable baud rate generator
496 db 2,astc1l,low 3, high 3
497 db 1,cntlb1,M_MPBT ;No MP Mode, X16
498 db 1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1
499 db 0
500 endif
501
502 ;--------------------------------------------------------------
503
504 dseg
505 asci0_ista:
506 push ix
507 ld ix,s0.inbuf ;
508 call ff_empty
509 pop ix
510 ret
511
512 ;--------------------------------------------------------------
513
514 asci1_ista:
515 push ix
516 ld ix,s1.inbuf ;
517 call ff_empty
518 pop ix
519 ret
520
521 ;--------------------------------------------------------------
522 ; Get an input character
523
524 if 0
525 asci0_inp:
526 push ix
527 ld ix,s0.inbuf ;
528 call ff_cnt
529 cp 32
530 jr nc,a0i_1
531 di
532 in0 a,(cntla0)
533 res RTS0,a
534 set EFR,a
535 out0 (cntla0),a
536 ei
537 a0i_1:
538 call ff_get
539 pop ix
540 ret
541 endif
542
543
544 asci0_inp:
545 push ix
546 ld ix,s0.inbuf ;
547 call ff_gech
548 ld a,b ;remaining chrs in buffer
549 cp s0.rx_len/4 ; < 32?
550 jr nc,a0i_1 ; no, just get char
551 bit CRTS_IFLOW,(ix+oint.fflags) ; yes, enable RTS if needed
552 jr z,a0i_1 ; no needed
553 di ; needed, enable
554 in0 a,(cntla0)
555 and ~M_RTS0 ;assert RTS
556 or M_EFR ;don't reset error flags
557 ei
558 out0 (cntla0),a
559 a0i_1:
560 ld a,c
561 pop ix
562 ret
563
564 ;--------------------------------------------------------------
565 ; Get an input character
566
567 asci1_inp:
568 push ix
569 ld ix,s1.inbuf ;
570 call ff_gech
571 ld a,b ; remaining chars in buffer
572 cp s0.rx_len/4 ; == 25% full?
573 jr nz,a1i_2 ; no, just get char
574 bit IXOFF,(ix+oint.fflags) ; XON/XOFF on input?
575 jr z,a1i_2 ; no
576 ; di
577 a1i_1: in0 a,(stat1) ; status reg ASCI1
578 bit TDRE,a ; Transmitter Data Reg. empty?
579 jr z,a1i_1 ; no, wait
580 ld a,11h ; DC1/XON
581 out0 (tdr1),a ; send out
582 ; ei
583 a1i_2:
584 ld a,c ; get back the char
585 pop ix
586 ret
587
588 ;--------------------------------------------------------------
589 ; Output status
590
591 asci0_osta:
592 push ix
593 ld ix,s0.outbuf ;
594 call ff_full
595 pop ix
596 ret
597
598 ;--------------------------------------------------------------
599 ; Output status
600
601 asci1_osta:
602 push ix
603 ld ix,s1.outbuf ;
604 call ff_full
605 pop ix
606 ret
607
608 ;--------------------------------------------------------------
609 ; put character in c in buffer
610 ; destroys hl, bc
611 ; returns output char in a
612
613 asci0_out:
614 push ix ;
615 ld ix,s0.outbuf ;
616 call ff_puth
617 pop ix ;
618 di ;
619 in0 c,(stat0) ;
620 set TIE,c ;
621 out0 (stat0),c ;
622 ei ;
623 ret
624
625 ;--------------------------------------------------------------
626 ; put character in c in buffer
627 ; destroys hl, bc
628 ; returns output char in a
629
630 asci1_out:
631 push ix ;
632 ld ix,s1.outbuf ;
633 call ff_puth
634 pop ix ;
635 di ;
636 in0 c,(stat1) ;
637 set TIE,c ;
638 out0 (stat1),c ;
639 ei ;
640 ret
641
642
643 ;--------------------------------------------------------------
644
645 cseg
646 rtxisvjmp0:
647 call isv_sw
648 dw asci0_int
649
650 rtxisvjmp1:
651 call isv_sw
652 dw asci1_int
653
654 ;--------------------------------------------------------------
655 ; ASCI 0/1 Transmit/Receive interupt routines
656
657 .lall
658 asci_int macro dev
659 local rxi_2,rxi_3,rxi_4
660
661 push ix
662 rxtxi&dev&_lp0:
663 ld ix,s&dev&.inbuf ;
664 rxtxi&dev&_lp1:
665 in0 a,(stat&dev) ;receive flag set?
666 jp p,txi&dev ;RDRF == Bit 7
667 and M_OVRN+M_PERR+M_FE
668 ld e,a
669
670 in0 a,(asext&dev)
671 and M_BREAK
672 or e
673 ld e,a
674
675 in0 d,(cntla&dev) ;
676 res EFR,d ;
677 out0 (cntla&dev),d
678
679 ld c,(ix+o.in_idx) ;input buffer pointer
680 ld b,0
681 ld hl,s&dev&.inbuf ;
682 add hl,bc
683
684 in0 a,(rdr&dev) ;get char
685 ld (hl),a
686 ;todo: break detection
687 ;todo: parity, framing overrun error
688
689 ld e,(ix+oint.fflags)
690
691 rxi_2:
692
693 ld a,c ;increment buffer in pointer
694 inc a ;
695 ld b,(ix+o.mask) ;
696 and b ;
697 ld c,a
698
699 sub (ix+o.out_idx) ;
700 jr z,rxtxi&dev&_lp1 ;skip if buffer is full
701
702 ld (ix+o.in_idx),c ;input buffer pointer
703
704 jr nc,$+3 ;
705 adc b ;
706
707 cp s&dev&.tx_len*3/4
708 jr c,rxi&dev&_noflow
709
710 if dev=0
711 bit CRTS_IFLOW,e
712 jr z,rxi_4
713
714 set EFR,d
715 set RTS0,d ;RTS inactive
716 out0 (cntla&dev),d ;
717 endif
718 if dev=1
719 bit IXOFF,e
720 jr z,rxi_4
721
722 ; di
723 rxi_3: in0 a,(stat&dev) ; status reg ASCI1
724 bit TDRE,a ; Transmitter Data Reg. empty?
725 jr z,rxi_3 ; no, wait
726 ld a,DC3 ; DC3/XOFF
727 out0 (tdr&dev),a ; send out
728 ; ei
729 endif
730
731 rxi_4:
732 ; bit IXOFF,e
733 ; jr z,rxtxi&dev&_lp1
734 ;todo: send XOFF
735 rxi&dev&_noflow:
736 jr rxtxi&dev&_lp1
737
738
739 txi&dev:
740 ld e,a
741 bit TDRE,e ;TX int?
742 jr z,rxtxi&dev&_exit
743
744 ;todo: xon/xoff
745
746 ld hl,s&dev&.outbuf+o.in_idx ;[in]
747 ld a,(hl) ;
748 inc hl ;[out]
749 ld c,(hl) ;
750 cp c ;
751 jr z,txi&dev&_empty ;
752 inc hl ;fifo base
753 ld b,0 ;
754 add hl,bc ;
755 ld a,(hl) ;
756 out0 (tdr&dev),a ;
757 inc c ;
758 ld a,(s&dev&.outbuf+o.mask) ;
759 and c ;
760 ld (s&dev&.outbuf+o.out_idx),a ;
761
762 jr rxtxi&dev&_lp0
763
764 txi&dev&_empty:
765 res TIE,e ;disable tx-int
766 out0 (stat&dev),e ; 5
767
768 rxtxi&dev&_exit:
769 pop ix
770 ret
771 endm
772
773 dseg
774 ;--------------------------------------------------------------
775 ; ASCI 0 Transmit/Receive interupt routines
776
777 asci0_int:
778 asci_int 0
779
780 ;--------------------------------------------------------------
781 ; ASCI 1 Transmit/Receive interupt routines
782
783 asci1_int:
784 asci_int 1
785
786 end