home *** CD-ROM | disk | FTP | other *** search
- ;
- ; Simple SCSI Device Driver
- ;
- PAGE 76,132
-
- 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
-