home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
165
/
ST0102.ZIP
/
SCSI.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-11-28
|
15KB
|
656 lines
;
; Simple SCSI Device Driver
;
PAGE 60,85
INCLUDE options.inc
INCLUDE equ.inc
INCLUDE struct.inc
ife oldcode
.286
else
.8086
pusha macro
push ax
push bx
push cx
push dx
push si
push di
endm
popa macro
pop di
pop si
pop dx
pop cx
pop bx
pop ax
endm
endif
;
; Start of Code and Data
;
_TEXT segment word public 'CODE'
assume cs:_TEXT, ds:_TEXT, es:_TEXT
org 0
;
; Device Header Required By DOS
;
scsi:
tape_link_ofs dw disk_link_ofs ;Forward Link
tape_link_seg dw -1
dw 0C800h ;Char Device
dw tape_strategy ;Address of 1st DOS Call
dw dev_interrupt ;Address of 2nd DOS Call
db 'SCSITAPE' ;Device Name
disk_link_ofs dw -1 ;Forward Link
disk_link_seg dw -1
if large_drives
dw 06042h ;Ioctl R/W, Block Device, Non-IBM, Get/Set, 32 bit
else
dw 06040h ;Ioctl R/W, Block Device, Non-IBM, Get/Set
endif
dw disk_strategy ;Address of 1st DOS Call
dw dev_interrupt ;Address of 2nd DOS Call
disk_count db 0 ;Number of Disks Present
db 7 dup(?)
;
; Work Space For Our Device Driver
;
even
rh_off dw ? ;Request Header Offset
rh_seg dw ? ;Request Header Segment
rh_type db ? ;Request Type
write_flag db FALSE ;TRUE When Tape Write Seen
read_flag db FALSE ;TRUE When Tape Read Seen
error_flag db FALSE ;TRUE When Tape Error Seen
load_flag db TRUE ;TRUE When Tape should Load/Unload
cur_drive db -1
vol_id db 'NO NAME ',0
;
; The Original INT 24 Vector
;
vect_int_24 equ word ptr 4 * 24h
orig_int_24 dd ? ;Original INT 24 Vector
;
; Define our own personal Stack
;
even
new_stack db STACK_SIZE-2 dup (?) ;Our Local Stack
new_stack_top dw ?
stack_ptr dw ? ;Old Stack Pointer
stack_seg dw ? ;Old Stack Segment
;
; Command Table
;
cmdtab label byte ;* = Char Only Devices
dw INITIALIZATION ;Initialization
dw MEDIA_CHECK ;Media Check (Block Only)
dw GET_BPB ;Build BPB (Block Only)
dw unknown ;IOCTL Read
dw READ ;Read Data
dw done ;*Non Destructive Read
dw done ;*Read Status
dw done ;*Flush Read Buffer
dw WRITE ;Write Data
dw WRITE_VERIFY ;Write With Verify
dw done ;*Write Status
dw done ;*Flush Write Buffer
dw WRITE_IOCTL ;IOCTL Write
dw OPEN_DEV ;Device Open
dw CLOSE_DEV ;Device Close
dw done ;Removable Check
dw unknown ;*Write Until Busy
dw unknown ;Unknown Call
dw unknown ;Unknown Call
dw IOCTL ;Generic Ioctl
dw unknown ;Unknown Call
dw unknown ;Unknown Call
dw unknown ;Unknown Call
dw GET_DEV ;Get Device
dw SET_DEV ;Set Device
;
; Int 24 (Fatal Error Handler)
;
; The test for our tape device only works because the
; device header for the tape is located at the start
; of the driver binary.
;
our_int_24 proc far
push ax
mov ax,cs ;Is it our Segment
cmp bp,ax
jnz not_our_tape
cmp si,0 ;Is it the Tape Device
jnz not_our_tape
pop ax
mov al,3 ;Fail the System Call
iret
not_our_tape: pop ax
jmp cs:orig_int_24 ;Pass the Request On
our_int_24 endp
;
; Strategy Procedure
;
disk_strategy proc far
mov cs:rh_seg,es ;Save Request Header Ptr Segment
mov cs:rh_off,bx ;Save Request Header Ptr Offset
mov cs:rh_type,DISK_REQUEST
ret
disk_strategy endp
tape_strategy proc far
mov cs:rh_seg,es ;Save Request Header Ptr Segment
mov cs:rh_off,bx ;Save Request Header Ptr Offset
mov cs:rh_type,TAPE_REQUEST
ret
tape_strategy endp
;
; Interrupt Procedure
;
dev_interrupt proc far
pushf ;Save Machine State On Entry
cli
push ds
push es
push ax
push bx
push cx
push dx
push si
push di
push bp
mov cs:stack_seg,ss ;Save Old Stack
mov cs:stack_ptr,sp
mov ax,cs ;Save us the Segment Override Crap
mov ds,ax
mov es,ax
mov ss,ax ;Setup Our Local Stack
lea ax,new_stack_top
mov sp,ax
sti ;We're Safe Now
;
; Perform branch based on the command passed in the Request Header
;
mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
mov al,es:[bx].rh_cmd ;Get Command Code
rol al,1 ;Get offset into table
lea di,cmdtab ;Get address of command table
mov ah,0 ;Clear hi order byte
add di,ax ;Add offset
jmp word ptr [di] ;Jump Indirect
;
; Command Procedures
;
INITIALIZATION: cmp rh_type,TAPE_REQUEST ;Is this SCSITAPE: Init?
jz init_skip
mov al,es:[bx].rh0_drv_ltr ;Save the starting Drive
add al,041h
mov cur_drive,al
call initial ;Setup
if use_kludge
call patch_us_in
endif
mov bx,rh_off
mov es,rh_seg
init_skip: lea ax,initial ;Set The Break Address
mov es:[bx].rh0_brk_ofs,ax
mov es:[bx].rh0_brk_seg,cs
mov al,disk_count ;Number of Disk Devices Supported
mov es:[bx].rh0_nunits,al
lea dx,bpb_array ;BPB Array
mov es:[bx].rh0_bpb_tbo,dx
mov es:[bx].rh0_bpb_tbs,cs
jmp done
;
; Has the Media Changed
;
MEDIA_CHECK: call find_unit
jc mc_jmp_err
mov di,cur_unit
mov al,[di].unit_mcheck ;Get Initial Status
mov [di].unit_mcheck,1 ;Always OK from then on
mov es:[bx].rh1_md_stat,al
lea dx,vol_id ;Address of Volume ID
mov es:[bx].rh1_volid_ofs,dx
mov es:[bx].rh1_volid_seg,cs
jmp done
mc_jmp_err: jmp bad_unit
;
; Get Disk Parameter Block
;
GET_BPB: call find_unit
jc get_jmp_err
mov dx,cur_bpb ;Address of BPB
mov es:[bx].rh2_pbpbo,dx
mov es:[bx].rh2_pbpbs,cs
jmp done
get_jmp_err: jmp bad_unit
;
; Read some data from the disk/tape
;
READ: cmp rh_type,DISK_REQUEST
jz read_a_disk
mov ax,tape_unit ;Do We Have a Tape?
cmp ax,-1
jz read_jmp_err1
mov cur_unit,ax
call tape_read
jc read_jmp_err2
jmp done
read_a_disk: call find_unit
jc read_jmp_err1
call disk_read
jc read_jmp_err2
jmp done
read_jmp_err1: jmp bad_unit
read_jmp_err2: jmp bad_read
;
; Write some data to the disk/tape
;
WRITE equ $
WRITE_VERIFY: cmp rh_type,DISK_REQUEST
jz write_a_disk
mov ax,tape_unit ;Do We Have a Tape?
cmp ax,-1
jz write_jmp_err1
mov cur_unit,ax
call tape_write
jc write_jmp_err2
jmp done
write_a_disk: call find_unit
jc write_jmp_err1
call disk_write
jc write_jmp_err2
jmp done
write_jmp_err1: jmp bad_unit
write_jmp_err2: jmp bad_write
write_jmp_err3: jmp unknown
;
; Write Ioctl Packet
;
WRITE_IOCTL: cmp rh_type,DISK_REQUEST
jz ioctl_a_disk
mov ax,tape_unit ;Do we have a SCSITAPE?
cmp ax,-1
jz write_jmp_err1
mov cur_unit,ax
jmp short ioctl_do
ioctl_a_disk: call find_unit
jc write_jmp_err1
ioctl_do: call scsi_ioctl_write
jc write_jmp_err3
jmp done
;
; Special Control Functions
;
IOCTL: call find_unit
jc ioctl_jmp_err1
call scsi_ioctl
jc ioctl_jmp_err2 ;Must have been a Verify error
jmp done
ioctl_jmp_err1: jmp bad_unit
ioctl_jmp_err2: jmp bad_read
;
; Open Tape Device
;
OPEN_DEV: mov di,tape_unit
cmp di,-1 ;Do We have a SCSITAPE: Unit?
jnz open_tape
jmp bad_unit
open_tape: mov cur_unit,di ;New Current Unit
lea bx,[di].unit_sense ;Buffer Offset
push ds ;Buffer Segment
pop es
mov cx,size sense ;Buffer Size
lea di,cmd_sense ;Command
call docmd
jc open_err
cmp load_flag,TRUE ;Should we LOAD?
jnz open_ok
ife mini_inquire
mov di,cur_unit ;Check Unit Type
mov ax,word ptr [di].unit_inq_buf.inq_manufact
lea di,cmd_rewind ;Default to Rewind
cmp ax,'ET' ;If this is a TEAC Unit
jz open_rewind
endif
lea di,cmd_load ;Now Load Tape
mov [di].load_cmd_type,LOAD_TAPE
open_rewind: call docmd
jnc open_ok
call scsi_sense
open_err: jmp general
open_ok: mov write_flag,FALSE ;No Writes Seen
mov read_flag,FALSE ;No Reads Seen
mov error_flag,FALSE ;No Error Yet
if use_kludge
mov opened_flag,TRUE ;We are Open
endif
mov ax,0 ;Patch Ourselves into
mov es,ax ;the INT 24 Vector
mov ax,es:[vect_int_24] ;Offset
mov word ptr orig_int_24,ax
lea ax,our_int_24
mov es:[vect_int_24],ax
mov ax,es:[vect_int_24+2] ;Segment
mov word ptr orig_int_24+2,ax
mov ax,cs
mov es:[vect_int_24+2],ax
jmp done
;
; Close Tape Device
;
CLOSE_DEV: mov di,tape_unit
cmp di,-1 ;Do We have a SCSITAPE: Unit?
jnz close_tape
jmp bad_unit
close_tape: mov ax,0 ;Restore
mov es,ax ;the INT 24 Vector
mov word ptr orig_int_24,ax
mov es:[vect_int_24],ax ;Offset
mov word ptr orig_int_24+2,ax
mov es:[vect_int_24+2],ax ;Segment
mov cur_unit,di ;New Current Unit
cmp error_flag,TRUE ;Any Tape Errors
jz skip_extras
cmp write_flag,TRUE ;Were We Writing?
jnz not_writing
lea di,cmd_twritefm ;End Tape with FM(s)
mov [di].fm_cmd_cnt_b0,CLOSE_FM_CNT
call docmd
jnc skip_extras
call get_sense
jmp short skip_extras
not_writing: cmp read_flag,TRUE ;Were We Reading?
jnz skip_extras
cmp load_flag,TRUE ;No Rewind?
jz skip_extras
lea di,cmd_space ;Space Forward
mov [di].space_cmd_code,1 ;By FileMark
mov [di].space_cmd_cnt2,0
mov [di].space_cmd_cnt1,0
mov [di].space_cmd_cnt0,1
call docmd
jnc skip_extras
call get_sense
skip_extras: cmp load_flag,TRUE ;Should we Unload?
jnz close_ok
ife mini_inquire
mov di,cur_unit ;Check Unit Type
mov ax,word ptr [di].unit_inq_buf.inq_manufact
lea di,cmd_rewind
cmp ax,'ET' ;Rewind instead of
jz close_rewind ;Unload TEAC Unit
endif
lea di,cmd_load ;Now Unload Tape
mov [di].load_cmd_type,UNLOAD_TAPE
close_rewind: call docmd
jnc close_ok
call scsi_sense
jmp general
close_ok: jmp done
;
; Get Device Assignment
;
GET_DEV: mov es:[bx].rh_unit,0
jmp done
;
; Set Device Assignment
;
SET_DEV: jmp done
bad_unit: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,8001h
jmp short done
unknown: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,8003h
jmp short done
bad_write: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,800Ah
jmp short done
bad_read: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,800Bh
jmp short done
general: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,800Ch
jmp short done
busy: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,0200h
done: mov es,rh_seg ;Point us at the Request Header
mov bx,rh_off
or es:[bx].rh_status,0100h
cli ;Make sure we're left alone
mov ax,cs:stack_seg ;Restore DOS Stack
mov ss,ax
mov ax,cs:stack_ptr
mov sp,ax
pop bp ;Restore All Registers
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
popf
ret
INCLUDE units.asm
INCLUDE subs.asm
INCLUDE ioctl.asm
INCLUDE dump.asm
if use_kludge
INCLUDE kludge.asm
endif
;
; End of Program
; Stuff Placed Here Gets Handed Back To DOS For Re-use
;
initial proc near
lea dx,hello_msg ;Tell them the driver version
call puts
push cs
pop dx
lea bx,seg_msg_value
call hex2asc4
lea dx,seg_msg ;And Were We Loaded
call puts
call scsi_reset ;Reset the bus
mov cx,0 ;Scan for devices
scan: mov ax,cx
add al,030h
mov scan_dev,al
mov ax,1 ;Create Select Bit
shl ax,cl
mov di,cur_unit
mov [di].unit_select,al
mov [di].unit_num_drv,0 ;No Drives to start with
mov al,disk_count ;We will start with
mov [di].unit_1st_drv,al ;Drive Number if any
lea dx,scan_dev ;Print the device number
call puts
call scsi_inquire ;Inquire as to its type
jnc scan_inq_ok
lea dx,no_dev ;If the error was
cmp al,CNOCONNECT ;'No Such Device'
jz puts_jmp
lea dx,dumb_disk_msg ;Assume it is a 'SCSI I'
jmp short scan_is_drv ;Old style disk
scan_inq_ok: mov di,cur_unit
if mini_inquire
lea dx,disk_dev_msg
else
lea dx,[di].unit_inq_buf.inq_manufact
mov [di].unit_inq_term,'$'
endif
mov al,[di].unit_inq_buf.inq_dev_type
or al,al ;Look at device type
jz scan_is_drv
if mini_inquire
lea dx,tape_dev_msg
endif
cmp tape_unit,-1 ;Do We Already Have A Tape?
jnz puts_jmp
call puts ;Make this our SCSITAPE: Unit
mov tape_unit,di
lea dx,tape_msg
puts_jmp: jmp scan_puts
scan_is_drv: call puts ;Output the Device String
call scsi_capacity ;Inquire as to its size
lea dx,err_size
jc scan_puts ;Do not use unknown drives
lea dx,crlf
call puts
scan_next_drv: mov di,cur_unit
mov al,disk_count ;Number Of Drives Found
inc al
mov disk_count,al
mov al,[di].unit_num_drv ;We have a valid Drive
inc al
mov [di].unit_num_drv,al
mov al,cur_drive ;Get Current Drive Letter
mov drv_msg_let,al ;Insert it in message
inc al ;Bump Drive Letter
mov cur_drive,al
call make_bpb ;Setup the BPB for this drive
mov di,cur_bpb ;Current Working BPB
if large_drives
mov dx,[di].bpb_ts_msw
mov ax,[di].bpb_ts_lsw
else
mov dx,0
mov ax,[di].bpb_ts
endif
mov bx,2048
div bx
inc ax
lea bx,drv_msg_size
call bin_ascii
mov bx,bpb_hw_mark ;Get the BPB High Water Mark
inc bx ;Bump HW Mark for next time
inc bx
mov ax,[bx] ;Get the BPB
mov cur_bpb,ax ;Make it the current BPB
mov bpb_hw_mark,bx
lea dx,drv_msg
call puts
ife large_drives
mov bx,cur_unit
mov ah,0
mov al,[bx].unit_num_drv ;Insert Drive Offset
dec al ;Into BPB for this Drive
mov [di].bpb_hs_msw,ax
mov al,[bx].unit_cap_buf.cap_sectors_b3
or al,[bx].unit_cap_buf.cap_sectors_b2
or al,[bx].unit_cap_buf.cap_sectors_b1
or al,[bx].unit_cap_buf.cap_sectors_b0
jnz scan_next_drv ;Room left for another Drive
endif
jmp short scan_next
scan_puts: call puts
lea dx,crlf
call puts
scan_next: inc cx
cmp cx,MAXUNIT ;End of devices?
jg scan_exit
mov bx,cx ;Bump to next unit
shl bx,1
mov ax,word ptr unit_array[bx]
mov cur_unit,ax
jmp scan
scan_exit: lea dx,crlf
call puts
ret
initial endp
;
; Data Area Used Only During Initialization
;
hello_msg db 0dh,0ah,'SCSI Device Driver Version 2.0, '
if oldcode
db '8086 Flavor',0Dh,0Ah,'$'
else
db '80286 Flavor',0Dh,0Ah,'$'
endif
seg_msg db 'Driver Loaded At Segment '
seg_msg_value db '0000',0dh,0ah,'$'
scan_dev db 'X - ','$'
no_dev db '(No Installed Device)$'
err_size db '(Unknown Size)$'
drv_msg db ' - Drive '
drv_msg_let db 'X: '
drv_msg_size db 'XXXXXX Meg',0dh,0ah,'$'
tape_msg db 0dh,0ah,' - Is The SCSITAPE: Device$'
dumb_disk_msg db 'UNKNOWN DUMB DISK $'
crlf db 0dh,0ah,'$'
if mini_inquire
disk_dev_msg db 'Disk Device $'
tape_dev_msg db 'Tape Device $'
endif
dev_interrupt endp
_TEXT ends
end