- page 200\r
\r
; Interrupt drivers for ASCI0 and ASCI1\r
\r
- global as0init\r
- global as0ista,as0inp\r
- global as0osta,as0out\r
- global as1init\r
- global as1ista,as1inp\r
- global as1osta,as1out\r
+ global as0_dev,as1_dev\r
\r
- extrn as_init\r
- extrn ff_empty,ff_get,ff_full,ff_put,ff_cnt\r
+ extrn @ctbl,f_cpu\r
+ extrn ff_empty,ff_get,ff_full,ff_put\r
+ extrn ff_puth,ff_cnt,ff_gech\r
extrn bufinit\r
- extrn isv_sw\r
+ extrn isv_sw,ijphl,add_hla,div32_r\r
+ extrn b_st_a,b_ld_a\r
\r
\r
\r
- include config.inc\r
- include z180reg.inc\r
+ maclib z180reg.inc\r
+ maclib config.inc\r
+ maclib ioctl.inc\r
+ maclib modebaud.inc\r
\r
\r
+ m2b mbxon_bit,mb$xon$xoff\r
\r
;-----------------------------------------------------\r
\r
dseg\r
\r
+ dw asci0_out\r
+ dw asci0_osta\r
+ dw asci0_inp\r
+ dw asci0_ista\r
+ dw asci_ioctl\r
+as0_dev:\r
+ db 0 ;absolute device #\r
+ db 0 ;relative device\r
+ db 0 ;iflags\r
+ db 0 ;fflags\r
+ db M_CS8 ;cflags\r
+o.absdev equ 0\r
+o.reldev equ 1\r
+o.iflags equ 2\r
+o.fflags equ 3\r
+o.cflags equ 4\r
+\r
+ db 0\r
+ db 0\r
+oint.iflags equ as0_dev+o.iflags-s0.inbuf\r
+oint.fflags equ as0_dev+o.fflags-s0.inbuf\r
mkbuf s0.rx_id, s0.inbuf, s0.rx_len\r
mkbuf s0.tx_id, s0.outbuf,s0.tx_len\r
+\r
+\r
+ dw asci1_out\r
+ dw asci1_osta\r
+ dw asci1_inp\r
+ dw asci1_ista\r
+ dw asci_ioctl\r
+as1_dev:\r
+ db 0 ;absolute device #\r
+ db 1 ;relative device\r
+ db 0 ;iflags\r
+ db 0 ;fflags\r
+ db M_CS8 ;cflags\r
+\r
+ db 0\r
+ db 0\r
mkbuf s1.rx_id, s1.inbuf, s1.rx_len\r
- mkbuf s1.tx_id, s1.outbuf, s1.tx_len\r
+ mkbuf s1.tx_id, s1.outbuf,s1.tx_len\r
\r
\r
\r
dseg\r
\r
+\r
+ioctl_ftab:\r
+ dw func_tcinit ;(00h) CP/M 3 DEVINI function\r
+ dw func_tcgeta ;(01h) Get the current serial port settings.\r
+ dw func_tcseta ;(02h) Set the current serial port settings.\r
+ dw func_tcsetaw ;(03h) Allow the output buffer to drain\r
+ dw func_tcsetaf ;(04h) Allow the output buffer to drain, discard pending input\r
+ dw func_tcsbrk ;(05h) Sending a break (250ms .. 500ms)\r
+ dw func_tcsbrkp ;(06h) arg is timeinterval in 0.1sec\r
+ dw func_tiocsbrk ;(07h) Turn break on\r
+ dw func_tioccbrk ;(08h) Turn break off\r
+ dw func_tcxonc ;(09h) Software flow control (TCOOFF, TCOON, TCIOFF, TCION)\r
+ dw func_tcflsh ;(0Ah) Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)\r
+ dw func_fionread ;(0Bh) Get the number of bytes in the input buffer.\r
+ dw func_tiocoutq ;(0Ch) Get the number of bytes in the output buffer.\r
+ dw func_tiocmget ;(0Dh) get the status of modem bits.\r
+ dw func_tiocmbis ;(0Eh) set the indicated modem bits.\r
+ dw func_tiocmbic ;(0Fh) clear the indicated modem bits.\r
+ dw func_tiocmset ;(10h) set the status of modem bits.\r
+ dw func_tiocgsoftcar ;(11h) Get the status of the CLOCAL flag in the c_cflag field\r
+ dw func_tiocssoftcar ;(12h) Set the CLOCAL flag when *argp is nonzero, and clear it otherwise.\r
+\r
+IOCTL_MAX equ ($-ioctl_ftab)/2\r
+ dw nofunc\r
+\r
+\r
;--------------------------------------------------------------\r
-; Init Serial I/O for input and output (ASCI 0/1)\r
;\r
-; b: device number\r
+; b: device number\r
+; c: command\r
+; de: ioctl arg pointer\r
+; hl: ptr to driver local data\r
;\r
\r
+asci_ioctl:\r
+ push hl\r
+ ex (sp),ix\r
+ ld (ix+o.absdev),b\r
+ ld hl,ioctl_ftab\r
+ ld a,IOCTL_MAX\r
+ cp c\r
+ jr c,$+3\r
+ ld a,c\r
+ add a,a\r
+ call add_hla\r
+ ld a,(hl)\r
+ inc hl\r
+ ld h,(hl)\r
+ ld l,a\r
+ call ijphl\r
+ pop ix\r
+nofunc:\r
+ or a\r
+ ret\r
\r
-;ser.init:\r
-; ld a,i\r
-; push af ;save IFF\r
-; di\r
-;---\r
-; pop af\r
-; ret po\r
-; ei\r
-; ret ;\r
+;--------------------------------------------------------------\r
+; CP/M 3 DEVINI function\r
+; Init Serial I/O for input and output (ASCI 0/1)\r
\r
-as0init:\r
- xor a ;\r
- out0 (stat0),a ;Disable rx/tx interrupts\r
- ld c,0 ;asci channel number\r
- call as_init\r
- ld hl,rtxisvjmp0 ;rx/tx int vector\r
- ld (ivtab + IV$ASCI0),hl ;\r
+func_tcinit:\r
+ call asci_stop\r
+\r
+init_st:\r
+ ld c,asext0 ;Enable baud rate generator\r
+ ld a,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS +M_BREAKEN\r
+ bit CCTS_OFLOW,(ix+o.fflags)\r
+ jr nz,$+4\r
+ or M_CTS0DIS\r
+ call out_asci_reg\r
+\r
+ ld b,(ix+o.absdev)\r
+ ld c,8 ;\r
+ mlt bc ;\r
+ ld hl,@ctbl+7 ;\r
+ add hl,bc ;\r
+ ld a,(hl) ;get baudrate index\r
+ call as_br_div\r
+ ld c,astc0l\r
+ ld a,l\r
+ call out_asci_reg\r
+ inc c\r
+ ld a,h\r
+ call out_asci_reg\r
+\r
+\r
+ ld c,cntlb0\r
+ ld a,M_MPBT ;No MP Mode, X16\r
+ bit PARODD,(ix+o.iflags)\r
+ jr z,$+4\r
+ or M_PEO\r
+ call out_asci_reg\r
+\r
+ ld c,cntla0\r
+ ld a,(ix+o.cflags)\r
+ srlan CS8\r
+ ld hl,mod_tab\r
+ call add_hla\r
+ ld a,(hl)\r
+ or a,M_RE+M_TE+M_RTS0+M_EFR ;Rx/Tx enable\r
+ call out_asci_reg\r
\r
+ push ix\r
+ bit 0,(ix+o.reldev)\r
+ jr nz,init_1\r
+ ld hl,rtxisvjmp0 ;rx/tx int vector\r
+ ld (ivtab + IV$ASCI0),hl ;\r
+ ld ix,s0.outbuf\r
+ call bufinit\r
ld ix,s0.inbuf\r
+ jr init_2\r
+init_1:\r
+ ld hl,rtxisvjmp1 ;rx/tx int vector\r
+ ld (ivtab + IV$ASCI1),hl ;\r
+ ld ix,s1.outbuf\r
call bufinit\r
- ld ix,s0.outbuf\r
+ ld ix,s1.inbuf\r
+init_2:\r
call bufinit\r
- ld a,M_RIE\r
- out0 (stat0),a ;Enable rx interrupts\r
+ pop ix\r
+ call asci_start\r
ret\r
\r
-as1init:\r
+;--------------------------------------------------------------\r
+\r
+mod_tab:\r
+ db 000B ; 7N1\r
+ db 100B ; 8N1\r
+ db 001B ; 7N2\r
+ db 101B ; 8N2\r
+ db 010B ; 7P1\r
+ db 110B ; 8P1\r
+ db 011B ; 7P2\r
+ db 111B ; 8P2\r
+\r
+\r
+;--------------------------------------------------------------\r
+; Get the current serial port settings.\r
+\r
+func_tcgeta:\r
+ ld a,d\r
+ or e\r
+ ld a,0ffh\r
+ jr z,fgeta_e\r
+\r
+ ld a,(ix+o.iflags)\r
+ call b_st_a\r
+ inc de\r
+ ld a,(ix+o.fflags)\r
+ call b_st_a\r
+ inc de\r
+\r
+ ld b,(ix+o.absdev)\r
+ ld c,8 ;\r
+ mlt bc ;\r
+ ld hl,@ctbl+7 ;\r
+ add hl,bc ;\r
+ ld a,(hl) ;get baudrate index\r
+ and M_CBAUD\r
+ ld b,a\r
+ ld a,(ix+o.cflags)\r
+ and ~M_CBAUD\r
+ or b\r
+ call b_st_a\r
+ dec de\r
+ dec de\r
+ xor a\r
+fgeta_e:\r
+ ret\r
+\r
+\r
+;--------------------------------------------------------------\r
+; Set the current serial port settings.\r
+\r
+func_tcseta:\r
+ ld a,d\r
+ or e\r
+ ld a,0ffh\r
+ jr z,fseta_e\r
+\r
+ call asci_stop\r
+\r
+ call b_ld_a\r
+ ld (ix+o.iflags),a\r
+ inc de\r
+ call b_ld_a\r
+ ld (ix+o.fflags),a\r
+ inc de\r
+\r
+ ld b,(ix+o.absdev)\r
+ ld c,8 ;\r
+ mlt bc ;\r
+ ld hl,@ctbl+7 ;\r
+ add hl,bc ;\r
+ call b_ld_a\r
+ ld (ix+o.cflags),a\r
+ and M_CBAUD\r
+ ld (hl),a ;set baudrate index\r
+ dec de\r
+ dec de\r
+ push de\r
+ call init_st\r
+ pop de\r
+ xor a\r
+fseta_e:\r
+ ret\r
+\r
+\r
+;--------------------------------------------------------------\r
+; Allow the output buffer to drain\r
+\r
+func_tcsetaw:\r
+\r
+;--------------------------------------------------------------\r
+; Allow the output buffer to drain, discard pending input\r
+\r
+func_tcsetaf:\r
+\r
+;--------------------------------------------------------------\r
+; Sending a break (250ms .. 500ms)\r
+\r
+func_tcsbrk:\r
+\r
+;--------------------------------------------------------------\r
+; arg is timeinterval in 0.1sec\r
+\r
+func_tcsbrkp:\r
+\r
+;--------------------------------------------------------------\r
+; Turn break on\r
+\r
+func_tiocsbrk:\r
+\r
+;--------------------------------------------------------------\r
+; Turn break off\r
+\r
+func_tioccbrk:\r
+\r
+;--------------------------------------------------------------\r
+; Software flow control (TCOOFF, TCOON, TCIOFF, TCION)\r
+\r
+func_tcxonc:\r
+\r
+;--------------------------------------------------------------\r
+; Flush input/output buffer (TCIFLUSH, TCOFLUSH, TCIOFLUSH)\r
+\r
+func_tcflsh:\r
+\r
+;--------------------------------------------------------------\r
+; Get the number of bytes in the input buffer.\r
+\r
+func_fionread:\r
+\r
+;--------------------------------------------------------------\r
+; Get the number of bytes in the output buffer.\r
+\r
+func_tiocoutq:\r
+\r
+;--------------------------------------------------------------\r
+; get the status of modem bits.\r
+\r
+func_tiocmget:\r
+\r
+;--------------------------------------------------------------\r
+; set the indicated modem bits.\r
+\r
+func_tiocmbis:\r
+\r
+;--------------------------------------------------------------\r
+; clear the indicated modem bits.\r
+\r
+func_tiocmbic:\r
+\r
+;--------------------------------------------------------------\r
+; set the status of modem bits.\r
+\r
+func_tiocmset:\r
+\r
+;--------------------------------------------------------------\r
+; Get the status of the CLOCAL flag in the c_cflag field\r
+\r
+func_tiocgsoftcar:\r
+\r
+;--------------------------------------------------------------\r
+; Set the CLOCAL flag when *argp is nonzero, and clear it otherwise.\r
+\r
+func_tiocssoftcar:\r
+\r
+ or 0ffh\r
+ ret\r
+\r
+;--------------------------------------------------------------\r
+\r
+asci_stop:\r
+ ld c,stat0 ;Disable rx/tx interrupts\r
xor a ;\r
- out0 (stat1),a ;Disable rx/tx interrupts\r
- ld c,1 ;asci channel number\r
- call as_init\r
+ call out_asci_reg\r
\r
- ld hl,rtxisvjmp1 ;rx/tx int vector\r
- ld (ivtab + IV$ASCI1),hl ;\r
+ ld c,cntla0 ;Disable receiver and transmitter\r
+ ld a,M_RTS0+M_EFR ;RTS/CKA1\r
+ jr out_asci_reg\r
\r
- push ix\r
- ld ix,s1.inbuf\r
- call bufinit\r
- ld ix,s1.outbuf\r
- call bufinit\r
- pop ix\r
+;--------------------------------------------------------------\r
+\r
+asci_start:\r
+ ld c,stat0 ;\r
ld a,M_RIE\r
- out0 (stat1),a ;Enable rx interrupts\r
+ jr out_asci_reg\r
+\r
+;--------------------------------------------------------------\r
+; output to asci0/1 register\r
+;\r
+; c: register address\r
+; a: value\r
+;\r
+\r
+out_asci_reg:\r
+ push bc\r
+ ld b,a\r
+ ld a,c\r
+ cp astc0l ;astc0/1 are 16 bit\r
+ jr c,$+5\r
+ add a,(ix+o.reldev)\r
+ add a,(ix+o.reldev)\r
+ ld c,a\r
+ ld a,b\r
+ ld b,0\r
+ out (c),a\r
+ pop bc\r
ret\r
\r
+;--------------------------------------------------------------\r
+; baud rate divider\r
+;\r
+; a: index\r
+; return\r
+; hl: divider\r
+\r
+as_br_div:\r
+ push de\r
+ push bc\r
+ and 0fh\r
+ add a,a ;get factor\r
+ ld hl,bd150_tab\r
+ call add_hla\r
+ ld c,(hl)\r
+ inc hl\r
+ ld b,(hl)\r
+ ld hl,(f_cpu)\r
+ ld de,(f_cpu+2)\r
+ call div32_r\r
+ ld bc,32*150\r
+ call div32_r\r
+ ld de,2\r
+ or a\r
+ sbc hl,de\r
+ pop bc\r
+ pop de\r
+ ret nc\r
+ ld hl,0\r
+ ret\r
\r
- cseg\r
-rtxisvjmp0:\r
- call isv_sw\r
- dw rxtxi0\r
-rtxisvjmp1:\r
- call isv_sw\r
- dw rxtxi1\r
+bd150_tab:\r
+; factor index baudrate orig. cp/m\r
+ dw 19200/150 ; 0 19200 -\r
+ dw 28800/150 ; 1 28800 50\r
+ dw 38400/150 ; 2 38400 75\r
+ dw 57600/150 ; 3 57600 110\r
+ dw 11520/15 ; 4 115200 134.5\r
+ dw 150/150 ; 5 150\r
+ dw 300/150 ; 6 300\r
+ dw 600/150 ; 7 600\r
+ dw 1200/150 ; 8 1200\r
+ dw 1800/150 ; 9 1800\r
+ dw 2400/150 ;10 2400\r
+ dw 3600/150 ;11 3600\r
+ dw 4800/150 ;12 4800\r
+ dw 7200/150 ;13 7200\r
+ dw 9600/150 ;14 9600\r
+ dw 19200/150 ;15 19200\r
+\r
+\r
+;--------------------------------------------------------------\r
+\r
+ if 0\r
+\r
+initab0:\r
+ db 1,stat0,0 ;Disable rx/tx interrupts\r
+ ;Enable baud rate generator\r
+ db 1,asext0,M_BRGMOD+M_DCD0DIS ; +M_CTS0DIS\r
+ db 2,astc0l\r
+init_br_off equ $ - initab0\r
+ dw 28\r
+ db 1,cntlb0,M_MPBT ;No MP Mode, X16\r
+ db 1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1\r
+ db 0\r
+\r
+initab1:\r
+ db 1,stat1,0 ;Disable rx/tx ints, disable CTS1\r
+ db 1,asext1,M_BRGMOD ;Enable baud rate generator\r
+ db 2,astc1l,low 3, high 3\r
+ db 1,cntlb1,M_MPBT ;No MP Mode, X16\r
+ db 1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1\r
+ db 0\r
+ endif\r
\r
;--------------------------------------------------------------\r
\r
dseg\r
-as0ista:\r
+asci0_ista:\r
push ix\r
ld ix,s0.inbuf ;\r
call ff_empty\r
\r
;--------------------------------------------------------------\r
\r
-as1ista:\r
+asci1_ista:\r
push ix\r
ld ix,s1.inbuf ;\r
call ff_empty\r
;--------------------------------------------------------------\r
; Get an input character\r
\r
-as0inp:\r
+asci0_inp:\r
push ix\r
ld ix,s0.inbuf ;\r
- call ff_cnt\r
- cp 32\r
+ call ff_gech\r
+ ld a,b\r
+ cp s0.rx_len/4\r
jr nc,a0i_1\r
di\r
in0 a,(cntla0)\r
ei\r
out0 (cntla0),a\r
a0i_1:\r
- call ff_get\r
+ ld a,c\r
pop ix\r
ret\r
\r
;--------------------------------------------------------------\r
; Get an input character\r
\r
-as1inp:\r
+asci1_inp:\r
push ix\r
ld ix,s1.inbuf ;\r
- call ff_get\r
+ call ff_gech\r
pop ix\r
ret\r
\r
;--------------------------------------------------------------\r
; Output status\r
\r
-as0osta:\r
+asci0_osta:\r
push ix\r
ld ix,s0.outbuf ;\r
call ff_full\r
;--------------------------------------------------------------\r
; Output status\r
\r
-as1osta:\r
+asci1_osta:\r
push ix\r
ld ix,s1.outbuf ;\r
call ff_full\r
; destroys hl, bc\r
; returns output char in a\r
\r
-as0out:\r
+asci0_out:\r
push ix ;\r
ld ix,s0.outbuf ;\r
- call ff_put\r
+ call ff_puth\r
+ pop ix ;\r
di ;\r
in0 c,(stat0) ;\r
set TIE,c ;\r
out0 (stat0),c ;\r
ei ;\r
- pop ix ;\r
ret\r
\r
;--------------------------------------------------------------\r
; destroys hl, bc\r
; returns output char in a\r
\r
-as1out:\r
+asci1_out:\r
push ix ;\r
ld ix,s1.outbuf ;\r
- call ff_put\r
+ call ff_puth\r
+ pop ix ;\r
di ;\r
in0 c,(stat1) ;\r
set TIE,c ;\r
out0 (stat1),c ;\r
ei ;\r
- pop ix ;\r
ret\r
\r
\r
-;------------------------------------------\r
+;--------------------------------------------------------------\r
+\r
+ cseg\r
+rtxisvjmp0:\r
+ call isv_sw\r
+ dw rxtxi0\r
+rtxisvjmp1:\r
+ call isv_sw\r
+ dw rxtxi1\r
+\r
+;--------------------------------------------------------------\r
; ASCI 0 Transmit/Receive interupt routines\r
\r
dseg\r
rxtxi0:\r
push ix\r
-rxtxi0_0:\r
- in0 e,(stat0) ;receive flag set?\r
- jp p,rxtxi0_1 ;\r
+rxtxi0_lp0:\r
+ ld ix,s0.inbuf ;\r
+rxtxi0_lp1:\r
+ in0 a,(stat0) ;receive flag set?\r
+ jp p,rxtxi0_1 ;RDRF == Bit 7\r
+ and M_OVRN+M_PERR+M_FE\r
+ ld e,a\r
\r
-rxi_0\r
- in0 a,(asext0) ;todo: break detection\r
+ in0 a,(asext0)\r
and M_BREAK\r
or e\r
ld e,a\r
\r
in0 d,(cntla0) ;\r
res EFR,d ;\r
+ out0 (cntla0),d\r
\r
- ld ix,s0.inbuf ;\r
- ld hl,s0.inbuf ;\r
- ld c,(ix+o.in_idx) ;-2\r
+\r
+ ld c,(ix+o.in_idx) ;\r
ld b,0\r
+ ld hl,s0.inbuf ;\r
add hl,bc\r
+\r
in0 a,(rdr0) ;\r
ld (hl),a\r
+ ;todo: break detection\r
+ ;todo: parity, framing overrun error\r
+\r
+\r
+ ld e,(ix+oint.fflags)\r
+ bit IXON,e\r
+ jr z,rxtxi0_2\r
+\r
+ ;todo: test XON/XOFF\r
+\r
+rxtxi0_2:\r
\r
- bit FE,e ;framing error?\r
- jr nz,?0ri_1\r
\r
ld a,c ;increment buffer in pointer\r
inc a ;\r
- and (ix+o.mask) ;-3\r
+ ld b,(ix+o.mask) ;\r
+ and b ;\r
ld c,a\r
- inc hl\r
- jr z,$+5\r
- ld hl,s0.inbuf ;\r
- sub (ix+o.out_idx) ;-1\r
- jr z,$+5 ;skip if buffer is full\r
- ld (ix+o.in_idx),c ;-2\r
- jr nc,$+6\r
- add (ix+o.mask) ;-3\r
- inc a\r
- cp 96\r
- jr c,$+4\r
- set RTS0,d ;RTS inactive\r
-?0ri_1:\r
+\r
+ sub (ix+o.out_idx) ;\r
+ jr z,rxtxi0_lp1 ;skip if buffer is full\r
+\r
+ ld (ix+o.in_idx),c ;\r
+\r
+ jr nc,$+3 ;\r
+ adc b ;\r
+\r
+ cp s0.tx_len*3/4\r
+ jr c,rxi0_noflow\r
+\r
+ bit CRTS_IFLOW,e\r
+ jr z,rxtxi0_4\r
+\r
+ set EFR,d\r
+ set RTS0,d ;RTS inactive\r
out0 (cntla0),d ;\r
- jr rxtxi0_0\r
+\r
+rxtxi0_4:\r
+ bit IXOFF,e\r
+ jr z,rxtxi0_lp1\r
+ ;todo: send XOFF\r
+\r
+rxi0_noflow:\r
+ jr rxtxi0_lp1\r
+\r
\r
rxtxi0_1:\r
+ ld e,a\r
bit TDRE,e ;TX int?\r
- jr z,rxtxi0_e\r
+ jr z,rxtxi0_e ;\r
+\r
\r
ld ix,s0.outbuf ;\r
\r
ld c,a\r
ld b,0\r
add hl,bc\r
- ld l,(hl)\r
- out0 (tdr0),l ; 7\r
+ ld b,(hl)\r
+ out0 (tdr0),b ; 7\r
\r
inc a\r
and (ix+o.mask)\r
ld (ix+o.out_idx),a\r
- jr ?0ti_3\r
+ jr rxtxi0_lp0\r
+\r
?0ti_2:\r
res TIE,e ;disable tx-int\r
out0 (stat0),e ; 5\r
-?0ti_3:\r
- jr rxtxi0_0\r
\r
rxtxi0_e:\r
pop ix\r
ret\r
\r
-;------------------------------------------\r
+\r
+;--------------------------------------------------------------\r
; ASCI 1 Transmit/Receive interupt routines\r
\r
dseg\r
rxtxi1:\r
in0 e,(stat1) ;receive flag set? 5\r
- jp p,txisv1 ;\r
+ jp p,txi1_0 ;\r
\r
in0 d,(rdr1) ;todo: break detection 9\r
bit FE,e ;framing error?\r
out0 (cntla1),a ; 1\r
ret\r
\r
-txisv1:\r
+txi1_0:\r
push ix\r
ld ix,s1.outbuf ;\r
\r