home *** CD-ROM | disk | FTP | other *** search
- From: briana@tau-ceti.isc-br.com (Brian Who?)
- Newsgroups: alt.sources
- Subject: SCSI Device Driver for the Seagate ST-01
- Message-ID: <660@tau-ceti.isc-br.com>
- Date: 30 Aug 90 02:03:34 GMT
-
-
- Here is a very simple minded device driver using the ST-01 SCSI
- interface card. It is none to fast, and the code is probably not what
- it could be, but for my first assembler project on a PC it does work.
- Enjoy!
-
- #
- # 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:
- # Makefile
- # Readme.10
- # dump.asm
- # equ.inc
- # ioctl.asm
- # scsi.asm
- # sformat.c
- # struct.inc
- # subs.asm
- # units.asm
- # This Archive created: Wed Aug 29 19:00:19 1990
- # By: Brian Who? at I Saute Cats - Barbecue Rats, Spokane, WA
- #
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'Makefile'" '(388 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^XX//' > 'Makefile' << \SHAR_EOF
- XX#
- XX# SCSI Stuff
- XX#
- XXall: scsi.sys sformat.exe
- XX
- XX#
- XX# SCSI Disk Device Driver
- XX#
- XXscsi.sys: scsi.obj
- XX link +scsi.obj, scsi ;
- XX exe2bin scsi.exe scsi.sys
- XX
- XXscsi.obj: scsi.asm subs.asm ioctl.asm dump.asm units.asm equ.inc struct.inc
- XX masm scsi.asm scsi.obj scsi.lst ;
- XX
- XX#
- XX# SCSI Disk Formatter
- XX#
- XXsformat.exe: sformat.c
- XX cl -G2 -Ox -o sformat.exe sformat.c
- XX
- XX#
- XX# clean
- XX#
- XXclean:
- XX rm -f *.exe *.obj *.lst
- SHAR_EOF
- if test 388 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 388 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Readme.10'" '(2706 characters)'
- if test -f 'Readme.10'
- then
- echo shar: will not over-write existing file "'Readme.10'"
- else
- sed 's/^XX//' > 'Readme.10' << \SHAR_EOF
- XXScsi Version 1.0
- XX
- XX The code you received with this file is a very simple SCSI device
- XXdriver that uses the Seagate ST-01 interface card. As this driver is
- XXmy first PC assembler project other then "hello world", please don't
- XXsnicker to loudly.
- XX
- XX The package includes the source for a device driver that will scan
- XXthe SCSI bus for disk drives and partition any drives found into chunks
- XXof 32Meg plus any leftovers. As soon as I discover a way to get DOS to
- XXlet me use > 512 byte sectors, It will just allocate the entire disk to
- XXa single logical drive. It also includes a utility to access the low
- XXlevel SCSI format function for any disk found. You may specify the
- XXinterleave when the low level format is done and the version of the
- XXdriver here seems to work fine at 1:1 with my 8Mhz NEC.
- XX
- XX Some of the things to look out for are:
- XX
- XX#1 The receive_data and send_data functions in subs.asm use polled I/O
- XX to transfer data to/from the card. I would have loved to just use
- XX the I/O Channel Ready line that the card is suppose to support, but
- XX my NEC does not seem to use that line. Hence the polling of the REQ
- XX bit in the status port.
- XX
- XX#2 I did not know how to do clock speed independent timing loops, so there
- XX is a wait100us function in subs.asm that is very processor speed
- XX dependent :-(
- XX
- XX#3 In ioctl.asm there is a commented out call to scsi_verify. This is
- XX used by the DOS format utility to scan for errors. You may want to
- XX enable the call after you get everything setup. I shut it off while
- XX I was testing as I didn't want to wait for the verify everytime I
- XX changed the interleave.
- XX
- XX To bring up the driver. Assemble and link scsi.sys and add it to
- XXyour config.sys file. After rebooting, you may optionaly do a low level
- XXformat of each disk found using sformat.exe. You then use the DOS format
- XXutility on each logical drive. I did figure out just what format needed
- XXin the way of ioctl support to get it to do the high level format for me.
- XXAt this point you should have fully functional DOS drives. In testing
- XXI found that with multi_sector support (subs.asm) enabled, the SCSI drives
- XXwere just about as fast as the ST-412 C: that came with the machine. I
- XXam sure that the speed problem is basic to the inner loop of the data
- XXtransfer routines, but I'm at a loss to figure out how to speed it up.
- XX
- XX Anyway, maybe someone can find some use for the code. I got the
- XXcard for free, so I can't really complain about the speed or cost too
- XXmuch :-)
- XX
- XX Also thanks to the people that sent me samples of other device drivers
- XXfor the PC. I lost the names to a disk crash, but here is the result of
- XXyour help and my thanks.
- XX
- XXBrian Antoine
- XXAug 29, 1990
- SHAR_EOF
- if test 2706 -ne "`wc -c < 'Readme.10'`"
- then
- echo shar: error transmitting "'Readme.10'" '(should have been 2706 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'dump.asm'" '(973 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 (dx => buffer)
- XX;
- XXbin_ascii proc near
- XX pusha
- XX push ax
- XX mov bx,dx
- 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 to Ascii
- XX;
- XX; dx = value
- XX; di => buffer
- XX;
- XXhex2asc proc near
- XX push cx
- XX push ax
- XX mov cx,4 ;Do Four Digits
- XXh1: push cx
- XX mov cl,4
- XX rol dx,cl
- XX mov al,dl ;Get the Current Digit
- XX and al,0Fh
- XX cmp al,0Ah ;Is It Hex?
- XX jge h2
- XX add al,30h ;Normal Digit
- XX jmp h3
- XXh2: add al,37h ;Hex Digit
- XXh3: mov cs:[di],al ;Insert in Buffer
- XX inc di
- XX pop cx ;Go Do Another
- XX loop h1
- XX pop ax
- XX pop cx
- XX ret
- XXhex2asc 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 973 -ne "`wc -c < 'dump.asm'`"
- then
- echo shar: error transmitting "'dump.asm'" '(should have been 973 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'equ.inc'" '(3049 characters)'
- if test -f 'equ.inc'
- then
- echo shar: will not over-write existing file "'equ.inc'"
- else
- sed 's/^XX//' > 'equ.inc' << \SHAR_EOF
- XX;
- XX; Equates
- XX;
- XXSCSI_CARD_SEG EQU 0DE00h ;Base Segment of Card
- XXSCSI_CMD_PORT EQU 01A00h ;Offset to Command Port
- XXSCSI_DATA_PORT EQU 01C00h ;Offset to Data Port
- XX
- XXSTACK_SIZE EQU 512 ;Our Local Stack
- XX
- XX;
- XX; How the 16 bit sector number is broken down
- XX; into a sector and cylinder number.
- XX;
- XX; x = Cylinder, y = track, always have only 1 head
- XX;
- XX; xxxx xxxx xxxx yyyy
- XX;
- XX; SECT_2_FS is computed as: ((unit_bpb.bpb_ts / CLUSTSIZE) * 2) / P_SECT)
- XX;
- XXSECT_TRACK EQU 16 ;Logical Sectors in a Track
- XXSECT_MASK EQU 0000Fh ;Mask for Sector
- XXCYL_MASK EQU 0FFF0h ;Mask for Cylinder
- XXSECT_2_CYL EQU 4 ;How far to shift to convert
- XX ;Sector to Cylinder Number
- XXSECT_2_FS EQU 10 ;How far to shift for
- XX ;Total Sectors to Fat Sectors
- XX
- XXMAXUNIT EQU 3 ;Maximum Unit Number
- XX
- XXP_SECT EQU 512 ;Physical Sector Size
- XXCLUSTSIZE EQU 4 ;Number of Sectors to a Cluster
- XX
- XX;
- XX; For multi_sector reads and writes,
- XX; set the following to '1'
- XX;
- XX; CHUNK_MASK is the maximum number of sectors to access in one
- XX; SCSI request. It MUST be a power of two, and CHUNK_MASK * P_SECT
- XX; MUST be <= 64K to prevent segment wrap problems.
- XX;
- XXmulti_sector = 1 ;1 = multi sector, 0 = single sector
- XXCHUNK_MAX EQU 32
- XX
- XXCMDENABLE EQU 080h ;Enable the output drivers
- XXCMDENINTR EQU 040h ;Enable Interrupt
- XXCMDPARITY EQU 020h ;Enable Parity
- XXCMDSTARB EQU 010h ;Start Bus Arbitration
- XXCMDATTN EQU 008h ;Assert ATTN
- XXCMDBSY EQU 004h ;Assert BSY
- XXCMDSEL EQU 002h ;Assert SEL
- XXCMDRST EQU 001h ;Assert RST
- XX
- XXCMDBASE EQU CMDPARITY ;Base value of all commands
- XX
- XXSTARBCOMPL EQU 080h ;Arbitration Complete
- XXSTPARERR EQU 040h ;Parity Error
- XXSTSEL EQU 020h ;SEL Asserted
- XXSTREQ EQU 010h ;REQ Asserted
- XXSTCD EQU 008h ;C/D Asserted
- XXSTIO EQU 004h ;I/O Asserted
- XXSTMSG EQU 002h ;MSG Asserted
- XXSTBSY EQU 001h ;BSY Asserted
- XX
- XXFREE_MASK EQU 03Fh
- XX
- XXREQ_MASK EQU STMSG or STCD or STIO
- XXREQ_DATAOUT EQU 000h ;Data Out Phase
- XXREQ_DATAIN EQU STIO ;Data In Phase
- XXREQ_CMDOUT EQU STCD ;Command Out Phase
- XXREQ_STATIN EQU STCD or STIO ;Status In Phase
- XXREQ_MSGOUT EQU STMSG or STCD ;Msg Out Phase
- XXREQ_MSGIN EQU STMSG or STCD or STIO ;Msg In Phase
- XX
- XXCOK EQU 0 ;Command Completed OK
- XXCNOCONNECT EQU 1 ;Unable to Connect to Target
- XXCBUSBUSY EQU 2 ;Bus Busy
- XXCTIMEOUT EQU 3 ;Timeout waiting for Response
- XXCERROR EQU 4 ;Target Return Error
- XXCBUSY EQU 5 ;Target was Busy
- XXCDISCONNECT EQU 6 ;Target Disconnected
- XX
- XXSCSI_TESTREADY EQU 000h ;Test Unit Ready (6 byte)
- XXSCSI_REQSENSE EQU 003h ;Request Sense (6 byte)
- XXSCSI_FORMATUNIT EQU 004h ;Format Disk (6 byte)
- XXSCSI_INQUIRY EQU 012h ;Inquire (6 byte)
- XXSCSI_READSIZE EQU 025h ;Read Drive Capacity (10 byte)
- XXSCSI_READBLK EQU 028h ;Read Sectors (10 byte)
- XXSCSI_WRITEBLK EQU 02Ah ;Write Sectors (10 byte)
- XXSCSI_VERIFYBLK EQU 02Fh ;Verify Blocks (10 byte)
- XX
- XXMSG_COMPLETE EQU 000h ;Command is Complete
- XXMSG_SAVE EQU 002h ;Save Data Pointers
- XXMSG_RESTORE EQU 003h ;Restore Data Pointers
- XXMSG_ERROR EQU 005h ;Error Detected
- XXMSG_ABORT EQU 006h ;Abort the Command
- XXMSG_REJECT EQU 007h ;Reject the Command
- XXMSG_NOP EQU 008h ;No Operation
- XXMSG_IDENTIFY EQU 080h ;Identify Yourself
- SHAR_EOF
- if test 3049 -ne "`wc -c < 'equ.inc'`"
- then
- echo shar: error transmitting "'equ.inc'" '(should have been 3049 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'ioctl.asm'" '(1824 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
- 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; call scsi_verify
- XX jmp scsi_i_exit
- XX
- XXscsi_i_60h: cmp al,60h ;Get Device Params?
- XX jnz scsi_i_62h
- XX 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 mov ax,[si].bpb_ts
- XX shr ax,SECT_2_CYL ;Convert Sect to Cyl
- 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 scsi_i_exit
- XX
- XXscsi_i_62h: cmp al,62h ;Verify?
- XX jnz scsi_i_error
- XX call scsi_verify
- XX jmp scsi_i_exit
- XX
- XXscsi_i_error: stc
- XXscsi_i_exit: ret
- XXscsi_ioctl endp
- XX
- XXscsi_ioctl_write proc
- XX mov di,es:[bx].rh12_buf_ofs
- XX mov ax,es:[bx].rh12_buf_seg
- XX mov es,ax
- XX mov ax,es:[di].ioc_command ;What Command
- XX cmp al,'F' ;Format?
- XX jnz scsi_i_w_error
- XX
- XX mov ax,es:[di].ioc_data ;Get Interleave
- XX lea di,cmd_format ;Insert into Command
- XX mov [di].fmt_cmd_il_b0,al
- XX mov [di].fmt_cmd_il_b1,ah
- XX call docmd
- XX jmp short scsi_i_w_exit
- XX
- XXscsi_i_w_error: stc
- XXscsi_i_w_exit: ret
- XXscsi_ioctl_write endp
- SHAR_EOF
- if test 1824 -ne "`wc -c < 'ioctl.asm'`"
- then
- echo shar: error transmitting "'ioctl.asm'" '(should have been 1824 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'scsi.asm'" '(8104 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 .286
- XX PAGE 76,132
- XX
- XX INCLUDE equ.inc
- XX INCLUDE struct.inc
- 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:
- XXnext_dev dd -1 ;No other Device Drivers
- XXattribute dw 6040h ;Ioctl R/W, Block Device, Non-IBM, Get/Set
- XXstrategy dw dev_strategy ;Address of 1st DOS Call
- XXinterrupt 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;
- XXrh_off dw ? ;Request Header Offset
- XXrh_seg dw ? ;Request Header Segment
- XX
- XXcur_drive db -1
- XXvol_id db 'NO NAME ',0
- 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
- 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 done ;Device Open
- XX dw done ;Device Close
- XX dw busy ;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; Strategy Procedure
- XX;
- XXdev_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 ret
- XXdev_strategy endp
- XX
- XX;
- XX; Interrupt Procedure
- XX;
- XXdev_interrupt proc far
- XX cli ;Save Machine State On Entry
- 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 pushf
- 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: 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 mov bx,rh_off
- XX mov es,rh_seg
- XX 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
- XXMEDIA_CHECK: call find_unit
- XX jc bad_unit
- 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
- XX
- XXGET_BPB: call find_unit
- XX jc bad_unit
- 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
- XX
- XX;
- XX; Read some data from the disk
- XX;
- XXREAD: call find_unit
- XX jc bad_unit
- XX call scsi_read
- XX jc bad_read
- XX jmp done
- XX
- XX;
- XX; Write some data to the disk
- XX;
- XXWRITE equ $
- XXWRITE_VERIFY: call find_unit
- XX jc bad_unit
- XX call scsi_write
- XX jc bad_write
- XX jmp done
- XX
- XX;
- XX; Write Ioctl Packet
- XX;
- XXWRITE_IOCTL: call find_unit
- XX jc bad_unit
- XX call scsi_ioctl_write
- XX jc unknown
- XX jmp done
- XX
- XX;
- XX; Special Control Functions
- XX;
- XXIOCTL: call find_unit
- XX jc bad_unit
- XX call scsi_ioctl
- XX jc unknown
- XX jmp done
- XX
- XXGET_DEV: mov es:[bx].rh_unit,0
- XX jmp done
- 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
- 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 popf ;Restore All Registers
- XX pop bp
- 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 sti ;We're Safe Now
- XX ret
- XX
- XX INCLUDE units.asm
- XX INCLUDE subs.asm
- XX INCLUDE ioctl.asm
- XX INCLUDE dump.asm
- 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 di,seg_msg_value
- XX call hex2asc
- 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 jmp scan_err
- XX
- XXscan_inq_ok: mov di,cur_unit
- XX lea dx,[di].unit_inq_buf.inq_manufact
- XX mov [di].unit_inq_term,'$'
- XX mov al,[di].unit_inq_buf.inq_dev_type
- XX or al,al ;Look at device type
- XX jz scan_is_drv
- XX jmp scan_puts ;Must be a Tape Drive
- 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 mov ax,[di].bpb_ts
- XX shr ax,11
- XX inc ax
- XX lea dx,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 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 jmp short scan_next
- XX
- XXscan_err: lea dx,no_dev
- XX cmp al,CNOCONNECT
- XX jz scan_puts
- XX lea dx,err_dev
- 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: ret
- XXinitial endp
- XX
- XX;
- XX; Data Area Used Only During Initialization
- XX;
- XXhello_msg db 0dh,0ah,'SCSI Device Driver Version 1.0',0Dh,0Ah,'$'
- 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_dev db '(Error On Device)$'
- XXerr_size db 'unknown size$'
- XXdrv_msg db ' - Drive '
- XXdrv_msg_let db 'X: '
- XXdrv_msg_size db 'XXXXXX Meg',0dh,0ah,'$'
- XXcrlf db 0dh,0ah,'$'
- XX
- XXdev_interrupt endp
- XX_TEXT ends
- XX end scsi
- SHAR_EOF
- if test 8104 -ne "`wc -c < 'scsi.asm'`"
- then
- echo shar: error transmitting "'scsi.asm'" '(should have been 8104 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'sformat.c'" '(1842 characters)'
- if test -f 'sformat.c'
- then
- echo shar: will not over-write existing file "'sformat.c'"
- else
- sed 's/^XX//' > 'sformat.c' << \SHAR_EOF
- XX/*
- XX** SCSI Disk Formatter (Low Level)
- XX**
- XX** usage: sformat drive: [interleave]
- XX**
- XX** Revision History:
- XX**
- XX** Version 1.0 08/03/90 Initial Release
- XX**
- XX** Version 1.1 08/20/90 Add verification message.
- XX*/
- XX#include <stdio.h>
- XX#include <dos.h>
- XX
- XX#define TRUE (1)
- XX#define FALSE (0)
- XX#define VERSION "sformat Version 1.1 BWA"
- XX
- XXextern int _doserrno;
- XX
- XXstruct cmd {
- XX short command; /* command type */
- XX short args; /* command args */
- XX} ioctl_data;
- XXunion REGS inregs, outregs;
- XXstruct SREGS segregs;
- XXunsigned short interleave = 0;
- XXunsigned char drive;
- XXchar far *cp;
- XX
- XXmain(argc, argv)
- XXint argc;
- XXchar *argv[];
- XX{
- XX /*
- XX ** say hello
- XX */
- XX puts(VERSION);
- XX
- XX /*
- XX ** figure out who to format
- XX */
- XX switch (argc)
- XX {
- XX case 3:
- XX interleave = atoi(argv[2]);
- XX case 2:
- XX if (argv[1][1] != ':') usage();
- XX drive = argv[1][0];
- XX drive = toupper(drive);
- XX drive -= '@';
- XX break;
- XX
- XX default:
- XX usage();
- XX break;
- XX }
- XX
- XX /*
- XX ** verify that this is what the user really wants to do
- XX */
- XX printf("Do you really wish to format the SCSI\n");
- XX printf("device that contains drive %c: (y,n)? ", argv[1][0]);
- XX fflush(stdout);
- XX if ( getchar() != 'y' )
- XX {
- XX puts("Aborting low level format ....");
- XX exit(1);
- XX }
- XX
- XX /*
- XX ** put together the command
- XX */
- XX inregs.h.ah = 0x44; /* ioctl */
- XX inregs.h.al = 0x05; /* write */
- XX inregs.h.bl = drive; /* unit */
- XX inregs.x.cx = sizeof(struct cmd);
- XX cp = (char *) &ioctl_data;
- XX inregs.x.dx = FP_OFF(cp);
- XX segregs.ds = FP_SEG(cp);
- XX ioctl_data.command = 'F';
- XX ioctl_data.args = interleave;
- XX
- XX /*
- XX ** start the format
- XX */
- XX puts("Now formating ....");
- XX puts("Please wait ....");
- XX intdosx(&inregs, &outregs, &segregs);
- XX
- XX /*
- XX ** see what happened
- XX */
- XX if ( outregs.x.cflag )
- XX printf("DOS error %d occured during format.\n", _doserrno);
- XX else
- XX puts("Formating complete.");
- XX exit(0);
- XX}
- XX
- XXusage()
- XX{
- XX puts("usage: sformat drive: [interleave]");
- XX exit(1);
- XX}
- SHAR_EOF
- if test 1842 -ne "`wc -c < 'sformat.c'`"
- then
- echo shar: error transmitting "'sformat.c'" '(should have been 1842 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'struct.inc'" '(5738 characters)'
- if test -f 'struct.inc'
- then
- echo shar: will not over-write existing file "'struct.inc'"
- else
- sed 's/^XX//' > 'struct.inc' << \SHAR_EOF
- XX;
- XX; Structures for SCSI commands
- XX;
- XXio_cmd struc
- XXio_cmd_op db ? ;Opcode
- XXio_cmd_lun db ?
- XXio_cmd_lba_b3 db ? ;Logical Block Address
- XXio_cmd_lba_b2 db ?
- XXio_cmd_lba_b1 db ?
- XXio_cmd_lba_b0 db ?
- XXio_cmd_dummy1 db ?
- XXio_cmd_cnt_b1 db ? ;Block Count
- XXio_cmd_cnt_b0 db ?
- XXio_cmd_dummy2 db ?
- XXio_cmd ends
- XX
- XX;
- XX; Format the Unit
- XX;
- XXfmt_cmd struc
- XXfmt_cmd_op db ? ;Opcode
- XXfmt_cmd_type db ? ;Format Type
- XXfmt_cmd_dummy1 db ?
- XXfmt_cmd_il_b1 db ? ;Interleave (MSB)
- XXfmt_cmd_il_b0 db ? ;Interleave (LSB)
- XXfmt_cmd_dummy3 db ?
- XXfmt_cmd ends
- XX
- XX;
- XX; Verify Sectors
- XX;
- XXver_cmd struc
- XXver_cmd_op db ? ;Opcode
- XXver_cmd_lun db ? ;Lun
- XXver_cmd_lba_b3 db ? ;Logical Block Address MSB
- XXver_cmd_lba_b2 db ?
- XXver_cmd_lba_b1 db ?
- XXver_cmd_lba_b0 db ? ;Logical Block Address LSB
- XXver_cmd_dummy1 db ?
- XXver_cmd_len_b1 db ? ;Length MSB
- XXver_cmd_len_b0 db ? ;Length LSB
- XXver_cmd_dummy2 db ?
- XXver_cmd ends
- XX
- XX;
- XX; Structure returned by the unit inquiry command
- XX;
- XXinq struc
- XXinq_dev_type db ? ;Device Type
- XXinq_dev_qual db ? ;Device Qualifier
- XXinq_stand_rev db ? ;Standard Revision Level
- XXinq_format db ? ;Response Format
- XXinq_length db ? ;Length of Extra Data
- XXinq_reserv1 db ?
- XXinq_reserv2 db ?
- XXinq_reserv3 db ?
- XXinq_manufact db 8 dup (?) ;Manufacture
- XXinq_product db 16 dup (?) ;Product
- XXinq ends
- XX
- XX;
- XX; Structure returned by the read drive capacity command
- XX;
- XXcap struc
- XXcap_sectors_b3 db ? ;MSB of sector count
- XXcap_sectors_b2 db ?
- XXcap_sectors_b1 db ?
- XXcap_sectors_b0 db ? ;LSB of sector count
- XXcap_size_b3 db ? ;MSB of sector size
- XXcap_size_b2 db ?
- XXcap_size_b1 db ?
- XXcap_size_b0 db ? ;LSB of sector size
- XXcap ends
- XX
- XX;
- XX; Structure Definitions For Our Device Driver
- XX;
- XXbpb struc
- XXbpb_ss dw ? ;Sector Size
- XXbpb_au db ? ;Cluster Size in Sectors
- XXbpb_rs dw ? ;Reserved Sectors
- XXbpb_nf db ? ;Number of Fats
- XXbpb_de dw ? ;Number of Root Directory Entries
- XXbpb_ts dw ? ;Total Number Of Sectors
- XXbpb_md db ? ;Media Descriptor
- XXbpb_fs dw ? ;Number of Sectors in each Fat
- XXbpb_st dw ? ;Number of Sectors per Track
- XXbpb_nh dw ? ;Number of Heads
- XXbpb_hs_lsw dw ? ;Hidden Sectors (Least Sig Word)
- XXbpb_hs_msw dw ? ;Hidden Sectors (Most Sig Word)
- XXbpb_ts_large dd ? ;Large Total Sector Count
- XXbpb_res db 6 dup (?) ;Reserved
- XXbpb ends
- XX
- XX;
- XX; ioctl function 42h
- XX;
- XXioctl_fmt struc
- XXioctl_fmt_spec db ? ;Special Flags
- XXioctl_fmt_head dw ? ;Head to Format
- XXioctl_fmt_cyl dw ? ;Cylinder to Format
- XXioctl_fmt ends
- XX
- XX;
- XX; ioctl function 60h
- XX;
- XXdpb struc
- XXdpb_special db ? ;Special Flags
- XXdpb_type db ? ;Device Type
- XXdpb_attr dw ? ;Device Attributes
- XXdpb_cyl dw ? ;Device Cylinder Count
- XXdpb_media db ? ;Device Media Type if Diskette
- XXdpb_bpb db size bpb dup (?)
- XXdpb_sectors dw ? ;Sectors in Track
- XXdpb_track dd SECT_TRACK dup (?)
- XXdpb ends
- XX
- XX;
- XX; The internal control structure for a SCSI device
- XX;
- XXunit struc
- XXunit_1st_drv db ? ;DOS Drive Numbers
- XXunit_num_drv db ? ;DOS Drive Count
- XXunit_select db ? ;SCSI Select Bit
- XXunit_mcheck db ? ;Media Check Byte
- XXunit_inq_buf db size inq dup (?)
- XXunit_inq_term db ?
- XXunit_cap_buf db size cap dup (?)
- XXunit ends
- XX
- XX;
- XX; Ioctl Commands
- XX;
- XXioc struc
- XXioc_command dw ? ;Command
- XXioc_data dw ? ;Command Dependent Data
- XXioc ends
- XX
- XX;
- XX; DOS requests
- XX;
- XXrh struc
- XXrh_len db ? ;Length of Packet
- XXrh_unit db ? ;Unit Code (Block Only)
- XXrh_cmd db ? ;Command Code
- XXrh_status dw ? ;Returned Status
- XXrh_res db 8 dup (?) ;Reserved
- XXrh ends
- XX
- XXrh0 struc ;INITIALIZATION
- XXrh0_rh db size rh dup (?) ;Fixed Portion
- XXrh0_nunits db ? ;Number of units (Block Only)
- XXrh0_brk_ofs dw ? ;Break Address (Offset)
- XXrh0_brk_seg dw ? ;Break Address (Segment)
- XXrh0_bpb_tbo dw ? ;Pointer to BPB Array (Offset)
- XXrh0_bpb_tbs dw ? ;Pointer to BPB Array (Segment)
- XXrh0_drv_ltr db ? ;First Available Drive (DOS 3+, Block Only)
- XXrh0 ends
- XX
- XXrh1 struc ;MEDIA CHECK
- XXrh1_rh db size rh dup (?) ;Fixed Portion
- XXrh1_media db ? ;Media Descriptor from DPB
- XXrh1_md_stat db ? ;Media Status returned by Device Driver
- XXrh1_volid_ofs dw ? ;Offset of Volume ID String (DOS 3+)
- XXrh1_volid_seg dw ? ;Segment of Volume ID String (DOS 3+)
- XXrh1 ends
- XX
- XXrh2 struc ;GET BPB
- XXrh2_rh db size rh dup (?) ;Fixed Portion
- XXrh2_media db ? ;Media Descriptor from DPB
- XXrh2_buf_ofs dw ? ;Offset of Data Transfer Area
- XXrh2_buf_seg dw ? ;Segment of Data Transfer Area
- XXrh2_pbpbo dw ? ;Offset of Pointer to BPB
- XXrh2_pbpbs dw ? ;Segment of Pointer to BPB
- XXrh2 ends
- XX
- XXrh4 struc ;INPUT
- XXrh4_rh db size rh dup (?) ;Fixed Portion
- XXrh4_media db ? ;Media Descriptor from DPB
- XXrh4_buf_ofs dw ? ;Offset of Data Transfer Area
- XXrh4_buf_seg dw ? ;Segment of Data Transfer Area
- XXrh4_count dw ? ;Transfer Count (Sectors)
- XXrh4_start dw ? ;Start Sector Number
- XXrh4 ends
- XX
- XXrh8 struc ;OUTPUT
- XXrh8_rh db size rh dup (?) ;Fixed Portion
- XXrh8_media db ? ;Media Descriptor from DPB
- XXrh8_buf_ofs dw ? ;Offset of Data Transfer Area
- XXrh8_buf_seg dw ? ;Segment of Data Transfer Area
- XXrh8_count dw ? ;Transfer Count (Sectors)
- XXrh8_start dw ? ;Start Sector Number
- XXrh8 ends
- XX
- XXrh9 struc ;OUTPUT VERIFY
- XXrh9_rh db size rh dup (?) ;Fixed Portion
- XXrh9_media db ? ;Media Descriptor from DPB
- XXrh9_buf_ofs dw ? ;Offset of Data Transfer Area
- XXrh9_buf_seg dw ? ;Segment of Data Transfer Area
- XXrh9_count dw ? ;Transfer Count (Sectors)
- XXrh9_start dw ? ;Start Sector Number
- XXrh9 ends
- XX
- XXrh12 struc ;OUTPUT IOCTL
- XXrh12_rh db size rh dup (?) ;Fixed Portion
- XXrh12_media db ? ;Media Descriptor from DPB
- XXrh12_buf_ofs dw ? ;Offset of Data Transfer Area
- XXrh12_buf_seg dw ? ;Segment of Data Transfer Area
- XXrh12_count dw ? ;Transfer Count (Sectors)
- XXrh12_start dw ? ;Start Sector Number
- XXrh12 ends
- XX
- XXrh19 struc ;IOCTL
- XXrh19_rh db size rh dup (?) ;Fixed Portion
- XXrh19_major db ? ;Major Code
- XXrh19_minor db ? ;Minor Code
- XXrh19_si dw ? ;Caller SI Register
- XXrh19_di dw ? ;Caller DI Register
- XXrh19_buf_ofs dw ? ;Caller Buffer Offset
- XXrh19_buf_seg dw ? ;Caller Buffer Segment
- XXrh19 ends
- SHAR_EOF
- if test 5738 -ne "`wc -c < 'struct.inc'`"
- then
- echo shar: error transmitting "'struct.inc'" '(should have been 5738 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'subs.asm'" '(11083 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_format db SCSI_FORMATUNIT,0,0,0,0,0
- 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
- XXcmd_inquire db SCSI_INQUIRY,0,0,0,size inq,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 even
- XXdocmd_cmd dw ?
- XXdocmd_buf dw ?
- XXdocmd_buf_seg dw ?
- XXdocmd_len dw ?
- XXdocmd_unit_sel db ?
- XXdocmd_status db ?
- 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 al,CMDBASE or CMDENABLE or CMDRST
- XX mov es:[si],al ;Reset the bus
- XX call wait1ms
- XX mov al,CMDBASE
- XX mov es:[si],al ;All done
- XX mov cx,250 ;Wait 250ms
- XXreset_loop: call wait1ms
- XX loop reset_loop
- XX
- XX popa
- XX ret
- XXscsi_reset endp
- XX
- XX;
- XX; Test the Ready Status of a unit
- XX;
- XX; al = return code, 'C' error
- XX;
- XXscsi_ready proc near
- XX lea di,cmd_ready ;Command
- XX call docmd
- XX ret
- XXscsi_ready endp
- XX
- XX;
- XX; Inquire about the type of a unit
- XX;
- XX; 'C' error indicates an error
- XX;
- XXscsi_inquire proc near
- XX push cx
- 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 pop cx
- XX ret
- XXscsi_inquire endp
- XX
- XX;
- XX; Determine the size of a disk
- XX;
- XX; 'C' error indicates an error
- XX;
- XXscsi_capacity proc near
- XX push cx
- XX 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 pop cx
- XX ret
- XXscsi_capacity endp
- XX
- XX;
- XX; Verify the Track given in an IOCTL Request
- XX;
- XX; 'C' indicates an error
- XX;
- XXscsi_verify proc near
- XX mov di,es:[bx].rh19_buf_ofs ;Command Offset
- XX mov ax,es:[bx].rh19_buf_seg ;Command Segment
- XX mov es,ax
- XX mov ax,es:[di].ioctl_fmt_cyl ;Track
- XX shl ax,SECT_2_CYL ;Convert to Sector
- XX
- XX mov di,cur_bpb ;Add to Drive Offset
- XX mov dx,[di].bpb_hs_msw
- XX
- 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 call docmd
- XX 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;
- XXscsi_read proc near
- XX mov di,bx
- XX mov cx,es:[di].rh4_count ;Sector Count
- XX mov dx,es:[di].rh4_start ;Starting Sector
- 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 mov ax,[si].bpb_hs_msw ;Drive Sector Offset
- XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
- XX mov [di].io_cmd_lba_b2,al ;Into the Command
- 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 scsi_r_cok1 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXscsi_r_cok1: shl ax,9 ;Convert to Buffer Size
- 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
- XXscsi_r_loop: jnc scsi_r_nowrap
- XX mov ax,bx ;Normalize the
- XX shr ax,4 ;Segment and
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XXscsi_r_nowrap: push cx
- 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 scsi_r_cok2 ;Check for Boundary
- XX mov cx,CHUNK_MAX
- XXscsi_r_cok2: mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
- XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
- XX shl cx,9 ;Convert to Buffer Size
- XX else
- XX mov cx,P_SECT ;Buffer Size
- XX endif
- XX call docmd
- XX pop cx
- XX jc scsi_r_exit
- 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 scsi_r_cok3 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXscsi_r_cok3: sub cx,ax ;Dec Sector Count
- XX jz scsi_r_exit
- XX add dx,ax ;Bump to next Sector
- XX shl ax,9 ;Convert to Buffer Size
- XX add bx,ax
- XX jmp short scsi_r_loop
- XX else
- XX inc dx ;Bump to next Sector
- XX add bx,P_SECT
- XX loop scsi_r_loop
- XX clc
- XX endif
- XXscsi_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
- XXscsi_read endp
- XX
- XX;
- XX; Write Some Blocks from the disk given
- XX; the request header in es:bx
- XX;
- XX; al = return code, 'C' indicates an error
- XX;
- XXscsi_write proc near
- XX mov di,bx
- XX mov cx,es:[di].rh8_count ;Sector Count
- XX mov dx,es:[di].rh8_start ;Starting Sector
- 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 mov ax,[si].bpb_hs_msw ;Drive Sector Offset
- XX mov [di].io_cmd_lba_b3,ah ;Insert Sector
- XX mov [di].io_cmd_lba_b2,al ;Into the Command
- 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 scsi_w_cok1 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXscsi_w_cok1: shl ax,9 ;Convert to Buffer Size
- 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
- XXscsi_w_loop: jnc scsi_w_nowrap
- XX mov ax,bx ;Normalize the
- XX shr ax,4 ;Segment and
- XX mov si,es ;Offset so that
- XX add si,ax ;It dosn't Wrap
- XX mov es,si
- XX and bx,000Fh
- XXscsi_w_nowrap: push cx
- 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 scsi_w_cok2 ;Check for Boundary
- XX mov cx,CHUNK_MAX
- XXscsi_w_cok2: mov [di].io_cmd_cnt_b1,ch ;Insert Sector Count
- XX mov [di].io_cmd_cnt_b0,cl ;Into the Command
- XX shl cx,9 ;Convert to Buffer Size
- XX else
- XX mov cx,P_SECT ;Buffer Size
- XX endif
- XX call docmd
- XX pop cx
- XX jc scsi_w_exit
- 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 scsi_w_cok3 ;Check for Boundary
- XX mov ax,CHUNK_MAX
- XXscsi_w_cok3: sub cx,ax ;Dec Sector Count
- XX jz scsi_w_exit
- XX add dx,ax ;Bump to next Sector
- XX shl ax,9 ;Convert to Buffer Size
- XX add bx,ax
- XX jmp short scsi_w_loop
- XX else
- XX inc dx ;Bump to next Sector
- XX add bx,P_SECT
- XX loop scsi_w_loop
- XX clc
- XX endif
- XXscsi_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
- XXscsi_write endp
- XX
- XX;
- XX; Do a command
- XX;
- XX; bx => buffer for returned information
- XX; cx = buffer len
- XX; di => command string
- XX; es = buffer segment for returned information
- 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
- XX mov ax,SCSI_CARD_SEG ;Point at the Card
- XX mov es,ax
- XX mov si,SCSI_CMD_PORT ;Command Port
- XX
- XX;
- XX; Wait for the Bus to become free
- XX;
- XX mov cx,65535
- XXidle_loop: mov al,es:[si] ;Get the Status
- XX and al,FREE_MASK
- XX jz try_sel
- XX loop idle_loop
- XX
- XX call scsi_reset
- XX mov al,CBUSBUSY ;Bus still BUSY?
- XX stc
- XX jmp docmd_exit
- XX
- XXtry_sel: mov al,CMDBASE ;Try to select target
- XX mov es:[si],al
- XX
- XX mov di,cur_unit
- XX mov al,[di].unit_select ;Get our Select Bit
- XX mov di,SCSI_DATA_PORT ;Data Port
- XX mov es:[di],al
- XX
- XX mov al,CMDBASE or CMDENABLE or CMDSEL
- XX mov es:[si],al
- 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 ;Look for BSY bit
- XX jnz cmd_xfer
- XX call wait100us
- XX loop sel_loop
- XX
- XX mov al,CNOCONNECT ;Nothing Answered
- XX stc
- XX jmp docmd_exit
- XX
- XX;
- XX; Start the Command
- XX;
- XXcmd_xfer: mov al,CMDBASE or CMDENABLE
- XX mov es:[si],al
- XXxfer_loop: mov al,es:[si]
- XX test al,STBSY ;Look for BSY bit
- XX jz xfer_error
- XX test al,STREQ ;And REQ bit
- XX jz xfer_loop
- XX
- XX and al,REQ_MASK ;Look at REQ type
- XX
- XX cmp al,REQ_DATAOUT ;Is it Data Out?
- XX jnz try_datain
- XX call send_data
- XX jmp short xfer_loop
- XX
- XXtry_datain: cmp al,REQ_DATAIN ;Is it Data In?
- XX jnz try_cmdout
- XX call receive_data
- XX jmp short xfer_loop
- XX
- XXtry_cmdout: cmp al,REQ_CMDOUT ;Is it Command Out?
- XX jnz try_statin
- XX call send_cmd
- XX jmp short xfer_loop
- XX
- XXtry_statin: cmp al,REQ_STATIN ;Is it Status In?
- XX jnz try_msgout
- XX mov al,es:[di] ;Get the Status Byte
- XX mov docmd_status,al
- XX jmp short xfer_loop
- XX
- XXtry_msgout: cmp al,REQ_MSGOUT ;Is it Message Out?
- XX jnz try_msgin
- XX call send_nop
- XX jmp short xfer_loop
- XX
- XXtry_msgin: cmp al,REQ_MSGIN ;Is it Message In?
- XX jnz xfer_error
- XX
- XX mov al,es:[di] ;Get Message Byte
- XX cmp al,MSG_COMPLETE ;Are We All Done?
- XX jnz short xfer_loop
- XX mov al,docmd_status
- XX cmp al,0
- XX jnz xfer_error
- XX mov al,COK
- XX clc
- XX jmp docmd_exit
- XX
- XXxfer_error: call scsi_reset
- XX mov al,CERROR
- XX stc
- XX
- XXdocmd_exit: mov docmd_status,al
- XX mov al,CMDBASE
- XX mov es:[si],al
- XX pop es
- XX popa
- XX mov al,docmd_status
- XX ret
- XXdocmd endp
- XX
- XX;
- XX; Receive a Data Stream from the card
- XX; On entry es:[di] points at the data port
- XX; es:[si] points at the command port
- XX;
- XXreceive_data proc near
- XX mov dx,es ;Save ES
- XX
- XX mov bx,si
- 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 si,SCSI_DATA_PORT ;Source Offset
- XX mov ds,ax ;Source Segment
- XX mov al,STREQ
- XX cld
- XX
- XXreceive_loop: movsb
- XX dec si ;Don't blow the card buffer
- XX dec cx
- XX jz receive_exit
- XXreceive_wait: test byte ptr [bx],al ;Ready?
- XX jnz receive_loop
- XX jmp short receive_wait
- XX
- XXreceive_exit: mov si,SCSI_CMD_PORT ;Restore the Environment
- XX mov di,SCSI_DATA_PORT
- XX mov ax,cs
- XX mov ds,ax
- XX mov es,dx
- XX ret
- XXreceive_data endp
- XX
- XX;
- XX; Send a Command to the card
- XX; On entry es:[di] points at the data port
- XX; es:[si] points at the command port
- XX;
- XXsend_cmd proc near
- XX mov bx,docmd_cmd ;Get Command Pointer
- XX mov al,[bx] ;Get a Command Byte
- XX mov es:[di],al ;Send it to Card
- XX inc bx ;Bump for Next Time
- XX mov docmd_cmd,bx
- XX ret
- XXsend_cmd endp
- XX
- XX;
- XX; Send a Data Stream to the card
- XX; On entry es:[di] points at the data port
- XX; es:[si] points at the command port
- XX;
- XXsend_data proc near
- 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 mov al,STREQ
- XX cld
- XX
- XXsend_loop: movsb
- XX dec di ;Don't blow the card buffer
- XX dec cx
- XX jz send_exit
- XXsend_wait: test byte ptr es:[bx],al ;Ready?
- XX jnz send_loop
- XX jmp short send_wait
- XX
- XXsend_exit: mov si,SCSI_CMD_PORT ;Restore the Environment
- XX mov di,SCSI_DATA_PORT
- XX mov ax,cs
- XX mov ds,ax
- XX ret
- XXsend_data endp
- XX
- XX;
- XX; Send a NOP Message
- XX;
- XXsend_nop proc near
- XX mov al,MSG_NOP ;Oops, send a nop
- XX mov es:[di],al
- XX mov al,CMDBASE or CMDENABLE
- XX mov es:[si],al
- XX ret
- XXsend_nop endp
- XX
- XX;
- XX; Wait One Milli second
- XX;
- XX; The value of 'cx' is computed for an 8 Mhz Clock
- XX;
- XXwait1ms proc near
- XX push cx ; (3) = 375ns
- XX mov cx,798 ; (2) = 250ns
- XXwait_m_loop: loop wait_m_loop ; (10) = 1250ns * X
- XX pop cx ; (5) = 625ns
- XX ret ; (11+) = 1375ns
- XXwait1ms 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,78 ; (2) = 250ns
- XXwait_u_loop: loop wait_u_loop ; (10) = 1250ns * X
- XX pop cx ; (5) = 625ns
- XX ret ; (11+) = 1375ns
- XXwait100us endp
- SHAR_EOF
- if test 11083 -ne "`wc -c < 'subs.asm'`"
- then
- echo shar: error transmitting "'subs.asm'" '(should have been 11083 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'units.asm'" '(3252 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 even
- XXunit7 db size unit dup (-1)
- 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 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
- 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 dw unit7
- 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 dw bpb8
- XX dw bpb9
- XX dw bpbA
- XX dw bpbB
- XX dw bpbC
- XX dw bpbD
- XX dw bpbE
- XX dw bpbF
- XXbpb_hw_mark dw bpb_array
- XX
- 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 inc dh ;Bump Drive Number
- XX dec al ;Dec Drive count
- XX jnz find_unit_loop ;Try next Drive
- 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 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 ah,[bx].unit_cap_buf.cap_sectors_b3
- XX mov al,[bx].unit_cap_buf.cap_sectors_b2
- XX or ax,ax
- XX jz make_bpb_last ;Use up the last few sectors
- XX dec ax ;Use up 65536 Sectors
- XX mov [bx].unit_cap_buf.cap_sectors_b3,ah
- XX mov [bx].unit_cap_buf.cap_sectors_b2,al
- XX mov dx,65535 ;Max of 32 Meg
- XX jmp short make_bpb_ts
- XXmake_bpb_last: mov dh,[bx].unit_cap_buf.cap_sectors_b1
- XX mov [bx].unit_cap_buf.cap_sectors_b1,0
- XX mov dl,0 ;Round to nearest Cyl
- XX mov [bx].unit_cap_buf.cap_sectors_b0,0
- XX dec dx ;Make it zero relative
- XXmake_bpb_ts: mov [di].bpb_ts,dx
- XX mov [di].bpb_md,0F8h
- XX shr dx,SECT_2_FS
- XX inc dx ;Allow for round-off
- XX mov [di].bpb_fs,dx
- 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 ret
- XXmake_bpb endp
- SHAR_EOF
- if test 3252 -ne "`wc -c < 'units.asm'`"
- then
- echo shar: error transmitting "'units.asm'" '(should have been 3252 characters)'
- fi
- fi # end of overwriting check
- #
- # End of shell archive
- #
- exit 0
-