v15i003: DOS Device Driver for the ST-01 (Part 2 of 2)

Brian Who? briana at tau-ceti.isc-br.com
Sat Oct 6 10:03:14 AEST 1990


Posting-number: Volume 15, Issue 3
Submitted-by: briana at tau-ceti.isc-br.com (Brian Who?)
Archive-name: st-01_scsi/part02

     Here is part two...

Submitted-by: briana at tau-ceti.isc-br.com
Archive-name: ST01SCSI.12/part02

#!/bin/sh
# This is part 02 of ST01SCSI.12
# ============= struct.inc ==============
if test -f 'struct.inc' -a X"$1" != X"-c"; then
	echo 'x - skipping struct.inc (File already exists)'
else
echo 'x - extracting struct.inc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'struct.inc' &&
X;
X; Structures for SCSI commands
X;
Xio_cmd		struc
Xio_cmd_op	db	?		;Opcode
X		if extended_io
Xio_cmd_lun	db	?
Xio_cmd_lba_b3	db	?		;Logical Block Address
Xio_cmd_lba_b2	db	?
Xio_cmd_lba_b1	db	?
Xio_cmd_lba_b0	db	?
Xio_cmd_dummy1	db	?
Xio_cmd_cnt_b1	db	?		;Block Count
Xio_cmd_cnt_b0	db	?
Xio_cmd_dummy2	db	?
X		else
Xio_cmd_lba_b2	db	?		;Logical Block Address / Lun
Xio_cmd_lba_b1	db	?
Xio_cmd_lba_b0	db	?
Xio_cmd_cnt_b0	db	?		;Block Count
Xio_cmd_dummy1	db	?
X		endif
Xio_cmd		ends
X
Xtio_cmd		struc
Xtio_cmd_op	db	?		;Opcode
Xtio_cmd_lun	db	?		;Lun
Xtio_cmd_cnt_b2	db	?		;Block Count
Xtio_cmd_cnt_b1	db	?
Xtio_cmd_cnt_b0	db	?
Xtio_cmd_dummy1	db	?
Xtio_cmd		ends
X
X;
X; Format the Unit
X;
Xfmt_cmd		struc
Xfmt_cmd_op	db	?		;Opcode
Xfmt_cmd_type	db	?		;Format Type
Xfmt_cmd_dummy1	db	?
Xfmt_cmd_il_b1	db	?		;Interleave (MSB)
Xfmt_cmd_il_b0	db	?		;Interleave (LSB)
Xfmt_cmd_dummy3	db	?
Xfmt_cmd		ends
X
X;
X; Verify Sectors
X;
Xver_cmd		struc
Xver_cmd_op	db	?		;Opcode
Xver_cmd_lun	db	?		;Lun
Xver_cmd_lba_b3	db	?		;Logical Block Address MSB
Xver_cmd_lba_b2	db	?
Xver_cmd_lba_b1	db	?
Xver_cmd_lba_b0	db	?		;Logical Block Address LSB
Xver_cmd_dummy1	db	?
Xver_cmd_len_b1	db	?		;Length MSB
Xver_cmd_len_b0	db	?		;Length LSB
Xver_cmd_dummy2	db	?
Xver_cmd		ends
X
X;
X; Load / Unload a Tape
X;
Xload_cmd	struc
Xload_cmd_op	db	?		;Opcode
Xload_cmd_lun	db	?		;Lun
Xload_cmd_dummy1	db	2 dup (?)
Xload_cmd_type	db	?		;Load / Unload
Xload_cmd_dummy2	db	?
Xload_cmd	ends
X
X;
X; Write Filemarks on a Tape
X;
Xfm_cmd		struc
Xfm_cmd_op	db	?		;Opcode
Xfm_cmd_lun	db	?		;Lun
Xfm_cmd_cnt_b2	db	?		;Filemark MSB
Xfm_cmd_cnt_b1	db	?
Xfm_cmd_cnt_b0	db	?		;Filemark LSB
Xfm_cmd_dummy	db	?
Xfm_cmd		ends
X
X;
X; Space a Tape
X;
Xspace_cmd	struc
Xspace_cmd_op	db	?		;Opcode
Xspace_cmd_code	db	?
Xspace_cmd_cnt2	db	?		;Count
Xspace_cmd_cnt1	db	?
Xspace_cmd_cnt0	db	?
Xspace_cmd_dummy	db	?
Xspace_cmd	ends
X
X;
X; Structure returned by the sense command
X;
Xsense		struc
X		if extended_sense
Xsense_ccs	db	?		;0x70 for Extended Sense
Xsense_dummy1	db	?
Xsense_sense	db	?		;Sense (Error) Group
Xsense_lba_b3	db	?		;Failed Block Address
Xsense_lba_b2	db	?
Xsense_lba_b1	db	?
Xsense_lba_b0	db	?
X		else
Xsense_sense	db	?		;Sense (Error) code
Xsense_lba_b2	db	?		;Failed Block Address
Xsense_lba_b1	db	?
Xsense_lba_b0	db	?
X		endif
Xsense		ends
X
X;
X; Structure returned by the unit inquiry command
X;
Xinq		struc
Xinq_dev_type	db	?		;Device Type
Xinq_dev_qual	db	?		;Device Qualifier
Xinq_stand_rev	db	?		;Standard Revision Level
Xinq_format	db	?		;Response Format
Xinq_length	db	?		;Length of Extra Data
Xinq_reserv1	db	?
Xinq_reserv2	db	?
Xinq_reserv3	db	?
Xinq_manufact	db	8 dup (?)	;Manufacture
Xinq_product	db	16 dup (?)	;Product
Xinq		ends
X
X;
X; Structure returned by the read drive capacity command
X;
Xcap		struc
Xcap_sectors_b3	db	?		;MSB of sector count
Xcap_sectors_b2	db	?
Xcap_sectors_b1	db	?
Xcap_sectors_b0	db	?		;LSB of sector count
Xcap_size_b3	db	?		;MSB of sector size
Xcap_size_b2	db	?
Xcap_size_b1	db	?
Xcap_size_b0	db	?		;LSB of sector size
Xcap		ends
X
X;
X; Structure Definitions For Our Device Driver
X;
Xbpb		struc
Xbpb_ss		dw	?		;Sector Size
Xbpb_au		db	?		;Cluster Size in Sectors
Xbpb_rs		dw	?		;Reserved Sectors
Xbpb_nf		db	?		;Number of Fats
Xbpb_de		dw	?		;Number of Root Directory Entries
Xbpb_ts		dw	?		;Total Number Of Sectors
Xbpb_md		db	?		;Media Descriptor
Xbpb_fs		dw	?		;Number of Sectors in each Fat
Xbpb_st		dw	?		;Number of Sectors per Track
Xbpb_nh		dw	?		;Number of Heads
Xbpb_hs_lsw	dw	?		;Hidden Sectors (Least Sig Word)
Xbpb_hs_msw	dw	?		;Hidden Sectors (Most Sig Word)
Xbpb_ts_large	dd	?		;Large Total Sector Count
Xbpb_res		db	6 dup (?)	;Reserved
Xbpb		ends
X
X;
X; ioctl function 42h
X;
Xioctl_fmt	struc
Xioctl_fmt_spec	db	?		;Special Flags
Xioctl_fmt_head	dw	?		;Head to Format
Xioctl_fmt_cyl	dw	?		;Cylinder to Format
Xioctl_fmt	ends
X
X;
X; ioctl function 60h
X;
Xdpb		struc
Xdpb_special	db	?		;Special Flags
Xdpb_type	db	?		;Device Type
Xdpb_attr	dw	?		;Device Attributes
Xdpb_cyl		dw	?		;Device Cylinder Count
Xdpb_media	db	?		;Device Media Type if Diskette
Xdpb_bpb		db	size bpb dup (?)
Xdpb_sectors	dw	?		;Sectors in Track
Xdpb_track	dd	SECT_TRACK dup (?)
Xdpb		ends
X
X;
X; The internal control structure for a SCSI device
X;
Xunit		struc
Xunit_1st_drv	db	?		;DOS Drive Numbers
Xunit_num_drv	db	?		;DOS Drive Count
Xunit_select	db	?		;SCSI Select Bit
Xunit_mcheck	db	?		;Media Check Byte
Xunit_inq_buf	db	size inq dup (?)
Xunit_inq_term	db	?
Xunit_cap_buf	db	size cap dup (?)
Xunit_sense_buf	db	size sense dup (?)
Xunit		ends
X
X;
X; Ioctl Commands
X;
Xioc		struc
Xioc_command	dw	?		;Command
Xioc_param1	dw	?		;Command Dependent Data
Xioc_param2	dw	?		;Command Dependent Data
Xioc		ends
X
X;
X; DOS requests
X;
Xrh		struc
Xrh_len		db	?		;Length of Packet
Xrh_unit		db	?		;Unit Code (Block Only)
Xrh_cmd		db	?		;Command Code
Xrh_status	dw	?		;Returned Status
Xrh_res		db	8 dup (?)	;Reserved
Xrh		ends
X
Xrh0		struc			;INITIALIZATION
Xrh0_rh		db	size rh dup (?)	;Fixed Portion
Xrh0_nunits	db	?		;Number of units (Block Only)
Xrh0_brk_ofs	dw	?		;Break Address (Offset)
Xrh0_brk_seg	dw	?		;Break Address (Segment)
Xrh0_bpb_tbo	dw	?		;Pointer to BPB Array (Offset)
Xrh0_bpb_tbs	dw	?		;Pointer to BPB Array (Segment)
Xrh0_drv_ltr	db	?		;First Available Drive (DOS 3+, Block Only)
Xrh0		ends
X
Xrh1		struc			;MEDIA CHECK
Xrh1_rh		db	size rh dup (?)	;Fixed Portion
Xrh1_media	db	?		;Media Descriptor from DPB
Xrh1_md_stat	db	?		;Media Status returned by Device Driver
Xrh1_volid_ofs	dw	?		;Offset of Volume ID String (DOS 3+)
Xrh1_volid_seg	dw	?		;Segment of Volume ID String (DOS 3+)
Xrh1		ends
X
Xrh2		struc			;GET BPB
Xrh2_rh		db	size rh dup (?)	;Fixed Portion
Xrh2_media	db	?		;Media Descriptor from DPB
Xrh2_buf_ofs	dw	?		;Offset of Data Transfer Area
Xrh2_buf_seg	dw	?		;Segment of Data Transfer Area
Xrh2_pbpbo	dw	?		;Offset of Pointer to BPB
Xrh2_pbpbs	dw	?		;Segment of Pointer to BPB
Xrh2		ends
X
Xrh4		struc			;INPUT
Xrh4_rh		db	size rh dup (?)	;Fixed Portion
Xrh4_media	db	?		;Media Descriptor from DPB
Xrh4_buf_ofs	dw	?		;Offset of Data Transfer Area
Xrh4_buf_seg	dw	?		;Segment of Data Transfer Area
Xrh4_count	dw	?		;Transfer Count (Sectors)
Xrh4_start	dw	?		;Start Sector Number
Xrh4		ends
X
Xrh8		struc			;OUTPUT
Xrh8_rh		db	size rh dup (?)	;Fixed Portion
Xrh8_media	db	?		;Media Descriptor from DPB
Xrh8_buf_ofs	dw	?		;Offset of Data Transfer Area
Xrh8_buf_seg	dw	?		;Segment of Data Transfer Area
Xrh8_count	dw	?		;Transfer Count (Sectors)
Xrh8_start	dw	?		;Start Sector Number
Xrh8		ends
X
Xrh9		struc			;OUTPUT VERIFY
Xrh9_rh		db	size rh dup (?)	;Fixed Portion
Xrh9_media	db	?		;Media Descriptor from DPB
Xrh9_buf_ofs	dw	?		;Offset of Data Transfer Area
Xrh9_buf_seg	dw	?		;Segment of Data Transfer Area
Xrh9_count	dw	?		;Transfer Count (Sectors)
Xrh9_start	dw	?		;Start Sector Number
Xrh9		ends
X
Xrh12		struc			;OUTPUT IOCTL
Xrh12_rh		db	size rh dup (?)	;Fixed Portion
Xrh12_media	db	?		;Media Descriptor from DPB
Xrh12_buf_ofs	dw	?		;Offset of Data Transfer Area
Xrh12_buf_seg	dw	?		;Segment of Data Transfer Area
Xrh12_count	dw	?		;Transfer Count (Sectors)
Xrh12_start	dw	?		;Start Sector Number
Xrh12		ends
X
Xrh19		struc			;IOCTL
Xrh19_rh		db	size rh dup (?)	;Fixed Portion
Xrh19_major	db	?		;Major Code
Xrh19_minor	db	?		;Minor Code
Xrh19_si		dw	?		;Caller SI Register
Xrh19_di		dw	?		;Caller DI Register
Xrh19_buf_ofs	dw	?		;Caller Buffer Offset
Xrh19_buf_seg	dw	?		;Caller Buffer Segment
Xrh19		ends
SHAR_EOF
chmod 0644 struct.inc ||
echo 'restore of struct.inc failed'
Wc_c="`wc -c < 'struct.inc'`"
test 7166 -eq "$Wc_c" ||
	echo 'struct.inc: original size 7166, current size' "$Wc_c"
