; $Id: mutil.asm,v 1.22 1996/09/04 15:24:04 cgregg Exp $
;	SECTION	MUTIL
;	include "adm.h"
;	include	"mutil.h"
;	include "mutil.def"
	ORG	P:
;**********************************************************************
; JTAGPRP prepares JTAG commands to be sent out over the SSI
;   Assumes: command(s) to be sent resides in the upper 4/8 bits of a1.
;   After last JTAG command has been sent, BANGBIT must be called
;**********************************************************************

JTAGPRP lsl	a1			;shift data left (0 in LSB)
	.IF	<CS> THEN		;if CARRY bit set then
	bset	#JTAGTDI,JTAGBDAT	;  set jtag msb
	.ELSE				;else
	bclr	#JTAGTDI,JTAGBDAT	;  clear jtag msb
	.ENDI				;endif

	.IF	<CS>			;if last jtag msb was set
	btst	#JTAGTDIV,JTAGBDAT		;  check valid bit
	.IF	<CS>			;  if bit is valid
	bset	#16,a			;    append a 1
	.ENDI				;  endif
	.ENDI				;endif
	bset	#JTAGTDIV,JTAGBDAT	;TDI bit has been saved, is now valid
	rts

;**********************************************************************
; BANGBIT configures port C for GPIO and sends the bit JTAGTDI ($0)
;   of JTAGBDAT (x:$23)
; Assumes: JTAG state machine in SHIFT-DR or SHIFT-IR state
;          JTAG state machine ends up in RUN-TEST/IDLE state
;          SSI has no data left to send
;**********************************************************************
BANGBIT	movep	#$0,PCC                 ;turn off SSI
 
	move	CLKRATE,n5		;preset for last bit shift
	btst	#JTAGTDI,JTAGBDAT		;check bit to send
	.IF	<CS> THEN		;if JTAGTDI==1 then
	bset	#DSI,PCD		;  send 1
	.ELSE				;else
	bclr	#DSI,PCD		;  send 0
	.ENDI				;endif
	bset	#JTAGTDOV,JTAGBDAT
	move	#SHIFT_EXIT,b1		;preset to shift to exit1
	jsr	TMSTOGGLE		;toggle tms pin
	bclr	#JTAGTDOV,JTAGBDAT
	movep	#$3e,IPR		;turn on IRQA,IRQB 
	bclr	#OnCEREQ,FLAGS 
	move	#EXIT_IDLE,b1		;need to finish jtag xfer states
	jsr	TMSTOGGLE
	bset	#POLLSTATUS,FLAGS	;need to poll for status
	bclr	#JTAGTDIV,JTAGBDAT	;saved TDI bit used, now invalid
	rts

;**********************************************************************
; TMSTOGGLE routine sends the proper number of clocks to preset
;   the JTAG state machine for transmitting commands and data in the
;   shift-dr state. At this time it is assumed that the target jtag
;   state machine is in the IDLE state.
;   Accumulator B will contain the tms data in the upper 16 bits and
;   the clock count in the lower 8 bits.
;**********************************************************************
TMSTOGGLE move	b1,b2			;get count
	bset    #TMS0FLAG,FLAGS

	movep	#0,PCC
	move	CLKRATE,n5
	do	b2,TMSTOGLE		;send out tms values
	lsl	b			;get bit value into carry bit
	jclr	#TMS0FLAG,FLAGS,SETTMS1	;check if toggling tms0 or tms1
	jcs	<CLKCALL		;setup for sending a 1
	bclr	#TMS0,PBD		;setup tms0 for 0
	jmp	<CLKCALL1
