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