fi
# ============= subs.asm ==============
if test -f 'subs.asm' -a X"$1" != X"-c"; then
	echo 'x - skipping subs.asm (File already exists)'
else
echo 'x - extracting subs.asm (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'subs.asm' &&
X;
X; Data storage for local subroutines
X;
Xcmd_ready	db	SCSI_TESTREADY,0,0,0,0,0
Xcmd_rewind	db	SCSI_REWIND,0,0,0,0,0
Xcmd_sense	db	SCSI_REQSENSE,0,0,0,size sense,0
Xcmd_format	db	SCSI_FORMATUNIT,0,0,0,0,0
Xcmd_space	db	SCSI_SPACE,1,0,0,0,0
X		if extended_io
Xcmd_read	db	SCSI_READBLK,0,0,0,0,0,0,0,1,0
Xcmd_write	db	SCSI_WRITEBLK,0,0,0,0,0,0,0,1,0
X		else
Xcmd_read	db	SCSI_READBLK,0,0,0,1,0
Xcmd_write	db	SCSI_WRITEBLK,0,0,0,1,0
X		endif
Xcmd_tread	db	SCSI_READBLK,1,0,0,0,0
Xcmd_twrite	db	SCSI_WRITEBLK,1,0,0,0,0
Xcmd_twritefm	db	SCSI_WRITEFM,0,0,0,1,0
Xcmd_inquire	db	SCSI_INQUIRY,0,0,0,size inq,0
Xcmd_erase	db	SCSI_ERASE,1,0,0,0,0
Xcmd_load	db	SCSI_LOAD,0,0,0,0,0
Xcmd_capacity	db	SCSI_READSIZE,0,0,0,0,0,0,0,0,0
Xcmd_verify	db	SCSI_VERIFYBLK,0,0,0,0,0,0,0,SECT_TRACK,0
X
X		even
Xdocmd_cmd	dw	?
Xdocmd_buf	dw	?
Xdocmd_buf_seg	dw	?
Xdocmd_len	dw	?
Xdocmd_status	db	?
Xdocmd_tempb	db	?
X
X		if dump_sense
Xsense_msg	db	0dh,07h,'SCSI Unit: 0x'
Xsense_unit	db	'xx, Sense Status: 0x'
Xsense_code	db	'xx, Block Address: 0x'
X		if extended_sense
Xsense_addr3	db	'xx'
X		endif
Xsense_addr2	db	'xx'
Xsense_addr1	db	'xx'
Xsense_addr0	db	'xx',0dh,0ah,'$'
X		endif
X
X;
X; Reset the SCSI Bus
X;
Xscsi_reset	proc	near
X		pusha
X
X		mov	ax,SCSI_CARD_SEG	;Point at the command port
X		mov	es,ax
X		mov	si,SCSI_CMD_PORT
X
X		mov	al,CMDBASE or CMDENABLE or CMDRST
X		mov	es:[si],al		;Reset the bus
X		call	wait1ms
X		mov	al,CMDBASE
X		mov	es:[si],al		;All done
X		mov	cx,250			;Wait 250ms
Xreset_loop:	call	wait1ms
X		loop	reset_loop
X
X		popa
X		ret
Xscsi_reset	endp
X
X;
X; Test the Ready Status of a unit
X;
X; al = return code, 'C' error
X;
Xscsi_ready	proc	near
X		lea	di,cmd_ready			;Command
X		call	docmd
X		ret
Xscsi_ready	endp
X
X;
X; Request Sense data from a unit and display the result
X; Called after every SCSI command with the exit code in 'al'
X;
Xscsi_sense	proc	near
X		pushf
X		pusha
X		mov	di,cur_unit			;Unit
X		lea	bx,[di].unit_sense_buf		;Buffer Offset
X		push	ds				;Buffer Segment
X		pop	es
X		mov	cx,size sense			;Buffer Size
X		lea	di,cmd_sense			;Command
X		call	docmd
X		if dump_sense
X		jc	sense_exit
X		mov	di,cur_unit
X		mov	dl,[di].unit_select
X		if reserve_addr
X		and	dl,07Fh			;Remove Cards Bit
X		endif
X		lea	bx,sense_unit		;Unit
X		call	hex2asc2
X		mov	dl,[di].unit_sense_buf.sense_sense
X		lea	bx,sense_code		;Sense
X		call	hex2asc2
X		if extended_sense
X		mov	dl,[di].unit_sense_buf.sense_lba_b3
X		lea	bx,sense_addr3		;Address
X		call	hex2asc2
X		endif
X		mov	dl,[di].unit_sense_buf.sense_lba_b2
X		lea	bx,sense_addr2
X		call	hex2asc2
X		mov	dl,[di].unit_sense_buf.sense_lba_b1
X		lea	bx,sense_addr1
X		call	hex2asc2
X		mov	dl,[di].unit_sense_buf.sense_lba_b0
X		lea	bx,sense_addr0
X		call	hex2asc2
X		lea	dx,sense_msg
X		call	puts
X		endif
Xsense_exit:	popa
X		popf
X		ret
Xscsi_sense	endp
X
X;
X; Inquire about the type of a unit
X;
X; al = return code, 'C' error indicates an error
X;
Xscsi_inquire	proc	near
X		push	cx
X		mov	di,cur_unit			;Unit
X		lea	bx,[di].unit_sense_buf		;Buffer Offset
X		push	ds				;Buffer Segment
X		pop	es
X		mov	cx,size sense			;Buffer Size
X		lea	di,cmd_sense			;Command
X		call	docmd				;Always ask first
X		jc	inquire_exit
X		mov	di,cur_unit			;Unit
X		lea	bx,[di].unit_inq_buf		;Buffer Offset
X		push	ds				;Buffer Segment
X		pop	es
X		mov	cx,size inq			;Buffer Size
X		lea	di,cmd_inquire			;Command
X		call	docmd
X		jnc	inquire_exit
X		call	scsi_sense
Xinquire_exit:	pop	cx
X		ret
Xscsi_inquire	endp
X
X;
X; Determine the size of a disk
X;
X; al = return code, 'C' error indicates an error
X;
Xscsi_capacity	proc	near
X		push	cx
X		mov	di,cur_unit			;Unit
X		lea	bx,[di].unit_cap_buf		;Buffer Offset
X		push	ds				;Buffer Segment
X		pop	es
X		mov	cx,size cap			;Buffer Size
X		lea	di,cmd_capacity			;Command
X		call	docmd
X		jnc	capacity_exit
X		call	scsi_sense
Xcapacity_exit:	pop	cx
X		ret
Xscsi_capacity	endp
X
X;
X; Verify the Track given in an IOCTL Request
X;
X; al = return code, 'C' indicates an error
X;
Xscsi_verify	proc	near
X		mov	di,es:[bx].rh19_buf_ofs		;Command Offset
X		mov	ax,es:[bx].rh19_buf_seg		;Command Segment
X		mov	es,ax
X		mov	ax,es:[di].ioctl_fmt_cyl	;Track
X		shl	ax,SECT_2_CYL			;Convert to Sector
X
X		mov	di,cur_bpb			;Add to Drive Offset
X		mov	dx,[di].bpb_hs_msw
X
X		lea	di,cmd_verify			;Command
X		mov	[di].ver_cmd_lba_b3,dh		;Insert Sector
X		mov	[di].ver_cmd_lba_b2,dl		; into Command
X		mov	[di].ver_cmd_lba_b1,ah		;Insert Sector
X		mov	[di].ver_cmd_lba_b0,al		; into Command
X		call	docmd
X		jnc	verify_exit
X		call	scsi_sense
Xverify_exit:	ret
Xscsi_verify	endp
X
X;
X; Read Some Blocks from the disk given
X; the request header in es:bx
X;
X; al = return code, 'C' indicates an error
X;
Xdisk_read	proc	near
X		mov	di,bx
X		mov	cx,es:[di].rh4_count		;Sector Count
X		mov	dx,es:[di].rh4_start		;Starting Sector
X		mov	bx,es:[di].rh4_buf_ofs		;Buffer Offset
X		mov	ax,es:[di].rh4_buf_seg		;Buffer Segment
X		mov	es,ax
X
X		mov	si,cur_bpb
X		lea	di,cmd_read			;Command
X		mov	ax,[si].bpb_hs_msw		;Drive Sector Offset
X		if extended_io
X		mov	[di].io_cmd_lba_b3,ah		;Insert Sector
X		endif
X		mov	[di].io_cmd_lba_b2,al		;Into the Command
X
X		if multi_sector
X		mov	ax,cx				;Get Sector Count
X		and	ax,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_r_cok1			;Check for Boundary
X		mov	ax,CHUNK_MAX
Xdisk_r_cok1:	shl	ax,9				;Convert to Buffer Size
X		add	ax,bx				;Check for Wrap
X		else
X		mov	ax,bx				;Check for Wrap
X		add	ax,P_SECT			;The First Time
X		endif
Xdisk_r_loop:	jnc	disk_r_nowrap
X		mov	ax,bx				;Normalize the
X		shr	ax,4				;Segment and
X		mov	si,es				;Offset so that
X		add	si,ax				;It dosn't Wrap
X		mov	es,si
X		and	bx,000Fh
Xdisk_r_nowrap:	push	cx
X		mov	[di].io_cmd_lba_b1,dh		;Insert Sector
X		mov	[di].io_cmd_lba_b0,dl		;Into the Command
X		if multi_sector
X		and	cx,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_r_cok2			;Check for Boundary
X		mov	cx,CHUNK_MAX
Xdisk_r_cok2:
X		if extended_io
X		mov	[di].io_cmd_cnt_b1,ch		;Insert Sector Count
X		endif
X		mov	[di].io_cmd_cnt_b0,cl		;Into the Command
X		shl	cx,9				;Convert to Buffer Size
X		else
X		mov	cx,P_SECT			;Buffer Size
X		endif
X		call	docmd
X		pop	cx
X		jc	disk_r_exit
X		if multi_sector
X		mov	ax,cx				;Get Sector Count
X		and	ax,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_r_cok3			;Check for Boundary
X		mov	ax,CHUNK_MAX
Xdisk_r_cok3:	sub	cx,ax				;Dec Sector Count
X		jz	disk_r_exit
X		add	dx,ax				;Bump to next Sector
X		shl	ax,9				;Convert to Buffer Size
X		add	bx,ax
X		jmp	short disk_r_loop
X		else
X		inc	dx				;Bump to next Sector
X		add	bx,P_SECT
X		loop	disk_r_loop
X		clc
X		endif
Xdisk_r_exit:	jnc	disk_r_exit2			;If no error occured
X		call	scsi_sense			;Display Sense Status
Xdisk_r_exit2:	mov	es,rh_seg
X		mov	bx,rh_off
X		pushf
X		mov	ax,es:[bx].rh4_count		;Update the Count
X		sub	ax,cx
X		mov	es:[bx].rh4_count,ax
X		popf
X		ret
Xdisk_read	endp
X
X;
X; Write Some Blocks to the disk given
X; the request header in es:bx
X;
X; al = return code, 'C' indicates an error
X;
Xdisk_write	proc	near
X		mov	di,bx
X		mov	cx,es:[di].rh8_count		;Sector Count
X		mov	dx,es:[di].rh8_start		;Starting Sector
X		mov	bx,es:[di].rh8_buf_ofs		;Buffer Offset
X		mov	ax,es:[di].rh8_buf_seg		;Buffer Segment
X		mov	es,ax
X
X		mov	si,cur_bpb
X		lea	di,cmd_write			;Command
X		mov	ax,[si].bpb_hs_msw		;Drive Sector Offset
X		if extended_io
X		mov	[di].io_cmd_lba_b3,ah		;Insert Sector
X		endif
X		mov	[di].io_cmd_lba_b2,al		;Into the Command
X
X		if multi_sector
X		mov	ax,cx				;Get Sector Count
X		and	ax,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_w_cok1			;Check for Boundary
X		mov	ax,CHUNK_MAX
Xdisk_w_cok1:	shl	ax,9				;Convert to Buffer Size
X		add	ax,bx				;Check for Wrap
X		else
X		mov	ax,bx				;Check for Wrap
X		add	ax,P_SECT			;The First Time
X		endif
Xdisk_w_loop:	jnc	disk_w_nowrap
X		mov	ax,bx				;Normalize the
X		shr	ax,4				;Segment and
X		mov	si,es				;Offset so that
X		add	si,ax				;It dosn't Wrap
X		mov	es,si
X		and	bx,000Fh
Xdisk_w_nowrap:	push	cx
X		mov	[di].io_cmd_lba_b1,dh		;Insert Sector
X		mov	[di].io_cmd_lba_b0,dl		;Into the Command
X		if multi_sector
X		and	cx,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_w_cok2			;Check for Boundary
X		mov	cx,CHUNK_MAX
Xdisk_w_cok2:
X		if extended_io
X		mov	[di].io_cmd_cnt_b1,ch		;Insert Sector Count
X		endif
X		mov	[di].io_cmd_cnt_b0,cl		;Into the Command
X		shl	cx,9				;Convert to Buffer Size
X		else
X		mov	cx,P_SECT			;Buffer Size
X		endif
X		call	docmd
X		pop	cx
X		jc	disk_w_exit
X		if multi_sector
X		mov	ax,cx				;Get Sector Count
X		and	ax,CHUNK_MAX-1			;Mask Off the I/O Chunk
X		jnz	disk_w_cok3			;Check for Boundary
X		mov	ax,CHUNK_MAX
Xdisk_w_cok3:	sub	cx,ax				;Dec Sector Count
X		jz	disk_w_exit
X		add	dx,ax				;Bump to next Sector
X		shl	ax,9				;Convert to Buffer Size
X		add	bx,ax
X		jmp	short disk_w_loop
X		else
X		inc	dx				;Bump to next Sector
X		add	bx,P_SECT
X		loop	disk_w_loop
X		clc
X		endif
Xdisk_w_exit:	jnc	disk_w_exit2			;If no error occured
X		call	scsi_sense			;Display Sense Status
Xdisk_w_exit2:	mov	es,rh_seg
X		mov	bx,rh_off
X		pushf
X		mov	ax,es:[bx].rh8_count		;Update the Count
X		sub	ax,cx
X		mov	es:[bx].rh8_count,ax
X		popf
X		ret
Xdisk_write	endp
X
X;
X; Read Some Blocks from the Tape
X;
Xtape_read	proc	near
X		mov	write_flag,FALSE		;Cancel if READ seen
X		mov	di,bx
X		mov	cx,es:[di].rh4_count		;Byte Count
X		mov	ax,cx				;Test for invalid
X		and	ax,P_SECT-1			;Byte Count
X		jz	tape_r_ok
X		mov	es:[di].rh4_count,0		;Nothing Read
X		stc					;Oops
X		ret
Xtape_r_ok:	mov	bx,es:[di].rh4_buf_ofs		;Buffer Offset
X		mov	ax,es:[di].rh4_buf_seg		;Buffer Segment
X		mov	es,ax
X		mov	ax,bx				;Normalize the
X		shr	ax,4				;Segment and
X		mov	si,es				;Offset so that
X		add	si,ax				;It dosn't Wrap
X		mov	es,si
X		and	bx,000Fh
X		lea	di,cmd_tread
X		mov	ax,cx				;Convert Bytes
X		shr	ax,9				;to Blocks
X		mov	[di].tio_cmd_cnt_b1,ah		;Insert into Command
X		mov	[di].tio_cmd_cnt_b0,al
X		call	docmd
X		jnc	tape_r_exit
X		call	scsi_sense
Xtape_r_exit:	ret
Xtape_read	endp
X
X;
X; Write Some Blocks to the Tape
X;
Xtape_write	proc	near
X		mov	write_flag,TRUE			;Write Done
X		mov	di,bx
X		mov	cx,es:[di].rh8_count		;Byte Count
X		mov	ax,cx				;Test for invalid
X		and	ax,P_SECT-1			;Byte Count
X		jz	tape_w_ok
X		mov	es:[di].rh8_count,0		;Nothing Write
X		mov	write_flag,FALSE		;Cancel if ERROR!
X		stc					;Oops
X		ret
Xtape_w_ok:	mov	cx,es:[di].rh8_count		;Byte Count
X		mov	bx,es:[di].rh8_buf_ofs		;Buffer Offset
X		mov	ax,es:[di].rh8_buf_seg		;Buffer Segment
X		mov	es,ax
X		mov	ax,bx				;Normalize the
X		shr	ax,4				;Segment and
X		mov	si,es				;Offset so that
X		add	si,ax				;It dosn't Wrap
X		mov	es,si
X		and	bx,000Fh
X		lea	di,cmd_twrite
X		mov	ax,cx				;Convert Bytes
X		shr	ax,9				;to Blocks
X		mov	[di].tio_cmd_cnt_b1,ah		;Insert into Command
X		mov	[di].tio_cmd_cnt_b0,al
X		call	docmd
X		jnc	tape_w_exit
X		mov	write_flag,FALSE		;Cancel if ERROR!
X		call	scsi_sense
Xtape_w_exit:	ret
Xtape_write	endp
X
X;
X; Do a command
X;
X; bx => buffer for returned information
X; cx = buffer len
X; di => command string
X; es = buffer segment for returned information
X;
X; al = return code, 'C' indicates an error
X;
Xdocmd		proc	near
X		pusha
X		push	es
X
X		mov	docmd_buf,bx		;Save our arguments
X		mov	docmd_buf_seg,es
X		mov	docmd_len,cx
X		mov	docmd_cmd,di
X
X		mov	ax,SCSI_CARD_SEG	;Point at the Card
X		mov	es,ax
X		mov	si,SCSI_CMD_PORT	;Command Port
X
X;
X; Wait for the Bus to become free
X;
X		mov	cx,65535
Xidle_loop:	mov	al,es:[si]		;Get the Status
X		and	al,FREE_MASK
X		jz	try_sel
X		loop	idle_loop
X
X		call	scsi_reset
X		mov	al,CBUSBUSY		;Bus still BUSY?
X		jmp	docmd_exit
X
Xtry_sel:	mov	al,CMDBASE		;Try to select target
X		mov	es:[si],al
X
X		mov	di,cur_unit
X		mov	al,[di].unit_select	;Get our Select Bit
X		mov	di,SCSI_DATA_PORT	;Data Port
X		mov	es:[di],al
X
X		call	wait100us		;Spec says wait 90us here
X		mov	al,CMDBASE or CMDENABLE or CMDSEL
X		mov	es:[si],al
X
X;
X; Wait 250 ms for the Target to be SELected
X;
X		mov	cx,2500
Xsel_loop:	test	byte ptr es:[si],STBSY	;Look for BSY bit
X		jnz	cmd_xfer
X		call	wait100us
X		loop	sel_loop
X
X		mov	al,CMDBASE or CMDSEL	;Release the data BUS
X		mov	es:[si],al
X		call	wait100us		;Spec says wait 290us
X		call	wait100us		;to abort selection phase
X		call	wait100us
X		test	byte ptr es:[si],STBSY	;Look one final time
X		jnz	cmd_xfer		;Device did answer
X		mov	al,CNOCONNECT		;Nothing Answered
X		jmp	docmd_exit
X
X;
X; Start the Command
X;
Xcmd_xfer:	call	wait100us		;Spec say wait 90us here
X		mov	al,CMDBASE or CMDENABLE	;Drop SEL and begin talking
X		mov	es:[si],al
Xxfer_loop:	mov	al,es:[si]
X		test	al,STBSY		;Look for BSY bit
X		jz	xfer_error
X		test	al,STREQ		;And REQ bit
X		jz	xfer_loop
X
X		and	al,REQ_MASK		;Look at REQ type
X
X		cmp	al,REQ_DATAOUT		;Is it Data Out?
X		jnz	try_datain
X		call	send_data
X		jmp	short xfer_loop
X
Xtry_datain:	cmp	al,REQ_DATAIN		;Is it Data In?
X		jnz	try_cmdout
X		call	receive_data
X		jmp	short xfer_loop
X
Xtry_cmdout:	cmp	al,REQ_CMDOUT		;Is it Command Out?
X		jnz	try_statin
X		call	send_cmd
X		jmp	short xfer_loop
X
Xtry_statin:	cmp	al,REQ_STATIN		;Is it Status In?
X		jnz	try_msgout
X		mov	al,es:[di]		;Get the Status Byte
X		mov	docmd_status,al
X		jmp	short xfer_loop
X
Xtry_msgout:	cmp	al,REQ_MSGOUT		;Is it Message Out?
X		jnz	try_msgin
X		call	send_nop
X		jmp	short xfer_loop
X
Xtry_msgin:	cmp	al,REQ_MSGIN		;Is it Message In?
X		jnz	xfer_error
X
X		mov	al,es:[di]		;Get Message Byte
X		cmp	al,MSG_COMPLETE		;Are We All Done?
X		jnz	short xfer_loop
X		mov	al,docmd_status
X		or	al,al			;Did we have an error?
X		mov	al,COK			;Preload OK code
X		jz	docmd_exit
X
Xxfer_error:	mov	al,CERROR		;Command Failed Somehow
X
Xdocmd_exit:	mov	docmd_tempb,al
X		mov	al,CMDBASE		;Release the BUS
X		mov	es:[si],al
X		pop	es
X		popa
X		mov	al,docmd_tempb
X		cmp	al,COK
X		jz	docmd_exit_ok
X		stc
Xdocmd_exit_ok:	ret
Xdocmd		endp
X
X;
X; Receive a Data Stream from the card
X; On entry es:[di] points at the data port
X;          es:[si] points at the command port
X;
Xreceive_data	proc	near
X		mov	dx,es			;Save ES
X
X		mov	bx,si
X		mov	ax,es
X		mov	cx,docmd_len		;Length
X		mov	di,docmd_buf		;Dest Offset
X		mov	es,docmd_buf_seg	;Dest Segment
X		mov	si,SCSI_DATA_PORT	;Source Offset
X		mov	ds,ax			;Source Segment
X		mov	al,STREQ
X		mov	ah,STBSY
X		cld
X
Xreceive_loop:	movsb
X		if multi_sector
X		dec	si			;Don't blow the card buffer
X		endif
X		dec	cx
X		jz	receive_exit
Xreceive_wait:	test	byte ptr [bx],al	;Ready?
X		jnz	receive_loop
X		test	byte ptr [bx],ah	;Busy?
X		jz	receive_exit
X		jmp	short receive_wait
X
Xreceive_exit:	mov	si,SCSI_CMD_PORT	;Restore the Environment
X		mov	di,SCSI_DATA_PORT
X		mov	ax,cs
X		mov	ds,ax
X		mov	es,dx
X		ret
Xreceive_data	endp
X
X;
X; Send a Command to the card
X; On entry es:[di] points at the data port
X;          es:[si] points at the command port
X;
Xsend_cmd	proc	near
X		mov	bx,docmd_cmd		;Get Command Pointer
X		mov	al,[bx]			;Get a Command Byte
X		mov	es:[di],al		;Send it to Card
X		inc	bx			;Bump for Next Time
X		mov	docmd_cmd,bx
X		ret
Xsend_cmd	endp
X
X;
X; Send a Data Stream to the card
X; On entry es:[di] points at the data port
X;          es:[si] points at the command port
X;
Xsend_data	proc	near
X		mov	bx,si
X		mov	cx,docmd_len		;Get the Data Count
X		mov	si,docmd_buf		;Source Offset
X		mov	ds,docmd_buf_seg	;Source Segment
X		mov	al,STREQ
X		mov	ah,STBSY
X		cld
X
Xsend_loop:	movsb
X		if multi_sector
X		dec	di			;Don't blow the card buffer
X		endif
X		dec	cx
X		jz	send_exit
Xsend_wait:	test	byte ptr es:[bx],al	;Ready?
X		jnz	send_loop
X		test	byte ptr es:[bx],ah	;Busy?
X		jz	send_exit
X		jmp	short send_wait
X
Xsend_exit:	mov	si,SCSI_CMD_PORT	;Restore the Environment
X		mov	di,SCSI_DATA_PORT
X		mov	ax,cs
X		mov	ds,ax
X		ret
Xsend_data	endp
X
X;
X; Send a NOP Message
X;
Xsend_nop	proc	near
X		mov	al,MSG_NOP		;Oops, send a nop
X		mov	es:[di],al
X		mov	al,CMDBASE or CMDENABLE
X		mov	es:[si],al
X		ret
Xsend_nop	endp
X
X;
X; Wait One Milli second
X;
X; The value of 'cx' is computed for an 8 Mhz Clock
X;
Xwait1ms		proc	near
X		push	cx		;   (3) = 375ns
X		mov	cx,798		;   (2) = 250ns
Xwait_m_loop:	loop	wait_m_loop	;  (10) = 1250ns * X
X		pop	cx		;   (5) = 625ns
X		ret			; (11+) = 1375ns
Xwait1ms		endp
X
X;
X; Wait One Hundred Micros Seconds
X;
X; The value of 'cx' is computed for an 8 Mhz Clock
X;
Xwait100us	proc	near
X		push	cx		;   (3) = 375ns
X		mov	cx,78		;   (2) = 250ns
Xwait_u_loop:	loop	wait_u_loop	;  (10) = 1250ns * X
X		pop	cx		;   (5) = 625ns
X		ret			; (11+) = 1375ns
Xwait100us	endp
SHAR_EOF
chmod 0644 subs.asm ||
echo 'restore of subs.asm failed'
Wc_c="`wc -c < 'subs.asm'`"
test 15830 -eq "$Wc_c" ||
	echo 'subs.asm: original size 15830, current size' "$Wc_c"
