[comp.sys.nsc.32k] SCSI Question.

rhyde@gibson.ucr.edu (randy hyde) (04/23/91)

I noticed in Bruce's SCSI driver that it says that SCSI always transfer
multiples
of four bytes.  Is this true?  Is this why I'm having troubles when I'm
attempting to transfer only 10 bytes for the read command?
*** Randy Hyde

culberts@hplwbc.hpl.hp.com (Bruce Culbertson) (04/25/91)

> I noticed in Bruce's SCSI driver that it says that SCSI always transfer
> multiples
> of four bytes.  Is this true?  
> *** Randy Hyde

This is only an issue when tranferring from the SCSI device to the pc532
(a "read" phase of a SCSI command).  Tranfers in the other direction are
always the correct length.

The SCSI controller's data register, from the CPU's point of view, is just
like ordinary memory.  When the CPU tries to read an address which is
mapped to the data register, it first tries to find the value in the cache.
The controller software has been carefully written to insure that the
values are never found in the cache -- a read always results in a cache
miss and, hence, the controller register actually gets read.  On a cache
miss, the CPU always fills an entire cache line (4 bytes), regardless of
the size of the object wanted.  Hence, groups of four bytes are always
read from the controller.  This does not mean that the SCSI device on
the other side of the SCSI bus has to send four bytes.  If the SCSI
device sends, say, two bytes, then those two bytes plus two garbage
bytes will be read by the CPU when it fills the cache line.  Study the
logic driving the CPU /RDY signal to see how this happens.

To prevent SCSI read transfers from ending prematurely, movd
instructions (more precisely, instructions operating on four byte
objects) should be used to read the SCSI controller data register.
This is explained in the comments in scsi_8490.c.  Hence, you should
provide a buffer which is a multiple of four bytes to receive a read
transfer, even if you are expecting a smaller transfer.

> Is this why I'm having troubles when I'm
> attempting to transfer only 10 bytes for the read command?

I doubt it.  Lots of people have Minix configured to do extended read
commands.  I use the six byte (obsolete) read command on my obsolete disk.

I just noticed that the monitor (as opposed to Minix) always transfers
multiples of four bytes, even on the write phases.  Shouldn't matter,
though.  The SCSI controller just stuffs the extra data into the
proverbial bit-bucket.

Bruce Culbertson

rhyde@ucrmath.ucr.edu (randy hyde) (04/26/91)

		
The program which follows is an attempt at a SCSI driver for the 8490
using the enhanced mode.  It seems to be transmitting the command bytes
just fine.  However, after the device receives the command, the SCSI
bus basically locks up  until I send a reset command.  After a few of
these, it doesn't lock up, I get the "command complete" message back,
but it didn't really do the command.  I've tried using pseudo-DMA
and the results were even worse-- it almost always locked up.  I don't
know if this is the DMA version or the polled version.  They differ
only in the Send routine.  In any case, if someone can see an obvious
error (I realize this is a long piece of code) I'd sure appreciate
a pointer or two.

Bruce-- I have a file called SCSI.C I got from somewhere.  Is this
code the same as SCSI_8490.C.  Has this code ever changed?

I know my disk drive works fine because Bruce's monitor accesses it
just fine (well, after an initial BUSY warning when the thing comes
up).  According to my SCSI.C listing, the monitor code does not
arbitrate for the bus, but my code does.  Could this be a problem?



	.program	x'30000
;
;
;
;
TimeOutDelay	.equ		2000000
;
; Absolute addresses:
;
icu		.equ		x'fffffe00
scsi		.equ		x'30000000
scsidma		.equ		x'38000000
;
;
; DP8490 Registers:
;
dpODR		.equ		0
dpCSD		.equ		0
dpICR		.equ		1
dpMR2		.equ		2
dpTCR		.equ		3
dpSER		.equ		4
dpCSB		.equ		4
dpBSR		.equ		5
dpSDS		.equ		5
dpSDT		.equ		6
dpIDR		.equ		6
dpSDI		.equ		7
dpRPI		.equ		7
dpEMR		.equ		7
dpISR		.equ		7
dpIMR		.equ		7
;
;
;
ph_odata	.equ		0
ph_idata	.equ		1
ph_cmd		.equ		2
ph_stat		.equ		3
ph_omsg		.equ		6
ph_imsg		.equ		7
ph_none		.equ		8
;
;
;
;
		.static
