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