CLKCALL bset	#TMS0,PBD
CLKCALL1 jsr	<CLKTOGGLE		;toggle clock
	btst	#JTAGTDOV,JTAGBDAT
	.IF	<CS> THEN		;if JTAGTDO is VALID for writing
	btst	#DSO,PCD		;  test TDO
	.IF	<CS> THEN		;  if TDO == 1
	bset	#JTAGTDO,JTAGBDAT	;    JTAGTDO=1
	.ELSE				;  else
	bclr	#JTAGTDO,JTAGBDAT	;    JTAGTDO=0
	.ENDI				;  endif
	.ENDI				;endif
	nop
TMSTOGLE rts
SETTMS1 jcs	<CLKCALL2		;setup for sending a 1
	bclr	#TMS1,PBD		;set tms1 to 0
	jmp	<CLKCALL1
CLKCALL2 bset	#TMS1,PBD
	jmp	<CLKCALL1

;***************************************************************************
; CLKTOGGLE routine is used to set and clear the clock line in 
;   software.  It is assumed that the data to be output is already
;   stable on the PC8_STD pin.  The value on the JTAG TDO pin is
;   saved in bit JTAGTDO ($2) of JTAGBDAT (x:$23)
;***************************************************************************
CLKTOGGLE movep	#0,PCC			;turn off ssi, turn on portc io
        bset	#DSCK,PCD		;set clock high
        rep	#2
        nop				;kill some time
	btst	#DSO,PCD		;get data bit value
	.IF	<CC> THEN		;If read is 0
        bclr	#DATAFLG,FLAGS		;clear data flag
	.ELSE
        bset	#DATAFLG,FLAGS		;else set it to 1
	.ENDI
CLKTOG  bset	#DSCK,PCD		;set clock high
        rep	n5
        nop				;set clock high
        bclr	#DSCK,PCD		;set clock low
        rep	n5
        nop				;set clock low
        rts
;**********************************************************************
; BANGCLK writes TDI before rising edge, reads TDO after rising edge
;   does not modify JTAG state machine
;   Assumes: JTAG state in SHIFT_DR or SHIFT_IR
;            SSI is done with transfer
;            bit #JTAGTDI of JTAGBDAT should be put on TDI
;**********************************************************************
BANGCLK	movep	#0,PCC			;turn off ssi, turn on portc io
	btst	#JTAGTDI,JTAGBDAT
	.IF	<CS>			;if TDI should be 1
	bset	#DSI,PCD		;  set TDI=1
	.ELSE				;else
	bclr	#DSI,PCD		;  set TDI=0
	.ENDI

	bset	#DSCK,PCD		;set clock high
        rep	n5			;hold clock high for n5 cycles
        nop				;  wait

	btst	#DSO,PCD		;get data bit value
	.IF	<CC> THEN		;if read is 0
	bclr	#JTAGTDO,JTAGBDAT	;  save TDO=0
	.ELSE				;else
	bset	#JTAGTDO,JTAGBDAT	;  save TDO=1
	.ENDI				;endif

        bclr	#DSCK,PCD		;set clock low
        rep	n5			;hold clock high for n5 cycles
        nop				;  wait

        rts
;*************************************************************************
; JXFERxx presets SSI for xx bit xfer, lsb first for JTAG communication
;   where xx is 24, 16, 12 or 8
;*************************************************************************
JXFER24	bset            #WL0,SSICLK		;set WL0 in cra
	bset            #WL1,SSICLK		;set WL1 in cra
	jmp		JXFER

JXFER16	bclr		#WL0,SSICLK		;clear WL0 in CRA
	bset		#WL1,SSICLK		;set   WL1 in CRA
	jmp		JXFER

JXFER12	bset		#WL0,SSICLK		;set   WL0 in CRA
	bclr		#WL1,SSICLK		;clear WL1 in CRA
	jmp		JXFER

JXFER8	bclr		#WL0,SSICLK		;clear WL0 in CRA
	bclr		#WL1,SSICLK		;clear WL1 in CRA

JXFER	ori             #$3,mr                  ;disable interrupts
        movep           #$0,IPR                 ;turn off IRQA,IRQB
	movep		#CRBLSB,CRB
        movep           #$0,PCC                 ;turn off SSI
	movep		SSICLK,CRA
        movep           #$1c0,PCC               ;turn on SSI
	rts 