;
SenseBuf	.blkb	24
MsgBuf		.blkb	4
StatBuf		.blkb	4
;
;
;
CmdRetry	.byte
;
		.endseg
;
;
;****************************************************************************
;
; The program begins here:
;
;
;
		br	StartTest:w
		br	CheckCondition
;
;
;
;
;
; Tabular Data:
;
;
MaskBits	.byte	x'ff, x'fe, x'fc, x'f8, x'f0, x'e0, x'c0, x'80
;
; Read one block starting at block zero:
;
SCSICmds	.byte	x'01, x'00, x'00, x'00, x'00, x'00, x'00
		.byte	x'00, x'01, x'00
;
ChkCond		.byte	x'03, x'00, x'00, x'00, 24, 0
;
;
;*****************************************************************************
;
;
uart		.equ	x'28000000
cr		.equ	13
lf		.equ	10
;
;
putc2		save	[R1]
		movd	uart, r1
putclp		tbitb	2, 1(r1)
		bfc	putclp
		movb	r0, tos			;Delay for serial chip.
		movb	tos, 3(r1)
		restore	[r1]
		ret	0
;
;
putc		bsr	putc2:b
		cmpb	cr, r0
		bne	NoLF:b
		movb	lf, r0
		bsr	putc2:b
		movb	cr, r0
NoLF		ret	0
;
putcr		save	[r0]
		movb	cr, r0
		bsr	putc
		restore	[r0]
		ret	0
;
;
;
; PRINT ROUTINE, PRINTS THE ZERO-TERMINATED STRING THAT
;       FOLLOWS THE CXP INSTRUCTION.
;
PRINT		ENTER		[R0,R1],0
;
RTNADRS		.EQU		4(FP)
;
;
; Note: TOS looks something like:
;
;        RETURN ADDRESS
;	 FRAME POINTER
;        R0
;        R1
;
		MOVD	RTNADRS,R1
PRINTLP		MOVB	0(R1),R0
		CMPQB	0,R0
		BEQ	PRTDONE
		BSR	PUTC
		ACBD	1,R1,PRINTLP
;
prtdone		addqd	1, r1
		movd	r1, rtnadrs
		exit	[r0, r1]
		ret	0
;
;
PRNBLS		MOVD		R0,TOS
		LSHD		R1,R0
		BSR		PRNIBBLE:B
		MOVD		TOS,R0
		ACBB		4,R1,PRNBLS
;
PRNIBBLE	ANDD		X'0F,R0
		MOVB		CHRS [R0:B], R0
		BR		PUTC
;
;
CHRS		.BYTE		'0123456789ABCDEF'
;
;
;
;
;
DOPRBYTE	SAVE		[R0,R1]
		MOVQD		-4,R1
		BR		FINISH:B
;
DOPRWORD	SAVE		[R0,R1]
		MOVXBD		-12,R1
		BR		FINISH:B
;
DOPRDBL		SAVE		[R0,R1]
		MOVXBD		-28,R1
FINISH		BSR		PRNBLS
		RESTORE		[R0,R1]
		RET		0
;
;
;****************************************************************************
;
;
; Reset the SCSI chip:
;
ResetSCSI	save	[r1,r7]
		bsr	print
		.byte	"Resetting SCSI Bus",cr,0
;
		movd	scsi, r7
		movqb	0, dpMR2(r7)
		movqb	0, dpODR(R7)
		movb	x'80, dpICR(r7)			;Hit the reset bit.
		movqb	-1, r1
RstChipDelay	acbb	-1, r1, RstChipDelay
		movb	x'0, dpICR(r7)			;Clear reset bit.
		movqw	-1, r1
Rst2ChipDelay	acbw	-1, r1, Rst2ChipDelay
		restore	[r1,r7]
		ret	0
;
;****************************************************************************
;
;
; Arbitrate- Arbitrates for the SCSI bus.  R1(b) contains the SCSI id
; of the device we want to access.
;
;
Arbitrate	save	[r0,r2,r3,r7]
		bsr	print
		.byte	"In Arbitration",cr,0
		movd	TimeOutDelay, r3
		br	DoArb:w
