File:  [MW Coherent from dump] / coherent / d / PS2_KERNEL / io.286 / ssas.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

////////
/
/ I/O for Seagate ST01/ST02 SCSI Host Adapters.
/
/ $Log: ssas.s,v $
/ Revision 1.1.1.1  2019/05/29 04:56:39  root
/ coherent
/
/ Revision 1.1  92/07/17  15:24:48  bin
/ Initial revision
/
/ Revision 1.7  91/06/01  10:51:00  hal
/ Add ffcopy().
/ 
/ Revision 1.6  91/06/01  10:32:51  hal
/ Do handshaking both ways.  Now names are ss_getb()/ss_putb().
/ 
/ Revision 1.5	91/05/20  17:22:03	root
/ Not using ss_put() any more.
/ 
/ Revision 1.4	91/05/20  16:21:35	root
/ Call to ss_putc() now works.
/ 
/ Revision 1.3	91/05/20  10:23:13	root
/ Drop 3rd arg.  Same code for Seagate & Future Domain.
/ 
/ Revision 1.2	91/05/17  00:24:17	root
/ Code ss_put - use REQ handshake.
/ 
/ Revision 1.1	91/05/16  14:16:21	root
/ Initial version - no code yet for ss_put().
/ 
/
/	Since these functions are called from the midst of C code in
/	the "ss" driver, they need to preserve the following registers:
/		SI  DI  SP  BP    SS  DS  ES
/	Additionally, surrounding C code is expected to leave the "D"
/	CPU flag clear (string op's increment index registers).
/
////////

////////
/
/	Export functions.
/
////////
	.globl	ss_getb_
	.globl	ss_putb_
	.globl	ffcopy_

////////
/
/ Constants
/
/	Relative to the RAM base address of the host adapter, offsets
/	for Control/Status Register (CSR) and Data Port (DAT) differ
/	between Seagate and Future Domain as follows:
/			Seagate		Future Domain
/		SS_CSR	0x1A00		0x1C00
/		SS_DAT	0x1C00		0x1E00
/	The difference between these (CSR_OFF) is 0x200 in either case.
/
////////

	BSIZE	= 0x200		/ Disk block size in bytes
	CSR_OFF	= 0x200

	REQ_LIM = 500
	RS_REQUEST = 0x10

////////
/
/ ss_getb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Fetch input bytes from host adapter and store at buffer address.
/
/ Do REQ handshaking and return the number of bytes remaining to transfer.
/ (So return value of 0 means no error.)
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_getb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ ss_dat_fp to DS:SI
	mov	bx, si		/ .. and to DS:BX
	sub	bx, $CSR_OFF	/ ss_csr to DS:BX
	les	di, 8(bp)	/ buf_fp to ES:DI
	mov	cx, $BSIZE	/ rep count to CX

G01:				/ start outer loop - reading bytes from SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
G02:				/ start inner loop - polling for REQ
	movb	dl, (bx)
	testb	dl, $RS_REQUEST
	jne	G03		/ got REQ
	dec	ax
	jnz	G02		/ no REQ - look again
	jmp	G04		/ no REQ - give up

G03:				/ got REQ - ok to read a byte
	movsb
	loop	G01
G04:				/ all done
	mov	ax, cx		/ normal exit returns 0

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ int ss_putb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Write output bytes to host adapter from buffer address.
/
/ Return the number of bytes remaining to be sent (should be 0).
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_putb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si 
	lds	si, 8(bp)	/ buf_fp to DS:SI
	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
	mov	bx, di		/ .. and to ES:BX
	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
	mov	cx, $BSIZE	/ count to CX

P01:				/ start outer loop - writing bytes to SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
P02:				/ start inner loop - polling for REQ
	movb	dl, es:(bx)
	testb	dl, $RS_REQUEST
	jne	P03		/ got REQ
	dec	ax
	jnz	P02		/ no REQ - look again
	jmp	P04		/ no REQ - give up

P03:				/ got REQ - ok to write a byte
	movsb
	loop	P01
P04:				/ all done - now restore registers
	mov	ax, cx
	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ void ffcopy(from_fp, to_fp, count)
/ faddr_t from_fp, to_fp;
/ int count;
/
/ Copy count bytes from from_fp to to_fp.
/
/ Here is the stack after initial "push bp":
/
/	12(bp)	count
/	10(bp)	FP_SEL(to_fp)
/	8(bp)	FP_OFF(to_fp)
/	6(bp)	FP_SEL(from_fp)
/	4(bp)	FP_OFF(from_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ffcopy_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ from_fp  to DS:SI
	les	di, 8(bp)	/ to_fp to ES:DI
	mov	cx, 12(bp)	/ rep count to CX
	rep
	movsb

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.