Newer
Older
uBix-Retro / dump / oa-2.0.9 / devices / scsi / ramdscsi.a65

/*
 * Generic SCSI driver for CS/A SCSI card
 *
 *  emulating a SCSI interface by using a disk image on the ramdisk 
 *  emulation of the xcsa emulator 
 *
 * Hardware:
 *
 *   2 addresses, $e870-$e871
 *
 *   $e870 : read SCSI data bus; write data for SCSI data bus
 *
 *   $e871 : read status
 *            bit 0:  I/O (SCSI in)
 *                1:  -ACK (SCSI out, from latch)
 *                2:  -RST (SCSI out, from latch)
 *                3:  BSY (SCSI in)
 *                4:  MSG (SCSI in)
 *                5:  
 *                6:  REQ (SCSI in)
 *                7:  C/D (SCSI in)
 *           write control
 *            bit 0:  1 = -SEL active
 *                1:  1 = activate ID bit for arbitration
 *                2:  1 = -BSY active
 *                3:  1 = -ATN active
 *                4:
 *                5:
 *                6:
 *                7:  1 = /RST active
 *
 *   $e872 : write any value -> pulse on /SEL (SCSI out)
 *
 * Software:
 *
 * This is a stateless SCSI driver with the following routines:
 *
 *   initscsi	<- a/y address of buffer (>=256 byte)
 *		-> a/y address of (static) table with device type 
 *		       of each device in it (0=disk, ff=none)
 *		   also available as "devtype"
 *		   x = number of table entries
 *
 *   inquiry	<- a/y address of buffer (>=256 byte)
 *		   x = device SCSI ID
 *		-> buffer contains SCSI return
 *
 *   getsize	<- a/y address of buffer (>=8 byte)
 *		   x = device SCSI ID
 *		-> buffer contains 4 byte # of blocks (hi-low format)
 *		   and 4 byte byte/blocks (hi-lo)
 *
 *   readblock	<- a/y address of buffer (>= N * byte/block)
 *		   x = SCSI device address
 *		   lba (4 byte) LBA of first block to read (hi-lo)
 *		   nsec (2 byte) # of blocks to read (consecutively)
 *		-> buffer contains data
 *   writeblock <- see readblock, buffer contains data
 *
 *
 * $Log$
 *
 */

#define	DEBUG
/* #undef	PRINT */
/* #undef	STANDALONE */

#define RAMD_DRV        $e870
#define RAMD_SECTOR     $e871

#define RAMD_DATA       $ec00

#ifdef DEBUG
#define	PRINT
#endif

#ifdef PRINT2
#define	PRINT
#endif

/**********************************************************************
 * system defines
 */
/*
#define	DATA	$e870
#define	CTRL	$e871
#define	STATUS	$e871

#define	DATA	$de70
#define	CTRL	$de71
#define	STATUS	$de71
*/

#define	DATA	0+SCSIBASE
#define	CTRL	1+SCSIBASE
#define	STATUS	1+SCSIBASE

#define	S_IO	%00000001
#define	S_ACK	%00000010
#define	S_RST	%00000100
#define	S_BSY	%00001000
#define	S_MSG	%00010000
#define	S_REQ	%01000000	/* check BVC/BVS */
#define	S_CD	%10000000	/* check BMI/BPL */

#define	S_PHASEMASK	S_IO+S_CD+S_MSG
#define	S_DATAIN	S_IO
#define	S_MSGIN		S_IO+S_CD+S_MSG
#define	S_STATUS	S_IO+S_CD
#define	S_COMMAND	S_CD

#define	C_RST	%10000000
#define	C_SEL	%00001000
#define	C_BSY	%00000100
#define	C_IDENT	%00000010
#define	C_ATN	%00000001

#define	MYID	7		/* hardcoded in controller */

#ifdef PRINT
#define	log(a)	ldx #a:jsr logout
#define	hout(a) lda a:jsr hexout
#define	crlf()	jsr crlfout
#else
#define	log(a)
#define	hout(a)
#define	crlf(a)
#endif

#ifdef DEBUG
#define	lc(a)	php:pha:lda #a:jsr cout:pla:plp
#else
#define	lc(a)
#endif