;
; Come here if we get a time-out during arbitration
;
ResetArb	bsr	print
		.byte	"Arbitration time-out",cr,0
		bsr	ResetSCSI
		movd	TimeOutDelay, r3
;
;
;
DoArb		movd    scsi, r7
		movqb	0, dpTCR(r7)			;During ARB, phase=0
;
;
; Put the chip into enhanced mode:
;
;
		movb	x'40, dpICR(r7)
		bicb	1, dpMR2(r7)			;Clear normal arb bit.
;
; Put out the scsi id of the disk drive (in R1(b))
;
		movb	r1, dpODR(r7)
		movb	x'41, dpICR(r7)		;Enable data bus & enh mode.
;
; Arbitration Loop:
;
ClearArb	movqb	2, dpEMR(r7)		;Reset Ints, Turn off Arb
		movqb	0, dpEMR(r7)		;Finish reset Ints.
		movqb	1, dpEMR(r7)		;Enable EMR/ARB.
ArbLoop		movqb	7, dpEMR(r7)		;Enhanced Arb, Read ISR
		tbitb	0, dpISR(r7)		;Done Arbitration?
		bfs	GotTheArb:b
		acbd	-1, r3, ArbLoop
		br	ResetArb
;
GotTheArb	tbitb	5, dpICR(r7)		;See if we lost arbitration.
		bfs	ClearArb
		movqb	2, dpEMR(r7)		;Reset interrupt status and
		movqb	0, dpEMR(r7)
;
; See if we were given the highest priority
;
		movqd	0, r2			;Find the bit position of
		ffsb	r1, r2			; our SCSI id.
		movzbd	r2, r2
		movb	dpCSD(r7), r0		;Mask out all the bits in the
		andb	MaskBits[r2:b], r0	; "winner's" ID below our ID.
		cmpb	r1, r0			;R1 contains the port we
		bne	ClearArb		; requested.
;
		restore	[r0,r2,r3,r7]
		ret	0
;
;
;****************************************************************************
;
;
;
; ConnectDevices- Arbitrates for the bus and connects us up with the disk
;		  drive.
;
ConnectDevices	movqd	1, r1			;Disk drive SCSI ID (0)
		bsr	Arbitrate
;
		bsr	print
		.byte	"Connecting Devices",cr,0
;
; Clear ID match register so we don't trip over the ID we're about to put
; on the bus.
;
		movd	scsi, r7
		movqb	0, dpSER(r7)
;
;
; Output device ID or'd with our ID (Disk is zero, we're seven):
;
		movb	x'1, dpODR(r7)
;
; Assert the SEL and DB lines and wait (at least) 1200 ns.
;
		movb	x'45, dpICR(r7)		;Also enables DB.
		movqb	5, r0
SELDelay	acbb	-1, r0, SELDelay
;
		movd	TimeOutDelay, r1	;Timeout delay
Wait4Busy	movb	dpCSB(r7), r0		;BSY set?
		tbitb	6, r0
		bfs	GotAttn
		acbd	-1, r1, Wait4Busy
		bsr	print
		.byte	"Select Timeout",cr,0
		bsr	resetSCSI
		br	cdTimeOut:w		;Uh-oh
;
;
;
GotAttn		movb	x'40, dpICR(r7)		;Remove SEL, Disable DB
		movqb	0, dpCSD(r7)		;Put zero into data out reg.
;
		movd	TimeOutDelay, r1
Wait4Req	tbitb	5, dpCSB(r7)		;See if REQ asserted.
		bfs	GotReq:w
		acbd	-1, r1, Wait4Req
		bsr	print
		.byte	"REQ Timeout",cr,0
		bsr	resetSCSI
		br	cd2TimeOut:w
;
GotReq		movb	dpCSB(r7), r0
		lshb	-2, r0
		andb	7, r0
		cmpqb	ph_cmd, r0
		beq	CDNoErr:w
		bsr	print
		.byte	"Bad Phase",cr,0
		br	CDPhaseError:w
;
cdNoErr		movqd	0, r0			;No Error
		br	DoRtn:b
;
cdTimeOut	movqd	3, r0
		br	DoRtn:b
;
cd2TimeOut	movqd	2, r0
		br	DoRtn:b
