TITLE ZRAM-205 Memory Disk Driver PAGE ,132 ;*************************************************************** ;** ZRAM205.ASM v1.13 07/19/85d 07/19/86 09/22/87 ;*************************************************************** ;** Copyright (c) 1986 FBE Research Company, Incorporated ** ;** P.O. Box 68234, Seattle, WA 98168 ** ;*************************************************************** ;** This program is yours. There is no license agreement. ** ;** However, the program is copyrighted and you may not sell ** ;** exact copies of it for profit. You may, however, modify ** ;** the program and sell the result as long as you include ** ;** our copyright notice (above). ** ;*************************************************************** ; ; This program is a memory-disk device driver. It works only ; on a Z-100 computer equipped with a Z-205 memory card modified ; with the FBE ZRAM-205 package and fully populated with 256K ; RAM's. The modified Z-205 card must be configured to use ; Port 98H as it's control port and must be origined at either ; 80000H (default), 30000H (option), or 40000H (option). ; ; If optionally selected, the driver may be rebooted without ; loss of the disk contents. ; ; Due to an undocumented design change in the Z-205, earlier ; versions of this program disabled partity detection. ; ;*************************************************************** ; Portions of the INIT code which allows for rebooting without ; losing the disk contents were written by: ; ; Steve Worcester ; 6870 Virginia Hills Drive ; Salt Lake City, Utah 84121 ; ;*************************************************************** ;** ASSEMBLY INSTRUCTIONS ;*************************************************************** ; ; MASM ZRAM205; ; LINK ZRAM205; ; EXE2BIN ZRAM205.EXE ZRAM205.DVD ; ERASE ZRAM205.EXE ; ERASE ZRAM205.OBJ ; ; Ignore the "Missing Stack Segment" error generated during the ; link process. ; ;*************************************************************** ;** INSTALLATION ;*************************************************************** ; ; Put ZRAM205.DVD on your boot disk and add the following line ; to CONFIG.SYS (create CONFIG.SYS if necessary) using a text ; editor (e.g., EDLIN): ; ; DEVICE=ZRAM205.DVD X Y ; ; Where X = 3 if the Z-205 starting address is to be 30000H. ; X = 4 if the Z-205 starting address is to be 40000H. ; X = 8 if the Z-205 starting address is to be 80000H. ; ; and whether the disk contents will survive a warm boot: ; ; Y = R Allow Warm Boot ; ; Omit X for the default starting address of 80000H. Omit Y ; if disk contents are to be erased upon rebooting. Note: Y ; may precede X and either X or Y or both may be omitted. R ; must be uppercae if used. ; ;*************************************************************** ;** DEFINITIONS ;*************************************************************** ; CPORT EQU 98H ;Control Port Address ; ; ASCII Characters: ; TAB EQU 9 LF EQU 10 CR EQU 13 ; ; Structure Indices: ; COMAND EQU 2 ;Static Request Header STATUS EQU 3 ; MCSTAT EQU 14 ;Media Check Command Block ; BCBADR EQU 18 ;Build BPB Command Block ; TRSADR EQU 14 ;Read/Write Command Block COUNT EQU 18 SECTOR EQU 20 ; UNITS EQU 13 ;Init Command Block BRKADR EQU 14 BPBADR EQU 18 ; ;*************************************************************** ;** START OF DRIVER ;*************************************************************** ; CSEG SEGMENT ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ; ZRM205: DW -1 ;Links DW -1 ; DW 0010000000000000B ;Non-IBM format DW OFFSET STRAT ;Address of Strategy Routine DW OFFSET INTRP ;Address of Interrupt Routine DB 1,' ' ;Number of Units and Name ; BPBVEC: DW OFFSET BPB ; BPB: DW 512 ;Bytes/Sector DB 1 ;Allocation Units DW 0 ;No Reserved Sectors DB 1 ;One FAT DW 256 ;Directory Entries DW 1536 ;Total Sectors DB 0FFH ;Media Descriptor FATSIZ: DW 5 ;FAT Sectors ; ;*************************************************************** ; STRATEGY ENTRY POINT ;*************************************************************** ; STRAT - ; Just save address of request block. ; STRAT PROC FAR ; MOV WORD PTR CS:RBPSAV,BX MOV WORD PTR CS:RBPSAV+2,ES RET ; STRAT ENDP ; ;*************************************************************** ;** INTERRUPT ENTRY POINT ;*************************************************************** ; INTRP - ; Access request block and execute requested command. ; INTRP PROC FAR ; PUSH AX ; CLI ;Setup Our Own Stack MOV CS:SSSAVE,SS MOV CS:SPSAVE,SP MOV AX,CS MOV SS,AX MOV SP,OFFSET STACK STI ; PUSH BX ;Save Things PUSH CX PUSH ES PUSH SI PUSH DI ; CLD ;Pointers Increment LES BX,CS:RBPSAV ;Point at Request Block MOV SI,OFFSET TABLE ;Command Table Offset MOV CL,ES:COMAND[BX] ;Get Command Byte XOR CH,CH ;Make a Word SHL CX,1 ;Double Up ADD SI,CX ;Add to Table Offset JMP WORD PTR CS:[SI] ;Jump Through Table ; ; Command processing routines return here if no error. ; OKEXIT: MOV AH,00000001B ;Exit Good XOR AL,AL ; EXIT: LES BX,CS:RBPSAV ;Point at Request Block MOV ES:STATUS[BX],AX ;Status to Request Block ; POP DI ;Restore Things POP SI POP ES POP CX POP BX ; CLI ;Restore Stack MOV SS,CS:SSSAVE MOV SP,CS:SPSAVE STI POP AX RET ; INTRP ENDP ; ;*************************************************************** ;** COMMAND ROUTINE ADDRESS TABLE ;*************************************************************** ; TABLE DW INIT ;Initialize DW MEDCHK ;Media Check DW BLDBPB ;Build BPB DW ERROR ;IOCTL Input DW READ ;Read DW ERROR ;Read Nondestructive DW ERROR ;Input Status DW ERROR ;Input Flush DW WRITE ;Write DW WRITE ;Write With Verify DW ERROR ;Output Status DW ERROR ;Output Flush DW ERROR ;IOCTL Output ; ;*************************************************************** ;** COMMAND PROCESSING ROUTINES ;*************************************************************** ; ERROR - ; Illegal function request. ; ERROR: MOV AH,10000000B ;Set Error Bit MOV AL,00000011B ;Set Error Code 3 JMP EXIT ; ;*************************************************************** ; MEDCHK - ; Check media. Return no change status. ; MEDCHK: MOV ES:BYTE PTR MCSTAT[BX],1 JMP OKEXIT ; ;*************************************************************** ; BLDBPB - ; Return address of our BPB. ; BLDBPB: MOV ES:WORD PTR BCBADR[BX],OFFSET BPB MOV ES:WORD PTR BCBADR[BX+2],CS JMP OKEXIT ; ;*************************************************************** ; READ - ; Read data. ; READ: PUSH DS CALL GETADR ;Get Pointers and Sector Count ; RLOOP: JCXZ REXIT ;Done If No Sectors ; PUSH ES ;Save Pointers PUSH DS PUSH DI PUSH SI ; CLI CALL SELBNK ;Select Proper Bank ; PUSH ES ;Swap Pointers for Read PUSH DS POP ES POP DS XCHG SI,DI ; CALL RDSEC ;Read Sector to Buffer ; MOV AL,01110000B ;Select Bank Zero OUT CPORT,AL STI ; CALL WRSEC ;Write Sector from Buffer ; POP SI ;Restore Pointers POP DI POP DS POP ES ; CALL MOVNXT ;Move to Next Sector JMP RLOOP ;Do Next ; REXIT: POP DS ;End of Transfer JMP OKEXIT ; ;*************************************************************** ; WRITE - ; Write data. ; WRITE: PUSH DS CALL GETADR ;Get Pointers and Sector Count ; WLOOP: JCXZ WEXIT ;Done If No Sectors ; PUSH ES ;Save Pointers PUSH DS PUSH DI PUSH SI ; CALL RDSEC ;Read Sector to Buffer ; CLI CALL SELBNK ;Select Proper Memory Bank ; CALL WRSEC ;Write Sector from Buffer ; MOV AL,01110000B ;Select Bank Zero OUT CPORT,AL STI ; POP SI ;Restore Pointers POP DI POP DS POP ES ; CALL MOVNXT ;Move to Next Sector JMP WLOOP ;Do Next ; WEXIT: POP DS ;End of Transfer JMP OKEXIT ; ;*************************************************************** ;** SUBROUTINES ;*************************************************************** ; GETADR - ; Get Transfer Address into DS:SI, Sector Address into ES:DI, ; and Sector Count into CX. ; GETADR: LDS SI,ES:TRSADR[BX] ;Transfer Address MOV DX,ES:COUNT[BX] ;Sector Count MOV BX,ES:SECTOR[BX] ;Requested Sector MOV CX,5 ;Convert Sector to Paragraph SHL BX,CL MOV ES,BX XOR DI,DI ; PUSH SI ;Make Transfer Paragraph MOV CX,4 SHR SI,CL MOV AX,DS ADD AX,SI MOV DS,AX ; POP SI ;Correct Pointer Address AND SI,000FH ; MOV CX,DX ;Sector Count to CX RET ; ;*************************************************************** ; SELBNK - ; Select bank. On entry ES:DI contains sector paragraph. On ; exit, ES:DI point to sector address. ; ; SELBNK: MOV AX,ES ;Remove Bank Bits PUSH AX AND AX,0011111111100000B ADD AX,CS:START ;Make true address MOV ES,AX ; POP AX ;Select the Bank ROL AX,1 ROL AX,1 INC AL AND AL,00000011B OR AL,01110000B OUT CPORT,AL RET ; ;*************************************************************** ; RDSEC - ; Read sector from DS:SI to Sector Buffer. ; RDSEC: PUSH ES ;Save Things PUSH DI PUSH CX ; MOV AX,CS ;Point at Buffer MOV ES,AX MOV DI,OFFSET SECBUF MOV CX,256 ;Set Word Count ; REP MOVSW ;Transfer ; POP CX ;Restore Things POP DI POP ES RET ; ;*************************************************************** ; WRSEC - ; Write sector from Sector Buffer to ES:DI. ; WRSEC: PUSH DS ;Save Things PUSH SI PUSH CX ; MOV AX,CS ;Point at Buffer MOV DS,AX MOV SI,OFFSET SECBUF MOV CX,256 ;Set Word Count ; REP MOVSW ;Transfer ; POP CX ;Restore Things POP SI POP DS RET ; ;*************************************************************** ; MOVNXT - ; Move pointers to next sector and count the sector. ; MOVNXT: MOV AX,DS ;Move Pointers ADD AX,32 MOV DS,AX ; MOV AX,ES ADD AX,32 MOV ES,AX ; DEC CX ;One Sector Done RET ; ;*************************************************************** ;** STORAGE ;*************************************************************** ; RBPSAV DD 0 ;Request Block Address ; START DW 8000H ;Starting Paragraph ; SSSAVE DW ? ;Stack stuff SPSAVE DW ? ; SECBUF DW 256 DUP (?) ;Sector Buffer ; DW 128 DUP (?) ;Our Stack STACK: ; DVDEND: ;End of Resident Portion ; ;*************************************************************** ;** INITIALIZATION ;*************************************************************** ; INIT - ; This code is executed only once when the driver is loaded and ; is overwritten. First, check the command line for the option ; and setup starting paragraph if necessary. Then update some ; parameters in the Init Command Block. Then display the drive ; identification message. If reboot flag is set, check to see ; if the RAM disk has been initialized. If so, ask user if he ; wants to reinitialize. If initialization is required (or if ; reboot flag is not set), fill banks 1, 2, and 3 with '0E5' ; bytes to initialize the parity bit and the directory area. ; Then zero the FAT. Then install label entry in directory. ; Then get the Break Address into DS:DX and return. ; INIT: PUSH ES ;Process Options LES DI,ES:DWORD PTR BPBADR[BX] ; ILOOP: CALL SWS ;Skip White Space CMP ES:BYTE PTR [DI],CR ;If CR, Exit JZ INITX ; CMP ES:BYTE PTR [DI],'3' JNZ INIT0 ; MOV WORD PTR START,3000H MOV BYTE PTR BANK,'3' JMP SHORT INEXT ; INIT0: CMP ES:BYTE PTR [DI],'4' JNZ INIT1 ; MOV WORD PTR START,4000H MOV BYTE PTR BANK,'4' JMP SHORT INEXT ; INIT1: CMP ES:BYTE PTR [DI],'R' JNZ INEXT ; MOV BYTE PTR RBFLAG,255 ;Set The Flag ; INEXT: CALL FBC ;Find Break Character JMP SHORT ILOOP ; INITX: POP ES MOV ES:WORD PTR UNITS[BX],1 MOV ES:WORD PTR BRKADR[BX],OFFSET DVDEND MOV ES:WORD PTR BRKADR[BX+2],CS MOV ES:WORD PTR BPBADR[BX],OFFSET BPBVEC MOV ES:WORD PTR BPBADR[BX+2],CS ; MOV AH,19H ;Get Current Disk INT 21H MOV DL,AL MOV AH,0EH ;Select Disk INT 21H ; ADD AL,'A' ;Make Drive Letter MOV DRIVE,AL ;Put Into Message MOV DX,OFFSET DRVMSG ;Show Message MOV AH,09H INT 21H ; PUSH ES ;Save This CMP BYTE PTR RBFLAG,255 ;Check Reboot Flag JNZ INITZR ;Not True So Branch ; CLI MOV AL,00000001B ;Select Bank 1 (No Parity) OUT CPORT,AL ; MOV AX,START ;Set up for string compare MOV ES,AX ;Point to base of ZRAM205 MOV AX,WORD PTR FATSIZ MOV CL,9 SHL AX,CL MOV DI,AX ;Compute Label Address ; MOV SI,OFFSET DSKLBL ;Point to Label MOV CX,11 REPE CMPSB ;Compare ; CMP CX,0 ;If not End of String Then JNZ INITZR ;Compare Failed So Initialize ; MOV AL,01110000B ;Select Bank 0 OUT CPORT,AL STI ;Enable Interupts ; MOV DX,OFFSET ASKRFD ;Else, Ask If Initialize MOV AH,09H INT 21H ; MOV AH,0CH ;Flush the Type Ahead Buffer MOV AL,01H ;Get Character and Echo INT 21H ; PUSH AX MOV DX,OFFSET CRLF ;Clean Up Screen MOV AH,9 INT 21H POP AX ; CMP AL,'Y' ;Check the Response JZ INITZR ; CMP AL,'y' JZ INITZR ; JMP BYPASS ;Do Not Format. ; INITZR: CLI ;Initialize The Disk MOV AX,0 MOV ES,AX ;Starting Sector Number XOR DI,DI FRLOOP: PUSH ES CALL SELBNK ;Select Proper Bank ; MOV CX,32768 ;Setup Word Counter MOV AX,0E5E5H ;Filler Bytes REP STOSW ;Fill 64K ; POP ES MOV AX,ES ADD AX,1000H ;Move to Next 64K Bank MOV ES,AX ; CMP AH,0C0H ;Past Last Sector? JNE FRLOOP ;Loop if Not ; MOV AL,01110001B ;Select Bank 1 OUT CPORT,AL ; MOV AX,CS:START ;Point to Bank Start MOV ES,AX ; MOV AX,WORD PTR FATSIZ ;Get FAT Size MOV CL,8 ;Make Word Counter SHL AX,CL MOV CX,AX XOR DI,DI XOR AX,AX REP STOSW ;Zero the FAT ; MOV BYTE PTR ES:[0],0FFH MOV WORD PTR ES:[1],0FF7H ; MOV SI,OFFSET DSKLBL ;Setup Volume Label MOV AX,WORD PTR FATSIZ MOV CL,9 SHL AX,CL MOV DI,AX ;Compute Label Address MOV CL,32 REP MOVSB ; MOV AL,01110000B ;Select Bank 0 OUT CPORT,AL STI ; BYPASS: POP ES LDS DX,ES:DWORD PTR BRKADR[BX] JMP OKEXIT ; ;*************************************************************** ;** INITIALIZATION SUBROUTINES ;*************************************************************** ; SWS - ; Skip command line nulls, tabs and spaces. ; SWS: CMP ES:BYTE PTR [DI],' ' JZ MNC ; CMP ES:BYTE PTR [DI],TAB JZ MNC ; CMP ES:BYTE PTR [DI],0 JZ MNC ; RET ;Exit, Found Something ; MNC: INC DI ;Move to Next Character JMP SHORT SWS ; ;*************************************************************** ; FBC - ; Find a null or return. ; FBC: CMP ES:BYTE PTR [DI],0 JZ BCF ; CMP ES:BYTE PTR [DI],CR JZ BCF ; CMP ES:BYTE PTR [DI],' ' JZ BCF ; CMP ES:BYTE PTR [DI],TAB JZ BCF ; INC DI ;Move to Next Character JMP SHORT FBC ; BCF: RET ;Exit, Break Character Found ; ;*************************************************************** ;** INITIALIZATION DATA ;*************************************************************** ; DRVMSG DB '>>>>> ZRAM-205 (' BANK DB '8) Memory Disk Installed as Drive ' DRIVE DB 'A: <<<<<' CRLF DB CR,LF DB '$' ; RBFLAG DB 0 ;Reboot Flag ; ASKRFD DB 'The ZRAM-205 Memory Disk Has Already Been' DB ' Initialized.' DB CR,LF DB 'Do You Wish To Reinitialize (Y/N )? ' DB '$' ; DSKLBL DB 'FBE ZRAM205' DB 8 DB 0,0,0,0,0,0,0,0,0,0 DW 0100100000000000B ;Time = 09:00 DW 0000110001111111B ;Date = 3/31/1986 DB 0,0,0,0,0,0 ; CSEG ENDS END ZRM205