;**********************************************************************
; FILLTDO reads DEVACTIVE and bangs data past all of the bypass
;  registers near TDO.
;  Must be called before READING from a OnCE register
;  Does not need to be called if the active device is the first
;    (closest to TDO) in the chain 
;**********************************************************************
FILLTDO	move	DEVACTIVE,a1
FILLTDO1 lsr	a1
	.IF	<CC>
	jsr	BANGCLK
	jmp	FILLTDO1
	.ENDI
	rts
	
;**********************************************************************
; FILLTDI reads DEVACTIVE and bangs data past all of the bypass
;  registers near TDI.
;  Must be called before WRITING to a OnCE register
;  Does not need to be called if the active device is the last
;    (closest to TDI) in the chain 
;**********************************************************************
FILLTDI clr	a
	move	DEVACTIVE,a1		;fetch active device list
	bclr	#0,SR			;clear carry
	rep	DEVCNT
	ror	a1
FILLTDI1 .IF	<CC>			;if device inactive
	jsr	BANGCLK			;  toggle clock
	lsl	a1			;  shift active list left
	jmp	FILLTDI1		;  go find active device
	
	.ENDI				;endif
	rts				;  return

;**********************************************************************
; OISSUE sends a command/data to OnCE shift registers.
;  Assumes: JTAG state machine in RTI
;           JTAG state machine ends up in RTI
;           Data to send is in upper bits of ACTIVECMD
;           Only one device in chain is active
;           Writes registers: A,B
;**********************************************************************
OISSUE24 move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	JXFER24			;init ssi for 24 bit transfer
	jmp	OISSUE1			;skip 8 & 16 bit init
OISSUE16 move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	JXFER16			;init ssi for 16 bit transfer
	jmp	OISSUE1			;skip 8 bit init
OISSUE8 move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	JXFER8			;init ssi for 8 bit transfer
OISSUE1
	move	ACTIVECMD,a1		;fetch active command
	jsr	JTAGPRP			;prepare data for JTAG
	xmit	a1			;send active command
	jsr	FILLTDI			;fill TDI bypass registers
	jsr	BANGBIT			;bang last bit in

	rts				;return

;**********************************************************************
; OREAD reads data from OnCE shift registers.
;  Assumes: JTAG state machine in RTI
;           JTAG state machine ends up in RTI
;           Only one device in chain is active
;           Writes registers: A,B
;**********************************************************************
OREAD24	move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	FILLTDO			;fill bypass registers
	jsr	JXFER24			;init ssi for 24 bit transfer
	jmp	OREAD1			;skip 8 & 16 bit init

OREAD16	move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	FILLTDO			;fill bypass registers
	jsr	JXFER16			;init ssi for 16 bit transfer
	jmp	OREAD1			;skip 8 bit init

OREAD8	move	#IDLE_SDR,b1		;Reset JTAG State, go to SIR
	jsr	<TMSTOGGLE		;toggle tms pin
	jsr	FILLTDO			;fill bypass registers
	jsr	JXFER8			;init ssi for 8 bit transfer

OREAD1
	clr	a
	clr	b
	recv	a1			;read into a1
	jset	#2,DEVICE,OREAD2
	jset	#5,TEMPAREA,OREAD2	;if 16 bit wrap it up
	move	a1,b1			;copy recieved data
	rep	#8
	lsl	a1
	rep	#8
	lsr	b1
OREAD2	move	a1,x:(r3)+		;save lower 16bits
	jset	#2,DEVICE,OREAD3
	move	b1,x:(r3)+		;save upper 8 bits
OREAD3	move	#SHIFT_IDLE,b1
	jsr	TMSTOGGLE
	movep	#$3e,IPR
	bclr	#OnCEREQ,FLAGS
	rts
