 sttl Z8038 FIO Handler
 pag

*
* fio_put - Set a FIO register
*   A - FIO register #
*   B - Value to store
*
fio_put pshs cc must mask interrupts
 seti
 sta FIOctl,u address register
 stb FIOctl,u set value
 puls cc,pc

*
* fio_get - Fetch the value of a FIO register
*   A - FIO register #
*   B - Returned value
*   U - FIO device address
*
fio_get pshs cc must mask interrupts
 seti
 sta FIOctl,u select register
 ldb FIOctl,u fetch value
 puls cc,pc return

*
* fio_send - Send a value via the FIO Mailbox
*   B - Value to send (one byte)
*   U - FIO device address
*
fio_send pshs b,x save register
 lda #msg_out select outgoing mailbox
 bsr fio_put
 ldx #$FFFF time-out counter
10 lda #ctl_reg1 wait till value consumed
 bsr fio_get
 bitb #$20 "mailbox full" flag
 beq 20f jump when consumed
 leax -1,x timed out?
 bne 10b
 ldx #00f
 jsr Pdata
 lda 0,s
 jsr Phex
 ldx #01f
 jsr Pdata
 lda #ctl_reg1 wait till value consumed
 bsr fio_get
 tfr b,a
 jsr Phex
 ldx #02f
 jsr Pdata
 lda #ist_reg0 wait till value consumed
 lbsr fio_get
 tfr b,a
 jsr Phex
 bra *
20 puls b,x
 rts
*
00 fcc $d,'IOP Time out - Sending $',0
01 fcc ', CTL1 = $',0
02 fcc ', ISR0 = $',0

*
* fio_rcv - Receive a value via the FIO Mailbox
*   B - Value received
*   U - FIO device address
*
fio_rcv lda #ist_reg0 check for mail ready
10 lbsr fio_get check status
 bitb #$20 "mailbox full"?
 beq 10b
 lda #msg_in pick up the mail
 jsr fio_get
 rts

*
* fio_delay - Delay an appropriate time for FIO reset
*
fio_delay bsr 00f -- Ask GIMIX about this!
00 rts


*
* fio_msg - Send a value via the FIO Mailbox & wait for response
*   D - Value to send (B = Command, A = Specific data)
*   U - FIO device address
*   Y - Interlock table
*   jsr fio_msg
*   D - Value returned (B = Error response, A = Specific data)
*
fio_msg pshs cc,d,x,y,u save registers
* -- Find an empty transaction box
10 seti turn off interrupts
 ldy 5,s get IOP control address
 jsr MBX_lock get access to IOP
 lbsr find_slot go find a slot
 beq 15f jump if one found
 ldy 5,s restore IOP structure pointer
 if DEB_SLP
 jsr p_slp_slot
 endif
 jsr MBX_unlock give up IOP until slot available
 lbsr find_slot make sure no slots available
 beq 10b jump if there is one
 ldy 5,s get IOP pointer
 leay iop_tflg,y sleep on transaction slots
 ldb #IOPPRI
 jsr sleep wait for available message slot
 if DEB_SLP
 ldy 5,s
 jsr p_chk_slot
 endif
 bra 10b try for a transaction slot
15 ldx utask set sequence # in slot
 ldd tstid,x
 std tran_seq,y
 ldb 0,s enable interrupts
 tfr b,cc
 pshs y save transaction slot pointer
 ldy 7,s restore IOP structure pointer
 ldb 4,s restore message code
 if DEB_MSG
 pshs d,x
 ldx #00f
 jsr Pdata
 lda 1,s
 jsr Phex
 ldx #01f
 jsr Pdata
 ldx utask
 ldd tstid,x
 jsr Phex2
 puls d,x
 endif
 lbsr fio_send
 ldx utask
 ldd tstid,x
 pshs d
 ldb ,s+ use task # as sequence #
 jsr fio_send
 ldb ,s+
 jsr fio_send
 ldb 3,s restore specific data
 jsr fio_send
 jsr MBX_unlock release mailbox