;
CDPhaseError	movqd	1, r0
DoRtn		ret	0
;
;
;****************************************************************************
;
;
; SendSCSI- transfers data from program to the SCSI device.
; 	    R5- Points at buffer containing data to write.
;	    R6- Points into SCSI DMA area (x'3800_0000).
;
;
SendSCSI        bsr	print
		.byte	"Sending SCSI data",cr,0
;
		movb	x'41, dpICR(r7)
		movb	4, dpMR2(r7)
		movb	x'80, dpEMR(r7)
ll1		tbitb	4, dpBSR(r7)
		bfs	GotInt3:w
		tbitb	5, dpCSB(r7)
		bfc	ll1			;Wait for REQ
;
		movb	0(r5), dpODR(r7)
		addqd	1, r5
		movb	x'51, dpICR(r7)		;Assert ACK
ll3		tbitb	5, dpCSB(r7)
		bfs	ll3
		movb	x'41, dpICR(r7)
		br	ll1
;
GotInt3		movb	dpBSR(r7), r0		;Get current status
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
		movb	x'40, dpICR(r7)		;Disable data bus.
		ret	0
;
		movb	x'41, dpICR(r7)		;Enable DB, clear SEL
		movb	6, dpMR2(r7)		;Monitor Busy, enable DMA
		movqb	0, dpSDS(r7)		;Start send DMA.
		movb	x'80, dpEMR(r7)
lpSendSCSI	tbitb	4, dpBSR(r7)		;Interrupt yet?
		bfs	GotInt:b
		movb	0(r5), 0(r6)
		addqw	1, r6
		acbd	1, r5, lpSendSCSI
;
GotInt          movb	dpBSR(r7), r0		;Get current status
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
		bicb	2, dpMR2(r7)		;Clear DMA mode
		movb	x'40, dpICR(r7)		;Disable data bus.
		ret	0
;
;
; RcvSCSI- Transfers data from the device to this program.
;	R5- Points at buffer to hold data.
;	R6- Points at SCSI DMA area.
;
; Note: unlike the above, we *must* increment R6 each time to prevent
;	the cache from kicking in and simply returning data from the
;	cache rather than reading from the SCSI device.  If I had any
;	brains I'd simply disable the data cache at this point.
;
RcvSCSI		bsr	print
		.byte	"Receiving SCSI data",cr,0
;
lpRcvSCSI	tbitb	4, dpBSR(r7)		;Interrupt yet?
		bfs	GotInt2:b
		movb	0(r6), 0(r5)
		addqw	1, r6
		acbd	1, r5, lpRcvSCSI		;Always taken
;
GotInt2		ret	0
;
;
;****************************************************************************
;
;
; SCSILowLevel- Executes a low level SCSI command.
;		Presumably, we've already selected the device at this point.
;
; On entry:
;
;	R1- Points at command buffer
;	R2- Points at data buffer
;	R3- Points at Status buffer
;	R4- Points at Msg buffer
;
; On Exit:
;
;	R0 contains error code:
;		0 if no error.
;		1 if we need to reset the SCSI device
;		2 if we lost the busy signal.
;
;
SCSILowLevel	save	[r5,r6]
		bsr	print
		.byte	"Starting SCSI command",cr,0
;
		movqb	ph_cmd, dpTCR(r7)		;Set up for cmd phase.
;
;
; The machine should be waiting for a command now:
;
		movd	scsidma, r6			;Point at SCSI DMA bank.
MainSCSILp	movb	dpCSB(r7), r0			;Get the current phase.
		lshb	-2, r0
		andb	7, r0				;Strip phase bits.
		cmpqb	ph_odata, r0			;Data Out phase?
		beq	DataOutPhase:w
		cmpqb	ph_idata, r0
		beq	DataInPhase:w
		cmpqb	ph_cmd, r0
		beq	CommandPhase:w
		cmpqb	ph_stat, r0
		beq	StatusPhase:w
;		cmpqb	ph_omsg, r0		;We're not sending any msgs for
;		beq	MsgOutPhase:w		; now so ignore this possibility.
		cmpqb	ph_imsg, r0
		beq	MsgInPhase:w
		br	PhaseError:w		;Bad phase at this point.
;
;
; If it's a command phase, load up the appropriate pointers and send bytes
; to the device until the phase changes:
;
CommandPhase    bsr	print
		.byte	"In Command Phase",cr,0
;
		movd	r1, r5			;Point r5 at command array.
		movqb	ph_cmd, dpTCR(r7)	;Set up for cmd phase.
		bsr	SendSCSI:w              ;Xmit the bytes.
		tbitb	6, r0			;See if "lost busy" error
		bfs	BSYError:w
		tbitb	3, r0			;Make sure we had a phase mismatch.
		bfs	RSTError:w		;Bad news if not phase mismatch.
		br      MainSCSILp
;
;
; Come down here if we're reading data from the device.
;
DataInPhase	bsr	print
		.byte	"In Data In Phase",cr,0
;
		movd	r2, r5			;Read data into data buffer.
		movqb	ph_idata, dpTCR(r7)	;Set up for data in phase.
		movb	x'40, dpICR(r7)		;Disable DB, clear SEL
		movb	6, dpMR2(r7)		;Monitor Busy, enable DMA
		movqb	4, dpEMR(r7)		;Start receive DMA.
		movqb	0, dpEMR(r7)
		bsr	RcvSCSI:w               ;Read the bytes.
		movb	dpBSR(r7), r0		;Get current status
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
		bicb	2, dpMR2(r7)		;Clear DMA mode
		tbitb	6, r0			;See if busy error
		bfs	BSYError:w
		tbitb	3, r0			;Make sure we had a phase mismatch.
		bfs	RSTError:w		;Bad news if not phase mismatch.
		br      MainSCSILp
;
;
;
; Come down here if we're writing data to the device.
;
DataOutPhase	bsr	print
		.byte	"In Data Out Phase",cr,0
;
		movd	r2, r6			;Write data from data buffer
		movqb	ph_odata, dpTCR(r7)	;Set up for data out phase.
		bsr	SendSCSI:w              ;Xmit the bytes.
		movb	dpBSR(r7), r0		;Get current status
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
		bicb	2, dpMR2(r7)		;Clear DMA mode
		movb	x'40, dpICR(r7)		;Disable data bus.
		tbitb	6, r0			;See if busy error
		bfs	BSYError:w
		tbitb	3, r0			;Make sure we had a phase mismatch.
		bfs	RSTError:w		;Bad news if not phase mismatch.
		br      MainSCSILp
;
;
; Come down here if we're reading status data from the device.
;
StatusPhase	bsr	print
		.byte	"In Status Phase",cr,0
;
		movqb	ph_stat, dpTCR(r7)	;Set up for data in phase.
		movb	x'40, dpICR(r7)		;Disable DB, clear SEL
		movb	4, dpMR2(r7)		;Monitor Busy, no DMA
		movqd	0, 0(r3)		;Clear previous status.
;
		movqd	0, r1
WaitStatus	tbitb	5, dpCSB(r7)		;Wait for REQ
		bfc	WaitStatus
		movb	dpCSD(r7), 0(r3)	;Store into status buffer
		movb	x'50, dpICR(r7)		;Assert ACK
Wait2Status	tbitb	5, dpCSB(r7)		;Wait for device to drop REQ
		bfs	Wait2Status
		movb	x'40, dpICR(r7)		;Drop ACK
;
; Short delay to let the chip get its wits about itself.
;
		movb	255, r0
StatusDelay	acbb	-1, r0, StatusDelay
;
		movb	dpBSR(r7), r0
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
		tbitb	2, r0			;See if busy error
		bfs	BSYError:w
		tbitb	3, r0			;Make sure we had a phase mismatch.
		bfs	RSTError:w		;Bad news if not phase mismatch.
		br	MainSCSILoop
;
;
;
;
; Come down here if we're reading a message byte from the device.
;
MsgInPhase	bsr	print
		.byte	"In Message In Phase",cr,0
;
		movqb	ph_imsg, dpTCR(r7)	;Set up for msg in phase.
		movb	x'40, dpICR(r7)		;Disable DB, clear SEL
		movb	4, dpMR2(r7)		;Monitor Busy, disable DMA
		movb	x'80, dpEMR(r7)		;Allow phase change errors.
;
WaitMsg		tbitb	5, dpCSB(r7)		;Wait for REQ
		bfc	WaitMsg
		movqd	0, 0(r4)
		movb	dpCSD(r7), 0(r4)	;Store into message buffer
		movb	x'50, dpICR(r7)		;Assert ACK
Wait2Msg	tbitb	5, dpCSB(r7)		;Wait for device to drop REQ
		bfs	Wait2Msg
		movb	x'40, dpICR(r7)		;Drop ACK
;
; Short delay to let the chip get its wits about itself.
;
		movb	255, r0
MsgDelay	acbb	-1, r0, MsgDelay
;
		tbitb	2, dpBSR(r7)		;Lost BSY signal interrupt.
		bfc	RSTError:w		;Yikes! Who knows what happened
;
		movqb	2, dpEMR(r7)		;Reset interrupts.
		movqb	0, dpEMR(r7)
;
; A message is what normally terminates the SCSI operation, so this is where
; we exit this code.
;
		movqd	0, r0			;Return no error.
		br	ErrorRtn:w
;
;
;
;
RSTError	movqd	1, r0			;Return "must reset" error.
		br	ErrorRtn:b
;
BSYError	movqd	2, r0			;Return "lost busy" error.
ErrorRtn	restore	[r5,r6]
		ret	0
;
;
;
;
;
;
;
;****************************************************************************
;
;
;
; SCSI Test code: Main Program
;
;
; Select the dp8490 chip:
;
StartTest	movd	icu, r7
		andb	x'7f, 20(r7)		;Select I/O, not port
		andb	x'7f, 21(r7)		;Select as output.
		andb	x'7f, 19(r7)		;Select dp8490 chip.
;
;
;
TryAgain	movqd	0, StatBuf
		bsr	ConnectDevices
		cmpqb	1, r0
		beq	PhaseError:w
		cmpqb	2, r0
		beq	TimeOutErr:w
		cmpqb	3, r0
		beq	TimeOut2Err:w
;
; Set up and execute a read command:
;
		addr	SCSICmds, r1		;Point R1 at command
		movd	x'10000, r2		;Data buffer address
		addr	StatBuf, r3		;Status buffer address
		addr	MsgBuf, r4		;Message return buffer
		bsr	SCSILowLevel		;Do the command
		cmpqb	1, r0			;Need to reset device?
		beq	StartTest
		cmpqb	2, r0			;Lost BSY signal?
		beq	GotBSYError:w
;
		bsr	print
		.byte	"Status = ",0
		movd	StatBuf, r0
		bsr	doprdbl
		bsr	print
		.byte	" Message = ",0
		movd	MsgBuf, r0
		bsr	doprdbl
		bsr	putcr
;
; Well, we didn't get a direct error, check the status and see if it went okay.
;
		movzbd	StatBuf, r0
		lshb	-1, r0
		andb	x'1f,r0
		cmpqb	0, r0
		beq	GoodOperation:w
		cmpqb	1, r0
		beq	CheckCondition:w
		cmpqb	2, r0
		beq	GoodOperation:w
		cmpqb	4, r0
		beq	DeviceIsBusy:w
		cmpb	r0, 8
		beq	GoodOperation:w
		cmpb	r0, 10
		beq	GoodOperation:w
		br	ReallyBadError:w
;
;
GoodOperation	movqd	0, r0
		bpt
;
; If the device is busy, delay a short while and try again later.
;
DeviceIsBusy	bsr	print
		.byte	"Device is busy, trying again (in a moment)",cr,0
;
		movd	6000000, r0
DIBLp		acbd	-1, r0, DIBLp
		br	TryAgain
;
;
; If we got a Check Condition status, we've got to execute the Check Condition
; command to see what went wrong.
;
CheckCondition  bsr	print
		.byte	"Had Check Condition",cr,0
;
		br	TryAgain
;
;
;
;***************************************************************************
;
;
; Errors:
;
; Select timeout error:
;
;
ReallyBadError	movd	x'104, r0
		bpt
GotBSYError	movd	x'103, r0
		bpt
PhaseError	movd	x'102, r0		;Unexpected phase error.
		bpt
TimeOut2Err	movd	x'101, r0
		bpt
TimeOutErr	movd	x'100, r0
GenericErr	bpt
;
;
;
;
		.ENDSEG