;**********************************************************************
; JREADSB - Read status bits from ACTIVE device, decode BYPASS in all
;           inactive devices and E_ONCE in the active device.
; JISSUE  - Read status bits from ACTIVE device, decode BYPASS in all
;           inactive devices and ACTIVECMD in the active device.
; JISSUE2 - Read status bits from ACTIVE device, decode INACTIVECMD in
;           all inactive devices and ACTIVECMD in the active device.
;**********************************************************************
JREADSB	move	#E_ONCE,a
	move	a,ACTIVECMD
JISSUE	move	#BYPASS,a
	move	a,INACTIVECMD
JISSUE2 bclr	#STATUSBUSY,FLAGS
	bset	#DEBUGMODE,FLAGS
	move	#IDLE_SIR,b1
	jsr	TMSTOGGLE		;JTAG <- SIR
	move	DEVACTIVE,b
	move	b1,DEVTMP		;init for CHKACTIVE
	do	DEVCNT,JREADSB1		;do DEVICE COUNT
	nop
	move	#>1,a			;
	move	lc,b			;
	cmp	b,a			;
	.IF	<EQ>			;  if last device
	bset	#JTAGLAST,JTAGBDAT	;    set last device bit
	.ELSE				;  else
	bclr	#JTAGLAST,JTAGBDAT	;    clear last device bit
	.ENDI				;  endif
	move	DEVCNT,b		;  b      <- DEVICE COUNT
	move	lc,y0			;  y0     <- Loop Count
	sub	y0,b			;  b      <- b-y0
	move	#>1,y0
	add	y0,b
	move	b,CURDEV		;  CURDEV <- b
	jsr	CHKACTIVE		;  check device for activity
	.IF	<CS>			;  if device active
	move	ACTIVECMD,a1
	jsr	J_RDWR			;    write ACTIVE_CMD, read SB
	move	JTAGDATA,b1		;    fetch status
	move	#>$d00000,y1		;    happy to see d
	move	#>$f00000,x1		;    setup mask
	and	x1,b			;    clear out junk
	cmp	y1,b			;    did we read status = d?

	.IF	<EQ>			;    if read d
	bclr	#POLLSTATUS,FLAGS	;      stop polling
	bset	#ACTVMODE,FLAGS
	.ELSE				;    else
	move	b,STATVAL		;      save statvalue
	bset	#STATUSBUSY,FLAGS	;      set status as busy
	bclr	#DEBUGMODE,FLAGS	;      clear debug mode
	bclr	#ACTVMODE,FLAGS		;      clear active mode
	.ENDI				;    endif
	.ELSE				;  else
;	move	x:JIRTABLE,r5		;    r5 <- JIRTABLE pointer
	move	p:JIRTABLE,r5		;    r5 <- JIRTABLE pointer
	move	CURDEV,n5		;    n5 <- DEV NUMBER ACTIVE
	nop