/*************************************************************************
 * load addr and Jump table
 */

#ifdef STANDALONE

	lda #<buffer
	ldy #>buffer
	jsr initscsi

	lda #0
	sta task+2
	sta task+3
	sta task+4
	sta task+5

	sta task+7
	lda #1
	sta task+8
	
	lda #<buffer
	ldy #>buffer
	ldx #0
	jsr readblock
	rts

#endif

	.(

/*************************************************************************
 * globals
 */

	; powers of 2

pow2	.byt 1, 2, 4, 8, 16, 32, 64, 128


	.zero
&dp	.word 0
	.text


/*************************************************************************
 * Read a block from the device
 * task+2/3/4/5 has block number (hi-lo), task+7/8 has number of blocks to rd
 * a/y has memory address of buffer where to write block to
 */

&readblock
	sta dp
	sty dp+1
	stx actdev

#ifdef PRINT2
	.(
	log(10)
	hout(actdev)
	log(11)
	ldy #0
rdll	lda lba,y
	jsr hexout
	iny
	cpy #4
	bcc rdll
	log(12)
	hout(nsec)
	hout(nsec+1)
	log(13)
	hout(dp+1)
	hout(dp)
	log(14)
nopr2
	.)
#endif
	lda #0
	sta task+1
	sta task+9

	lda #0
	sta RAMD_DRV
	lda lba+3
	sta RAMD_SECTOR
	lda lba+2
	sta RAMD_SECTOR+1
	lda lba+1
	sta RAMD_SECTOR+2
	lda lba
	bne rderr
	; sta RAMD_SECTOR+3
	
	ldy #0
rdloop	lda RAMD_DATA,y
	sta (dp),y
	iny
	bne rdloop
	inc dp+1
rdl2	lda RAMD_DATA+$100,y
	sta (dp),y
	iny
	bne rdl2
	clc
	rts

rderr	sec
	rts

/*************************************************************************
 * Read a block from the device
 * task+2/3/4/5 has block number (hi-lo), task+7/8 has number of blocks to rd
 * a/y has memory address of buffer where to write block to
 */

&writeblock
	sta dp
	sty dp+1
	stx actdev

#ifdef PRINT2
	.(
	log(15)
	hout(actdev)
	log(11)
	ldy #0
rdll	lda lba,y
	jsr hexout
	iny
	cpy #4
	bcc rdll
	log(12)
	hout(nsec)
	hout(nsec+1)
	log(13)
	hout(dp+1)
	hout(dp)
	log(14)
nopr2
	.)
#endif
	lda #0
	sta task+1
	sta task+9

	lda #0
	sta RAMD_DRV
	lda lba+3
	sta RAMD_SECTOR
	lda lba+2
	sta RAMD_SECTOR+1
	lda lba+1
	sta RAMD_SECTOR+2
	lda lba
	bne wrerr
	; sta RAMD_SECTOR+3
	
	ldy #0
wrloop	
	lda (dp),y
	sta RAMD_DATA,y
	iny
	bne wrloop
	inc dp+1
wrl2	
	lda (dp),y
	sta RAMD_DATA+$100,y
	iny
	bne wrl2
	clc
	rts

wrerr	sec
	rts

/*************************************************************************
 * Initialization (a/y = buffer)
 */

&initscsi
	sta dp
	sty dp+1

	log(0)

; scan SCSI bus for devices

	lda #0
	sta actdev	; start with first device
iniloop
	lda actdev
	cmp #MYID
	beq nodev

	cmp #0
	beq iniok

	log(1)
	hout(actdev)
	crlf()
	jmp next

iselerr	cli
	log(4)
	hout(actdev)
	crlf()
	jmp nodev

iniok	log(3)
	hout(actdev)
	crlf()

	lda dp
	ldy dp+1
	ldx actdev
	jsr inquire
#ifdef PRINT
	pha
	jsr loginquire
	pla
#endif
	.byt $2c
nodev	lda #$ff
	ldx actdev
	sta devtype,x
	
#ifdef PRINT
	cmp #5
	beq print
	cmp #0
	bne next
print	
	lda dp
	ldy dp+1
	ldx actdev
	jsr getsize
	jsr printsize
#endif
next	
	inc actdev
	lda actdev
	cmp #8
	bcc iniloop

	lda #<devtype
	ldy #>devtype
	ldx #8
	clc
	rts

selerr	cli
	log(4)
	hout(actdev)
	crlf()
	sec
	rts

/*************************************************************************
 * Inquire device status/info into buffer (addr=a/y)
 */

inqdata	.byt 0, 0, 1, 0, 0, 0, 0, 0
	.byt "VICE XCSA EMU           "

&inquire
	sta dp
	sty dp+1
	stx actdev

	ldy #0
inl	lda inqdata,y
	sta (dp),y
	iny
	cpy #32
	bne inl
indone	
#ifdef DEBUG
	lc("d")
	tya
	jsr hexout
#endif
inrts	ldy #0
	lda (dp),y	; 0 = disk, 1 = Tape, 5 = CDROM
	rts


/*************************************************************************
 * Get Medium capacity, a/y = buffer
 * returns 4 byte # of blocks (hi-low format) + 4 byte byte/block in 
 * buffer
 */

getsdata .byt $00, $01, $38, $80
	.byt $00, $00, $02, $00

&getsize
	sta dp
	sty dp+1
	stx actdev
	ldy #0
gsl	lda getsdata,y
	sta (dp),y
	iny
	cpy #8
	bne gsl
	clc
	rts

/*************************************************************************
 * Print data subroutines
 *************************************************************************/

#ifdef PRINT

/*************************************************************************
 * Print inquiry data
 */

loginquire
	ldy #8
li1	lda (dp),y
	jsr cout
	iny
	cpy #32
	bcc li1
	log(5)
	ldy #0
	lda (dp),y
	and #%00011111
	jsr hexout
	log(6)
	ldy #2
	lda (dp),y
	and #%00000111
	jsr hexout
liret 	log(7)
	rts

/*************************************************************************
 * Print media size
 */

printsize
	log(8)

	ldy #0
pl1	lda (dp),y
	jsr hexout
	iny
	cpy #4
	bcc pl1

	log(9)

	ldy #4
pl2	lda (dp),y
	jsr hexout
	iny
	cpy #8
	bcc pl2

	jmp liret
	

/*************************************************************************
 * Generic Subroutines
 */

logout	txa
	asl
	tax
	lda laddr+1,x
	tay
	lda laddr,x
	jmp txtout

laddr	.word logt0, logt1, logt2, logt3, logt4, int0, int1, int2, ps1, ps2
#ifdef PRINT2
	.word rd1, rd2, rd3, rd4, rd5, rd6
#endif

logt0	.asc 13,10,"CS/A65 SCSI driver",13,10
	.asc 13,10,"Resetting SCSI bus",13,10,0
logt1	.asc "Device not ready ",0
logt2	.asc "Device error bit set",13,10,0
logt3	.asc "Device found ",0
logt4	.asc "Device select timeout ",0

int0	.asc "[Type ",0
int1	.asc ", SCSI Rev. ",0
int2	.asc "]",13,10,0

ps1	.asc "       [Blocks: ",0
ps2	.asc ", Byte/Block: ",0

#ifdef PRINT2

rd1	.asc "Read Block Dev: ",0
rd2	.asc ", Sect: ",0
rd3	.asc ", nsec: ",0
rd4	.asc " To: ",0
rd5	.asc 13,10,0
rd6	.asc "Write Block Dev: ",0

#endif

#endif	/* PRINT */

/*************************************************************************
 * Data structures (no extended read/writes)
 */

	.bss

; active device number (0-7)

actdev	.byt 0

; contains the device type for each SCSI ID

&devtype .dsb 8

; this structure is sent as it is for one command

task	.byt 0		; command code
	.byt 0		; LUN 
&lba	.byt 0		; 
	.byt 0		; 
	.byt 0		; 
	.byt 0		;
	.byt 0
&nsec	.byt 0
	.byt 0
	.byt 0

	.)

#ifdef STANDALONE

buffer	=*

#endif
	.text