20 puls y get transaction slot address
 seti mask interrupts
 tst tran_resp,y any response yet?
 bne 30f yes - go process
 ldx 5,s get IOP control address
 ldd iop_fifo,x does this task own the FIFO?
 bne 25f yes - don't allow interrupts!
 pshs y,u save registers
 ldd umark1 set up to allow interruptable sleep
 pshs d
 ldx #27f interrupt handling label
 pshs x
 sts umark1
 ldb #TTYIPR set interruptable priority
 jsr sleep wait for IOP response
 puls d,x,y,u restore registers
 stx umark1 restore interrupt point
 bra 30f continue
27 puls x,y,u Interrupt happened! - (D) already popped
 stx umark1 restore stack mark
 lda #E_ABORT aborted transaction!
 sta tran_resp,y
 ldb 2,s send "interrupt" message to IOP
 andb #$03 get terminal #
 orb #O_INTRPT
 jsr fio_send
 jsr fio_send -- These fields are ignored
 jsr fio_send -- and there will be no response
 jsr fio_send --
 bra 30f
25 ldb #IOPPRI
 pshs x,y,u save registers
 jsr sleep
 puls x,y,u restore registers
30 ldx utask
 if DEB_MSG
 pshs d,x
 ldx #05f
 jsr Pdata
 lda tran_resp,y
 jsr Phex
 ldx #01f
 jsr Pdata
 ldd tran_seq,y
 jsr Phex2
 puls d,x
 endif
 seti turn off interrupts while fiddling with transaction slots
 ldd #0 release transaction slot
 std tran_seq,y
 ldb tran_resp,y get response code
 clr tran_resp,y
 lda tran_val,y get response value
 std 1,s set return value
 ldy 5,s wake anybody waiting for this slot
 leay iop_tflg,y
 jsr wakeup
 lda 2,s interrupted transaction?
 cmpa #E_ABORT
 bne 50f no - continue
 lds umark1 yes - get out
 rts
50 puls cc,d,x,y,u,pc return
 if DEB_MSG
00 fcc $d,'FIO MSG = $',0
01 fcc "/",0
05 fcc $d,'MSG Response = $',0
 endif

*
* find_slot - find a transaction slot
*   Y - IOP control address
*   jsr find_slot
*   Y - Transaction slot
*   <NE> if none available
*
find_slot pshs x,y save register
 leay iop_tran,y point to transactions
 ldb #MAX_TRAN
 pshs b
10 ldd tran_seq,y entry busy?
 ldx utask allocated by me?
 cmpd tstid,x
 beq 30f yes - use it!
 leay TRAN_SIZ,y
 dec 0,s any more?
 bne 10b
 ldy 3,s restore IOP pointer
 leay iop_tran,y point to transactions
 ldb #MAX_TRAN
 stb 0,s
20 ldd tran_seq,y entry busy?
 beq 30f no - use it!
 leay TRAN_SIZ,y
 dec 0,s any more?
 bne 20b
 lda #1 return NE - no slot
 bra 99f
30 sty 3,s return value
 clra return EQ - slot found
99 puls b,x,y,pc clean stack & return

*
* fifo_out - Select outgoing FIFO mode
*   U - FIO address
*
fifo_out pshs d,x,y,u save registers
 lda #ctl_reg3 FIFO direction bit in reg 3
 jsr fio_get
 andb #!FIO_IN set direction = OUT
 jsr fio_put
99 puls d,x,y,u,pc return

*
* fifo_in - Select incoming FIFO mode
*   U - FIO address
*
fifo_in pshs d,x,y,u save registers
 lda #ctl_reg3 FIFO direction bit in reg 3
 jsr fio_get
 orb #FIO_IN set direction = IN
 jsr fio_put
99 puls d,x,y,u,pc return
