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