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