home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume25
/
st01scsi
/
part02
< prev
next >
Wrap
Text File
|
1991-11-04
|
59KB
|
2,505 lines
Newsgroups: comp.sources.misc
From: briana@tau-ceti.isc-br.com (Brian W. Antoine)
Subject: v25i019: st01scsi - DOS SCSI Driver for the Seagate ST-01, v2.0, Part02/02
Message-ID: <1991Nov5.033452.4414@sparky.imd.sterling.com>
X-Md4-Signature: db7f3dda25e39475703534e67a7028f3
Date: Tue, 5 Nov 1991 03:34:52 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: briana@tau-ceti.isc-br.com (Brian W. Antoine)
Posting-number: Volume 25, Issue 19
Archive-name: st01scsi/part02
Environment: DOS, ST-01
Supersedes: ST01SCSI.12: Volume 15, Issue 2-3
#
# This is a Shell Archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through #! /bin/sh.
# -----cut here-----cut here-----cut here-----cut here-----
#! /bin/sh
# Execute the file with #! /bin/sh (not csh) to create the files:
# dump.asm
# ioctl.asm
# kludge.asm
# scsi.asm
# subs.asm
# units.asm
# This Archive created: Fri Oct 18 22:46:09 1991
# By: Brian W. Antoine at ISC - Bunker Ramo, Spokane, WA
#
export PATH; PATH=/bin:$PATH
echo shar: extracting "'dump.asm'" '(1362 characters)'
if test -f 'dump.asm'
then
echo shar: will not over-write existing file "'dump.asm'"
else
sed 's/^XX//' > 'dump.asm' << \SHAR_EOF
XX;
XX; Convert bin (ax) to ascii (bx => buffer)
XX;
XXbin_ascii proc near
XX pusha
XX push ax
XX mov cx,6
XXfill_buff: mov byte ptr [bx],' '
XX inc bx
XX loop fill_buff
XX mov si,10
XX or ax,ax
XX jns clr_dvd
XX neg ax
XXclr_dvd: sub dx,dx
XX div si
XX add dx,'0'
XX dec bx
XX mov [bx],dl
XX inc cx
XX or ax,ax
XX jnz clr_dvd
XX pop ax
XX or ax,ax
XX jns no_more
XX dec bx
XX mov byte ptr [bx],'-'
XXno_more: popa
XX ret
XXbin_ascii endp
XX
XX;
XX; Convert Hex (dx) to Ascii (bx => buffer)
XX;
XXhex2asc4 proc near
XX push cx
XX push ax
XX mov cx,4 ;Do Four Digits
XXh241: rol dx,1
XX rol dx,1
XX rol dx,1
XX rol dx,1
XX mov al,dl ;Get the Current Digit
XX and al,0Fh
XX cmp al,0Ah ;Is It Hex?
XX jge h242
XX add al,30h ;Normal Digit
XX jmp h243
XXh242: add al,37h ;Hex Digit
XXh243: mov [bx],al ;Insert in Buffer
XX inc bx
XX loop h241
XX pop ax
XX pop cx
XX ret
XXhex2asc4 endp
XX
XX;
XX; Convert Hex (dl) to Ascii (bx => buffer)
XX;
XXhex2asc2 proc near
XX push cx
XX push ax
XX mov cx,2 ;Do Two Digits
XXh221: rol dl,1
XX rol dl,1
XX rol dl,1
XX rol dl,1
XX mov al,dl ;Get the Current Digit
XX and al,0Fh
XX cmp al,0Ah ;Is It Hex?
XX jge h222
XX add al,30h ;Normal Digit
XX jmp h223
XXh222: add al,37h ;Hex Digit
XXh223: mov [bx],al ;Insert in Buffer
XX inc bx
XX loop h221
XX pop ax
XX pop cx
XX ret
XXhex2asc2 endp
XX
XX;
XX; Print a string
XX;
XX; ds:dx => string
XX;
XXputs proc near
XX pusha
XX mov ah,9 ;DOS print string
XX int 21h
XX popa
XX ret
XXputs endp
SHAR_EOF
if test 1362 -ne "`wc -c < 'dump.asm'`"
then
echo shar: error transmitting "'dump.asm'" '(should have been 1362 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ioctl.asm'" '(5778 characters)'
if test -f 'ioctl.asm'
then
echo shar: will not over-write existing file "'ioctl.asm'"
else
sed 's/^XX//' > 'ioctl.asm' << \SHAR_EOF
XX;
XX; Process an ioctl request for the current unit
XX;
XX; return 'C' on error
XX;
XXscsi_ioctl proc
XX mov al,es:[bx].rh19_minor ;Get the minor number
XX cmp al,40h ;Set Device Params?
XX jnz scsi_i_42h
XX clc
XX jmp scsi_i_exit
XX
XXscsi_i_42h: cmp al,42h ;Format and Verify?
XX jnz scsi_i_60h
XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
XX mov ax,es:[bx].rh19_buf_seg
XX mov es,ax
XX mov ax,es:[di].ioctl_fmt_cyl ;Cylinder
XX mov bx,SECT_TRACK
XX mul bx ;Convert to Sector
XX mov cx,es:[di].ioctl_fmt_head ;Head
XX or cx,cx
XX jz head0_42h
XXhead_loop_42h: add ax,SECT_TRACK ;Add Head Tracks
XX adc dx,0
XX loop head_loop_42h
XXhead0_42h: mov bx,0
XX mov cx,es:[di].ioctl_fmt_len ;How Many Tracks
XXlen_loop_42h: add bx,SECT_TRACK ;Convert to Sectors
XX loop len_loop_42h
XX mov cx,bx
XX
XX ife large_drives
XX mov di,cur_bpb ;Add Drive Offset
XX mov dx,[di].bpb_hs_msw
XX endif
XX
XX call scsi_verify
XX jmp scsi_i_exit
XX
XXscsi_i_60h: cmp al,60h ;Get Device Params?
XX jnz scsi_i_61h
XXbuild_bpb: mov si,cur_bpb ;Get the Current BPB
XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
XX mov ax,es:[bx].rh19_buf_seg
XX mov es,ax
XX mov es:[di].dpb_special,05h ;Sect Same/Use Cur BPB
XX mov es:[di].dpb_type,05h ;Fixed Disk
XX mov es:[di].dpb_attr,0001h ;Not Removable
XX if large_drives
XX mov dx,[si].bpb_ts_msw
XX mov ax,[si].bpb_ts_lsw
XX else
XX mov dx,0
XX mov ax,[si].bpb_ts
XX endif
XX add ax,1 ;Sectors (1-n)
XX adc dx,0
XX mov bx,SECT_TRACK
XX div bx
XX mov es:[di].dpb_cyl,ax
XX mov es:[di].dpb_media,0 ;????
XX mov es:[di].dpb_sectors,SECT_TRACK ;Sectors per Track
XX
XX push di
XX lea di,es:[di].dpb_bpb ;Copy the bpb into
XX mov cx,size bpb ;the requestors buffer
XX cld
XX rep movsb
XX pop di
XX
XX lea di,es:[di].dpb_track ;Build the Track List
XX mov cx,SECT_TRACK
XX mov ax,0 ;Start with Sector 0
XXscsi_i_t_loop: mov es:[di],ax ;Sector Number
XX inc ax
XX inc di
XX inc di
XX mov word ptr es:[di],P_SECT ;Sector Size
XX inc di
XX inc di
XX loop scsi_i_t_loop
XX clc
XX jmp short scsi_i_exit
XX
XXscsi_i_61h: cmp al,61h ;Read Track?
XX jnz scsi_i_62h
XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
XX mov ax,es:[bx].rh19_buf_seg
XX mov es,ax
XX mov ax,es:[di].ioctl_read_cyl ;Cylinder
XX mov bx,SECT_TRACK
XX mul bx ;Convert to Sector
XX mov cx,es:[di].ioctl_read_head ;Head
XX or cx,cx
XX jz head0_61h
XXhead_loop_61h: add ax,SECT_TRACK ;Add Head Tracks
XX adc dx,0
XX loop head_loop_61h
XXhead0_61h: add ax,es:[di].ioctl_read_sect ;Offset into the Track
XX adc dx,0
XX mov cx,es:[di].ioctl_read_len ;How Many Sectors
XX
XX ife large_drives
XX mov di,cur_bpb ;Add Drive Offset
XX mov dx,[di].bpb_hs_msw
XX endif
XX
XX call scsi_verify
XX jc scsi_i_error
XX mov es,rh_seg
XX mov bx,rh_off
XX jmp build_bpb
XX
XXscsi_i_62h: cmp al,62h ;Verify?
XX jnz scsi_i_error
XX mov di,es:[bx].rh19_buf_ofs ;Get the Param Buffer
XX mov ax,es:[bx].rh19_buf_seg
XX mov es,ax
XX mov ax,es:[di].ioctl_fmt_cyl ;Cylinder
XX mov bx,SECT_TRACK
XX mul bx ;Convert to Sector
XX mov cx,es:[di].ioctl_fmt_head ;Head
XX or cx,cx
XX jz head0_62h
XXhead_loop_62h: add ax,SECT_TRACK ;Add Head Tracks
XX adc dx,0
XX loop head_loop_62h
XXhead0_62h: mov bx,0
XX mov cx,es:[di].ioctl_fmt_len ;How Many Tracks
XXlen_loop_62h: add bx,SECT_TRACK ;Convert to Sectors
XX loop len_loop_62h
XX mov cx,bx
XX
XX ife large_drives
XX mov di,cur_bpb ;Add Drive Offset
XX mov dx,[di].bpb_hs_msw
XX endif
XX
XX call scsi_verify
XX jmp short scsi_i_exit
XX
XXscsi_i_error: stc
XXscsi_i_exit: ret
XXscsi_ioctl endp
XX
XX;
XX; Process an ioctl_write request
XX;
XXscsi_ioctl_write proc
XX mov di,es:[bx].rh12_buf_ofs ;Get The Command
XX mov ax,es:[bx].rh12_buf_seg ;Buffer
XX mov es,ax
XX mov ax,es:[di].ioc_command ;What Command
XX
XX;
XX; Format Disk Unit
XX;
XX cmp al,'F' ;Format?
XX jnz try_erase
XX mov ax,es:[di].ioc_param1 ;Get Interleave
XX mov bx,es:[di].ioc_buf_ofs ;Get Buffer Offset
XX mov cx,es:[di].ioc_buf_len ;Get Buffer Length
XX mov dx,es:[di].ioc_param2 ;Get Format Type
XX mov es,es:[di].ioc_buf_seg ;Get Buffer Seg
XX lea di,cmd_format ;Insert into Command
XX mov [di].fmt_cmd_il_b1,ah
XX mov [di].fmt_cmd_il_b0,al
XX mov [di].fmt_cmd_type,dl
XX call docmd
XX jnc format_exit
XX call scsi_sense
XXformat_exit: jmp scsi_i_w_exit
XX
XX;
XX; Erase Tape Unit
XX;
XXtry_erase: cmp al,'E' ;Erase?
XX jnz try_rewind
XX lea di,cmd_erase ;Now Erase Tape
XX call docmd
XX jnc erase_exit
XX call scsi_sense
XXerase_exit: jmp scsi_i_w_exit
XX
XX;
XX; Rewind Tape Unit
XX;
XXtry_rewind: cmp al,'R' ;Rewind?
XX jnz try_load
XX lea di,cmd_rewind ;Now Rewind Tape
XX call docmd
XX jnc rewind_exit
XX call scsi_sense
XXrewind_exit: jmp scsi_i_w_exit
XX
XX;
XX; Load Tape on Open
XX;
XXtry_load: cmp al,'L' ;Load?
XX jnz try_noload
XX mov load_flag,TRUE
XX jmp scsi_i_w_exit
XX
XX;
XX; No Load Tape on Open
XX;
XXtry_noload: cmp al,'N' ;No Load?
XX jnz try_space
XX mov load_flag,FALSE
XX jmp scsi_i_w_exit
XX
XX;
XX; Space Tape
XX;
XXtry_space: cmp al,'S' ;Space?
XX jnz try_filemark
XX mov ax,es:[di].ioc_param1 ;Get Count
XX mov bx,es:[di].ioc_param2 ;Get Type
XX lea di,cmd_space ;Insert into Command
XX mov [di].space_cmd_code,bl
XX mov [di].space_cmd_cnt2,ah ;Dup of ah
XX mov [di].space_cmd_cnt1,ah
XX mov [di].space_cmd_cnt0,al
XX call docmd
XX jnc scsi_i_w_exit
XX call scsi_sense
XX jmp scsi_i_w_exit
XX
XX;
XX; Write Filemarks
XX;
XXtry_filemark: cmp al,'M' ;Mark?
XX jnz try_remap
XX mov ax,es:[di].ioc_param1 ;Get Count
XX lea di,cmd_twritefm ;Insert into Command
XX mov [di].fm_cmd_cnt_b1,ah
XX mov [di].fm_cmd_cnt_b0,al
XX call docmd
XX jnc scsi_i_w_exit
XX call scsi_sense
XX jmp scsi_i_w_exit
XX
XX;
XX; Reassign Block
XX;
XXtry_remap: cmp al,'A' ;ReAssign?
XX jnz scsi_i_w_error
XX mov bx,es:[di].ioc_buf_ofs ;Get Buffer Offset
XX mov cx,es:[di].ioc_buf_len ;Get Buffer Length
XX mov es,es:[di].ioc_buf_seg ;Get Buffer Seg
XX lea di,cmd_remap ;Command
XX call docmd
XX jnc scsi_i_w_exit
XX call scsi_sense
XX jmp scsi_i_w_exit
XX
XXscsi_i_w_error: stc
XXscsi_i_w_exit: ret
XXscsi_ioctl_write endp
SHAR_EOF
if test 5778 -ne "`wc -c < 'ioctl.asm'`"
then
echo shar: error transmitting "'ioctl.asm'" '(should have been 5778 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'kludge.asm'" '(2417 characters)'
if test -f 'kludge.asm'
then
echo shar: will not over-write existing file "'kludge.asm'"
else
sed 's/^XX//' > 'kludge.asm' << \SHAR_EOF
XX;
XX; This code is needed because DOS insists on opening a char device
XX; in cooked mode. The problem is that without adding code to every
XX; application that would ever use us, we have no way to alter this
XX; because the use of O_BINARY or setmode() do not affect char devices.
XX;
XX; The solution (kludge) is to watch open requests issued thru the
XX; INT 21 vector. If we see a open request followed by a OPEN_DEV
XX; call to us, it must have been an open for us. So during the return,
XX; force a call to the ioctl facility that will switch to raw mode.
XX;
XX
XX;
XX; The Original INT 21 Vector
XX;
XXvect_int_21 equ word ptr 4 * 21h
XXorig_int_21 dd ? ;Original INT 21 Vector
XX
XX;
XX; OPEN_DEV flag is TRUE when we are opened
XX;
XXopened_flag db FALSE
XX
XXpatch_us_in proc near
XX push es
XX push ax
XX mov ax,0 ;Patch Ourselves into
XX mov es,ax ;the INT 21 Vector
XX mov ax,es:[vect_int_21] ;Offset
XX mov word ptr orig_int_21,ax
XX lea ax,our_int_21
XX mov es:[vect_int_21],ax
XX mov ax,es:[vect_int_21+2] ;Segment
XX mov word ptr orig_int_21+2,ax
XX mov ax,cs
XX mov es:[vect_int_21+2],ax
XX pop ax
XX pop es
XX ret
XXpatch_us_in endp
XX
XXour_int_21 proc far
XX pushf ;Save entry flags
XX cmp ah,3Dh ;Is it an open request?
XX jnz not_open_req
XX popf ;Restore entry flags
XX;
XX; We need to set things up so the 'iret' done by the INT 21
XX; code will have some the right stuff on the stack.
XX; #1 Flags with interrupts enabled
XX; #2 Return Address
XX;
XX sti ;Allow interrupts
XX pushf ;After the iret
XX cli ;Shut interrupts off
XX call cs:orig_int_21 ;While we Pass the request on
XX;
XX; Upon return, interrupts are enabled, so shut them off while we work
XX;
XX pushf
XX cli
XX cmp cs:opened_flag,FALSE ;Was it an open for us?
XX jz not_our_open
XX mov cs:opened_flag,FALSE ;Clear for next time
XX;
XX; We need to forge a call to the ioctl interface
XX; to switch DOS to raw mode when it talks to us
XX;
XX pusha
XX mov bx,ax ;Save the Handle
XX mov ax,4400h ;Get Device Information
XX pushf
XX call cs:orig_int_21
XX mov dh,0 ;Setup
XX or dl,20h ;for RAW Mode
XX mov ax,4401h ;Set Device Information
XX pushf
XX call cs:orig_int_21
XX popa
XX
XXnot_our_open: popf ;The Original Flags to return
XX;
XX; When we return, we need to pop the flags that the original INT 21
XX; call left on the stack, and return the flags we got back
XX;
XX ret 2 ;Return and discard flags
XX
XXnot_open_req: popf ;Pop the saved flags
XX jmp cs:orig_int_21 ;Continue with original code
XXour_int_21 endp
SHAR_EOF
if test 2417 -ne "`wc -c < 'kludge.asm'`"
then
echo shar: error transmitting "'kludge.asm'" '(should have been 2417 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'scsi.asm'" '(14291 characters)'
if test -f 'scsi.asm'
then
echo shar: will not over-write existing file "'scsi.asm'"
else
sed 's/^XX//' > 'scsi.asm' << \SHAR_EOF
XX;
XX; Simple SCSI Device Driver
XX;
XX PAGE 76,132
XX
XX INCLUDE options.inc
XX INCLUDE equ.inc
XX INCLUDE struct.inc
XX
XX ife oldcode
XX .286
XX else
XX .8086
XXpusha macro
XX push ax
XX push bx
XX push cx
XX push dx
XX push si
XX push di
XX endm
XX
XXpopa macro
XX pop di
XX pop si
XX pop dx
XX pop cx
XX pop bx
XX pop ax
XX endm
XX endif
XX
XX;
XX; Start of Code and Data
XX;
XX_TEXT segment word public 'CODE'
XX assume cs:_TEXT, ds:_TEXT, es:_TEXT
XX
XX org 0
XX
XX;
XX; Device Header Required By DOS
XX;
XXscsi:
XXtape_link_ofs dw disk_link_ofs ;Forward Link
XXtape_link_seg dw -1
XX dw 0C800h ;Char Device
XX dw tape_strategy ;Address of 1st DOS Call
XX dw dev_interrupt ;Address of 2nd DOS Call
XX db 'SCSITAPE' ;Device Name
XX
XXdisk_link_ofs dw -1 ;Forward Link
XXdisk_link_seg dw -1
XX if large_drives
XX dw 06042h ;Ioctl R/W, Block Device, Non-IBM, Get/Set, 32 bit
XX else
XX dw 06040h ;Ioctl R/W, Block Device, Non-IBM, Get/Set
XX endif
XX dw disk_strategy ;Address of 1st DOS Call
XX dw dev_interrupt ;Address of 2nd DOS Call
XXdisk_count db 0 ;Number of Disks Present
XX db 7 dup(?)
XX
XX;
XX; Work Space For Our Device Driver
XX;
XX even
XXrh_off dw ? ;Request Header Offset
XXrh_seg dw ? ;Request Header Segment
XXrh_type db ? ;Request Type
XX
XXwrite_flag db FALSE ;TRUE When Tape Write Seen
XXread_flag db FALSE ;TRUE When Tape Read Seen
XXerror_flag db FALSE ;TRUE When Tape Error Seen
XXload_flag db TRUE ;TRUE When Tape should Load/Unload
XXcur_drive db -1
XXvol_id db 'NO NAME ',0
XX
XX;
XX; The Original INT 24 Vector
XX;
XXvect_int_24 equ word ptr 4 * 24h
XXorig_int_24 dd ? ;Original INT 24 Vector
XX
XX;
XX; Define our own personal Stack
XX;
XX even
XXnew_stack db STACK_SIZE-2 dup (?) ;Our Local Stack
XXnew_stack_top dw ?
XX
XXstack_ptr dw ? ;Old Stack Pointer
XXstack_seg dw ? ;Old Stack Segment
XX
XX;
XX; Command Table
XX;
XXcmdtab label byte ;* = Char Only Devices
XX dw INITIALIZATION ;Initialization
XX dw MEDIA_CHECK ;Media Check (Block Only)
XX dw GET_BPB ;Build BPB (Block Only)
XX dw unknown ;IOCTL Read
XX dw READ ;Read Data
XX dw done ;*Non Destructive Read
XX dw done ;*Read Status
XX dw done ;*Flush Read Buffer
XX dw WRITE ;Write Data
XX dw WRITE_VERIFY ;Write With Verify
XX dw done ;*Write Status
XX dw done ;*Flush Write Buffer
XX dw WRITE_IOCTL ;IOCTL Write
XX dw OPEN_DEV ;Device Open
XX dw CLOSE_DEV ;Device Close
XX dw done ;Removable Check
XX dw unknown ;*Write Until Busy
XX dw unknown ;Unknown Call
XX dw unknown ;Unknown Call
XX dw IOCTL ;Generic Ioctl
XX dw unknown ;Unknown Call
XX dw unknown ;Unknown Call
XX dw unknown ;Unknown Call
XX dw GET_DEV ;Get Device
XX dw SET_DEV ;Set Device
XX
XX;
XX; Int 24 (Fatal Error Handler)
XX;
XX; The test for our tape device only works because the
XX; device header for the tape is located at the start
XX; of the driver binary.
XX;
XXour_int_24 proc far
XX push ax
XX mov ax,cs ;Is it our Segment
XX cmp bp,ax
XX jnz not_our_tape
XX cmp si,0 ;Is it the Tape Device
XX jnz not_our_tape
XX pop ax
XX mov al,3 ;Fail the System Call
XX iret
XXnot_our_tape: pop ax
XX jmp cs:orig_int_24 ;Pass the Request On
XXour_int_24 endp
XX
XX;
XX; Strategy Procedure
XX;
XXdisk_strategy proc far
XX mov cs:rh_seg,es ;Save Request Header Ptr Segment
XX mov cs:rh_off,bx ;Save Request Header Ptr Offset
XX mov cs:rh_type,DISK_REQUEST
XX ret
XXdisk_strategy endp
XX
XXtape_strategy proc far
XX mov cs:rh_seg,es ;Save Request Header Ptr Segment
XX mov cs:rh_off,bx ;Save Request Header Ptr Offset
XX mov cs:rh_type,TAPE_REQUEST
XX ret
XXtape_strategy endp
XX
XX;
XX; Interrupt Procedure
XX;
XXdev_interrupt proc far
XX pushf ;Save Machine State On Entry
XX cli
XX push ds
XX push es
XX push ax
XX push bx
XX push cx
XX push dx
XX push si
XX push di
XX push bp
XX
XX mov cs:stack_seg,ss ;Save Old Stack
XX mov cs:stack_ptr,sp
XX
XX mov ax,cs ;Save us the Segment Override Crap
XX mov ds,ax
XX mov es,ax
XX
XX mov ss,ax ;Setup Our Local Stack
XX lea ax,new_stack_top
XX mov sp,ax
XX sti ;We're Safe Now
XX
XX;
XX; Perform branch based on the command passed in the Request Header
XX;
XX mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX
XX mov al,es:[bx].rh_cmd ;Get Command Code
XX rol al,1 ;Get offset into table
XX lea di,cmdtab ;Get address of command table
XX mov ah,0 ;Clear hi order byte
XX add di,ax ;Add offset
XX jmp word ptr [di] ;Jump Indirect
XX
XX;
XX; Command Procedures
XX;
XXINITIALIZATION: cmp rh_type,TAPE_REQUEST ;Is this SCSITAPE: Init?
XX jz init_skip
XX mov al,es:[bx].rh0_drv_ltr ;Save the starting Drive
XX add al,041h
XX mov cur_drive,al
XX call initial ;Setup
XX if use_kludge
XX call patch_us_in
XX endif
XX mov bx,rh_off
XX mov es,rh_seg
XXinit_skip: lea ax,initial ;Set The Break Address
XX mov es:[bx].rh0_brk_ofs,ax
XX mov es:[bx].rh0_brk_seg,cs
XX mov al,disk_count ;Number of Disk Devices Supported
XX mov es:[bx].rh0_nunits,al
XX lea dx,bpb_array ;BPB Array
XX mov es:[bx].rh0_bpb_tbo,dx
XX mov es:[bx].rh0_bpb_tbs,cs
XX jmp done
XX
XX;
XX; Has the Media Changed
XX;
XXMEDIA_CHECK: call find_unit
XX jc mc_jmp_err
XX mov di,cur_unit
XX mov al,[di].unit_mcheck ;Get Initial Status
XX mov [di].unit_mcheck,1 ;Always OK from then on
XX mov es:[bx].rh1_md_stat,al
XX lea dx,vol_id ;Address of Volume ID
XX mov es:[bx].rh1_volid_ofs,dx
XX mov es:[bx].rh1_volid_seg,cs
XX jmp done
XXmc_jmp_err: jmp bad_unit
XX
XX;
XX; Get Disk Parameter Block
XX;
XXGET_BPB: call find_unit
XX jc get_jmp_err
XX mov dx,cur_bpb ;Address of BPB
XX mov es:[bx].rh2_pbpbo,dx
XX mov es:[bx].rh2_pbpbs,cs
XX jmp done
XXget_jmp_err: jmp bad_unit
XX
XX;
XX; Read some data from the disk/tape
XX;
XXREAD: cmp rh_type,DISK_REQUEST
XX jz read_a_disk
XX mov ax,tape_unit ;Do We Have a Tape?
XX cmp ax,-1
XX jz read_jmp_err1
XX mov cur_unit,ax
XX call tape_read
XX jc read_jmp_err2
XX jmp done
XXread_a_disk: call find_unit
XX jc read_jmp_err1
XX call disk_read
XX jc read_jmp_err2
XX jmp done
XXread_jmp_err1: jmp bad_unit
XXread_jmp_err2: jmp bad_read
XX
XX;
XX; Write some data to the disk/tape
XX;
XXWRITE equ $
XXWRITE_VERIFY: cmp rh_type,DISK_REQUEST
XX jz write_a_disk
XX mov ax,tape_unit ;Do We Have a Tape?
XX cmp ax,-1
XX jz write_jmp_err1
XX mov cur_unit,ax
XX call tape_write
XX jc write_jmp_err2
XX jmp done
XXwrite_a_disk: call find_unit
XX jc write_jmp_err1
XX call disk_write
XX jc write_jmp_err2
XX jmp done
XXwrite_jmp_err1: jmp bad_unit
XXwrite_jmp_err2: jmp bad_write
XXwrite_jmp_err3: jmp unknown
XX
XX;
XX; Write Ioctl Packet
XX;
XXWRITE_IOCTL: cmp rh_type,DISK_REQUEST
XX jz ioctl_a_disk
XX mov ax,tape_unit ;Do we have a SCSITAPE?
XX cmp ax,-1
XX jz write_jmp_err1
XX mov cur_unit,ax
XX jmp short ioctl_do
XXioctl_a_disk: call find_unit
XX jc write_jmp_err1
XXioctl_do: call scsi_ioctl_write
XX jc write_jmp_err3
XX jmp done
XX
XX;
XX; Special Control Functions
XX;
XXIOCTL: call find_unit
XX jc ioctl_jmp_err1
XX call scsi_ioctl
XX jc ioctl_jmp_err2 ;Must have been a Verify error
XX jmp done
XXioctl_jmp_err1: jmp bad_unit
XXioctl_jmp_err2: jmp bad_read
XX
XX;
XX; Open Tape Device
XX;
XXOPEN_DEV: mov di,tape_unit
XX cmp di,-1 ;Do We have a SCSITAPE: Unit?
XX jnz open_tape
XX jmp bad_unit
XXopen_tape: mov cur_unit,di ;New Current Unit
XX lea bx,[di].unit_sense ;Buffer Offset
XX push ds ;Buffer Segment
XX pop es
XX mov cx,size sense ;Buffer Size
XX lea di,cmd_sense ;Command
XX call docmd
XX jc open_err
XX cmp load_flag,TRUE ;Should we LOAD?
XX jnz open_ok
XX ife mini_inquire
XX mov di,cur_unit ;Check Unit Type
XX mov ax,word ptr [di].unit_inq_buf.inq_manufact
XX lea di,cmd_rewind ;Default to Rewind
XX cmp ax,'ET' ;If this is a TEAC Unit
XX jz open_rewind
XX endif
XX lea di,cmd_load ;Now Load Tape
XX mov [di].load_cmd_type,LOAD_TAPE
XXopen_rewind: call docmd
XX jnc open_ok
XX call scsi_sense
XXopen_err: jmp general
XXopen_ok: mov write_flag,FALSE ;No Writes Seen
XX mov read_flag,FALSE ;No Reads Seen
XX mov error_flag,FALSE ;No Error Yet
XX if use_kludge
XX mov opened_flag,TRUE ;We are Open
XX endif
XX mov ax,0 ;Patch Ourselves into
XX mov es,ax ;the INT 24 Vector
XX mov ax,es:[vect_int_24] ;Offset
XX mov word ptr orig_int_24,ax
XX lea ax,our_int_24
XX mov es:[vect_int_24],ax
XX mov ax,es:[vect_int_24+2] ;Segment
XX mov word ptr orig_int_24+2,ax
XX mov ax,cs
XX mov es:[vect_int_24+2],ax
XX jmp done
XX
XX;
XX; Close Tape Device
XX;
XXCLOSE_DEV: mov di,tape_unit
XX cmp di,-1 ;Do We have a SCSITAPE: Unit?
XX jnz close_tape
XX jmp bad_unit
XXclose_tape: mov ax,0 ;Restore
XX mov es,ax ;the INT 24 Vector
XX mov word ptr orig_int_24,ax
XX mov es:[vect_int_24],ax ;Offset
XX mov word ptr orig_int_24+2,ax
XX mov es:[vect_int_24+2],ax ;Segment
XX mov cur_unit,di ;New Current Unit
XX cmp error_flag,TRUE ;Any Tape Errors
XX jz skip_extras
XX cmp write_flag,TRUE ;Were We Writing?
XX jnz not_writing
XX lea di,cmd_twritefm ;End Tape with FM(s)
XX mov [di].fm_cmd_cnt_b0,CLOSE_FM_CNT
XX call docmd
XX jnc skip_extras
XX call get_sense
XX jmp short skip_extras
XXnot_writing: cmp read_flag,TRUE ;Were We Reading?
XX jnz skip_extras
XX cmp load_flag,TRUE ;No Rewind?
XX jz skip_extras
XX lea di,cmd_space ;Space Forward
XX mov [di].space_cmd_code,1 ;By FileMark
XX mov [di].space_cmd_cnt2,0
XX mov [di].space_cmd_cnt1,0
XX mov [di].space_cmd_cnt0,1
XX call docmd
XX jnc skip_extras
XX call get_sense
XXskip_extras: cmp load_flag,TRUE ;Should we Unload?
XX jnz close_ok
XX ife mini_inquire
XX mov di,cur_unit ;Check Unit Type
XX mov ax,word ptr [di].unit_inq_buf.inq_manufact
XX lea di,cmd_rewind
XX cmp ax,'ET' ;Rewind instead of
XX jz close_rewind ;Unload TEAC Unit
XX endif
XX lea di,cmd_load ;Now Unload Tape
XX mov [di].load_cmd_type,UNLOAD_TAPE
XXclose_rewind: call docmd
XX jnc close_ok
XX call scsi_sense
XX jmp general
XXclose_ok: jmp done
XX
XX;
XX; Get Device Assignment
XX;
XXGET_DEV: mov es:[bx].rh_unit,0
XX jmp done
XX
XX;
XX; Set Device Assignment
XX;
XXSET_DEV: jmp done
XX
XXbad_unit: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,8001h
XX jmp short done
XX
XXunknown: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,8003h
XX jmp short done
XX
XXbad_write: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,800Ah
XX jmp short done
XX
XXbad_read: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,800Bh
XX jmp short done
XX
XXgeneral: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,800Ch
XX jmp short done
XX
XXbusy: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,0200h
XX
XXdone: mov es,rh_seg ;Point us at the Request Header
XX mov bx,rh_off
XX or es:[bx].rh_status,0100h
XX
XX cli ;Make sure we're left alone
XX mov ax,cs:stack_seg ;Restore DOS Stack
XX mov ss,ax
XX mov ax,cs:stack_ptr
XX mov sp,ax
XX
XX pop bp ;Restore All Registers
XX pop di
XX pop si
XX pop dx
XX pop cx
XX pop bx
XX pop ax
XX pop es
XX pop ds
XX popf
XX ret
XX
XX INCLUDE units.asm
XX INCLUDE subs.asm
XX INCLUDE ioctl.asm
XX INCLUDE dump.asm
XX if use_kludge
XX INCLUDE kludge.asm
XX endif
XX
XX;
XX; End of Program
XX; Stuff Placed Here Gets Handed Back To DOS For Re-use
XX;
XXinitial proc near
XX lea dx,hello_msg ;Tell them the driver version
XX call puts
XX push cs
XX pop dx
XX lea bx,seg_msg_value
XX call hex2asc4
XX lea dx,seg_msg ;And Were We Loaded
XX call puts
XX
XX call scsi_reset ;Reset the bus
XX
XX mov cx,0 ;Scan for devices
XXscan: mov ax,cx
XX add al,030h
XX mov scan_dev,al
XX mov ax,1 ;Create Select Bit
XX shl ax,cl
XX mov di,cur_unit
XX mov [di].unit_select,al
XX mov [di].unit_num_drv,0 ;No Drives to start with
XX mov al,disk_count ;We will start with
XX mov [di].unit_1st_drv,al ;Drive Number if any
XX
XX lea dx,scan_dev ;Print the device number
XX call puts
XX call scsi_inquire ;Inquire as to its type
XX jnc scan_inq_ok
XX
XX lea dx,no_dev ;If the error was
XX cmp al,CNOCONNECT ;'No Such Device'
XX jz puts_jmp
XX
XX lea dx,dumb_disk_msg ;Assume it is a 'SCSI I'
XX jmp short scan_is_drv ;Old style disk
XX
XXscan_inq_ok: mov di,cur_unit
XX if mini_inquire
XX lea dx,disk_dev_msg
XX else
XX lea dx,[di].unit_inq_buf.inq_manufact
XX mov [di].unit_inq_term,'$'
XX endif
XX mov al,[di].unit_inq_buf.inq_dev_type
XX or al,al ;Look at device type
XX jz scan_is_drv
XX if mini_inquire
XX lea dx,tape_dev_msg
XX endif
XX cmp tape_unit,-1 ;Do We Already Have A Tape?
XX jnz puts_jmp
XX call puts ;Make this our SCSITAPE: Unit
XX mov tape_unit,di
XX lea dx,tape_msg
XXputs_jmp: jmp scan_puts
XX
XXscan_is_drv: call puts ;Output the Device String
XX call scsi_capacity ;Inquire as to its size
XX lea dx,err_size
XX jc scan_puts ;Do not use unknown drives
XX lea dx,crlf
XX call puts
XX
XXscan_next_drv: mov di,cur_unit
XX mov al,disk_count ;Number Of Drives Found
XX inc al
XX mov disk_count,al
XX mov al,[di].unit_num_drv ;We have a valid Drive
XX inc al
XX mov [di].unit_num_drv,al
XX mov al,cur_drive ;Get Current Drive Letter
XX mov drv_msg_let,al ;Insert it in message
XX inc al ;Bump Drive Letter
XX mov cur_drive,al
XX call make_bpb ;Setup the BPB for this drive
XX mov di,cur_bpb ;Current Working BPB
XX if large_drives
XX mov dx,[di].bpb_ts_msw
XX mov ax,[di].bpb_ts_lsw
XX else
XX mov dx,0
XX mov ax,[di].bpb_ts
XX endif
XX mov bx,2048
XX div bx
XX inc ax
XX lea bx,drv_msg_size
XX call bin_ascii
XX mov bx,bpb_hw_mark ;Get the BPB High Water Mark
XX inc bx ;Bump HW Mark for next time
XX inc bx
XX mov ax,[bx] ;Get the BPB
XX mov cur_bpb,ax ;Make it the current BPB
XX mov bpb_hw_mark,bx
XX lea dx,drv_msg
XX call puts
XX ife large_drives
XX mov bx,cur_unit
XX mov ah,0
XX mov al,[bx].unit_num_drv ;Insert Drive Offset
XX dec al ;Into BPB for this Drive
XX mov [di].bpb_hs_msw,ax
XX mov al,[bx].unit_cap_buf.cap_sectors_b3
XX or al,[bx].unit_cap_buf.cap_sectors_b2
XX or al,[bx].unit_cap_buf.cap_sectors_b1
XX or al,[bx].unit_cap_buf.cap_sectors_b0
XX jnz scan_next_drv ;Room left for another Drive
XX endif
XX jmp short scan_next
XX
XXscan_puts: call puts
XX lea dx,crlf
XX call puts
XX
XXscan_next: inc cx
XX cmp cx,MAXUNIT ;End of devices?
XX jg scan_exit
XX mov bx,cx ;Bump to next unit
XX shl bx,1
XX mov ax,word ptr unit_array[bx]
XX mov cur_unit,ax
XX jmp scan
XX
XXscan_exit: lea dx,crlf
XX call puts
XX ret
XXinitial endp
XX
XX;
XX; Data Area Used Only During Initialization
XX;
XXhello_msg db 0dh,0ah,'SCSI Device Driver Version 2.0, '
XX if oldcode
XX db '8086 Flavor',0Dh,0Ah,'$'
XX else
XX db '80286 Flavor',0Dh,0Ah,'$'
XX endif
XXseg_msg db 'Driver Loaded At Segment '
XXseg_msg_value db '0000',0dh,0ah,'$'
XXscan_dev db 'X - ','$'
XXno_dev db '(No Installed Device)$'
XXerr_size db '(Unknown Size)$'
XXdrv_msg db ' - Drive '
XXdrv_msg_let db 'X: '
XXdrv_msg_size db 'XXXXXX Meg',0dh,0ah,'$'
XXtape_msg db 0dh,0ah,' - Is The SCSITAPE: Device$'
XXdumb_disk_msg db 'UNKNOWN DUMB DISK $'
XXcrlf db 0dh,0ah,'$'
XX if mini_inquire
XXdisk_dev_msg db 'Disk Device $'
XXtape_dev_msg db 'Tape Device $'
XX endif
XX
XX
XXdev_interrupt endp
XX_TEXT ends
XX end
SHAR_EOF
if test 14291 -ne "`wc -c < 'scsi.asm'`"
then
echo shar: error transmitting "'scsi.asm'" '(should have been 14291 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'subs.asm'" '(22277 characters)'
if test -f 'subs.asm'
then
echo shar: will not over-write existing file "'subs.asm'"
else
sed 's/^XX//' > 'subs.asm' << \SHAR_EOF
XX;
XX; Data storage for local subroutines
XX;
XXcmd_ready db SCSI_TESTREADY,0,0,0,0,0
XXcmd_rewind db SCSI_REWIND,0,0,0,0,0
XXcmd_sense db SCSI_REQSENSE,0,0,0,size sense,0
XXcmd_e_sense db SCSI_REQSENSE,0,0,0,size e_sense,0
XXcmd_format db SCSI_FORMATUNIT,FORMAT_NORMAL,0,0,0,0
XXcmd_remap db SCSI_REASSIGN,0,0,0,0,0
XXcmd_space db SCSI_SPACE,1,0,0,0,0
XX if extended_io
XXcmd_read db SCSI_READBLK,0,0,0,0,0,0,0,1,0
XXcmd_write db SCSI_WRITEBLK,0,0,0,0,0,0,0,1,0
XX else
XXcmd_read db SCSI_READBLK,0,0,0,1,0
XXcmd_write db SCSI_WRITEBLK,0,0,0,1,0
XX endif
XXcmd_tread db SCSI_READBLK,1,0,0,0,0
XXcmd_twrite db SCSI_WRITEBLK,1,0,0,0,0
XXcmd_twritefm db SCSI_WRITEFM,0,0,0,CLOSE_FM_CNT,0
XXcmd_inquire db SCSI_INQUIRY,0,0,0,size inq,0
XXcmd_erase db SCSI_ERASE,1,0,0,0,0
XXcmd_load db SCSI_LOAD,0,0,0,0,0
XXcmd_capacity db SCSI_READSIZE,0,0,0,0,0,0,0,0,0
XXcmd_verify db SCSI_VERIFYBLK,0,0,0,0,0,0,0,SECT_TRACK,0
XX
XX if large_drives
XX even
XXlsect_lsw dw ?
XXlsect_msw dw ?
XX endif
XX
XX even
XXdocmd_cmd dw ?
XXdocmd_buf dw ?
XXdocmd_buf_seg dw ?
XXdocmd_len dw ?
XXdocmd_ustatus db ?
XXdocmd_estatus db ?
XXdocmd_message db ?
XX
XXsense_ustatus db ?
XXsense_estatus db ?
XXsense_message db ?
XX
XXretry_cnt db ?
XX
XX if dump_sense
XXsense_msg1 db 0dh,07h,'Unit '
XXsense_unit db 'xxh, Err '
XXsense_err db 'xxh, Stat '
XXsense_ustat db 'xxh, Msg '
XXsense_msg db 'xxh, Retry '
XXsense_retry db 'xxh$'
XXsense_msg2 db ', Sense '
XXsense_code db 'xxh, Addr '
XXsense_addr3 db 'xx'
XXsense_addr2 db 'xx'
XXsense_addr1 db 'xx'
XXsense_addr0 db 'xxh$'
XX ife monitor
XXsense_msg3 db 0dh,0ah,'$'
XX endif
XX endif
XX
XX;
XX; Reset the SCSI Bus
XX;
XXscsi_reset proc near
XX pusha
XX
XX mov ax,SCSI_CARD_SEG ;Point at the command port
XX mov es,ax
XX mov si,SCSI_CMD_PORT
XX
XX mov byte ptr es:[si],CMDBASE or CMDRST
XX call wait100us
XX mov byte ptr es:[si],CMDBASE
XX call wait100us
XX
XX popa
XX ret
XXscsi_reset endp
XX
XX;
XX; Request Sense data from a unit and display the result
XX; Called after every SCSI command with the exit code in 'al'
XX;
XXscsi_sense proc near
XX pushf
XX pusha
XX push es
XX
XX if dump_sense
XX;
XX; Print out the first part even if we can't retrieve any sense status
XX;
XX mov al,docmd_estatus ;Save for printing
XX mov sense_estatus,al
XX mov al,docmd_ustatus
XX mov sense_ustatus,al
XX mov al,docmd_message
XX mov sense_message,al
XX mov di,cur_unit
XX mov dl,[di].unit_select
XX lea bx,sense_unit ;Unit
XX call hex2asc2
XX mov dl,sense_estatus ;Error (from docmd)
XX lea bx,sense_err
XX call hex2asc2
XX mov dl,sense_ustatus ;Status (from unit)
XX lea bx,sense_ustat
XX call hex2asc2
XX mov dl,sense_message ;Msg (from unit)
XX lea bx,sense_msg
XX call hex2asc2
XX mov dl,retry_cnt ;Retry
XX lea bx,sense_retry
XX call hex2asc2
XX lea dx,sense_msg1
XX call puts
XX endif
XX
XX;
XX; Try to retrieve sense status
XX;
XX mov di,cur_unit ;Unit
XX lea bx,[di].unit_sense ;Buffer Offset
XX mov cx,size sense ;Buffer Size
XX lea dx,cmd_sense ;Command
XX cmp [di].unit_sense.sense_sense,SENSE_CCS
XX jnz no_e_sense
XX lea bx,[di].unit_e_sense ;Buffer Offset
XX mov cx,size e_sense ;Buffer Size
XX lea dx,cmd_e_sense ;Command
XXno_e_sense: push ds ;Buffer Segment
XX pop es
XX mov di,dx
XX call docmd
XX
XX if dump_sense
XX;
XX; If we got something, print it
XX;
XX jnc sense_dump
XX jmp sense_exit
XX
XXsense_dump: mov di,cur_unit
XX cmp [di].unit_sense.sense_sense,SENSE_CCS
XX jz dump_e_sense
XX
XX mov dl,[di].unit_sense.sense_sense
XX lea bx,sense_code ;Sense
XX call hex2asc2
XX mov dl,0
XX lea bx,sense_addr3
XX call hex2asc2
XX mov dl,[di].unit_sense.sense_lba_b2
XX lea bx,sense_addr2
XX call hex2asc2
XX mov dl,[di].unit_sense.sense_lba_b1
XX lea bx,sense_addr1
XX call hex2asc2
XX mov dl,[di].unit_sense.sense_lba_b0
XX lea bx,sense_addr0
XX call hex2asc2
XX jmp short sense_print
XX
XXdump_e_sense: mov dl,[di].unit_e_sense.e_sense_sense
XX lea bx,sense_code ;Sense
XX call hex2asc2
XX mov dl,[di].unit_e_sense.e_sense_lba_b3
XX lea bx,sense_addr3 ;Address
XX call hex2asc2
XX mov dl,[di].unit_e_sense.e_sense_lba_b2
XX lea bx,sense_addr2
XX call hex2asc2
XX mov dl,[di].unit_e_sense.e_sense_lba_b1
XX lea bx,sense_addr1
XX call hex2asc2
XX mov dl,[di].unit_e_sense.e_sense_lba_b0
XX lea bx,sense_addr0
XX call hex2asc2
XX
XXsense_print: lea dx,sense_msg2
XX call puts
XX endif
XX
XXsense_exit: if dump_sense
XX if monitor
XX mov cx,20000
XXsense_wait: call wait100us
XX loop sense_wait
XX else
XX lea dx,sense_msg3 ;Terminate the Message
XX call puts
XX endif
XX endif
XX
XX pop es
XX popa
XX popf
XX ret
XXscsi_sense endp
XX
XX;
XX; Get the Extended Sense Status from the current Unit
XX;
XXget_sense proc near
XX mov di,cur_unit ;Unit
XX lea bx,[di].unit_e_sense ;Buffer Offset
XX push ds ;Buffer Segment
XX pop es
XX mov cx,size e_sense ;Buffer Size
XX lea di,cmd_e_sense ;Command
XX call docmd ;Always ask first
XX ret
XXget_sense endp
XX
XX;
XX; Inquire about the type of a unit
XX;
XX; This MUST be the first call to a unit after the reset is done!
XX;
XX; al = return code, 'C' error indicates an error
XX;
XXscsi_inquire proc near
XX push cx
XX
XX;
XX; First thing we should do is wait for the unit to be ready
XX; as it takes some drives a while to spin up.
XX;
XX mov retry_cnt,READY_RETRY
XXready_loop1: lea di,cmd_ready ;Command
XX call docmd
XX jnc unit_is_ready
XX cmp al,CNOCONNECT ;No such unit?
XX jz ready_error
XX push cx
XX mov cx,10000 ;Wait 1 Second
XXready_loop2: call wait100us
XX loop ready_loop2
XX pop cx
XX dec retry_cnt ;RETRY Times
XX jns ready_loop1
XX jmp short unit_is_ready ;Still Try the Inquire
XXready_error: stc
XX jmp short inquire_exit
XX
XX;
XX; Then requests its sense status.
XX; This gives us a chance to find out if the
XX; device supports the Command Command Set (CCS)
XX;
XXunit_is_ready: call get_sense
XX jc inquire_exit
XX
XX;
XX; Ok, Now find out what kind of device it is
XX;
XX mov di,cur_unit ;Unit
XX lea bx,[di].unit_inq_buf ;Buffer Offset
XX push ds ;Buffer Segment
XX pop es
XX mov cx,size inq ;Buffer Size
XX lea di,cmd_inquire ;Command
XX call docmd
XX
XXinquire_exit: pop cx
XX ret
XXscsi_inquire endp
XX
XX;
XX; Determine the size of a disk
XX;
XX; al = return code, 'C' error indicates an error
XX;
XXscsi_capacity proc near
XX push cx
XX mov retry_cnt,MAX_RETRY
XX
XXcapacity_retry: mov di,cur_unit ;Unit
XX lea bx,[di].unit_cap_buf ;Buffer Offset
XX push ds ;Buffer Segment
XX pop es
XX mov cx,size cap ;Buffer Size
XX lea di,cmd_capacity ;Command
XX call docmd
XX jnc capacity_exit
XX call scsi_sense
XX dec retry_cnt
XX jns capacity_retry
XX stc
XX
XXcapacity_exit: pop cx
XX ret
XXscsi_capacity endp
XX
XX;
XX; Verify (cx) Sectors starting with (dx:ax)
XX;
XX; al = return code, 'C' indicates an error
XX;
XX
XXscsi_verify proc near
XX mov retry_cnt,0 ;Don't do retrys
XX lea di,cmd_verify ;Command
XX mov [di].ver_cmd_lba_b3,dh ;Insert Sector
XX mov [di].ver_cmd_lba_b2,dl ; into Command
XX mov [di].ver_cmd_lba_b1,ah ;Insert Sector
XX mov [di].ver_cmd_lba_b0,al ; into Command
XX mov [di].ver_cmd_len_b1,ch ;Insert Length
XX mov [di].ver_cmd_len_b0,cl ; into Command
XX call docmd
XX jnc verify_exit
XX call scsi_sense
XX
XXverify_exit: ret
XXscsi_verify endp
XX
XX;
XX; Read Some Blocks from the disk given
XX; the request header in es:bx
XX;
XX; al = return code, 'C' indicates an error
XX;
XXdisk_read proc near
XX mov retry_cnt,MAX_RETRY
XX
XX mov di,bx
XX mov cx,es:[di].rh4_count ;Sector Count
XX if large_drives
XX mov dx,es:[di].rh4_lsect_lsw ;Starting Sector
XX mov lsect_lsw,dx
XX mov dx,es:[di].rh4_lsect_msw
XX mov lsect_msw,dx
XX else
XX mov dx,es:[di].rh4_sector ;Starting Sector
XX endif
XX mov bx,es:[di].rh4_buf_ofs ;Buffer Offset
XX mov ax,es:[di].rh4_buf_seg ;Buffer Segment
XX mov es,ax
XX
XX mov si,cur_bpb
XX lea di,cmd_read ;Command
XX ife large_drives
XX mov ax,[si].bpb_hs_msw ;Drive Sector Offset
XX if extended_io
XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
XX endif
XX mov [di].io_cmd_lba_b2,al ;Into the Command
XX endif
XX
XX if multi_sector
XX mov ax,cx ;Get Sector Count
XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_r_cok1 ;Check for Boundary
XX mov ax,CHUNK_MAX
XX if oldcode
XXdisk_r_cok1: shl ax,1 ;Convert to Buffer Size
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX else
XXdisk_r_cok1: shl ax,9 ;Convert to Buffer Size
XX endif
XX add ax,bx ;Check for Wrap
XX else
XX mov ax,bx ;Check for Wrap
XX add ax,P_SECT ;The First Time
XX endif
XXdisk_r_loop: jnc disk_r_nowrap
XX mov ax,bx ;Normalize the
XX if oldcode
XX shr ax,1 ;Segment and
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,4 ;Segment and
XX endif
XX mov si,es ;Offset so that
XX add si,ax ;It dosn't Wrap
XX mov es,si
XX and bx,000Fh
XXdisk_r_nowrap: push cx
XX if large_drives
XX mov dx,lsect_msw
XX if extended_io
XX mov [di].io_cmd_lba_b3,dh
XX mov [di].io_cmd_lba_b2,dl
XX else
XX and dl,01Fh
XX mov [di].io_cmd_lba_b2,dl
XX endif
XX mov dx,lsect_lsw
XX endif
XX mov [di].io_cmd_lba_b1,dh ;Insert Sector
XX mov [di].io_cmd_lba_b0,dl ;Into the Command
XX if multi_sector
XX and cx,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_r_cok2 ;Check for Boundary
XX mov cx,CHUNK_MAX
XXdisk_r_cok2:
XX if extended_io
XX mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
XX endif
XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
XX if oldcode
XX shl cx,1 ;Convert to Buffer Size
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX else
XX shl cx,9 ;Convert to Buffer Size
XX endif
XX else
XX mov cx,P_SECT ;Buffer Size
XX endif
XXdisk_r_retry: call docmd
XX jnc disk_r_cok3
XX call scsi_sense
XX dec retry_cnt
XX jns disk_r_retry ;Already Setup
XX pop cx
XX stc
XX jmp short disk_r_exit
XX if multi_sector
XXdisk_r_cok3: pop cx
XX mov ax,cx ;Get Sector Count
XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_r_cok4 ;Check for Boundary
XX mov ax,CHUNK_MAX
XXdisk_r_cok4: sub cx,ax ;Dec Sector Count
XX jz disk_r_exit
XX if large_drives
XX add lsect_lsw,ax ;Bump to next Sector
XX adc lsect_msw,0
XX else
XX add dx,ax ;Bump to next Sector
XX endif
XX if oldcode
XX shl ax,1 ;Convert to Buffer Size
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX else
XX shl ax,9 ;Convert to Buffer Size
XX endif
XX add bx,ax
XX jmp disk_r_loop
XX else
XXdisk_r_cok3: pop cx
XX if large_drives
XX add lsect_lsw,1 ;Bump to next Sector
XX adc lsect_msw,0
XX else
XX inc dx ;Bump to next Sector
XX endif
XX add bx,P_SECT
XX loop disk_r_loop
XX clc
XX endif
XX
XXdisk_r_exit: mov es,rh_seg
XX mov bx,rh_off
XX pushf
XX mov ax,es:[bx].rh4_count ;Update the Count
XX sub ax,cx
XX mov es:[bx].rh4_count,ax
XX popf
XX ret
XXdisk_read endp
XX
XX;
XX; Write Some Blocks to the disk given
XX; the request header in es:bx
XX;
XX; al = return code, 'C' indicates an error
XX;
XXdisk_write proc near
XX mov retry_cnt,MAX_RETRY
XX
XX mov di,bx
XX mov cx,es:[di].rh8_count ;Sector Count
XX if large_drives
XX mov dx,es:[di].rh8_lsect_lsw ;Starting Sector
XX mov lsect_lsw,dx
XX mov dx,es:[di].rh8_lsect_msw
XX mov lsect_msw,dx
XX else
XX mov dx,es:[di].rh8_sector ;Starting Sector
XX endif
XX mov bx,es:[di].rh8_buf_ofs ;Buffer Offset
XX mov ax,es:[di].rh8_buf_seg ;Buffer Segment
XX mov es,ax
XX
XX mov si,cur_bpb
XX lea di,cmd_write ;Command
XX ife large_drives
XX mov ax,[si].bpb_hs_msw ;Drive Sector Offset
XX if extended_io
XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
XX endif
XX mov [di].io_cmd_lba_b2,al ;Into the Command
XX endif
XX
XX if multi_sector
XX mov ax,cx ;Get Sector Count
XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_w_cok1 ;Check for Boundary
XX mov ax,CHUNK_MAX
XX if oldcode
XXdisk_w_cok1: shl ax,1 ;Convert to Buffer Size
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX else
XXdisk_w_cok1: shl ax,9 ;Convert to Buffer Size
XX endif
XX add ax,bx ;Check for Wrap
XX else
XX mov ax,bx ;Check for Wrap
XX add ax,P_SECT ;The First Time
XX endif
XXdisk_w_loop: jnc disk_w_nowrap
XX mov ax,bx ;Normalize the
XX if oldcode
XX shr ax,1 ;Segment and
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,4 ;Segment and
XX endif
XX mov si,es ;Offset so that
XX add si,ax ;It dosn't Wrap
XX mov es,si
XX and bx,000Fh
XXdisk_w_nowrap: push cx
XX if large_drives
XX mov dx,lsect_msw
XX if extended_io
XX mov [di].io_cmd_lba_b3,dh
XX mov [di].io_cmd_lba_b2,dl
XX else
XX and dl,01Fh
XX mov [di].io_cmd_lba_b2,dl
XX endif
XX mov dx,lsect_lsw
XX endif
XX mov [di].io_cmd_lba_b1,dh ;Insert Sector
XX mov [di].io_cmd_lba_b0,dl ;Into the Command
XX if multi_sector
XX and cx,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_w_cok2 ;Check for Boundary
XX mov cx,CHUNK_MAX
XXdisk_w_cok2:
XX if extended_io
XX mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
XX endif
XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
XX if oldcode
XX shl cx,1 ;Convert to Buffer Size
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX shl cx,1
XX else
XX shl cx,9 ;Convert to Buffer Size
XX endif
XX else
XX mov cx,P_SECT ;Buffer Size
XX endif
XXdisk_w_retry: call docmd
XX jnc disk_w_cok3
XX call scsi_sense
XX dec retry_cnt
XX jns disk_w_retry ;Already Setup
XX pop cx
XX stc
XX jmp short disk_w_exit
XX if multi_sector
XXdisk_w_cok3: pop cx
XX mov ax,cx ;Get Sector Count
XX and ax,CHUNK_MAX-1 ;Mask Off the I/O Chunk
XX jnz disk_w_cok4 ;Check for Boundary
XX mov ax,CHUNK_MAX
XXdisk_w_cok4: sub cx,ax ;Dec Sector Count
XX jz disk_w_exit
XX if large_drives
XX add lsect_lsw,ax ;Bump to next Sector
XX adc lsect_msw,0
XX else
XX add dx,ax ;Bump to next Sector
XX endif
XX if oldcode
XX shl ax,1 ;Convert to Buffer Size
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX shl ax,1
XX else
XX shl ax,9 ;Convert to Buffer Size
XX endif
XX add bx,ax
XX jmp disk_w_loop
XX else
XXdisk_w_cok3: pop cx
XX if large_drives
XX add lsect_lsw,1 ;Bump to next Sector
XX adc lsect_msw,0
XX else
XX inc dx ;Bump to next Sector
XX endif
XX add bx,P_SECT
XX loop disk_w_loop
XX clc
XX endif
XX
XXdisk_w_exit: mov es,rh_seg
XX mov bx,rh_off
XX pushf
XX mov ax,es:[bx].rh8_count ;Update the Count
XX sub ax,cx
XX mov es:[bx].rh8_count,ax
XX popf
XX ret
XXdisk_write endp
XX
XX;
XX; Read Some Blocks from the Tape
XX;
XXtape_read proc near
XX mov read_flag,TRUE ;Data Read from Tape
XX mov di,bx
XX mov cx,es:[di].rh4_count ;Byte Count
XX mov ax,cx ;Test for invalid
XX and ax,P_SECT-1 ;Byte Count
XX jz tape_r_valid
XX mov error_flag,TRUE
XX mov es:[di].rh4_count,0 ;Nothing Read
XX stc ;Oops
XX ret
XXtape_r_valid: mov bx,es:[di].rh4_buf_ofs ;Buffer Offset
XX mov ax,es:[di].rh4_buf_seg ;Buffer Segment
XX mov es,ax
XX mov ax,bx ;Normalize the
XX if oldcode
XX shr ax,1 ;Segment and
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,4 ;Segment and
XX endif
XX mov si,es ;Offset so that
XX add si,ax ;It dosn't Wrap
XX mov es,si
XX and bx,000Fh
XX lea di,cmd_tread
XX mov ax,cx ;Convert Bytes
XX if oldcode
XX shr ax,1 ;to Blocks
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,9 ;to Blocks
XX endif
XX mov [di].tio_cmd_cnt_b1,ah ;Insert into Command
XX mov [di].tio_cmd_cnt_b0,al
XX call docmd
XX jnc tape_r_ok
XX;
XX; Get the Extended Sense Status to check for reading FileMark
XX;
XX call get_sense ;Get Extended Sense
XX jc tape_r_kaboom
XX mov di,cur_unit ;Unit
XX cmp [di].unit_e_sense.e_sense_sense,80h
XX jnz tape_r_eom
XXtape_r_kaboom: mov error_flag,TRUE ;Real Error Occured
XX stc
XX ret
XXtape_r_eom: mov es,rh_seg
XX mov bx,rh_off
XX mov es:[bx].rh4_count,0 ;Nothing Read
XX clc
XXtape_r_ok: ret
XXtape_read endp
XX
XX;
XX; Write Some Blocks to the Tape
XX;
XXtape_write proc near
XX mov write_flag,TRUE ;Data Written to Tape
XX mov di,bx
XX mov cx,es:[di].rh8_count ;Byte Count
XX mov ax,cx ;Test for invalid
XX and ax,P_SECT-1 ;Byte Count
XX jz tape_w_valid
XX mov es:[di].rh8_count,0 ;Nothing Written
XX mov error_flag,TRUE ;ERROR!
XX stc ;Oops
XX ret
XXtape_w_valid: mov cx,es:[di].rh8_count ;Byte Count
XX mov bx,es:[di].rh8_buf_ofs ;Buffer Offset
XX mov ax,es:[di].rh8_buf_seg ;Buffer Segment
XX mov es,ax
XX mov ax,bx ;Normalize the
XX if oldcode
XX shr ax,1 ;Segment and
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,4 ;Segment and
XX endif
XX mov si,es ;Offset so that
XX add si,ax ;It dosn't Wrap
XX mov es,si
XX and bx,000Fh
XX lea di,cmd_twrite
XX mov ax,cx ;Convert Bytes
XX if oldcode
XX shr ax,1 ;to Blocks
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX shr ax,1
XX else
XX shr ax,9 ;to Blocks
XX endif
XX mov [di].tio_cmd_cnt_b1,ah ;Insert into Command
XX mov [di].tio_cmd_cnt_b0,al
XX call docmd
XX jnc tape_w_ok
XX;
XX; Get the Sense Status and see if we hit EOM.
XX; This is to allow the FileMark to still be written
XX; during the close processing.
XX;
XX call get_sense ;Get Extended Sense
XX jc tape_w_kaboom
XX mov di,cur_unit ;Unit
XX cmp [di].unit_e_sense.e_sense_sense,40h
XX jz tape_w_eom
XXtape_w_kaboom: mov error_flag,TRUE ;Real Error Occured
XX mov es,rh_seg
XX mov bx,rh_off
XX mov es:[bx].rh8_count,0 ;Nothing Written
XXtape_w_eom: stc
XXtape_w_ok: ret
XXtape_write endp
XX
XX;
XX; Do a command
XX;
XX; bx = buffer offset
XX; es = buffer segment
XX; cx = buffer len
XX; di => command string
XX;
XX; al = return code, 'C' indicates an error
XX;
XXdocmd proc near
XX pusha
XX push es
XX
XX mov docmd_buf,bx ;Save our arguments
XX mov docmd_buf_seg,es
XX mov docmd_len,cx
XX mov docmd_cmd,di
XX mov docmd_ustatus,0FFh
XX
XX if monitor
XX mov ax,'F' ;Arbitrate for Bus
XX call show_phase
XX endif
XX
XX mov ax,SCSI_CARD_SEG ;Point at the Card
XX mov es,ax
XX mov si,SCSI_CMD_PORT ;Command Port
XX mov di,SCSI_DATA_PORT ;Data Port
XX mov bx,cur_unit
XX mov al,[bx].unit_select ;Get our Select Bit
XX
XX if reserve_addr
XX;
XX; Get us control of the BUS by starting Arbitration
XX; Wait a maximum of 250ms for Control of the Bus
XX;
XX or al,080h ;Add our Address
XX mov byte ptr es:[si],CMDBASE
XX nop
XX mov byte ptr es:[di],080h ;Our Address
XX nop
XX mov byte ptr es:[si],CMDBASE or CMDSTARB
XX mov cx,2500
XXarb_loop: test byte ptr es:[si],STARBCOMPL
XX jnz try_sel
XX call wait100us
XX loop arb_loop
XX else
XX;
XX; Wait 250ms for the Bus to become free
XX;
XX mov cx,2500
XXidle_loop: test byte ptr es:[si],STBSY ;Busy?
XX jz try_sel
XX call wait100us
XX loop idle_loop
XX endif
XX
XX call scsi_reset
XX mov al,CBUSBUSY ;Bus still BUSY?
XX jmp docmd_exit
XX
XXtry_sel: mov byte ptr es:[di],al ;Select Bit
XX nop
XX mov byte ptr es:[si],CMDBASE or CMDENABLE or CMDSEL
XX
XX if monitor
XX mov ax,'S' ;Select Target
XX call show_phase
XX endif
XX
XX;
XX; Wait 250 ms for the Target to be SELected
XX;
XX mov cx,2500
XXsel_loop: test byte ptr es:[si],STBSY ;Wait for BSY
XX jnz cmd_xfer
XX call wait100us
XX loop sel_loop
XX
XX if monitor
XX mov ax,'A' ;Abort Selection
XX call show_phase
XX endif
XX
XX mov byte ptr es:[si],CMDBASE or CMDSEL
XX call wait100us ;Spec says wait 200us
XX call wait100us ;to abort selection phase
XX test byte ptr es:[si],STBSY ;Look one final time
XX jnz cmd_xfer ;Device did answer
XX mov al,CNOCONNECT ;Nothing Answered
XX jmp docmd_exit
XX
XX;
XX; Start the Command, (al) contains last known status
XX;
XXcmd_xfer: mov byte ptr es:[si],CMDBASE or CMDENABLE
XX nop
XXxfer_loop: mov al,es:[si] ;Get Status Byte
XX test al,STBSY ;Look for BSY bit
XX jnz still_busy
XX jmp xfer_offline
XX if scsi_parity
XXstill_busy: test al,STPARERR ;Parity Error?
XX jz still_good
XX jmp xfer_parerr
XXstill_good: test al,STREQ ;Request?
XX jz xfer_loop
XX else
XXstill_busy: test al,STREQ ;Request?
XX jz xfer_loop
XX endif
XX
XX;
XX; Figure out what type of request it is
XX;
XX and al,REQ_MASK
XX cmp al,REQ_CMDOUT ;Is it Command Out?
XX jnz try_dataout
XX
XX if monitor
XX mov ax,'C' ;Command
XX call show_phase
XX endif
XX
XX mov si,docmd_cmd ;Get Command Pointer
XX movsb ;Send Byte to Card
XX mov docmd_cmd,si
XX mov si,SCSI_CMD_PORT ;Restore Command Port
XX mov di,SCSI_DATA_PORT ;Restore Data Port
XX jmp xfer_loop
XX
XXtry_dataout: cmp al,REQ_DATAOUT ;Is it Data Out?
XX jnz try_datain
XX
XX if monitor
XX mov ax,'W' ;Write
XX call show_phase
XX endif
XX
XX mov bx,si
XX mov cx,docmd_len ;Get the Data Count
XX mov si,docmd_buf ;Source Offset
XX mov ds,docmd_buf_seg ;Source Segment
XX cld
XX
XXdataout_loop: test byte ptr es:[bx],STBSY ;Must be BUSY
XX jz dataout_exit
XX test byte ptr es:[bx],STREQ ;Wait for REQ
XX jz dataout_loop
XX movsb ;Transfer a Byte
XX dec di ;Keep in Valid
XX loop dataout_loop ;Done Yet?
XX
XXdataout_exit: mov si,bx ;Restore the Environment
XX mov ax,cs
XX mov ds,ax
XX jmp xfer_loop
XX
XXtry_datain: cmp al,REQ_DATAIN ;Is it Data In?
XX jnz try_statin
XX
XX if monitor
XX mov ax,'R' ;Read
XX call show_phase
XX endif
XX
XX mov bx,si
XX mov si,di ;Source Offset
XX mov ax,es
XX mov cx,docmd_len ;Length
XX mov di,docmd_buf ;Dest Offset
XX mov es,docmd_buf_seg ;Dest Segment
XX mov ds,ax ;Source Segment
XX cld
XX
XXdatain_loop: test byte ptr [bx],STBSY ;Must be BUSY
XX jz datain_exit
XX test byte ptr [bx],STREQ ;Wait for REQ
XX jz datain_loop
XX movsb ;Transfer a Byte
XX dec si ;Keep in Valid
XX loop datain_loop ;Done Yet?
XX
XXdatain_exit: mov ax,ds ;Restore the Environment
XX mov es,ax
XX mov ax,cs
XX mov ds,ax
XX mov di,si
XX mov si,bx
XX jmp xfer_loop
XX
XXtry_statin: cmp al,REQ_STATIN ;Is it Status In?
XX jnz try_msgout
XX
XX if monitor
XX mov ax,'s' ;Status
XX call show_phase
XX endif
XX
XX mov al,es:[di] ;Get the Status Byte
XX mov docmd_ustatus,al
XX jmp xfer_loop
XX
XXtry_msgout: cmp al,REQ_MSGOUT ;Is it Message Out?
XX jnz try_msgin
XX
XX if monitor
XX mov ax,'M' ;Message Out
XX call show_phase
XX endif
XX
XX mov byte ptr es:[di],MSG_REJECT
XX jmp xfer_loop
XX
XXtry_msgin: cmp al,REQ_MSGIN ;Is it Message In?
XX jnz kaboom
XX
XX if monitor
XX mov ax,'m' ;Message In
XX call show_phase
XX endif
XX
XX mov al,es:[di] ;Get the MSG Byte
XX mov docmd_message,al ;And Save it
XX cmp al,MSG_COMPLETE ;Are We All Done?
XX jnz xfer_error
XX cmp docmd_ustatus,0 ;Did we have an error?
XX mov al,COK ;Preload OK code
XX jz docmd_exit
XX jmp xfer_error ;Oops
XX
XXkaboom: call scsi_reset ;Reset the BUS
XX
XX if monitor
XX mov ax,'?' ;Message In
XX call show_phase
XX endif
XX
XXxfer_error: mov al,CERROR ;Command Failed with Bad Status
XX jmp short docmd_exit
XXxfer_offline: mov al,COFFLINE ;Unit went OffLine
XX jmp short docmd_exit
XXxfer_parerr: mov al,CPARERR ;Parity Error Detected
XX jmp short docmd_exit
XXxfer_selerr: mov al,CSELERR ;Re-Select?
XX
XXdocmd_exit: mov docmd_estatus,al
XX mov byte ptr es:[si],CMDBASE
XX pop es
XX popa
XX mov al,docmd_estatus
XX cmp al,COK
XX jz docmd_exit_ok
XX stc
XXdocmd_exit_ok: ret
XXdocmd endp
XX
XX;
XX; Wait One Hundred Micros Seconds
XX;
XX; The value of 'cx' is computed for an 8 Mhz Clock
XX;
XXwait100us proc near
XX push cx ; (3) = 375ns
XX mov cx,79 ; (2) = 250ns
XXwait_u_loop: loop wait_u_loop ; (10) = 1250ns * X
XX pop cx ; (5) = 625ns
XX ret ; (11+) = 1375ns
XXwait100us endp
XX
XX;
XX; Monitor the Bus Phase on the Video Screen
XX;
XX if monitor
XXshow_phase proc
XX push es
XX push di
XX or ax,VIDEO_COLOR
XX mov di,VIDEO_SEG
XX mov es,di
XX mov di,VIDEO_OFS
XX stosw
XX pop di
XX pop es
XX ret
XXshow_phase endp
XX endif
SHAR_EOF
if test 22277 -ne "`wc -c < 'subs.asm'`"
then
echo shar: error transmitting "'subs.asm'" '(should have been 22277 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'units.asm'" '(3996 characters)'
if test -f 'units.asm'
then
echo shar: will not over-write existing file "'units.asm'"
else
sed 's/^XX//' > 'units.asm' << \SHAR_EOF
XX;
XX; target information/control structures
XX;
XX even
XXunit0 db size unit dup (-1)
XX even
XXunit1 db size unit dup (-1)
XX even
XXunit2 db size unit dup (-1)
XX even
XXunit3 db size unit dup (-1)
XX even
XXunit4 db size unit dup (-1)
XX even
XXunit5 db size unit dup (-1)
XX even
XXunit6 db size unit dup (-1)
XX ife reserve_addr
XX even
XXunit7 db size unit dup (-1)
XX endif
XX
XX;
XX; basic BPB array
XX;
XX even
XXbpb0 db size bpb dup (-1)
XX even
XXbpb1 db size bpb dup (-1)
XX even
XXbpb2 db size bpb dup (-1)
XX even
XXbpb3 db size bpb dup (-1)
XX even
XXbpb4 db size bpb dup (-1)
XX even
XXbpb5 db size bpb dup (-1)
XX even
XXbpb6 db size bpb dup (-1)
XX even
XXbpb7 db size bpb dup (-1)
XX
XX;
XX; Additional entries if needed
XX;
XX ife large_drives
XX even
XXbpb8 db size bpb dup (-1)
XX even
XXbpb9 db size bpb dup (-1)
XX even
XXbpbA db size bpb dup (-1)
XX even
XXbpbB db size bpb dup (-1)
XX even
XXbpbC db size bpb dup (-1)
XX even
XXbpbD db size bpb dup (-1)
XX even
XXbpbE db size bpb dup (-1)
XX even
XXbpbF db size bpb dup (-1)
XX endif
XX
XX even
XXunit_array dw unit0
XX dw unit1
XX dw unit2
XX dw unit3
XX dw unit4
XX dw unit5
XX dw unit6
XX ife reserve_addr
XX dw unit7
XX endif
XX
XX even
XXbpb_array dw bpb0 ;BPB Array for DOS
XX dw bpb1
XX dw bpb2
XX dw bpb3
XX dw bpb4
XX dw bpb5
XX dw bpb6
XX dw bpb7
XX ife large_drives
XX dw bpb8
XX dw bpb9
XX dw bpbA
XX dw bpbB
XX dw bpbC
XX dw bpbD
XX dw bpbE
XX dw bpbF
XX endif
XXbpb_hw_mark dw bpb_array
XX
XXtape_unit dw -1
XXcur_unit dw unit0
XXcur_bpb dw bpb0
XX
XX;
XX; Given the request header in es:bx
XX; Return a pointer in ds:di to the unit entry
XX; or 'C' if no such unit exists.
XX;
XX; Do not destroy es:bx !!!
XX;
XXfind_unit proc near
XX pusha
XX mov ah,es:[bx].rh_unit ;What drive did they want
XX lea di,unit_array
XX lea si,bpb_array
XX mov cx,MAXUNIT ;How many to search
XXfind_loop: mov bx,[di] ;Point at a unit
XX mov al,[bx].unit_num_drv ;Does this SCSI device
XX or al,al ;Have any Drives Defined?
XX jz find_next
XX mov dh,[bx].unit_1st_drv ;Get First Drive Number
XXfind_unit_loop: cmp ah,dh ;Is this the correct drive?
XX jz find_match
XX inc si ;Bump to next BPB
XX inc si
XX ife large_drives
XX inc dh ;Bump Drive Number
XX dec al ;Dec Drive count
XX jnz find_unit_loop ;Try next Drive
XX endif
XX jmp short find_next ;Try next SCSI device
XXfind_match: mov cur_unit,bx ;Found a match
XX mov ax,[si]
XX mov cur_bpb,ax
XX clc
XX jmp find_exit
XXfind_next: inc di
XX inc di
XX loop find_loop
XX stc ;No More units, Error
XXfind_exit: popa
XX ret
XXfind_unit endp
XX
XX;
XX; Given the data in a unit entry,
XX; create the bpb for the unit.
XX;
XXmake_bpb proc near
XX mov di,cur_bpb ;Get the current BPB
XX mov bx,cur_unit ;Get the current Unit
XX;
XX; First the basic stuff
XX;
XX mov [di].bpb_ss,P_SECT
XX mov [di].bpb_au,CLUSTSIZE
XX mov [di].bpb_rs,1
XX mov [di].bpb_nf,2
XX mov [di].bpb_de,512
XX mov [di].bpb_st,SECT_TRACK
XX mov [di].bpb_nh,1
XX mov [di].bpb_hs_lsw,0
XX mov [di].bpb_hs_msw,0
XX mov [di].bpb_md,0F8h
XX;
XX; then the size and fat sectors
XX;
XX mov dh,[bx].unit_cap_buf.cap_sectors_b3
XX mov dl,[bx].unit_cap_buf.cap_sectors_b2
XX mov ah,[bx].unit_cap_buf.cap_sectors_b1
XX mov al,[bx].unit_cap_buf.cap_sectors_b0
XX if large_drives
XX mov [di].bpb_ts,0 ;(32 bit size)
XX and ax,ROUND_CYL ;Round to nearest Cyl
XX mov [di].bpb_ts_lsw,ax
XX mov [di].bpb_ts_msw,dx
XX sub [di].bpb_ts_lsw,1 ;Make it zero relative
XX sbb [di].bpb_ts_msw,0
XX mov bx,P_SECT ;Figure out how many
XX div bx ;sectors it will take
XX mov dx,0 ;to hold the FAT for
XX mov bx,CLUSTSIZE ;this drive.
XX div bx
XX mov dx,0
XX mov bx,2
XX mul bx
XX else
XX or dx,dx
XX jz make_bpb_last ;Use up the last few sectors
XX dec dx ;Use up 65536 Sectors
XX mov [bx].unit_cap_buf.cap_sectors_b3,dh
XX mov [bx].unit_cap_buf.cap_sectors_b2,dl
XX mov dx,0 ;Max of 32 Meg
XX mov ax,65535
XX jmp short make_bpb_ts
XXmake_bpb_last: mov [bx].unit_cap_buf.cap_sectors_b1,0
XX mov [bx].unit_cap_buf.cap_sectors_b0,0
XX and ax,ROUND_CYL ;Round to nearest Cyl
XX dec ax ;Make it zero relative
XXmake_bpb_ts: mov [di].bpb_ts,ax
XX shr ax,SECT_2_FS
XX endif
XX inc ax ;Allow for round-off
XX mov [di].bpb_fs,ax
XX ret
XXmake_bpb endp
SHAR_EOF
if test 3996 -ne "`wc -c < 'units.asm'`"
then
echo shar: error transmitting "'units.asm'" '(should have been 3996 characters)'
fi
fi # end of overwriting check
#
# End of shell archive
#
exit 0
--
Brian Antoine |
ISC-Bunker Ramo | ...uunet!isc-br!tau-ceti!briana
Spokane, WA | briana@tau-ceti.isc-br.com
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.