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