fi
# ============= units.asm ==============
if test -f 'units.asm' -a X"$1" != X"-c"; then
	echo 'x - skipping units.asm (File already exists)'
else
echo 'x - extracting units.asm (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'units.asm' &&
X;
X; target information/control structures
X;
X		even
Xunit0		db	size unit dup (-1)
X		even
Xunit1		db	size unit dup (-1)
X		even
Xunit2		db	size unit dup (-1)
X		even
Xunit3		db	size unit dup (-1)
X		even
Xunit4		db	size unit dup (-1)
X		even
Xunit5		db	size unit dup (-1)
X		even
Xunit6		db	size unit dup (-1)
X		ife reserve_addr
X		even
Xunit7		db	size unit dup (-1)
X		endif
X
X		even
Xbpb0		db	size bpb dup (-1)
X		even
Xbpb1		db	size bpb dup (-1)
X		even
Xbpb2		db	size bpb dup (-1)
X		even
Xbpb3		db	size bpb dup (-1)
X		even
Xbpb4		db	size bpb dup (-1)
X		even
Xbpb5		db	size bpb dup (-1)
X		even
Xbpb6		db	size bpb dup (-1)
X		even
Xbpb7		db	size bpb dup (-1)
X		even
Xbpb8		db	size bpb dup (-1)
X		even
Xbpb9		db	size bpb dup (-1)
X		even
XbpbA		db	size bpb dup (-1)
X		even
XbpbB		db	size bpb dup (-1)
X		even
XbpbC		db	size bpb dup (-1)
X		even
XbpbD		db	size bpb dup (-1)
X		even
XbpbE		db	size bpb dup (-1)
X		even
XbpbF		db	size bpb dup (-1)
X
X		even
Xunit_array	dw	unit0
X		dw	unit1
X		dw	unit2
X		dw	unit3
X		dw	unit4
X		dw	unit5
X		dw	unit6
X		ife reserve_addr
X		dw	unit7
X		endif
X
X		even
Xbpb_array	dw	bpb0		;BPB Array for DOS
X		dw	bpb1
X		dw	bpb2
X		dw	bpb3
X		dw	bpb4
X		dw	bpb5
X		dw	bpb6
X		dw	bpb7
X		dw	bpb8
X		dw	bpb9
X		dw	bpbA
X		dw	bpbB
X		dw	bpbC
X		dw	bpbD
X		dw	bpbE
X		dw	bpbF
Xbpb_hw_mark	dw	bpb_array
X
Xtape_unit	dw	-1
Xcur_unit	dw	unit0
Xcur_bpb		dw	bpb0
X
X;
X; Given the request header in es:bx
X; Return a pointer in ds:di to the unit entry
X; or 'C' if no such unit exists.
X;
X; Do not destroy es:bx !!!
X;
Xfind_unit	proc	near
X		pusha
X		mov	ah,es:[bx].rh_unit	;What drive did they want
X		lea	di,unit_array
X		lea	si,bpb_array
X		mov	cx,MAXUNIT		;How many to search
Xfind_loop:	mov	bx,[di]			;Point at a unit	
X		mov	al,[bx].unit_num_drv	;Does this SCSI device
X		or	al,al			;Have any Drives Defined?
X		jz	find_next
X		mov	dh,[bx].unit_1st_drv	;Get First Drive Number
Xfind_unit_loop:	cmp	ah,dh			;Is this the correct drive?
X		jz	find_match
X		inc	si			;Bump to next BPB
X		inc	si
X		inc	dh			;Bump Drive Number
X		dec	al			;Dec Drive count
X		jnz	find_unit_loop		;Try next Drive
X		jmp	short find_next		;Try next SCSI device
Xfind_match:	mov	cur_unit,bx		;Found a match
X		mov	ax,[si]
X		mov	cur_bpb,ax
X		clc
X		jmp	find_exit
Xfind_next:	inc	di
X		inc	di
X		loop	find_loop
X		stc				;No More units, Error
Xfind_exit:	popa
X		ret
Xfind_unit	endp
X
X;
X; Given the data in a unit entry,
X; create the bpb for the unit.
X;
Xmake_bpb	proc	near
X		mov	di,cur_bpb		;Get the current BPB
X		mov	bx,cur_unit		;Get the current Unit
X		mov	[di].bpb_ss,P_SECT
X		mov	[di].bpb_au,CLUSTSIZE
X		mov	[di].bpb_rs,1
X		mov	[di].bpb_nf,2
X		mov	[di].bpb_de,512
X		mov	ah,[bx].unit_cap_buf.cap_sectors_b3
X		mov	al,[bx].unit_cap_buf.cap_sectors_b2
X		or	ax,ax
X		jz	make_bpb_last		;Use up the last few sectors
X		dec	ax			;Use up 65536 Sectors
X		mov	[bx].unit_cap_buf.cap_sectors_b3,ah
X		mov	[bx].unit_cap_buf.cap_sectors_b2,al
X		mov	dx,65535		;Max of 32 Meg
X		jmp	short make_bpb_ts
Xmake_bpb_last:	mov	dh,[bx].unit_cap_buf.cap_sectors_b1
X		mov	[bx].unit_cap_buf.cap_sectors_b1,0
X		mov	dl,0			;Round to nearest Cyl
X		mov	[bx].unit_cap_buf.cap_sectors_b0,0
X		dec	dx			;Make it zero relative
Xmake_bpb_ts:	mov	[di].bpb_ts,dx
X		mov	[di].bpb_md,0F8h
X		shr	dx,SECT_2_FS
X		inc	dx			;Allow for round-off
X		mov	[di].bpb_fs,dx
X		mov	[di].bpb_st,SECT_TRACK
X		mov	[di].bpb_nh,1
X		mov	[di].bpb_hs_lsw,0
X		mov	[di].bpb_hs_msw,0
X		ret
Xmake_bpb	endp
SHAR_EOF
chmod 0644 units.asm ||
echo 'restore of units.asm failed'
Wc_c="`wc -c < 'units.asm'`"
test 3322 -eq "$Wc_c" ||
	echo 'units.asm: original size 3322, current size' "$Wc_c"
fi
exit 0



More information about the Comp.sources.misc mailing list