;	move	x:(r5+n5),b		;    b  <- JTAG IR LENGTH
	move	p:(r5+n5),b		;    b  <- JTAG IR LENGTH
	bclr	#23,b1			;    test and clear high bit
	.IF	<CS>			;    if NOT_A_DSP (bit set)
	move	#>1,x1			;      x1 <- 1
	sub	x1,b			;      b  <- b-1
	move	b1,a2			;      a2 <- b (#bits to send - 1)
	move	#>$ffffff,a1		;      a1 set to all 1s (bypass)
	.ELSE				;    else
	move	INACTIVECMD,a1		;      will send INACTIVECMD (bypass)
	move	#3,a2			;      hack, need to send 4 bits
	.ENDI				;    endif
	jsr	J_WR1			;    just write INACTIVECMD (no read sb)
	.ENDI				;  endif
	nop
	nop
JREADSB1 nop				;enddo
	move	#EXIT_IDLE,b1		;will goto IDLE
	jsr	TMSTOGGLE		;JTAG <- IDLE
	rts				;return
;*******************************************************************
;       J_RDWR routine toggles data in/out, then increments state
;       machine to exit1 so that last bit of data is retrieved/sent.
;
;       This is necessary since the jtag state machine will contine
;       transferring data until the state machine decoder is not decoding
;       a shift-data or shift-ir command.
;
;       This routine assumes the data is in the A accumulator for sending
;       and that data received is in the B accumulator.
;
;******************************************************************
J_RDWR move            a1,a2                   ;set up clock count
;*****************************************************************
;       SHIFT DATA RIGHT 8 BITS AND SEND/RECEIVE IT
;	IN LINE CODE TO REDUCE NUMBER OF SUBROUTINE CALLS.
;	THIS USED TO BE SHIFTTOG
;*****************************************************************
J_RDWR1 rep            #8              	;need to shift data in A
        lsr             a
        move            CLKRATE,n5      	;preset clock rate
        do              a2,J_RDWR2
        jsr             <SHIFTDATA      	;go preset data to port pin
        jsr             <CLKTOGGLE      	;go toggle clock
	move            JTAGDATA,b      	;get current value
        btst            #DATAFLG,FLAGS  	;chek if next bit is 0 or 1
        ror             b               	;get bit
        move            b1,JTAGDATA     	;save value
J_RDWR2 nop
        jsr             <SHIFTDATA              ;shift last bit onto port
	btst	#JTAGLAST,JTAGBDAT		;is this the last command?
	.IF	<CS>				;if last command

        move            #SHIFT_EXIT,b1          ;  preset for shift to exit
        jsr             <TMSTOGGLE		;  toggle tms pin and
	move		JTAGDATA,b      	;  get current value
        btst            #DATAFLG,FLAGS  	;  chek if next bit is 0 or 1
        ror             b               	;  get bit
        move            b1,JTAGDATA     	;  save value
	.ELSE					;else
	jsr	<CLKTOGGLE			;  toggle clock
	move	JTAGDATA,b			;  get current value
	btst	#DATAFLG,FLAGS			;  check for 0 or 1
	ror	b				;  get bit
	move	b1,JTAGDATA			;  save bit
	.ENDI					;endif and nasty HACK!
        rts                                     ;return
;***************************************************************************
;       J_WR routine sends the proper bit values through the TDO
;       pin for an n bit data stream.  It will be used for boundary scan
;       registers and loading instructions of various lengths.
;       Data to be sent is in A accum. and data received is in B accum.
;       a2 contains the number of bits to xmit - 1.
;***************************************************************************
J_WR	move	JTAGDATA,a1		;get data to send
J_WR1	move	CLKRATE,n5		;preset clock rate
	rep	#8
        lsr             a
	do	a2,J_WR6
	bset	#23,a1			;ensure a 1 in high bit of a1
	lsr	a			;check if data is 1 or 0
	.IF	<CS>			;if data 1
	bset	#DSI,PCD		;  send 1
	.ELSE				;else
	bclr	#DSI,PCD		;  send 0
	.ENDI				;endif
	jsr	CLKTOGGLE		;toggle clock
	nop
	nop
J_WR6	bset	#23,a1			;ensure 1 in high bit of a1
	lsr	a               	;check if data is 1 or 0
	.IF	<CS>			;if data 1
	bset	#DSI,PCD		;  send 1
	.ELSE				;else
	bclr	#DSI,PCD		;  send 0
	.ENDI				;endif
	btst	#JTAGLAST,JTAGBDAT	;test for last device
	.IF	<CS>			;if last device
	move	#SHIFT_EXIT,b1		;  preset for SHIFT_EXIT
	jsr	TMSTOGGLE		;  JTAG <- EXIT
	.ELSE				;else
	jsr	CLKTOGGLE		;  just toggle clock
	.ENDI				;endif
	rts				;return
;***************************************************************************
;       SHIFTDATA presents the data at the port pin so it may be sent
;       to the target.  The last bit of data must be present when exiting
;       so that when the jtag state machine transitions to the exit1 state
;       it will capture the last bit of data.
;       Assumption is that the data going out is in A and data coming in is
;       in B.
;**************************************************************************
SHIFTDATA lsr             a               ;check if data is 1 or 0
SHIFTDATA1 jcs             <DATATOGL2      ;if carry clear send 0
        bclr            #DSI,PCD        ;else need to send 1
        jmp             <DATATOGL5
DATATOGL2 bset          #DSI,PCD        ;send 1 if carry set
DATATOGL5 rts

;***************************************************************************
;       CHKACTIVE routine checks if the current device being addressed
;       is in bypass mode or in enable_once mode.
;***************************************************************************
CHKACTIVE move          DEVTMP,b1               ;or if active
        lsr             b                       ;
        move            b1,DEVTMP               ;save last device tested
        rts

;***************************************************************************
; POLLUSR - poll devices in user mode. Notify host if a device stops.
;   remove device from USRLIST if not in user mode.
;   ASSUMES: JTAG state in IDLE
;***************************************************************************
POLLUSR move	DEVCNT,b
	tst	b	USRLIST,a
	.IF	<EQ>				;if DEVCNT==0
	rts					;  return
	.ENDI					;endif
	tst	a	DEVACTIVE,b
	.IF	<EQ>				;if USRLIST==0
	rts					;  return
	.ENDI					;endif
	tst	b	a,USRTMP
	.IF	<EQ>				;if DEVACTIVE==0
	rts					;  return
	.ENDI					;endif
	move	b,SAVEACTIV			;save off ACTIVE DEVICE
	move	DEVNUMA,b
	move	b,SAVENUMA
	move	#JRESET_IDL,b1
	jsr	TMSTOGGLE
	move	#>0,b
	move	b,DEVNUMA
	move	#>1,b
	move	b,DEVACTIVE			;set DEVACTIVE to device 1
	do	DEVCNT,ENDPOLL			;do DEVCOUNT
	move	DEVNUMA,r5
	nop
	move	(r5)+
	move	r5,DEVNUMA
	move	USRTMP,b			;  fetch temporary user list
	lsr	b				;  shift user right
	.IF	<CS>				;  if device was in user mode
	move	b,USRTMP			;    save temporary user list
	jsr	JREADSB				;    get status
	btst	#DEBUGMODE,FLAGS
	.IF	<CS>				;    if in debug mode
	jsr	USRDEL				;      remove from USRLIST
	jsr	POLLOFF				;      notify host (no hndshk)
	move	DEVNUMA,r5			;      fetch device number
	move	r5,DEVSERVICE			;      save as reqesting service
	enddo
	jmp	ENDPOLL
	.ENDI					;    endif
	.ELSE					;  else
	move	b,USRTMP			;    save temporary user list
	.ENDI					;  endif
	move	DEVACTIVE,a			;  fetch active device
	lsl	a				;  shift active left
	move	a,DEVACTIVE			;  save new devactive
ENDPOLL 					;enddo
	move	SAVEACTIV,b			;restore original active device
	move	b,DEVACTIVE
	move	SAVENUMA,b
	move	b,DEVNUMA
	jsr	JREADSB				;decode enable once in JIR
	rts					;return

;*******************************************************************
; USRADD adds the active device to the user mode list
;    writes to x1,b,USRLIST
;*******************************************************************

USRADD	move	USRLIST,x1
	move	DEVACTIVE,b
	or	x1,b
	move	b,USRLIST
	rts

;*******************************************************************
; USRDEL removes the active device from the user mode list
;    writes to x1,b,USRLIST
;*******************************************************************
USRDEL	move	USRLIST,x1
	move	DEVACTIVE,b
	not	b
	and	x1,b
	move	b,USRLIST
	rts
