diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DEV/SMARTDRV | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/DEV/SMARTDRV')
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/ABOVE.ASM | 62 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/AB_MACRO.ASM | 180 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/CMACROS.INC | 932 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/DEVSYM.ASM | 128 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/DIRENT.ASM | 56 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/EMM.ASM | 223 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/FL13.ASM | 148 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/FLMES.ASM | 86 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/FLUSH13.C | 686 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/FLUSH13.LNK | 4 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/INT13.DOC | 369 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/LOADALL.ASM | 35 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/MAKEFILE | 19 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/MI.ASM | 18 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/OLI.CMP | 464 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM | 7587 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/SMARTDRV.LNK | 3 | ||||
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/SYSCALL.ASM | 147 |
18 files changed, 11147 insertions, 0 deletions
diff --git a/v4.0/src/DEV/SMARTDRV/ABOVE.ASM b/v4.0/src/DEV/SMARTDRV/ABOVE.ASM new file mode 100644 index 0000000..058124b --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/ABOVE.ASM | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | BREAK <ABOVE BOARD Equates> | ||
| 2 | |||
| 3 | ; | ||
| 4 | ; Assorted equates for use with Intel Above Board | ||
| 5 | ; | ||
| 6 | |||
| 7 | ; | ||
| 8 | ; EMM INT 67H Function codes | ||
| 9 | ; | ||
| 10 | ABOVE_STATUS EQU 40H | ||
| 11 | ABOVE_GET_SEG EQU 41H | ||
| 12 | ABOVE_GET_FREE EQU 42H | ||
| 13 | ABOVE_ALLOC EQU 43H | ||
| 14 | ABOVE_MAP EQU 44H | ||
| 15 | ABOVE_DEALLOC EQU 45H | ||
| 16 | ABOVE_GET_VERSION EQU 46H | ||
| 17 | ABOVE_SAVE_MAP_PID EQU 47H | ||
| 18 | ABOVE_RESTORE_MAP_PID EQU 48H | ||
| 19 | |||
| 20 | ; | ||
| 21 | ; NEW call not implemented in version 1.00 Above Board | ||
| 22 | ; | ||
| 23 | ABOVE_GETSET_MAP EQU 4EH | ||
| 24 | ; | ||
| 25 | ; 4EH AX equates for subfunctions | ||
| 26 | ; | ||
| 27 | ABOVE_GETSET_GET EQU 4E00H | ||
| 28 | ABOVE_GETSET_SET EQU 4E01H | ||
| 29 | ABOVE_GETSET_GETSET EQU 4E02H | ||
| 30 | |||
| 31 | |||
| 32 | ; | ||
| 33 | ; "Maintenance" calls | ||
| 34 | ; | ||
| 35 | ABOVE_GET_IOPORT EQU 49H | ||
| 36 | ABOVE_GET_MAP_ARRAY EQU 4AH | ||
| 37 | ABOVE_GET_PIDS EQU 4BH | ||
| 38 | ABOVE_GET_PAGES EQU 4CH | ||
| 39 | ABOVE_GET_ALLOC EQU 4DH | ||
| 40 | ABOVE_REALLOCATE_PID EQU 51H | ||
| 41 | |||
| 42 | |||
| 43 | ; | ||
| 44 | ; EMM INT 67H AH return values | ||
| 45 | ; | ||
| 46 | ABOVE_SUCCESSFUL EQU 0 | ||
| 47 | ABOVE_ERROR_SOFTWARE EQU 80H | ||
| 48 | ABOVE_ERROR_HARDWARE EQU 81H | ||
| 49 | ABOVE_ERROR_BUSY EQU 82H | ||
| 50 | ABOVE_ERROR_BAD_PID EQU 83H | ||
| 51 | ABOVE_ERROR_BAD_FUNC EQU 84H | ||
| 52 | ABOVE_ERROR_OUT_OF_PIDS EQU 85H | ||
| 53 | ABOVE_ERROR_MAP_CNTXT EQU 86H | ||
| 54 | ABOVE_ERROR_INSUFF_MEM EQU 87H | ||
| 55 | ABOVE_ERROR_INSUFF_FREE EQU 88H | ||
| 56 | ABOVE_ERROR_ALLOC_ZERO EQU 89H | ||
| 57 | ABOVE_ERROR_LOG_INVALID EQU 8AH | ||
| 58 | ABOVE_ERROR_PHYS_INVALID EQU 8BH | ||
| 59 | ABOVE_ERROR_CNTXT_NO_STACK EQU 8CH | ||
| 60 | ABOVE_ERROR_SECOND_SAVE EQU 8DH | ||
| 61 | ABOVE_ERROR_NO_CNTXT EQU 8EH | ||
| 62 | ABOVE_ERROR_BAD_PARM EQU 8FH | ||
diff --git a/v4.0/src/DEV/SMARTDRV/AB_MACRO.ASM b/v4.0/src/DEV/SMARTDRV/AB_MACRO.ASM new file mode 100644 index 0000000..f15367a --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/AB_MACRO.ASM | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2 | ; | ||
| 3 | ; MACRO definitions for expanded memory manager | ||
| 4 | ; | ||
| 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6 | ; | ||
| 7 | ; 1. MACRO to save mapping context in case somebody else has | ||
| 8 | ; mapped the page registers. | ||
| 9 | ; | ||
| 10 | save_mapping_context macro | ||
| 11 | local save_agn_m,save_err_m,save_ok_m,save_exit_m | ||
| 12 | ; | ||
| 13 | ; the save mapping call for the above board --> | ||
| 14 | ; | ||
| 15 | ; mov ah,47h | ||
| 16 | ; mov dx,handle | ||
| 17 | ; int 67h | ||
| 18 | ; | ||
| 19 | ; on return ax = 0 signifies success | ||
| 20 | ; | ||
| 21 | ; | ||
| 22 | push ax ; save registers | ||
| 23 | push dx | ||
| 24 | ; | ||
| 25 | ; set up emm registers and execute call to save mapping context | ||
| 26 | ; | ||
| 27 | save_agn_m: | ||
| 28 | mov dx,cs:[above_pid] ; get emm handle | ||
| 29 | mov ah,above_save_map_pid ; save map call | ||
| 30 | int 67h ; call the manager | ||
| 31 | or ah,ah ; is there an error? | ||
| 32 | jz save_ok_m ; if not we are done | ||
| 33 | ; | ||
| 34 | ; error in saving mapping context, check for error | ||
| 35 | ; | ||
| 36 | cmp ah,above_error_busy ; if the emm manager was busy | ||
| 37 | jz save_agn_m ; we would like to try again | ||
| 38 | ; | ||
| 39 | ; unrecoverable error, indicate error type in al | ||
| 40 | ; | ||
| 41 | pop dx | ||
| 42 | pop dx ; pop the regs off the stack | ||
| 43 | ; | ||
| 44 | mov al,0aah ; drive not ready | ||
| 45 | cmp ah,above_error_cntxt_no_stack ; | ||
| 46 | jz save_err_m | ||
| 47 | cmp ah,above_error_second_save ; | ||
| 48 | ja save_err_m | ||
| 49 | mov al,0bbh ; general failure | ||
| 50 | save_err_m: | ||
| 51 | stc | ||
| 52 | jmp short save_exit_m | ||
| 53 | save_ok_m: | ||
| 54 | clc | ||
| 55 | pop dx | ||
| 56 | pop ax ; restore registers | ||
| 57 | save_exit_m: | ||
| 58 | endm | ||
| 59 | ; | ||
| 60 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 61 | ; | ||
| 62 | ; 2. MACRO to restore the mapping context saved earlier | ||
| 63 | ; | ||
| 64 | restore_mapping_context macro | ||
| 65 | local rest_agn_m, rest_ok_m, rest_exit_m | ||
| 66 | ; | ||
| 67 | ; the restore above map call --> | ||
| 68 | ; | ||
| 69 | ; mov ah,48h | ||
| 70 | ; mov dx,handle | ||
| 71 | ; int 67h | ||
| 72 | ; ah = 0 is success | ||
| 73 | ; | ||
| 74 | ; | ||
| 75 | push ax | ||
| 76 | pushf | ||
| 77 | ; | ||
| 78 | rest_agn_m: | ||
| 79 | mov dx,cs:[above_pid] ; get emm handle | ||
| 80 | mov ah,above_restore_map_pid ; restore map call | ||
| 81 | int 67h ; call manager | ||
| 82 | or ah,ah ; is there any error | ||
| 83 | jz rest_ok_m ; if not go to finish up | ||
| 84 | ; | ||
| 85 | ; error condition, check for recoverable error | ||
| 86 | ; | ||
| 87 | cmp ah,above_error_busy ; if manager was busy | ||
| 88 | jz rest_agn_m ; we sure can try again | ||
| 89 | cmp ah,above_error_no_cntxt ; | ||
| 90 | jz rest_ok_m ; ignore invalid pid error | ||
| 91 | ; | ||
| 92 | ; unrecoverable error | ||
| 93 | ; | ||
| 94 | pop dx | ||
| 95 | pop dx | ||
| 96 | mov al,0bbh ; general failure | ||
| 97 | stc | ||
| 98 | jmp short rest_exit_m | ||
| 99 | ; | ||
| 100 | rest_ok_m: | ||
| 101 | popf | ||
| 102 | pop ax | ||
| 103 | rest_exit_m: | ||
| 104 | ; | ||
| 105 | endm | ||
| 106 | ; | ||
| 107 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 108 | ; | ||
| 109 | ; 3. MACRO to map a page in the physical page map onto a logical | ||
| 110 | ; page. | ||
| 111 | ; | ||
| 112 | ; the map above page requires | ||
| 113 | ; mov ah,44h | ||
| 114 | ; mov dx,handle | ||
| 115 | ; mov al,physical_page# (0-3) | ||
| 116 | ; mov bx,logical_page# | ||
| 117 | ; int 67H | ||
| 118 | ; ah = 0 success and this routine zaps ax,dx and bx | ||
| 119 | ; | ||
| 120 | map_page macro | ||
| 121 | local map_agn_m,map_exit_m,map_fin_m | ||
| 122 | ; | ||
| 123 | mov ah,above_map ; function map page | ||
| 124 | mov dx,cs:[above_pid] ; get emm handle | ||
| 125 | ; | ||
| 126 | push ax | ||
| 127 | ; | ||
| 128 | map_agn_m: | ||
| 129 | pop ax | ||
| 130 | push ax | ||
| 131 | push bx | ||
| 132 | push dx ; "damn call above_map zaps these registers" | ||
| 133 | ; | ||
| 134 | int 67h ; map call | ||
| 135 | pop dx | ||
| 136 | pop bx | ||
| 137 | ; | ||
| 138 | or ah,ah ; is there an error? | ||
| 139 | jz map_fin_m ; if not go to finish up | ||
| 140 | ; | ||
| 141 | ; error condition - check for recoverable error | ||
| 142 | ; | ||
| 143 | cmp ah,above_error_busy ; if manager was busy | ||
| 144 | jz map_agn_m ; we sure can try again | ||
| 145 | ; | ||
| 146 | ; unrecoverable error | ||
| 147 | ; | ||
| 148 | pop ax | ||
| 149 | mov al,0aah ; device not ready error | ||
| 150 | stc | ||
| 151 | jmp short map_exit_m | ||
| 152 | ; | ||
| 153 | ; exit point | ||
| 154 | ; | ||
| 155 | map_fin_m: | ||
| 156 | clc | ||
| 157 | pop ax | ||
| 158 | map_exit_m: | ||
| 159 | ; | ||
| 160 | endm | ||
| 161 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 162 | ; | ||
| 163 | ; OTHER MACROS | ||
| 164 | ; | ||
| 165 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 166 | ; | ||
| 167 | ; 1) MACRO to switch es:di with ds:si | ||
| 168 | ; | ||
| 169 | src_dest_switch macro | ||
| 170 | ; | ||
| 171 | push ds | ||
| 172 | push es | ||
| 173 | push si | ||
| 174 | mov si,di | ||
| 175 | pop di | ||
| 176 | pop ds | ||
| 177 | pop es | ||
| 178 | ; | ||
| 179 | endm | ||
| 180 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
diff --git a/v4.0/src/DEV/SMARTDRV/CMACROS.INC b/v4.0/src/DEV/SMARTDRV/CMACROS.INC new file mode 100644 index 0000000..28dcb1b --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/CMACROS.INC | |||
| @@ -0,0 +1,932 @@ | |||
| 1 | comment $ | ||
| 2 | cmacros - assembly macros for interfacing to HHLs | ||
| 3 | (C)Copyright 1988 Microsoft Corporation | ||
| 4 | $ | ||
| 5 | if1 | ||
| 6 | outif MACRO name,defval,onmsg,offmsg | ||
| 7 | ifndef name | ||
| 8 | ifb <defval> | ||
| 9 | name=0 | ||
| 10 | else | ||
| 11 | name=defval | ||
| 12 | endif | ||
| 13 | endif | ||
| 14 | if name | ||
| 15 | name=1 | ||
| 16 | ifnb <onmsg> | ||
| 17 | %out ! onmsg | ||
| 18 | endif | ||
| 19 | else | ||
| 20 | ifnb <offmsg> | ||
| 21 | %out ! offmsg | ||
| 22 | endif | ||
| 23 | endif | ||
| 24 | endm | ||
| 25 | |||
| 26 | error MACRO msg | ||
| 27 | bug | ||
| 28 | %out E r r o r ----- msg | ||
| 29 | ENDM | ||
| 30 | %out cMacros Version 1.04 | ||
| 31 | outif memS,0,<Small Model> | ||
| 32 | outif memM,0,<Medium Model> | ||
| 33 | outif memL,0,<Large Model> | ||
| 34 | outif memC,0,<Compact Model> | ||
| 35 | outif memH,0,<Huge Model> | ||
| 36 | memMOD= memS + memM + memL + memC + memH | ||
| 37 | if memMOD ne 1 | ||
| 38 | if memMOD eq 0 | ||
| 39 | memS= 1 | ||
| 40 | outif memS,0,<Small Model> | ||
| 41 | else | ||
| 42 | error <Must have only 1 memory model selected> | ||
| 43 | endif | ||
| 44 | endif | ||
| 45 | sizeC= memM + memL + memH | ||
| 46 | sizeD= memL + memC + (memH*2) | ||
| 47 | outif ?DF,0,<No segments or groups will be defined> | ||
| 48 | outif ?WIN,0,<Windows Support> | ||
| 49 | outif ?PLM,0,<PLM calling convention> | ||
| 50 | endif | ||
| 51 | .XCREF | ||
| 52 | .XCREF ?N,?AX,?AH,?AL,?BX,?BH | ||
| 53 | .XCREF ?BL,?CX,?CH,?CL,?DX,?DH | ||
| 54 | .XCREF ?DL,?SI,?DI,?ES,?DS,?BP | ||
| 55 | .XCREF ?SP,?SS,?CS | ||
| 56 | .XCREF ?RSL,?CPD,?argl,?argc,?BA | ||
| 57 | .XCREF ?ACB,???,?PO | ||
| 58 | .XCREF ?PAS,?PC | ||
| 59 | .XCREF Uconcat,mPush,mPop | ||
| 60 | .XCREF ?RI,?pp,?pp1,?al1 | ||
| 61 | .XCREF ?aD,?AP,?Atal,?pd,?dd,?dd1,?ex1,?cas | ||
| 62 | .XCREF ?pg,?pg1,?aloc,?cs1,?cs2 | ||
| 63 | .XCREF ?lb1,?lblpu | ||
| 64 | .XCREF ?DF,?PLM,?WIN,?IA,?PU,?ADJ | ||
| 65 | .CREF | ||
| 66 | ?RSL = 0 | ||
| 67 | ?CPD = 0 | ||
| 68 | ?ArgL = 0 | ||
| 69 | ?ArgC = 0 | ||
| 70 | ?BA = 0 | ||
| 71 | ?ACB = 0 | ||
| 72 | ??? = 0 | ||
| 73 | ?PO = 0 | ||
| 74 | ?PAS = 0 | ||
| 75 | ?PC = 0 | ||
| 76 | ?IA = 0 | ||
| 77 | ?PU = 0 | ||
| 78 | ?ADJ = 0 | ||
| 79 | ?lblpu = 0 | ||
| 80 | ?N = 0000000000000000B | ||
| 81 | ?AX = 0000000000000011B | ||
| 82 | ?AH = 0000000000000001B | ||
| 83 | ?AL = 0000000000000010B | ||
| 84 | ?BX = 0000000000001100B | ||
| 85 | ?BH = 0000000000000100B | ||
| 86 | ?BL = 0000000000001000B | ||
| 87 | ?CX = 0000000000110000B | ||
| 88 | ?CH = 0000000000010000B | ||
| 89 | ?CL = 0000000000100000B | ||
| 90 | ?DX = 0000000011000000B | ||
| 91 | ?DH = 0000000001000000B | ||
| 92 | ?DL = 0000000010000000B | ||
| 93 | ?SI = 0000000100000000B | ||
| 94 | ?DI = 0000001000000000B | ||
| 95 | ?ES = 0000010000000000B | ||
| 96 | ?DS = 0000100000000000B | ||
| 97 | ?BP = 0001000000000000B | ||
| 98 | ?SP = 0010000000000000B | ||
| 99 | ?SS = 0100000000000000B | ||
| 100 | ?CS = 1000000000000000B | ||
| 101 | uconcat macro n1,n2,o1,o2,p1,p2 | ||
| 102 | n1&n2 o1&o2 p1&p2 | ||
| 103 | endm | ||
| 104 | mpush macro rV | ||
| 105 | irp x,<ax,bx,cx,dx,si,di,es,ds,bp,sp,ss,cs> | ||
| 106 | if rV AND ?&&x | ||
| 107 | push x | ||
| 108 | endif | ||
| 109 | endm | ||
| 110 | endm | ||
| 111 | mpop macro rV | ||
| 112 | irp x,<cs,ss,sp,bp,ds,es,di,si,dx,cx,bx,ax> | ||
| 113 | if rV AND ?&&x | ||
| 114 | pop x | ||
| 115 | endif | ||
| 116 | endm | ||
| 117 | endm | ||
| 118 | SAVE macro rL | ||
| 119 | ?RSL = 0 | ||
| 120 | ?RI ?RSL,<rL> | ||
| 121 | endm | ||
| 122 | smashes macro n,rL | ||
| 123 | .xcref | ||
| 124 | .xcref ?SM&n | ||
| 125 | .cref | ||
| 126 | ?SM&n = 0 | ||
| 127 | ?RI ?SM&n,<rL> | ||
| 128 | endm | ||
| 129 | ?RI macro n,rL | ||
| 130 | irp x,<rL> | ||
| 131 | ifdef ?&&x | ||
| 132 | n = n or ?&&x | ||
| 133 | endif | ||
| 134 | endm | ||
| 135 | endm | ||
| 136 | parmB macro nl | ||
| 137 | ?pp <&nL>,<byte>,2,1 | ||
| 138 | endm | ||
| 139 | parmW macro nl | ||
| 140 | ?pp <&nL>,<word>,2,2 | ||
| 141 | endm | ||
| 142 | parmD macro nl | ||
| 143 | ife ?PLM | ||
| 144 | irp x,<nL> | ||
| 145 | ?pp <&&x>,<DWORD>,0,4 | ||
| 146 | ?pp <Off_&&x>,<WORD>,2,2 | ||
| 147 | ?pp <Seg_&&x>,<WORD>,2,2 | ||
| 148 | endm | ||
| 149 | else | ||
| 150 | irp x,<nL> | ||
| 151 | ?pp <Seg_&&x>,<WORD>,2,2 | ||
| 152 | ?pp <Off_&&x>,<WORD>,2,2 | ||
| 153 | ?pp <&&x>,<DWORD>,0,4 | ||
| 154 | endm | ||
| 155 | endif | ||
| 156 | endm | ||
| 157 | parmQ macro nl | ||
| 158 | ?pp <&nL>,<QWORD>,8,8 | ||
| 159 | endm | ||
| 160 | parmT macro nl | ||
| 161 | ?pp <&nL>,<TBYTE>,10,10 | ||
| 162 | endm | ||
| 163 | if sizeC | ||
| 164 | parmCP macro nl | ||
| 165 | parmD <nl> | ||
| 166 | endm | ||
| 167 | else | ||
| 168 | parmCP macro nl | ||
| 169 | parmW <nl> | ||
| 170 | endm | ||
| 171 | endif | ||
| 172 | if sizeD | ||
| 173 | parmDP macro nl | ||
| 174 | parmD <nl> | ||
| 175 | endm | ||
| 176 | else | ||
| 177 | parmDP macro nl | ||
| 178 | parmW <nl> | ||
| 179 | endm | ||
| 180 | endif | ||
| 181 | ?pp macro nL,t,l,s | ||
| 182 | if ?CPD | ||
| 183 | .xcref | ||
| 184 | ife ?PLM | ||
| 185 | irp x,<nL> | ||
| 186 | ?pp1 x,<t>,%?PO,%?adj,%(?PO+?adj) | ||
| 187 | ?PO = ?PO + l | ||
| 188 | .xcref ?T&&x | ||
| 189 | ?T&&x = s | ||
| 190 | endm | ||
| 191 | else | ||
| 192 | irp x,<nL> | ||
| 193 | ?PO = ?PO + l | ||
| 194 | ?pp1 x,<t>,%?PO,%?adj,%(?PO+?adj) | ||
| 195 | .xcref ?T&&x | ||
| 196 | ?T&&x = s | ||
| 197 | endm | ||
| 198 | endif | ||
| 199 | .cref | ||
| 200 | else | ||
| 201 | %out Parm(s) "&nl" declared outside proc def. | ||
| 202 | endif | ||
| 203 | endm | ||
| 204 | ?pp1 macro n,t,o,a,b | ||
| 205 | ife ?PLM | ||
| 206 | n equ t ptr [bp+b] | ||
| 207 | else | ||
| 208 | n equ t ptr [bp+a+?PO-o] | ||
| 209 | endif | ||
| 210 | endm | ||
| 211 | localB macro nL | ||
| 212 | ?aLoc <&nL>,<BYTE ptr>,1,1,0 | ||
| 213 | endm | ||
| 214 | localW macro nL | ||
| 215 | ?aLoc <&nL>,<WORD PTR>,2,2,1 | ||
| 216 | endm | ||
| 217 | localD macro nL | ||
| 218 | irp x,<nL> | ||
| 219 | ?aLoc <Seg_&&x>,<WORD PTR>,2,2,1 | ||
| 220 | ?aLoc <Off_&&x>,<WORD PTR>,2,2,1 | ||
| 221 | ?aLoc <&&x>,<DWORD PTR>,0,4,1 | ||
| 222 | endm | ||
| 223 | endm | ||
| 224 | localQ macro nL | ||
| 225 | ?aLoc <&nL>,<QWORD PTR>,8,8,1 | ||
| 226 | endm | ||
| 227 | localT macro nL | ||
| 228 | ?aLoc <&nL>,<TBYTE PTR>,10,10,1 | ||
| 229 | endm | ||
| 230 | if sizeC | ||
| 231 | localCP macro nL | ||
| 232 | localD <nL> | ||
| 233 | endm | ||
| 234 | else | ||
| 235 | localCP macro nL | ||
| 236 | localW <nL> | ||
| 237 | endm | ||
| 238 | endif | ||
| 239 | if sizeD | ||
| 240 | localDP macro nL | ||
| 241 | localD <nL> | ||
| 242 | endm | ||
| 243 | else | ||
| 244 | localDP macro nL | ||
| 245 | localW <nL> | ||
| 246 | endm | ||
| 247 | endif | ||
| 248 | localV macro n,a | ||
| 249 | ?aLoc <&n>,,%(&a),0,1 | ||
| 250 | endm | ||
| 251 | ?aLoc macro nL,t,l,s,a | ||
| 252 | if ?CPD | ||
| 253 | .xcref | ||
| 254 | ??? = ??? + l | ||
| 255 | if a | ||
| 256 | ??? = ((??? + 1) AND 0FFFEH) | ||
| 257 | endif | ||
| 258 | irp x,<nL> | ||
| 259 | ?aL1 x,<t>,%??? | ||
| 260 | .xcref ?T&&x | ||
| 261 | ?T&&x = s | ||
| 262 | endm | ||
| 263 | .cref | ||
| 264 | else | ||
| 265 | %out Locals "&nl" declared outside procedure def. | ||
| 266 | endif | ||
| 267 | endm | ||
| 268 | ?aL1 macro n,t,o | ||
| 269 | if ?IA | ||
| 270 | n equ t [bp-?IA-o] | ||
| 271 | else | ||
| 272 | n equ t [bp-o] | ||
| 273 | endif | ||
| 274 | endm | ||
| 275 | globalB macro n,i,s | ||
| 276 | ?aD <n>,1 | ||
| 277 | ?dd n,1,<BYTE>,<DB>,<i>,<s> | ||
| 278 | endm | ||
| 279 | globalW macro n,i,s | ||
| 280 | ?aD <n>,2 | ||
| 281 | ?dd n,1,<WORD>,<DW>,<i>,<s> | ||
| 282 | endm | ||
| 283 | globalD macro n,i,s | ||
| 284 | ?aD <n>,4 | ||
| 285 | ?dd n,1,<DWORD>,<DD>,<i>,<s> | ||
| 286 | endm | ||
| 287 | globalQ macro n,i,s | ||
| 288 | ?aD <n>,8 | ||
| 289 | ?dd n,1,<QWORD>,<DQ>,<i>,<s> | ||
| 290 | endm | ||
| 291 | globalT macro n,i,s | ||
| 292 | ?aD <n>,10 | ||
| 293 | ?dd n,1,<TBYTE>,<DT>,<i>,<s> | ||
| 294 | endm | ||
| 295 | if sizeC | ||
| 296 | globalCP macro n,i,s | ||
| 297 | globalD n,<i>,<s> | ||
| 298 | endm | ||
| 299 | else | ||
| 300 | globalCP macro n,i,s | ||
| 301 | globalW n,<i>,<s> | ||
| 302 | endm | ||
| 303 | endif | ||
| 304 | if sizeD | ||
| 305 | globalDP macro n,i,s | ||
| 306 | globalD n,<i>,<s> | ||
| 307 | endm | ||
| 308 | else | ||
| 309 | globalDP macro n,i,s | ||
| 310 | globalW n,<i>,<s> | ||
| 311 | endm | ||
| 312 | endif | ||
| 313 | staticB macro n,i,s | ||
| 314 | ?aD <n>,1 | ||
| 315 | ?dd n,0,<BYTE>,<DB>,<i>,<s> | ||
| 316 | endm | ||
| 317 | staticW macro n,i,s | ||
| 318 | ?aD <n>,2 | ||
| 319 | ?dd n,0,<WORD>,<DW>,<i>,<s> | ||
| 320 | endm | ||
| 321 | staticD macro n,i,s | ||
| 322 | ?aD <n>,4 | ||
| 323 | ?dd n,0,<DWORD>,<DD>,<i>,<s> | ||
| 324 | endm | ||
| 325 | staticQ macro n,i,s | ||
| 326 | ?aD <n>,8 | ||
| 327 | ?dd n,0,<QWORD>,<DQ>,<i>,<s> | ||
| 328 | endm | ||
| 329 | staticT macro n,i,s | ||
| 330 | ?aD <n>,10 | ||
| 331 | ?dd n,0,<TBYTE>,<DT>,<i>,<s> | ||
| 332 | endm | ||
| 333 | if sizeC | ||
| 334 | staticCP macro n,i,s | ||
| 335 | staticD n,<i>,<s> | ||
| 336 | endm | ||
| 337 | else | ||
| 338 | staticCP macro n,i,s | ||
| 339 | staticW n,<i>,<s> | ||
| 340 | endm | ||
| 341 | endif | ||
| 342 | if sizeD | ||
| 343 | staticDP macro n,i,s | ||
| 344 | staticD n,<i>,<s> | ||
| 345 | endm | ||
| 346 | else | ||
| 347 | staticDP macro n,i,s | ||
| 348 | staticW n,<i>,<s> | ||
| 349 | endm | ||
| 350 | endif | ||
| 351 | ?dd macro n,p,t,d,i,s | ||
| 352 | ife ?PLM | ||
| 353 | n label t | ||
| 354 | ?dd1 _&n,p,<d>,<i>,<s> | ||
| 355 | else | ||
| 356 | ?dd1 n,p,<d>,<i>,<s> | ||
| 357 | endif | ||
| 358 | endm | ||
| 359 | ?dd1 macro n,p,d,i,s | ||
| 360 | if p | ||
| 361 | PUBLIC n | ||
| 362 | endif | ||
| 363 | ifb <s> | ||
| 364 | n d i | ||
| 365 | else | ||
| 366 | ifb <i> | ||
| 367 | n d s DUP (?) | ||
| 368 | else | ||
| 369 | n d s DUP (i) | ||
| 370 | endif | ||
| 371 | endif | ||
| 372 | endm | ||
| 373 | externB macro nL | ||
| 374 | ?ex1 <&nL>,1,<BYTE> | ||
| 375 | endm | ||
| 376 | externW macro nL | ||
| 377 | ?ex1 <&nL>,2,<WORD> | ||
| 378 | endm | ||
| 379 | externD macro nL | ||
| 380 | ?ex1 <&nL>,4,<DWORD> | ||
| 381 | endm | ||
| 382 | externQ macro nL | ||
| 383 | ?ex1 <&nL>,8,<QWORD> | ||
| 384 | endm | ||
| 385 | externT macro nL | ||
| 386 | ?ex1 <&nL>,10,<TBYTE> | ||
| 387 | endm | ||
| 388 | externNP macro nL | ||
| 389 | ?ex1 <&nL>,2,<NEAR> | ||
| 390 | endm | ||
| 391 | externFP macro nL | ||
| 392 | ?ex1 <&nL>,4,<FAR> | ||
| 393 | endm | ||
| 394 | if sizeC | ||
| 395 | externP macro nL | ||
| 396 | ?ex1 <&nL>,4,<FAR> | ||
| 397 | endm | ||
| 398 | else | ||
| 399 | externP macro nL | ||
| 400 | ?ex1 <&nL>,2,<NEAR> | ||
| 401 | endm | ||
| 402 | endif | ||
| 403 | if sizeC | ||
| 404 | externCP macro nL | ||
| 405 | ?ex1 <&nL>,4,<DWORD> | ||
| 406 | endm | ||
| 407 | else | ||
| 408 | externCP macro nL | ||
| 409 | ?ex1 <&nL>,2,<WORD> | ||
| 410 | endm | ||
| 411 | endif | ||
| 412 | if sizeD | ||
| 413 | externDP macro nL | ||
| 414 | ?ex1 <&nL>,4,<DWORD> | ||
| 415 | endm | ||
| 416 | else | ||
| 417 | externDP macro nL | ||
| 418 | ?ex1 <&nL>,2,<WORD> | ||
| 419 | endm | ||
| 420 | endif | ||
| 421 | ?ex1 macro nL,s,d | ||
| 422 | irp x,<nL> | ||
| 423 | .xcref | ||
| 424 | .xcref ?T&&x | ||
| 425 | .cref | ||
| 426 | ?T&&x = s | ||
| 427 | ife ?PLM | ||
| 428 | extrn _&&x:&d | ||
| 429 | x equ _&&x | ||
| 430 | else | ||
| 431 | extrn x:&d | ||
| 432 | endif | ||
| 433 | endm | ||
| 434 | endm | ||
| 435 | labelB macro nL | ||
| 436 | ?lb1 <&nL>,1,<BYTE> | ||
| 437 | endm | ||
| 438 | labelW macro nL | ||
| 439 | ?lb1 <&nL>,2,<WORD> | ||
| 440 | endm | ||
| 441 | labelD macro nL | ||
| 442 | ?lb1 <&nL>,4,<DWORD> | ||
| 443 | endm | ||
| 444 | labelQ macro nL | ||
| 445 | ?lb1 <&nL>,8,<QWORD> | ||
| 446 | endm | ||
| 447 | labelT macro nL | ||
| 448 | ?lb1 <&nL>,10,<TBYTE> | ||
| 449 | endm | ||
| 450 | labelNP macro nL | ||
| 451 | ?lb1 <&nL>,2,<NEAR> | ||
| 452 | endm | ||
| 453 | labelFP macro nL | ||
| 454 | ?lb1 <&nL>,4,<FAR> | ||
| 455 | endm | ||
| 456 | if sizeC | ||
| 457 | labelP macro nL | ||
| 458 | ?lb1 <&nL>,4,<FAR> | ||
| 459 | endm | ||
| 460 | else | ||
| 461 | labelP macro nL | ||
| 462 | ?lb1 <&nL>,2,<NEAR> | ||
| 463 | endm | ||
| 464 | endif | ||
| 465 | if sizeC | ||
| 466 | labelCP macro nL | ||
| 467 | ?lb1 <&nL>,4,<DWORD> | ||
| 468 | endm | ||
| 469 | else | ||
| 470 | labelCP macro nL | ||
| 471 | ?lb1 <&nL>,2,<WORD> | ||
| 472 | endm | ||
| 473 | endif | ||
| 474 | if sizeD | ||
| 475 | labelDP macro nL | ||
| 476 | ?lb1 <&nL>,4,<DWORD> | ||
| 477 | endm | ||
| 478 | else | ||
| 479 | labelDP macro nL | ||
| 480 | ?lb1 <&nL>,2,<WORD> | ||
| 481 | endm | ||
| 482 | endif | ||
| 483 | ?lb1 macro nL,s,d | ||
| 484 | ?lblpu = 0 | ||
| 485 | irp x,<nL> | ||
| 486 | ifidn <x>,<PUBLIC> | ||
| 487 | ?lblpu = 1 | ||
| 488 | else | ||
| 489 | .xcref | ||
| 490 | .xcref ?T&&x | ||
| 491 | .cref | ||
| 492 | ?T&&x = s | ||
| 493 | ife ?PLM | ||
| 494 | if ?lblpu | ||
| 495 | public _&&x | ||
| 496 | endif | ||
| 497 | _&&x label &d | ||
| 498 | x equ _&&x | ||
| 499 | else | ||
| 500 | if ?lblpu | ||
| 501 | public x | ||
| 502 | endif | ||
| 503 | x label &d | ||
| 504 | endif | ||
| 505 | endif | ||
| 506 | endm | ||
| 507 | endm | ||
| 508 | defB macro nL | ||
| 509 | ?aD <&nL>,1 | ||
| 510 | endm | ||
| 511 | defW macro nL | ||
| 512 | ?aD <&nL>,2 | ||
| 513 | endm | ||
| 514 | defD macro nL | ||
| 515 | ?aD <&nL>,4 | ||
| 516 | endm | ||
| 517 | defQ macro nL | ||
| 518 | ?aD <&nL>,8 | ||
| 519 | endm | ||
| 520 | defT macro nL | ||
| 521 | ?aD <&nL>,10 | ||
| 522 | endm | ||
| 523 | if sizeC | ||
| 524 | defCP macro nL | ||
| 525 | defD <nL> | ||
| 526 | endm | ||
| 527 | else | ||
| 528 | defCP macro nL | ||
| 529 | defW <nL> | ||
| 530 | endm | ||
| 531 | endif | ||
| 532 | if sizeD | ||
| 533 | defDP macro nL | ||
| 534 | defD <nL> | ||
| 535 | endm | ||
| 536 | else | ||
| 537 | defDP macro nL | ||
| 538 | defW <nL> | ||
| 539 | endm | ||
| 540 | endif | ||
| 541 | ?aD macro nL,s | ||
| 542 | irp x,<nL> | ||
| 543 | .xcref | ||
| 544 | .xcref ?T&&x | ||
| 545 | .cref | ||
| 546 | ?T&&x = s | ||
| 547 | endm | ||
| 548 | endm | ||
| 549 | regPtr macro n,S,O | ||
| 550 | .xcref | ||
| 551 | .xcref ?T&n,?SR&n,?OR&n | ||
| 552 | .cref | ||
| 553 | ?T&n = 0FFFFH | ||
| 554 | ?SR&n = 0 | ||
| 555 | ?RI ?SR&n,<&S> | ||
| 556 | ?OR&n = 0 | ||
| 557 | ?RI ?OR&n,<&O> | ||
| 558 | endm | ||
| 559 | arg macro aL | ||
| 560 | irp x,<aL> | ||
| 561 | ?argc = ?argc + 1 | ||
| 562 | ?Atal <x>,%?argc | ||
| 563 | endm | ||
| 564 | endm | ||
| 565 | ?Atal macro n,i | ||
| 566 | .xcref | ||
| 567 | .xcref ?ALI&i | ||
| 568 | .cref | ||
| 569 | ?ALI&i ¯o | ||
| 570 | ?AP n | ||
| 571 | &endm | ||
| 572 | endm | ||
| 573 | ?AP macro n | ||
| 574 | ?argl = ?argl + 2 | ||
| 575 | ifdef ?T&n | ||
| 576 | ife ?T&n-1 | ||
| 577 | push word ptr (n) | ||
| 578 | exitm | ||
| 579 | endif | ||
| 580 | ife ?T&n-2 | ||
| 581 | push n | ||
| 582 | exitm | ||
| 583 | endif | ||
| 584 | ife ?T&n-4 | ||
| 585 | push word ptr (n)+2 | ||
| 586 | push word ptr (n) | ||
| 587 | ?argl = ?argl + 2 | ||
| 588 | exitm | ||
| 589 | endif | ||
| 590 | ife ?T&n-8 | ||
| 591 | push word ptr (n)+6 | ||
| 592 | push word ptr (n)+4 | ||
| 593 | push word ptr (n)+2 | ||
| 594 | push word ptr (n) | ||
| 595 | ?argl = ?argl + 6 | ||
| 596 | exitm | ||
| 597 | endif | ||
| 598 | ife ?T&n-0FFFFH | ||
| 599 | mpush %(?SR&n),1 | ||
| 600 | mpush %(?OR&n),1 | ||
| 601 | ?argl = ?argl + 2 | ||
| 602 | exitm | ||
| 603 | endif | ||
| 604 | ife ?T&n | ||
| 605 | push word ptr (n) | ||
| 606 | exitm | ||
| 607 | endif | ||
| 608 | endif | ||
| 609 | push n | ||
| 610 | endm | ||
| 611 | ife ?PLM | ||
| 612 | ccall macro n,a,sleaze | ||
| 613 | ifnb <a> | ||
| 614 | Arg <a> | ||
| 615 | endif | ||
| 616 | ifdef ?SM&n | ||
| 617 | ?RSL = ?RSL AND ?SM&n | ||
| 618 | endif | ||
| 619 | mpush %?RSL | ||
| 620 | ?argl = 0 | ||
| 621 | ?ACB = ?argc | ||
| 622 | rept ?argc | ||
| 623 | uconcat <?ALI>,%?ACB | ||
| 624 | uconcat <purge>,,<?ALI>,%?ACB | ||
| 625 | ?ACB = ?ACB - 1 | ||
| 626 | endm | ||
| 627 | ife ?PLM | ||
| 628 | ifb <sleaze> | ||
| 629 | call _&n | ||
| 630 | else | ||
| 631 | call n | ||
| 632 | endif | ||
| 633 | else | ||
| 634 | call n | ||
| 635 | endif | ||
| 636 | if ?argl | ||
| 637 | add sp,?argl | ||
| 638 | endif | ||
| 639 | mpop %?RSL | ||
| 640 | ?RSL = 0 | ||
| 641 | ?argc = 0 | ||
| 642 | ?argl = 0 | ||
| 643 | endm | ||
| 644 | else | ||
| 645 | ccall macro n,a | ||
| 646 | ifnb <a> | ||
| 647 | Arg <a> | ||
| 648 | endif | ||
| 649 | ifdef ?SM&n | ||
| 650 | ?RSL = ?RSL AND ?SM&n | ||
| 651 | endif | ||
| 652 | mpush %?RSL | ||
| 653 | ?argl = 0 | ||
| 654 | ?ACB = 1 | ||
| 655 | rept ?argc | ||
| 656 | uconcat <?ALI>,%?ACB | ||
| 657 | uconcat <purge>,,<?ALI>,%?ACB | ||
| 658 | ?ACB = ?ACB + 1 | ||
| 659 | endm | ||
| 660 | ife ?PLM | ||
| 661 | call _&n | ||
| 662 | else | ||
| 663 | call n | ||
| 664 | endif | ||
| 665 | mpop %?RSL | ||
| 666 | ?RSL = 0 | ||
| 667 | ?argc = 0 | ||
| 668 | ?argl = 0 | ||
| 669 | endm | ||
| 670 | endif | ||
| 671 | cProc macro n,cl,s | ||
| 672 | ?pd n,<cl>,<s>,4 | ||
| 673 | endm | ||
| 674 | ?pd macro n,c,a,i | ||
| 675 | if ?CPD | ||
| 676 | ?UTPE | ||
| 677 | endif | ||
| 678 | ?CPD = 1 | ||
| 679 | ??? = 0 | ||
| 680 | ?argc = 0 | ||
| 681 | ?BA = 0 | ||
| 682 | ?PO = 0 | ||
| 683 | ?PU = 0 | ||
| 684 | ?IA = 0 | ||
| 685 | ?adj = i | ||
| 686 | ?PAS = 0 | ||
| 687 | ifnb <a> | ||
| 688 | ?RI ?PAS,<a> | ||
| 689 | endif | ||
| 690 | ?PC = sizeC | ||
| 691 | irp x,<c> | ||
| 692 | ifidn <x>,<FAR> | ||
| 693 | ?PC = 1 | ||
| 694 | endif | ||
| 695 | ifidn <x>,<NEAR> | ||
| 696 | ?PC = 0 | ||
| 697 | endif | ||
| 698 | ifidn <x>,<PUBLIC> | ||
| 699 | ?PU = 1 | ||
| 700 | endif | ||
| 701 | endm | ||
| 702 | if ?PC | ||
| 703 | if ?WIN | ||
| 704 | ?IA = 2 | ||
| 705 | endif | ||
| 706 | ?adj = ?adj + 2 | ||
| 707 | endif | ||
| 708 | ife ?PLM | ||
| 709 | ife ?PC | ||
| 710 | n label near | ||
| 711 | else | ||
| 712 | n label far | ||
| 713 | endif | ||
| 714 | ?pg <_&n>,%?PU,%?PC,%?PAS | ||
| 715 | else | ||
| 716 | ?pg <n>,%?PU,%?PC,%?PAS | ||
| 717 | endif | ||
| 718 | endm | ||
| 719 | ?pg macro n,p,c,a | ||
| 720 | .xcref | ||
| 721 | cBegin ¯o g | ||
| 722 | .xcref | ||
| 723 | ?pg1 <n>,c,a,%?PO | ||
| 724 | ?CPD = 0 | ||
| 725 | ?argc = 0 | ||
| 726 | ?BA = 1 | ||
| 727 | ??? = (???+1) AND 0FFFEH | ||
| 728 | if p | ||
| 729 | PUBLIC n | ||
| 730 | endif | ||
| 731 | ife c | ||
| 732 | n proc NEAR | ||
| 733 | else | ||
| 734 | n proc FAR | ||
| 735 | endif | ||
| 736 | ifidn <g>,<nogen> | ||
| 737 | if ???+?PO+a | ||
| 738 | %out <cBegin - possible invalid use of nogen> | ||
| 739 | endif | ||
| 740 | else | ||
| 741 | if ?IA | ||
| 742 | mov ax,ds | ||
| 743 | nop | ||
| 744 | inc bp | ||
| 745 | push bp | ||
| 746 | mov bp,sp | ||
| 747 | push ds | ||
| 748 | mov ds,ax | ||
| 749 | else | ||
| 750 | push bp | ||
| 751 | mov bp,sp | ||
| 752 | endif | ||
| 753 | if ??? | ||
| 754 | sub sp,??? | ||
| 755 | endif | ||
| 756 | mPush a,1 | ||
| 757 | endif | ||
| 758 | .cref | ||
| 759 | purge cBegin | ||
| 760 | &endm | ||
| 761 | ?UTPE ¯o | ||
| 762 | %out Unterminated Procedure Definition: "&n" | ||
| 763 | &endm | ||
| 764 | endm | ||
| 765 | |||
| 766 | ?pg1 macro n,c,a,o | ||
| 767 | .xcref | ||
| 768 | cEnd ¯o g | ||
| 769 | .xcref | ||
| 770 | ?BA = 0 | ||
| 771 | ifidn <g>,<nogen> | ||
| 772 | if o+a | ||
| 773 | %out <cEnd - possible invalid use of nogen> | ||
| 774 | endif | ||
| 775 | else | ||
| 776 | mPop a,1 | ||
| 777 | if ?IA | ||
| 778 | sub bp,2 | ||
| 779 | mov sp,bp | ||
| 780 | pop ds | ||
| 781 | pop bp | ||
| 782 | dec bp | ||
| 783 | else | ||
| 784 | mov sp,bp | ||
| 785 | pop bp | ||
| 786 | endif | ||
| 787 | ife ?PLM | ||
| 788 | ret | ||
| 789 | else | ||
| 790 | ret o | ||
| 791 | endif | ||
| 792 | endif | ||
| 793 | n endp | ||
| 794 | .cref | ||
| 795 | purge cEnd | ||
| 796 | &endm | ||
| 797 | .cref | ||
| 798 | endm | ||
| 799 | |||
| 800 | assumes macro s,g | ||
| 801 | local assumed | ||
| 802 | assumed = 0 | ||
| 803 | ifidn <code>,<g> | ||
| 804 | ?cas <s> | ||
| 805 | assumed = 1 | ||
| 806 | endif | ||
| 807 | ifidn <CODE>,<g> | ||
| 808 | ?cas <s> | ||
| 809 | assumed = 1 | ||
| 810 | endif | ||
| 811 | ifidn <data>,<g> | ||
| 812 | assume s&:dgroup | ||
| 813 | assumed = 1 | ||
| 814 | endif | ||
| 815 | ifidn <DATA>,<g> | ||
| 816 | assume s&:dgroup | ||
| 817 | assumed = 1 | ||
| 818 | endif | ||
| 819 | ife assumed | ||
| 820 | assume s&:&g | ||
| 821 | endif | ||
| 822 | endm | ||
| 823 | if sizeC | ||
| 824 | ?cas macro s | ||
| 825 | assume s&:_TEXT | ||
| 826 | endm | ||
| 827 | else | ||
| 828 | ?cas macro s | ||
| 829 | assume s&:IGROUP | ||
| 830 | endm | ||
| 831 | endif | ||
| 832 | createSeg macro n,ln,a,co,cl,grp | ||
| 833 | ifnb <grp> | ||
| 834 | ifidn <grp>,<IGROUP> | ||
| 835 | ife sizeC | ||
| 836 | addSeg IGROUP,n | ||
| 837 | endif | ||
| 838 | else | ||
| 839 | addSeg grp,n | ||
| 840 | endif | ||
| 841 | endif | ||
| 842 | ifnb <cl> | ||
| 843 | n segment a co '&cl' | ||
| 844 | else | ||
| 845 | n segment a co | ||
| 846 | endif | ||
| 847 | n ends | ||
| 848 | ?cs1 <n>,<ln> | ||
| 849 | endm | ||
| 850 | if1 | ||
| 851 | ASMpass=1 | ||
| 852 | else | ||
| 853 | ASMpass=2 | ||
| 854 | endif | ||
| 855 | addSeg macro grp,seg | ||
| 856 | ifndef def_&grp | ||
| 857 | def_&grp= 0 | ||
| 858 | endif | ||
| 859 | if def_&grp ne ASMpass | ||
| 860 | add_&grp ¯o s | ||
| 861 | in_&grp <seg>,s | ||
| 862 | &endm | ||
| 863 | in_&grp ¯o sl,s | ||
| 864 | ifb <s> | ||
| 865 | grp group sl | ||
| 866 | else | ||
| 867 | add_&grp ¯o ns | ||
| 868 | in_&grp <sl,s>,ns | ||
| 869 | &endm | ||
| 870 | endif | ||
| 871 | &endm | ||
| 872 | def_&grp=ASMpass | ||
| 873 | else | ||
| 874 | add_&grp seg | ||
| 875 | endif | ||
| 876 | endm | ||
| 877 | defGrp macro nam | ||
| 878 | addSeg nam | ||
| 879 | endm | ||
| 880 | ?cs1 macro n,ln | ||
| 881 | begin&ln ¯o | ||
| 882 | ?cs2 <n> | ||
| 883 | n segment | ||
| 884 | &endm | ||
| 885 | endm | ||
| 886 | |||
| 887 | ?cs2 macro n | ||
| 888 | sEnd ¯o | ||
| 889 | n ends | ||
| 890 | &endm | ||
| 891 | endm | ||
| 892 | |||
| 893 | sBegin macro ln | ||
| 894 | begin&ln | ||
| 895 | endm | ||
| 896 | |||
| 897 | ife ?DF | ||
| 898 | createSeg _TEXT,code,byte,public,CODE,IGROUP | ||
| 899 | createSeg _DATA,data,word,public,DATA,DGROUP | ||
| 900 | if ?WIN | ||
| 901 | ife sizeC | ||
| 902 | createSeg _INITTEXT,initcode,byte,public,CODE,IGROUP | ||
| 903 | createSeg _INITDATA,initdata,word,public,DATA,DGROUP | ||
| 904 | endif | ||
| 905 | endif | ||
| 906 | ife sizeC | ||
| 907 | defGrp IGROUP | ||
| 908 | endif | ||
| 909 | defGrp DGROUP | ||
| 910 | if sizeC | ||
| 911 | codeOFFSET equ OFFSET _TEXT: | ||
| 912 | else | ||
| 913 | codeOFFSET equ OFFSET IGROUP: | ||
| 914 | endif | ||
| 915 | dataOFFSET equ OFFSET DGROUP: | ||
| 916 | endif | ||
| 917 | |||
| 918 | errnz macro x | ||
| 919 | if2 | ||
| 920 | if x | ||
| 921 | errnz1 <x>,%(x) | ||
| 922 | endif | ||
| 923 | endif | ||
| 924 | endm | ||
| 925 | |||
| 926 | errnz1 macro x1,x2 | ||
| 927 | = *ERRNZ* x1 = x2 | ||
| 928 | endm | ||
| 929 | |||
| 930 | errn$ macro l,x | ||
| 931 | errnz <OFFSET $ - OFFSET l x> | ||
| 932 | endm | ||
diff --git a/v4.0/src/DEV/SMARTDRV/DEVSYM.ASM b/v4.0/src/DEV/SMARTDRV/DEVSYM.ASM new file mode 100644 index 0000000..44a1ab8 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/DEVSYM.ASM | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | BREAK <Device table and SRH definition> | ||
| 2 | |||
| 3 | ; The device table list has the form: | ||
| 4 | SYSDEV STRUC | ||
| 5 | SDEVNEXT DD ? ;Pointer to next device header | ||
| 6 | SDEVATT DW ? ;Attributes of the device | ||
| 7 | SDEVSTRAT DW ? ;Strategy entry point | ||
| 8 | SDEVINT DW ? ;Interrupt entry point | ||
| 9 | SDEVNAME DB 8 DUP (?) ;Name of device (only first byte used for block) | ||
| 10 | SYSDEV ENDS | ||
| 11 | |||
| 12 | ; | ||
| 13 | ; Attribute bit masks | ||
| 14 | ; | ||
| 15 | ; Character devices: | ||
| 16 | ; | ||
| 17 | ; Bit 15 -> must be 1 | ||
| 18 | ; 14 -> 1 if the device understands IOCTL control strings | ||
| 19 | ; 13 -> 1 if the device supports output-until-busy | ||
| 20 | ; 12 -> unused | ||
| 21 | ; 11 -> 1 if the device understands Open/Close | ||
| 22 | ; 10 -> must be 0 | ||
| 23 | ; 9 -> must be 0 | ||
| 24 | ; 8 -> unused | ||
| 25 | ; 7 -> unused | ||
| 26 | ; 6 -> unused | ||
| 27 | ; 5 -> unused | ||
| 28 | ; 4 -> 1 if device is recipient of INT 29h | ||
| 29 | ; 3 -> 1 if device is clock device | ||
| 30 | ; 2 -> 1 if device is null device | ||
| 31 | ; 1 -> 1 if device is console output | ||
| 32 | ; 0 -> 1 if device is console input | ||
| 33 | ; | ||
| 34 | ; Block devices: | ||
| 35 | ; | ||
| 36 | ; Bit 15 -> must be 0 | ||
| 37 | ; 14 -> 1 if the device understands IOCTL control strings | ||
| 38 | ; 13 -> 1 if the device determines media by examining the FAT ID byte. | ||
| 39 | ; This requires the first sector of the fat to *always* reside in | ||
| 40 | ; the same place. | ||
| 41 | ; 12 -> unused | ||
| 42 | ; 11 -> 1 if the device understands Open/Close/removable media | ||
| 43 | ; 10 -> must be 0 | ||
| 44 | ; 9 -> must be 0 | ||
| 45 | ; 8 -> unused | ||
| 46 | ; 7 -> unused | ||
| 47 | ; 6 -> unused | ||
| 48 | ; 5 -> unused | ||
| 49 | ; 4 -> unused | ||
| 50 | ; 3 -> unused | ||
| 51 | ; 2 -> unused | ||
| 52 | ; 1 -> unused | ||
| 53 | ; 0 -> unused | ||
| 54 | |||
| 55 | DevTyp EQU 8000H ; Bit 15 - 1 if Char, 0 if block | ||
| 56 | CharDev EQU 8000H | ||
| 57 | DevIOCtl EQU 4000H ; Bit 14 - CONTROL mode bit | ||
| 58 | ISFATBYDEV EQU 2000H ; Bit 13 - Device uses FAT ID bytes, | ||
| 59 | ; comp media. | ||
| 60 | OutTilBusy EQU 2000h ; Output until busy is enabled | ||
| 61 | ISNET EQU 1000H ; Bit 12 - 1 if a NET device, 0 if | ||
| 62 | ; not. Currently block only. | ||
| 63 | DEVOPCL EQU 0800H ; Bit 11 - 1 if this device has | ||
| 64 | ; OPEN,CLOSE and REMOVABLE MEDIA | ||
| 65 | ; entry points, 0 if not | ||
| 66 | |||
| 67 | EXTENTBIT EQU 0400H ; Bit 10 - Currently 0 on all devs | ||
| 68 | ; This bit is reserved for future use | ||
| 69 | ; to extend the device header beyond | ||
| 70 | ; its current form. | ||
| 71 | |||
| 72 | ; NOTE Bit 9 is currently used on IBM systems to indicate "drive is shared". | ||
| 73 | ; See IOCTL function 9. THIS USE IS NOT DOCUMENTED, it is used by some | ||
| 74 | ; of the utilities which are supposed to FAIL on shared drives on server | ||
| 75 | ; machines (FORMAT,CHKDSK,RECOVER,..). | ||
| 76 | |||
| 77 | ISSPEC EQU 0010H ;Bit 4 - This device is special | ||
| 78 | ISCLOCK EQU 0008H ;Bit 3 - This device is the clock device. | ||
| 79 | ISNULL EQU 0004H ;Bit 2 - This device is the null device. | ||
| 80 | ISCOUT EQU 0002H ;Bit 1 - This device is the console output. | ||
| 81 | ISCIN EQU 0001H ;Bit 0 - This device is the console input. | ||
| 82 | |||
| 83 | ;Static Request Header | ||
| 84 | SRHEAD STRUC | ||
| 85 | REQLEN DB ? ;Length in bytes of request block | ||
| 86 | REQUNIT DB ? ;Device unit number | ||
| 87 | REQFUNC DB ? ;Type of request | ||
| 88 | REQSTAT DW ? ;Status Word | ||
| 89 | DB 8 DUP(?) ;Reserved for queue links | ||
| 90 | SRHEAD ENDS | ||
| 91 | |||
| 92 | ;Status word masks | ||
| 93 | STERR EQU 8000H ;Bit 15 - Error | ||
| 94 | STBUI EQU 0200H ;Bit 9 - Buisy | ||
| 95 | STDON EQU 0100H ;Bit 8 - Done | ||
| 96 | STECODE EQU 00FFH ;Error code | ||
| 97 | |||
| 98 | ;Function codes | ||
| 99 | DEVINIT EQU 0 ;Initialization | ||
| 100 | DINITHL EQU 26 ;Size of init header | ||
| 101 | DEVMDCH EQU 1 ;Media check | ||
| 102 | DMEDHL EQU 15 ;Size of media check header | ||
| 103 | DEVBPB EQU 2 ;Get BPB | ||
| 104 | DEVRDIOCTL EQU 3 ;IOCTL read | ||
| 105 | DBPBHL EQU 22 ;Size of Get BPB header | ||
| 106 | DEVRD EQU 4 ;Read | ||
| 107 | DRDWRHL EQU 22 ;Size of RD/WR header | ||
| 108 | DEVRDND EQU 5 ;Non destructive read no wait (character devs) | ||
| 109 | DRDNDHL EQU 14 ;Size of non destructive read header | ||
| 110 | DEVIST EQU 6 ;Input status | ||
| 111 | DSTATHL EQU 13 ;Size of status header | ||
| 112 | DEVIFL EQU 7 ;Input flush | ||
| 113 | DFLSHL EQU 15 ;Size of flush header | ||
| 114 | DEVWRT EQU 8 ;Write | ||
| 115 | DEVWRTV EQU 9 ;Write with verify | ||
| 116 | DEVOST EQU 10 ;Output status | ||
| 117 | DEVOFL EQU 11 ;Output flush | ||
| 118 | DEVWRIOCTL EQU 12 ;IOCTL write | ||
| 119 | DEVOPN EQU 13 ;Device open | ||
| 120 | DEVCLS EQU 14 ;Device close | ||
| 121 | DOPCLHL EQU 13 ;Size of OPEN/CLOSE header | ||
| 122 | DEVRMD EQU 15 ;Removable media | ||
| 123 | REMHL EQU 13 ;Size of Removable media header | ||
| 124 | |||
| 125 | DevOUT EQU 16 ; output until busy. | ||
| 126 | DevOutL EQU DevWrt ; length of output until busy | ||
| 127 | |||
| 128 | SUBTTL | ||
diff --git a/v4.0/src/DEV/SMARTDRV/DIRENT.ASM b/v4.0/src/DEV/SMARTDRV/DIRENT.ASM new file mode 100644 index 0000000..e7150c8 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/DIRENT.ASM | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | Break <Directory entry> | ||
| 2 | |||
| 3 | ; | ||
| 4 | ; +---------------------------+ | ||
| 5 | ; | (12 BYTE) filename/ext | 0 0 | ||
| 6 | ; +---------------------------+ | ||
| 7 | ; | (BYTE) attributes | 11 B | ||
| 8 | ; +---------------------------+ | ||
| 9 | ; | (10 BYTE) reserved | 12 C | ||
| 10 | ; +---------------------------+ | ||
| 11 | ; | (WORD) time of last write | 22 16 | ||
| 12 | ; +---------------------------+ | ||
| 13 | ; | (WORD) date of last write | 24 18 | ||
| 14 | ; +---------------------------+ | ||
| 15 | ; | (WORD) First cluster | 26 1A | ||
| 16 | ; +---------------------------+ | ||
| 17 | ; | (DWORD) file size | 28 1C | ||
| 18 | ; +---------------------------+ | ||
| 19 | ; | ||
| 20 | ; First byte of filename = E5 -> free directory entry | ||
| 21 | ; = 00 -> end of allocated directory | ||
| 22 | ; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour | ||
| 23 | ; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980 | ||
| 24 | ; | ||
| 25 | |||
| 26 | dir_entry STRUC | ||
| 27 | dir_name DB 11 DUP (?) ; file name | ||
| 28 | dir_attr DB ? ; attribute bits | ||
| 29 | dir_pad DB 10 DUP (?) ; reserved for expansion | ||
| 30 | dir_time DW ? ; time of last write | ||
| 31 | dir_date DW ? ; date of last write | ||
| 32 | dir_first DW ? ; first allocation unit of file | ||
| 33 | dir_size_l DW ? ; low 16 bits of file size | ||
| 34 | dir_size_h DW ? ; high 16 bits of file size | ||
| 35 | dir_entry ENDS | ||
| 36 | |||
| 37 | attr_read_only EQU 1h | ||
| 38 | attr_hidden EQU 2h | ||
| 39 | attr_system EQU 4h | ||
| 40 | attr_volume_id EQU 8h | ||
| 41 | attr_directory EQU 10h | ||
| 42 | attr_archive EQU 20h | ||
| 43 | attr_device EQU 40h ; This is a VERY special bit. | ||
| 44 | ; NO directory entry on a disk EVER | ||
| 45 | ; has this bit set. It is set non-zero | ||
| 46 | ; when a device is found by GETPATH | ||
| 47 | |||
| 48 | attr_all EQU attr_hidden+attr_system+attr_directory | ||
| 49 | ; OR of hard attributes for FINDENTRY | ||
| 50 | |||
| 51 | attr_ignore EQU attr_read_only+attr_archive+attr_device | ||
| 52 | ; ignore this(ese) attribute(s) during | ||
| 53 | ; search first/next | ||
| 54 | |||
| 55 | attr_changeable EQU attr_read_only+attr_hidden+attr_system+attr_archive | ||
| 56 | ; changeable via CHMOD | ||
diff --git a/v4.0/src/DEV/SMARTDRV/EMM.ASM b/v4.0/src/DEV/SMARTDRV/EMM.ASM new file mode 100644 index 0000000..ff61ab0 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/EMM.ASM | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | BREAK <EMM control sector layout> | ||
| 2 | |||
| 3 | ; | ||
| 4 | ; The EMM control sector is a 1024 byte record which ALWAYS occupies the | ||
| 5 | ; very first 1024 bytes of "extra" memory that needs to be managed. Its | ||
| 6 | ; function is to provide a method to allocate available "extra" memory | ||
| 7 | ; to programs which desire to use it and avoid program conflicts that | ||
| 8 | ; would occur if two different programs attempted to use the same piece | ||
| 9 | ; of "extra" memory. | ||
| 10 | ; | ||
| 11 | |||
| 12 | ; | ||
| 13 | ; The EMM_CTRL structure defines the offsets into the 1024 byte control | ||
| 14 | ; sector of the various fields. The EMM_REC structure defines a sub-structure | ||
| 15 | ; contained within the EMM_CTRL structure which represents a particular | ||
| 16 | ; piece of allocated "extra" memory (an allocation record). | ||
| 17 | ; | ||
| 18 | |||
| 19 | ; Layout of each EMM record. | ||
| 20 | |||
| 21 | EMM_REC STRUC | ||
| 22 | EMM_FLAGS DW 0 | ||
| 23 | EMM_SYSTEM DW 0 | ||
| 24 | EMM_BASE DD ? ; 24 bit address of start of region | ||
| 25 | EMM_KSIZE DW ? ; Size of region in kbytes | ||
| 26 | EMM_REC ENDS | ||
| 27 | |||
| 28 | ; EMM_FLAGS Bits | ||
| 29 | EMM_ALLOC EQU 0000000000000001B ; Zero -> record is free | ||
| 30 | EMM_ISDRIVER EQU 0000000000000010B ; 1 -> driver is installed | ||
| 31 | ; for this region | ||
| 32 | |||
| 33 | ; EMM_SYSTEM Values | ||
| 34 | EMM_EMM EQU 0 ; Allocated to EMM | ||
| 35 | EMM_MSDOS EQU 1 | ||
| 36 | EMM_XENIX EQU 2 | ||
| 37 | EMM_APPLICATION EQU 3 | ||
| 38 | |||
| 39 | ; Layout of EMM control 1024 byte record | ||
| 40 | |||
| 41 | EMM_CTRL STRUC | ||
| 42 | EMM_VER DB 50 DUP(?) | ||
| 43 | EMM_TOTALK DW ? ; EXCLUDING the 1k of this record | ||
| 44 | EMM_AVAILK DW ? ; Amount of above NOT allocated | ||
| 45 | DB SIZE EMM_REC DUP(?) ; NULL (0th) RECORD | ||
| 46 | EMM_RECORD DB (1024 - 50 - 4 - 10 - (SIZE EMM_REC)) DUP(?) | ||
| 47 | ; EMM_REC structures | ||
| 48 | EMM_TAIL_SIG DB 10 DUP(?) | ||
| 49 | EMM_CTRL ENDS | ||
| 50 | |||
| 51 | EMM_NUMREC EQU (1024 - 50 - 4 - 10 - (SIZE EMM_REC)) / (SIZE EMM_REC) | ||
| 52 | |||
| 53 | |||
| 54 | ; | ||
| 55 | ; The current initial (no "extra" memory allocated) EMM_CTRL sector is | ||
| 56 | ; | ||
| 57 | ; EMM_CONTROL LABEL BYTE | ||
| 58 | ; DB "MICROSOFT EMM CTRL VERSION 1.00 CONTROL BLOCK " | ||
| 59 | ; DW EXTMEM_TOTALK - 1 | ||
| 60 | ; DW EXTMEM_TOTALK - 1 | ||
| 61 | ; ; NULL 0th record | ||
| 62 | ; DW EMM_ALLOC + EMM_ISDRIVER | ||
| 63 | ; DW EMM_EMM | ||
| 64 | ; DW EXTMEM_LOW + 1024 | ||
| 65 | ; DW EXTMEM_HIGH | ||
| 66 | ; DW 0 | ||
| 67 | ; ;** | ||
| 68 | ; DB 950 DUP(0) | ||
| 69 | ; DB "ARRARRARRA" | ||
| 70 | ; | ||
| 71 | ; Where EXTMEM_LOW:EXTMEM_HIGH is the 32 bit address of the first byte | ||
| 72 | ; of the EMM_CTRL sector (first byte of "extra" memory) and EXTMEM_TOTALK | ||
| 73 | ; is the size in K of the available "extra" memory. One is subtracted | ||
| 74 | ; from EXTMEM_TOTALK because the sizes in the EMM_CTRL record DO NOT | ||
| 75 | ; include the 1k taken up by the EMM_CTRL sector. | ||
| 76 | ; | ||
| 77 | ; The reason for the existance of the NULL 0th record is to facilitate | ||
| 78 | ; the computation of EMM_BASE for the first EMM_REC allocation record | ||
| 79 | ; created. | ||
| 80 | ; | ||
| 81 | ; The EMM_REC structures CANNOT be sparse. In other words if one sets | ||
| 82 | ; up a scan of the EMM_REC structures in the EMM_CTRL sector, as soon as | ||
| 83 | ; an EMM_REC structure WITHOUT the EMM_ALLOC bit set in its flag word | ||
| 84 | ; is encountered it is not necessary to scan further because it IS KNOWN | ||
| 85 | ; that all of the EMM_REC structures after the first one with EMM_ALLOC | ||
| 86 | ; clear also have EMM_ALLOC clear. What this means is that EMM_CTRL | ||
| 87 | ; memory CANNOT BE deallocated. Once an EMM_REC structure has its | ||
| 88 | ; EMM_ALLOC bit set, there is NO correct program operation which | ||
| 89 | ; can clear the bit UNLESS it IS KNOWN that the next EMM_REC structure | ||
| 90 | ; has its EMM_ALLOC bit clear or the EMM_REC structure is the last one. | ||
| 91 | ; | ||
| 92 | ; | ||
| 93 | ; USING THE EMM_CTRL SECTOR: | ||
| 94 | ; | ||
| 95 | ; A program which wishes to use the EMM_CTRL sector to access "extra" | ||
| 96 | ; memory should work as follows: | ||
| 97 | ; | ||
| 98 | ; Figure out how much memory you wish to allocate | ||
| 99 | ; | ||
| 100 | ; Figure out the location and size of the "extra" memory in the system | ||
| 101 | ; | ||
| 102 | ; IF (the first 1024 bytes of "extra" memory DO NOT contain a valid | ||
| 103 | ; EMM_CTRL record determined by checking for the existence of the | ||
| 104 | ; correct EMM_VER and EMM_TAIL_SIG strings) | ||
| 105 | ; Write a correct initial EMM_CTRL sector to the first 1024 | ||
| 106 | ; bytes of extra memory. Be sure to fill in EMM_TOTALK, | ||
| 107 | ; EMM_AVAILK and EMM_BASE in the 0th record. | ||
| 108 | ; | ||
| 109 | ; Set up a scan of the EMM_REC structures in the EMM_CTRL sector. | ||
| 110 | ; NOTE: You can skip the NULL 0th record if you want since it has | ||
| 111 | ; known value. | ||
| 112 | ; | ||
| 113 | ; FOR (i=0;i<EMM_NUMREC;i++) | ||
| 114 | ; IF ( this EMM_REC has EMM_ALLOC clear) | ||
| 115 | ; IF ( EMM_AVAILK < amount I want to alloc) | ||
| 116 | ; ERROR insufficient memory | ||
| 117 | ; EMM_AVAILK = EMM_AVAILK - amount I want to alloc | ||
| 118 | ; EMM_FLAGS = EMM_ALLOC + EMM_ISDRIVER | ||
| 119 | ; EMM_KSIZE = amount I want to alloc | ||
| 120 | ; EMM_SYSTEM = appropriate value | ||
| 121 | ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC + | ||
| 122 | ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC) | ||
| 123 | ; break | ||
| 124 | ; ELSE | ||
| 125 | ; address next EMM_REC structure | ||
| 126 | ; | ||
| 127 | ; IF (i >= EMM_NUMREC) | ||
| 128 | ; ERROR no free EMM_REC structures | ||
| 129 | ; | ||
| 130 | ; | ||
| 131 | ; You can now see why we need that NUL 0th EMM_REC structure. In order to | ||
| 132 | ; perform this step | ||
| 133 | ; | ||
| 134 | ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC + | ||
| 135 | ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC) | ||
| 136 | ; | ||
| 137 | ; when the very first EMM_REC is allocated we must have a "previous EMM_REC" | ||
| 138 | ; structure to point at. | ||
| 139 | ; | ||
| 140 | ; The above code is rather simplistic in that all it does is do a simple | ||
| 141 | ; allocation. The EMM_ISDRIVER bit allows us to do some more sophisticated | ||
| 142 | ; things. In particular in the case of a RAMDrive type of program it is | ||
| 143 | ; desirable to "re-find" the same RAMDrive area in "extra" memory when the | ||
| 144 | ; system is re-booted. The EMM_ISDRIVER bit is used to help us do this. | ||
| 145 | ; | ||
| 146 | ; The EMM_ISDRIVER bit means "there is presently a piece of code in the | ||
| 147 | ; system which is using this memory". If we find an EMM_REC structure | ||
| 148 | ; which has its EMM_ALLOC bit set, but the EMM_ISDRIVER bit is clear | ||
| 149 | ; it means that the piece of code that originally allocated | ||
| 150 | ; the memory is gone and we may want to "re-find" this memory by | ||
| 151 | ; setting the EMM_ISDRIVER bit again. A RAMDrive program would have | ||
| 152 | ; slightly different code than the above: | ||
| 153 | ; | ||
| 154 | ; FOR (i=0;i<EMM_NUMREC;i++) | ||
| 155 | ; IF ( this EMM_REC has EMM_ALLOC clear) | ||
| 156 | ; IF ( EMM_AVAILK < amount I want to alloc) | ||
| 157 | ; ERROR insufficient memory | ||
| 158 | ; EMM_AVAILK = EMM_AVAILK - amount I want to alloc | ||
| 159 | ; EMM_FLAGS = EMM_ALLOC + EMM_ISDRIVER | ||
| 160 | ; EMM_KSIZE = amount I want to alloc | ||
| 161 | ; EMM_SYSTEM = appropriate value | ||
| 162 | ; EMM_BASE = EMM_BASE of PREVIOUS EMM_REC + | ||
| 163 | ; (1024 * EMM_KSIZE of PREVIOUS EMM_REC) | ||
| 164 | ; break | ||
| 165 | ; ELSE | ||
| 166 | ; IF ((EMM_SYSTEM == my value for EMM_SYSTEM) && | ||
| 167 | ; (EMM_ISDRIVER is clear)) | ||
| 168 | ; deal with differences between amount | ||
| 169 | ; I want to allocate and EMM_KSIZE | ||
| 170 | ; Set EMM_ISDRIVER | ||
| 171 | ; EMM_BASE is the base address of this piece | ||
| 172 | ; of memory and EMM_KSIZE is its size. | ||
| 173 | ; break | ||
| 174 | ; address next EMM_REC structure | ||
| 175 | ; | ||
| 176 | ; In this way we "re-find" memory that was previosly allocated (presumably | ||
| 177 | ; by us, or a related program). | ||
| 178 | ; | ||
| 179 | ; NOTE THAT THIS USE OF EMM_ISDRIVER REQUIRES SOME MECHANISM FOR CLEARING | ||
| 180 | ; EMM_ISDRIVER WHEN THE CODE OF INTEREST IS REMOVED FROM THE SYSTEM. | ||
| 181 | ; In the case of a RAMDrive program the code is removed whenever the system | ||
| 182 | ; is re-booted. For this reason a RAMDrive program will need code that is | ||
| 183 | ; invoked whenever a system re-boot is detected. What this code does is | ||
| 184 | ; scan the EMM_REC structures in the EMM_CTRL sector turning off the | ||
| 185 | ; EMM_ISDRIVER bits: | ||
| 186 | ; | ||
| 187 | ; FOR (i=0;i<EMM_NUMREC;i++) | ||
| 188 | ; IF ( this EMM_REC has EMM_ALLOC clear) | ||
| 189 | ; break | ||
| 190 | ; ELSE IF (EMM_SYSTEM == my value for EMM_SYSTEM) | ||
| 191 | ; clear EMM_ISDRIVER bit | ||
| 192 | ; address next EMM_REC | ||
| 193 | ; | ||
| 194 | ; Note that this code clears ALL of the ISDRIVER bits for EMM_SYSTEM | ||
| 195 | ; values of a certain value. This means there is a GLOBAL piece of | ||
| 196 | ; re-boot code for ALL of the programs using a particular EMM_SYSTEM | ||
| 197 | ; value. An alternative is to have each EMM_CTRL user clear the | ||
| 198 | ; EMM_ISDRIVER bits ONLY for those EMM_REC structures that it allocated. | ||
| 199 | ; This requires that the program keep a record of which EMM_REC structures | ||
| 200 | ; it is responsible for: | ||
| 201 | ; | ||
| 202 | ; FOR each of my EMM_REC structures | ||
| 203 | ; INDEX this EMM_REC structure in the EMM_CTRL sector | ||
| 204 | ; Clear EMM_ISDRIVER | ||
| 205 | ; | ||
| 206 | ; NOTE about this step: | ||
| 207 | ; | ||
| 208 | ; deal with differences between amount | ||
| 209 | ; I want to allocate and EMM_KSIZE | ||
| 210 | ; | ||
| 211 | ; in the above code. There are a lot of options here depending on the desired | ||
| 212 | ; behavior. If the NEXT EMM_REC structure has EMM_ALLOC clear, then it may | ||
| 213 | ; be possible for me to grow or shrink the block I found by adjusting | ||
| 214 | ; EMM_KSIZE and EMM_AVAILK. If the NEXT EMM_REC structure has EMM_ALLOC | ||
| 215 | ; set, then I am forced to either adjust the amount I want to allocate | ||
| 216 | ; to match EMM_KSIZE, or skip this EMM_REC without setting EMM_ISDRIVER. | ||
| 217 | ; | ||
| 218 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 219 | ; for rom 1nt15 extended memory interface | ||
| 220 | emm_int equ 15h | ||
| 221 | emm_size equ 88h | ||
| 222 | emm_blkm equ 87h | ||
| 223 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
diff --git a/v4.0/src/DEV/SMARTDRV/FL13.ASM b/v4.0/src/DEV/SMARTDRV/FL13.ASM new file mode 100644 index 0000000..6ae1e44 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/FL13.ASM | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | TITLE Assembler helper routines for FLUSH13 | ||
| 2 | |||
| 3 | PAGE 58,132 | ||
| 4 | |||
| 5 | |||
| 6 | memS EQU 1 ; Small model | ||
| 7 | ?PLM = 0 ; Standard 'C' | ||
| 8 | ?WIN = 0 ; Not windows | ||
| 9 | |||
| 10 | include cmacros.inc | ||
| 11 | |||
| 12 | ;extern int IOCTLOpen(char *); | ||
| 13 | ;extern int IOCTLWrite(int,char *,int); | ||
| 14 | ;extern int IOCTLRead(int,status *,int); | ||
| 15 | ;extern int IOCTLClose(int); | ||
| 16 | |||
| 17 | sBegin CODE | ||
| 18 | |||
| 19 | assumes CS, CODE | ||
| 20 | assumes DS, DATA | ||
| 21 | |||
| 22 | ;** IOCTLOpen - Open the indicated device and make sure it's a device | ||
| 23 | ; | ||
| 24 | ; ENTRY: | ||
| 25 | ; Pointer to name of device | ||
| 26 | ; EXIT: | ||
| 27 | ; AX = -1 if error, device not opened | ||
| 28 | ; else AX = handle of open device | ||
| 29 | ; USES: | ||
| 30 | ; Standard 'C' | ||
| 31 | ; | ||
| 32 | cProc IOCTLOpen, <PUBLIC>, <si,di,es> | ||
| 33 | |||
| 34 | ParmW Nameptr | ||
| 35 | |||
| 36 | cBegin | ||
| 37 | mov dx,Nameptr | ||
| 38 | MOV AX,3D02H | ||
| 39 | INT 21H ; Open the device | ||
| 40 | JC NO_DEV_ERR ; No device | ||
| 41 | MOV BX,AX | ||
| 42 | MOV AX,4400H | ||
| 43 | INT 21H ; Make sure it IS a device | ||
| 44 | JC CLOSE_NO_DEV | ||
| 45 | TEST DX,4080H | ||
| 46 | JZ CLOSE_NO_DEV | ||
| 47 | mov ax,bx ; Return the handle | ||
| 48 | jmp short PXDONE | ||
| 49 | |||
| 50 | CLOSE_NO_DEV: | ||
| 51 | mov ax,3e00H ; Close | ||
| 52 | int 21H | ||
| 53 | NO_DEV_ERR: | ||
| 54 | mov ax,-1 | ||
| 55 | PXDONE: | ||
| 56 | cEnd | ||
| 57 | |||
| 58 | ;** IOCTLClose - Close the indicated handle | ||
| 59 | ; | ||
| 60 | ; ENTRY: | ||
| 61 | ; Handle | ||
| 62 | ; EXIT: | ||
| 63 | ; None | ||
| 64 | ; USES: | ||
| 65 | ; Standard 'C' | ||
| 66 | ; | ||
| 67 | cProc IOCTLClose, <PUBLIC>, <si,di,es> | ||
| 68 | |||
| 69 | ParmW Handle | ||
| 70 | |||
| 71 | cBegin | ||
| 72 | mov bx,Handle | ||
| 73 | MOV AX,3E00H | ||
| 74 | INT 21H ; close the device | ||
| 75 | cEnd | ||
| 76 | |||
| 77 | ;** IOCTLWrite - Perform IOCTLWrite to device handle | ||
| 78 | ; | ||
| 79 | ; ENTRY: | ||
| 80 | ; Handle to open device | ||
| 81 | ; Pointer to data to write | ||
| 82 | ; Count in bytes of data to write | ||
| 83 | ; EXIT: | ||
| 84 | ; AX = -1 error | ||
| 85 | ; else AX = input count | ||
| 86 | ; USES: | ||
| 87 | ; Standard 'C' | ||
| 88 | ; | ||
| 89 | cProc IOCTLWrite, <PUBLIC>, <si,di,es> | ||
| 90 | |||
| 91 | ParmW WHandle | ||
| 92 | ParmW WDataPtr | ||
| 93 | ParmW WCount | ||
| 94 | |||
| 95 | cBegin | ||
| 96 | mov bx,WHandle | ||
| 97 | mov cx,WCount | ||
| 98 | mov dx,WDataPtr | ||
| 99 | MOV AX,4403H ; IOCTL Write | ||
| 100 | INT 21H | ||
| 101 | JC Werr | ||
| 102 | CMP AX,CX | ||
| 103 | JNZ Werr | ||
| 104 | jmp short WDONE | ||
| 105 | |||
| 106 | WERR: | ||
| 107 | mov ax,-1 | ||
| 108 | WDONE: | ||
| 109 | cEnd | ||
| 110 | |||
| 111 | ;** IOCTLRead - Perform IOCTLRead to device handle | ||
| 112 | ; | ||
| 113 | ; ENTRY: | ||
| 114 | ; Handle to open device | ||
| 115 | ; Pointer to data area to read into | ||
| 116 | ; Count in bytes of size of data area | ||
| 117 | ; EXIT: | ||
| 118 | ; AX = -1 error | ||
| 119 | ; else AX = input count | ||
| 120 | ; USES: | ||
| 121 | ; Standard 'C' | ||
| 122 | ; | ||
| 123 | cProc IOCTLRead, <PUBLIC>, <si,di,es> | ||
| 124 | |||
| 125 | ParmW RHandle | ||
| 126 | ParmW RDataPtr | ||
| 127 | ParmW RCount | ||
| 128 | |||
| 129 | cBegin | ||
| 130 | mov bx,RHandle | ||
| 131 | mov cx,RCount | ||
| 132 | mov dx,RDataPtr | ||
| 133 | MOV AX,4402H ; IOCTL Read | ||
| 134 | INT 21H | ||
| 135 | JC Rerr | ||
| 136 | CMP AX,CX | ||
| 137 | JNZ Rerr | ||
| 138 | jmp short RDONE | ||
| 139 | |||
| 140 | RERR: | ||
| 141 | mov ax,-1 | ||
| 142 | RDONE: | ||
| 143 | cEnd | ||
| 144 | |||
| 145 | |||
| 146 | sEnd CODE | ||
| 147 | |||
| 148 | end | ||
diff --git a/v4.0/src/DEV/SMARTDRV/FLMES.ASM b/v4.0/src/DEV/SMARTDRV/FLMES.ASM new file mode 100644 index 0000000..25177ba --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/FLMES.ASM | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | TITLE Message texts for FLUSH13 | ||
| 2 | |||
| 3 | PAGE 58,132 | ||
| 4 | |||
| 5 | CONST SEGMENT WORD PUBLIC 'DATA' | ||
| 6 | CONST ENDS | ||
| 7 | |||
| 8 | _BSS SEGMENT WORD PUBLIC 'DATA' | ||
| 9 | _BSS ENDS | ||
| 10 | |||
| 11 | _DATA SEGMENT WORD PUBLIC 'DATA' | ||
| 12 | _DATA ENDS | ||
| 13 | |||
| 14 | DGROUP GROUP CONST, _BSS, _DATA | ||
| 15 | |||
| 16 | ASSUME DS:DGROUP | ||
| 17 | |||
| 18 | _DATA SEGMENT | ||
| 19 | |||
| 20 | public _SWTCH_CONF | ||
| 21 | public _BAD_PARM | ||
| 22 | public _NO_DEV_MESS | ||
| 23 | public _IOCTL_BAD_MESS | ||
| 24 | public _STATUS_MES1 | ||
| 25 | public _STATUS_MES2 | ||
| 26 | public _DISSTRING | ||
| 27 | public _ENSTRING | ||
| 28 | public _OFFSTRING | ||
| 29 | public _ONSTRING | ||
| 30 | public _LOCKSTRING | ||
| 31 | public _UNLSTRING | ||
| 32 | public _REBOOT_MES | ||
| 33 | public _STATUS_3R | ||
| 34 | public _STATUS_3W | ||
| 35 | public _STATUS_3T | ||
| 36 | public _CACHE_MES | ||
| 37 | public _WT_MES | ||
| 38 | public _WB_MES | ||
| 39 | public _L_MES | ||
| 40 | public _C_MES | ||
| 41 | public _T_MES | ||
| 42 | public _STATUS_4 | ||
| 43 | public _STATUS_5 | ||
| 44 | |||
| 45 | ; | ||
| 46 | ; Messages | ||
| 47 | ; | ||
| 48 | _SWTCH_CONF DB "Conflicting switch specified",13,10 | ||
| 49 | _BAD_PARM DB "Usage:",13,10," FLUSH13 [/s|/sx|/sr] [/d|/e] [/l|/u] [/i] [/f] [/wt:on|/wt:off]",13,10 | ||
| 50 | DB " [/wc:on|/wc:off] [/t:nnnnn] [/c:on|/c:off]",0 | ||
| 51 | |||
| 52 | _NO_DEV_MESS DB "SMARTDRV device not found, or device error",0 | ||
| 53 | |||
| 54 | _IOCTL_BAD_MESS DB "SMARTDRV device function failed",0 | ||
| 55 | |||
| 56 | _STATUS_MES1 DB "SMARTDRV Device is NUL (instalation failed)",13,10,0 | ||
| 57 | |||
| 58 | _STATUS_MES2 DB "FLUSH13/SMARTDRV version 1.00",13,10,0 | ||
| 59 | _CACHE_MES DB " Caching is %-8s",0 | ||
| 60 | _L_MES DB " Cache is %-8s",13,10,0 | ||
| 61 | |||
| 62 | _WB_MES DB " Write Caching is %-3s",0 | ||
| 63 | _REBOOT_MES DB " Reboot flush is %-3s",13,10,0 | ||
| 64 | |||
| 65 | _C_MES DB " Caching of full track reads is %-3s",0 | ||
| 66 | _WT_MES DB " Write Through is %-3s",13,10,0 | ||
| 67 | |||
| 68 | _T_MES DB " Cache is auto flushed every %2u:%02u minutes (%u ticks)",13,10,0 | ||
| 69 | |||
| 70 | _DISSTRING DB "DISABLED",0 | ||
| 71 | _ENSTRING DB "ENABLED",0 | ||
| 72 | _OFFSTRING DB "OFF",0 | ||
| 73 | _ONSTRING DB "ON",0 | ||
| 74 | _LOCKSTRING DB "LOCKED",0 | ||
| 75 | _UNLSTRING DB "UNLOCKED",0 | ||
| 76 | |||
| 77 | |||
| 78 | _STATUS_3W DB " %10lu Write hits out of %10lu Total Writes. Hit rate %3u%%",13,10,0 | ||
| 79 | _STATUS_3R DB " %10lu Read hits out of %10lu Total Reads. Hit rate %3u%%",13,10,0 | ||
| 80 | _STATUS_3T DB " %10lu hits out of %10lu Total operations. Hit rate %3u%%",13,10,0 | ||
| 81 | _STATUS_4 DB " %3u Total tracks, %3u are used, %3u are locked, %3u are dirty",13,10,0 | ||
| 82 | |||
| 83 | _STATUS_5 DB " %4u - Current Size, %4u - Initial Size, %4u - Minimum Size",13,10,0 | ||
| 84 | |||
| 85 | _DATA ENDS | ||
| 86 | END | ||
diff --git a/v4.0/src/DEV/SMARTDRV/FLUSH13.C b/v4.0/src/DEV/SMARTDRV/FLUSH13.C new file mode 100644 index 0000000..cf01107 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/FLUSH13.C | |||
| @@ -0,0 +1,686 @@ | |||
| 1 | /* | ||
| 2 | * FLUSH13 -- Device mod utility for INT13 memory cache | ||
| 3 | * | ||
| 4 | * FLUSH13 [/s|/sx|/sr] [/d|/e] [/l|/u] [/i] [/f] [/wt:on|/wt:off] | ||
| 5 | * [/wc:on|/wc:off] [/t:nnnnn] [/r:on|/r:off] [/c:on|/c:off] | ||
| 6 | * | ||
| 7 | * No arguments - This causes FLUSH13 to flush out any "dirty" | ||
| 8 | * tracks in the INT13 cache. A "dirty" track is one | ||
| 9 | * which has been written into the cache, but not yet | ||
| 10 | * written to the disk. This invokation causes all dirty tracks | ||
| 11 | * to be written out to the disk so that the system can | ||
| 12 | * be re-booted or turned off. NOTE: FAILURE TO FLUSH | ||
| 13 | * THE CACHE BEFORE A RE-BOOT OR POWER OFF CAN CAUSE THE | ||
| 14 | * INFORMATION ON THE HARDFILE TO BE CORRUPTED. | ||
| 15 | * | ||
| 16 | * /f - Flush. Same as the no arguments case, but allows you to | ||
| 17 | * perform the flush and do something else (like /s). | ||
| 18 | * | ||
| 19 | * /i - Flush and invalidate. This is the same as the no argument | ||
| 20 | * case except that all of the information in the cache | ||
| 21 | * is also discarded. This makes the cache EMPTY. | ||
| 22 | * | ||
| 23 | * /d - Disable caching. This causes all dirty cache information | ||
| 24 | * to be flushed and all caching to stop. | ||
| 25 | * | ||
| 26 | * /e - Enable caching. This causes caching to be enabled after | ||
| 27 | * a previous /d disable. When INT13 is started it is enabled. | ||
| 28 | * | ||
| 29 | * /l - Lock the cache. This causes all dirty information to be | ||
| 30 | * flushed, and the cache contents to be locked in the cache. | ||
| 31 | * When in this mode the locked elements will not be discarded | ||
| 32 | * to make room for new tracks. This can be used | ||
| 33 | * to "load" the cache with desired things. For instance if | ||
| 34 | * you use the "foobar" program a lot, you can run foobar, | ||
| 35 | * causing it to be loaded into the cache, then lock the cache. | ||
| 36 | * This causes the foobar program to always be in the cache. | ||
| 37 | * You may lock the cache as many times as you want. Each lock | ||
| 38 | * causes the current information (including any previously | ||
| 39 | * locked information) to be locked. | ||
| 40 | * NOTE: Information in a locked cache is READ ONLY!! Any write | ||
| 41 | * operation on information in a locked cache causes the | ||
| 42 | * information to be unlocked. | ||
| 43 | * | ||
| 44 | * /u - Unlock the cache. This undoes a previous /l and returns | ||
| 45 | * the cache to normal operation. | ||
| 46 | * | ||
| 47 | * /s - Print status. This displays the settings of the setable | ||
| 48 | * device parameters. | ||
| 49 | * /sx - Print extended status. Same as /s, only additional | ||
| 50 | * Statistical information is also given. | ||
| 51 | * /sr - Reset statistics. Same as /sx, only the additional | ||
| 52 | * Statistical information is reset to 0. | ||
| 53 | * | ||
| 54 | * /wt:on off - Enable or Disable write through. When INT13 is caching | ||
| 55 | * write information, it is a good idea to imply a flush of | ||
| 56 | * the cache on some operations so that in case of a crash or | ||
| 57 | * power failure the information in the cache which is not on | ||
| 58 | * the disk will not be lost. /wt:on enables write through on full | ||
| 59 | * track INT 13s which are to tracks not currently in the cache. | ||
| 60 | * /wt:off disables it. INT13 is faster with write through | ||
| 61 | * off, at the expense of there being a bigger risk of | ||
| 62 | * loosing data. /wt:on IS NOT a substitute for flushing before | ||
| 63 | * a re-boot!!!! This write through mechanism is far from perfect, | ||
| 64 | * all it is is a risk REDUCER, not a risk eliminator. /wt:off | ||
| 65 | * is the setting when INT13 is started. | ||
| 66 | * | ||
| 67 | * /wc:on off - Enable or Disable write caching. There is risk when | ||
| 68 | * caching "dirty" information that the system will crash, | ||
| 69 | * or be re-booted, or be turned off before this information | ||
| 70 | * can be written to the disk. This may corrupt the disk. | ||
| 71 | * This risk can be ELIMINATED, at the expense of cache | ||
| 72 | * performance, by NOT caching any dirty information. | ||
| 73 | * /wc:off disables the caching of dirty information, | ||
| 74 | * eliminating the risk. /wc:on enables the caching of dirty | ||
| 75 | * information. /wc:on is the default when INT13 is started. | ||
| 76 | * | ||
| 77 | * WARNING: You must be careful to flush the cache before | ||
| 78 | * re-booting the system, or turning it off if /wc:on is selected. | ||
| 79 | * You should also be careful to disable the cache (/d), or do | ||
| 80 | * /wc:off before running any program under development which | ||
| 81 | * has a chance of crashing due to bugs. | ||
| 82 | * | ||
| 83 | * NOTE: When /wc:off is selected, write info CAN get into | ||
| 84 | * the cache (when the write is to a track which is currently | ||
| 85 | * in the cache). The difference is that this "dirty" information | ||
| 86 | * is IMMEDIATELY written out to the disk instead of being | ||
| 87 | * held in the cache in the "dirty" state. When the write is | ||
| 88 | * to a track that is not in the cache, it will be passed | ||
| 89 | * through to the disk without being cached. | ||
| 90 | * | ||
| 91 | * /t:nnnnn - Set the auto flush interval. INT13 listens on the system | ||
| 92 | * timer to note the passage of time and "age" the dirty | ||
| 93 | * information in the cache. Every nnnnn ticks, the cache is | ||
| 94 | * flushed. The timer ticks 18.2 times a second. | ||
| 95 | * | ||
| 96 | * nnnnn | | ||
| 97 | * =========================================== | ||
| 98 | * 18 | Flush every second | ||
| 99 | * 1092 | Flush every minute | ||
| 100 | * 5460 | Flush every 5 minutes | ||
| 101 | * 10920 | Flush every 10 minutes | ||
| 102 | * 21840 | Flush every 20 minutes | ||
| 103 | * 32760 | Flush every 30 minutes | ||
| 104 | * 65520 | Flush every hour | ||
| 105 | * | ||
| 106 | * The default setting of nnnnn is 1092 or every minute. | ||
| 107 | * NOTE: There is no way to "disable" this tick aging. Setting | ||
| 108 | * nnnnn = 0 causes a wait for 65536 ticks which is a | ||
| 109 | * little over an hour. The max value for nnnnn is 65535. | ||
| 110 | * Disabling the cache (/d), or turning write caching | ||
| 111 | * off (/wc:off) effectively prevents the aging from | ||
| 112 | * doing anything as there is never anything to flush | ||
| 113 | * in these cases. Setting very low values of nnnnn | ||
| 114 | * should be avoided as it places a lot of overhead into | ||
| 115 | * the timer interrupt service. Rather than set low values, | ||
| 116 | * it is better to just turn off write caching (/wc:off). | ||
| 117 | * NOTE: As stated above, the max value for nnnnn is 65535. It | ||
| 118 | * should be noted however that FLUSH13 DOES NOT object if | ||
| 119 | * you specify a number larger than this! It will simply | ||
| 120 | * use only the low 16 bits of the number. | ||
| 121 | * | ||
| 122 | * /r:on off - En/Disable reboot flush. | ||
| 123 | * INT13 has a provision for detecting Ctrl-Alt-Del user | ||
| 124 | * reboots. /r:on enables a flush of the cache at this time | ||
| 125 | * to prevent the disks from being corrupted. The default | ||
| 126 | * setting is /r:off. NOTE WARNING DANGER!!!!! Enabling | ||
| 127 | * this feature can prevent disks from being damaged BUT | ||
| 128 | * the mechanism has flaws. For one, you will have to hit | ||
| 129 | * Ctrl-Alt-Del a second time to get the system to reboot. | ||
| 130 | * YOU MUST NOT POUND ON THE KEY. You will crash the system if | ||
| 131 | * you do. Hit the key ONCE, if the system re-boots, fine. If | ||
| 132 | * there is info to flush out of the cache, the drive light | ||
| 133 | * will come on and the system will probably NOT reboot. WAIT | ||
| 134 | * until the drive light is OFF before hitting Ctrl-Alt-Del | ||
| 135 | * again. This feature of INT13 MAY NOT WORK with other | ||
| 136 | * software in the system. USER BEWARE!!!!!!!!!!!!!!!!!!! | ||
| 137 | * | ||
| 138 | * /c:on off - En/Disable all cache on reads. | ||
| 139 | * Normally INT13 does not cache EVERY I/O. Whenever | ||
| 140 | * it sees a full track I/O which is not currently in | ||
| 141 | * the cache, it DOES NOT cache that track. This is | ||
| 142 | * an optimization for "typical" operation, and actually | ||
| 143 | * increases performance. This is the default setting | ||
| 144 | * (/c:off). There may be some cases where it is desirable | ||
| 145 | * that ALL reads be cached. One example is that you are | ||
| 146 | * "loading" the cache prior to locking it with FLUSH13 /l. | ||
| 147 | * With /c:off, some pieces of what you're trying to load | ||
| 148 | * may not get into the cache. Another example is that | ||
| 149 | * you continually access in a sequential manner (like | ||
| 150 | * program load) some large file which happens to be | ||
| 151 | * contiguous on the disk. Again, there may be some "piece" | ||
| 152 | * of the file which does not get into the cache with | ||
| 153 | * /c:off. /c:on enables the caching of ALL reads. | ||
| 154 | * NOTE: The same "don't bother caching operations which | ||
| 155 | * are full track and not in the cache" applies | ||
| 156 | * to writes as well. /c has NO EFFECT on this | ||
| 157 | * behavior however. /c only effects read operations. | ||
| 158 | * | ||
| 159 | * MODIFICATION HISTORY | ||
| 160 | * | ||
| 161 | * 1.10 5/26/86 ARR First version in assembler | ||
| 162 | * 1.20 5/27/86 ARR Lock cache function added. | ||
| 163 | * 1.22 5/30/86 ARR /r reboot flush code added | ||
| 164 | * 1.23 6/03/86 ARR Cache statistics added | ||
| 165 | * 1.24 6/05/86 ARR Added /a "all cache" code | ||
| 166 | * 1.25 6/10/86 ARR Added total used, total locked to status | ||
| 167 | * RECODED in 'C'. | ||
| 168 | * /f switch added. | ||
| 169 | * 1.26 6/12/86 ARR /wb changed to /wc. Some status report wording | ||
| 170 | * changed. This was to align the behavior with the | ||
| 171 | * documentation a little better. | ||
| 172 | * 1.27 1/22/87 ARR Change to format of status information. | ||
| 173 | */ | ||
| 174 | |||
| 175 | #include <stdio.h> | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Messages in flmes.asm | ||
| 179 | */ | ||
| 180 | extern char NO_DEV_MESS[], IOCTL_BAD_MESS[], STATUS_MES2[], SWTCH_CONF[]; | ||
| 181 | extern char BAD_PARM[], STATUS_MES1[], DISSTRING[], ENSTRING[]; | ||
| 182 | extern char LOCKSTRING[], UNLSTRING[], REBOOT_MES[]; | ||
| 183 | extern char STATUS_3R[], STATUS_3W[], STATUS_3T[]; | ||
| 184 | extern char CACHE_MES[], WT_MES[], WB_MES[], L_MES[], C_MES[], T_MES[]; | ||
| 185 | extern char STATUS_4[], ONSTRING[], OFFSTRING[], STATUS_5[]; | ||
| 186 | |||
| 187 | /* | ||
| 188 | * Structure of the data returned by the status call to INT13 | ||
| 189 | */ | ||
| 190 | typedef struct { | ||
| 191 | unsigned char write_through; | ||
| 192 | unsigned char write_buff; | ||
| 193 | unsigned char enable_13; | ||
| 194 | unsigned char nuldev; | ||
| 195 | unsigned int ticksetting; | ||
| 196 | unsigned char lock_cache; | ||
| 197 | unsigned char reboot_flush; | ||
| 198 | unsigned char all_cache; | ||
| 199 | unsigned char pad; | ||
| 200 | unsigned long total_writes; | ||
| 201 | unsigned long write_hits; | ||
| 202 | unsigned long total_reads; | ||
| 203 | unsigned long read_hits; | ||
| 204 | unsigned int ttracks; | ||
| 205 | unsigned int total_used; | ||
| 206 | unsigned int total_locked; | ||
| 207 | unsigned int total_dirty; | ||
| 208 | unsigned int current_size; | ||
| 209 | unsigned int initial_size; | ||
| 210 | unsigned int minimum_size; | ||
| 211 | } status; | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Assembler routines in fl13.asm | ||
| 215 | */ | ||
| 216 | extern int IOCTLOpen(char *); | ||
| 217 | extern int IOCTLWrite(int,char *,int); | ||
| 218 | extern int IOCTLRead(int,status *,int); | ||
| 219 | extern int IOCTLClose(int); | ||
| 220 | |||
| 221 | /* | ||
| 222 | * GetNum - Read an unsigned 16 bit decimal number | ||
| 223 | * | ||
| 224 | * ENTRY: cptr points to string where decimal number is | ||
| 225 | * iptr points to unsigned int where number goes | ||
| 226 | * | ||
| 227 | * NOTES: Calls Fatal (which doesn't return) if no number is present. | ||
| 228 | * No error if number is > 16 bits, only low 16 bits are returned. | ||
| 229 | * | ||
| 230 | * EXIT: returns cptr advanced past number | ||
| 231 | * iptr contains number found | ||
| 232 | * | ||
| 233 | */ | ||
| 234 | char *GetNum(cptr,iptr) | ||
| 235 | unsigned char *cptr; | ||
| 236 | unsigned int *iptr; | ||
| 237 | { | ||
| 238 | *iptr = 0; | ||
| 239 | if((*cptr < '0') || (*cptr > '9')) | ||
| 240 | Fatal(BAD_PARM); | ||
| 241 | while((*cptr >= '0') && (*cptr <= '9')) | ||
| 242 | *iptr = (*iptr * 10) + ((unsigned int) (*cptr++ - '0')); | ||
| 243 | return(cptr); | ||
| 244 | } | ||
| 245 | |||
| 246 | /* | ||
| 247 | * GetOnOff - Check for :on or :off string | ||
| 248 | * | ||
| 249 | * ENTRY: cptr points to string where :on or :off is supposed to be | ||
| 250 | * iptr points to unsigned int which is a boolean | ||
| 251 | * | ||
| 252 | * NOTES: Calls Fatal (which doesn't return) if :on or :off is not found. | ||
| 253 | * Case insensitive. | ||
| 254 | * | ||
| 255 | * EXIT: returns cptr advanced past :on or :off | ||
| 256 | * iptr contains 1 if :on was found | ||
| 257 | * iptr contains 0 if :off was found | ||
| 258 | * | ||
| 259 | */ | ||
| 260 | char *GetOnOff(cptr,iptr) | ||
| 261 | char *cptr; | ||
| 262 | int *iptr; | ||
| 263 | { | ||
| 264 | if(*cptr++ != ':') | ||
| 265 | Fatal(BAD_PARM); | ||
| 266 | *cptr |= 0x20; | ||
| 267 | if(*cptr++ != 'o') | ||
| 268 | Fatal(BAD_PARM); | ||
| 269 | *cptr |= 0x20; | ||
| 270 | if(*cptr == 'n') { | ||
| 271 | cptr++; | ||
| 272 | *iptr = 1; | ||
| 273 | } | ||
| 274 | else if(*cptr == 'f'){ | ||
| 275 | cptr++; | ||
| 276 | *cptr |= 0x20; | ||
| 277 | if(*cptr++ != 'f') | ||
| 278 | Fatal(BAD_PARM); | ||
| 279 | *iptr = 0; | ||
| 280 | } | ||
| 281 | else | ||
| 282 | Fatal(BAD_PARM); | ||
| 283 | return(cptr); | ||
| 284 | } | ||
| 285 | |||
| 286 | |||
| 287 | /* | ||
| 288 | * Flush13 | ||
| 289 | * | ||
| 290 | * ENTRY: Std | ||
| 291 | * | ||
| 292 | * NOTES: | ||
| 293 | * | ||
| 294 | * EXIT: exit(0) if OK, exit(-1) if error. | ||
| 295 | * | ||
| 296 | */ | ||
| 297 | main(argc, argv, envp) | ||
| 298 | int argc; | ||
| 299 | char **argv; | ||
| 300 | char **envp; | ||
| 301 | |||
| 302 | { | ||
| 303 | |||
| 304 | int handle,boolval; | ||
| 305 | char *cptr; | ||
| 306 | unsigned long total_hits,total_ops; | ||
| 307 | unsigned int minutes,seconds; | ||
| 308 | struct { | ||
| 309 | unsigned SWITCH_S : 1; | ||
| 310 | unsigned SWITCH_I : 1; | ||
| 311 | unsigned SWITCH_D : 1; | ||
| 312 | unsigned SWITCH_E : 1; | ||
| 313 | unsigned SWITCH_L : 1; | ||
| 314 | unsigned SWITCH_U : 1; | ||
| 315 | unsigned SWITCH_T : 1; | ||
| 316 | unsigned SWITCH_WCON : 1; | ||
| 317 | unsigned SWITCH_WCOFF : 1; | ||
| 318 | unsigned SWITCH_WTON : 1; | ||
| 319 | unsigned SWITCH_WTOFF : 1; | ||
| 320 | unsigned SWITCH_ROFF : 1; | ||
| 321 | unsigned SWITCH_RON : 1; | ||
| 322 | unsigned SWITCH_SX : 1; | ||
| 323 | unsigned SWITCH_SR : 1; | ||
| 324 | unsigned SWITCH_CON : 1; | ||
| 325 | unsigned SWITCH_COFF : 1; | ||
| 326 | unsigned SWITCH_F : 1; | ||
| 327 | } switches; | ||
| 328 | struct { | ||
| 329 | unsigned char Tchar; | ||
| 330 | unsigned char tickvall; /* this is actually an unsigned int */ | ||
| 331 | unsigned char tickvalh; /* but we have to declare it this way */ | ||
| 332 | } tickpacket; /* so that the compiler doesn't word align */ | ||
| 333 | status config; | ||
| 334 | |||
| 335 | /* Check for no arguments case and process if found */ | ||
| 336 | |||
| 337 | handle = -1; | ||
| 338 | if (argc == 1) { /* no arguments */ | ||
| 339 | if((handle = IOCTLOpen("SMARTAAR")) == -1) | ||
| 340 | Fatal(NO_DEV_MESS); | ||
| 341 | if(IOCTLWrite(handle,"\x00",1) == -1) | ||
| 342 | Fatal(IOCTL_BAD_MESS); | ||
| 343 | IOCTLClose(handle); | ||
| 344 | exit(0); | ||
| 345 | } | ||
| 346 | |||
| 347 | /* Initialize data associated with the argument parse */ | ||
| 348 | |||
| 349 | switches.SWITCH_S = switches.SWITCH_I = switches.SWITCH_D = 0; | ||
| 350 | switches.SWITCH_E = switches.SWITCH_L = switches.SWITCH_U = 0; | ||
| 351 | switches.SWITCH_T = switches.SWITCH_WCON = switches.SWITCH_WCOFF = 0; | ||
| 352 | switches.SWITCH_WTON = switches.SWITCH_WTOFF = switches.SWITCH_ROFF = 0; | ||
| 353 | switches.SWITCH_RON = switches.SWITCH_SX = switches.SWITCH_SR = 0; | ||
| 354 | switches.SWITCH_CON = switches.SWITCH_COFF = switches.SWITCH_F = 0; | ||
| 355 | |||
| 356 | /* Parse the arguments */ | ||
| 357 | |||
| 358 | ++argv; /* Skip argv[0] */ | ||
| 359 | while(--argc) { /* While arguments */ | ||
| 360 | cptr = *argv; | ||
| 361 | if(*cptr++ != '/') /* all arguments are switches */ | ||
| 362 | Fatal(BAD_PARM); | ||
| 363 | if(*cptr == '\0') /* trailing / error? */ | ||
| 364 | Fatal(BAD_PARM); | ||
| 365 | *cptr |= 0x20; /* lower case */ | ||
| 366 | switch (*cptr++) { | ||
| 367 | |||
| 368 | /* Status */ | ||
| 369 | case 's': | ||
| 370 | if(switches.SWITCH_S || switches.SWITCH_SX || switches.SWITCH_SR) | ||
| 371 | Fatal(SWTCH_CONF); | ||
| 372 | if(*cptr == '\0') | ||
| 373 | switches.SWITCH_S = 1; | ||
| 374 | else { | ||
| 375 | *cptr |= 0x20; | ||
| 376 | if(*cptr == 'r') | ||
| 377 | switches.SWITCH_SR = 1; | ||
| 378 | else if(*cptr == 'x') | ||
| 379 | switches.SWITCH_SX = 1; | ||
| 380 | else | ||
| 381 | Fatal(BAD_PARM); | ||
| 382 | cptr++; | ||
| 383 | } | ||
| 384 | break; | ||
| 385 | |||
| 386 | /* c on or off */ | ||
| 387 | case 'c': | ||
| 388 | if(switches.SWITCH_CON || switches.SWITCH_COFF) | ||
| 389 | Fatal(SWTCH_CONF); | ||
| 390 | cptr = GetOnOff(cptr,&boolval); | ||
| 391 | if(boolval) | ||
| 392 | switches.SWITCH_CON = 1; | ||
| 393 | else | ||
| 394 | switches.SWITCH_COFF = 1; | ||
| 395 | break; | ||
| 396 | |||
| 397 | /* t set tick value */ | ||
| 398 | case 't': | ||
| 399 | if(switches.SWITCH_T) | ||
| 400 | Fatal(SWTCH_CONF); | ||
| 401 | if(*cptr++ != ':') | ||
| 402 | Fatal(BAD_PARM); | ||
| 403 | cptr = GetNum(cptr,&tickpacket.tickvall); | ||
| 404 | tickpacket.Tchar = '\x0B'; /* set tick is call 5 */ | ||
| 405 | switches.SWITCH_T = 1; | ||
| 406 | break; | ||
| 407 | |||
| 408 | /* wt or wb on or off */ | ||
| 409 | case 'w': | ||
| 410 | *cptr |= 0x20; | ||
| 411 | if(*cptr == 'c') { | ||
| 412 | cptr++; | ||
| 413 | if(switches.SWITCH_WCOFF || switches.SWITCH_WCON) | ||
| 414 | Fatal(SWTCH_CONF); | ||
| 415 | cptr = GetOnOff(cptr,&boolval); | ||
| 416 | if(boolval) | ||
| 417 | switches.SWITCH_WCON = 1; | ||
| 418 | else | ||
| 419 | switches.SWITCH_WCOFF = 1; | ||
| 420 | } | ||
| 421 | else if(*cptr == 't') { | ||
| 422 | cptr++; | ||
| 423 | if(switches.SWITCH_WTOFF || switches.SWITCH_WTON) | ||
| 424 | Fatal(SWTCH_CONF); | ||
| 425 | cptr = GetOnOff(cptr,&boolval); | ||
| 426 | if(boolval) | ||
| 427 | switches.SWITCH_WTON = 1; | ||
| 428 | else | ||
| 429 | switches.SWITCH_WTOFF = 1; | ||
| 430 | } | ||
| 431 | else | ||
| 432 | Fatal(BAD_PARM); | ||
| 433 | break; | ||
| 434 | |||
| 435 | /* d disable */ | ||
| 436 | case 'd': | ||
| 437 | if(switches.SWITCH_D || switches.SWITCH_E) | ||
| 438 | Fatal(SWTCH_CONF); | ||
| 439 | switches.SWITCH_D = 1; | ||
| 440 | break; | ||
| 441 | |||
| 442 | /* e enable */ | ||
| 443 | case 'e': | ||
| 444 | if(switches.SWITCH_D || switches.SWITCH_E) | ||
| 445 | Fatal(SWTCH_CONF); | ||
| 446 | switches.SWITCH_E = 1; | ||
| 447 | break; | ||
| 448 | |||
| 449 | /* l lock */ | ||
| 450 | case 'l': | ||
| 451 | if(switches.SWITCH_L || switches.SWITCH_U) | ||
| 452 | Fatal(SWTCH_CONF); | ||
| 453 | switches.SWITCH_L = 1; | ||
| 454 | break; | ||
| 455 | |||
| 456 | /* u unlock */ | ||
| 457 | case 'u': | ||
| 458 | if(switches.SWITCH_L || switches.SWITCH_U) | ||
| 459 | Fatal(SWTCH_CONF); | ||
| 460 | switches.SWITCH_U = 1; | ||
| 461 | break; | ||
| 462 | |||
| 463 | /* i invalidate */ | ||
| 464 | case 'i': | ||
| 465 | if(switches.SWITCH_I) | ||
| 466 | Fatal(SWTCH_CONF); | ||
| 467 | switches.SWITCH_I = 1; | ||
| 468 | break; | ||
| 469 | |||
| 470 | /* f flush */ | ||
| 471 | case 'f': | ||
| 472 | if(switches.SWITCH_F) | ||
| 473 | Fatal(SWTCH_CONF); | ||
| 474 | switches.SWITCH_F = 1; | ||
| 475 | break; | ||
| 476 | |||
| 477 | /* r on or off */ | ||
| 478 | case 'r': | ||
| 479 | if(switches.SWITCH_RON || switches.SWITCH_ROFF) | ||
| 480 | Fatal(SWTCH_CONF); | ||
| 481 | cptr = GetOnOff(cptr,&boolval); | ||
| 482 | if(boolval) | ||
| 483 | switches.SWITCH_RON = 1; | ||
| 484 | else | ||
| 485 | switches.SWITCH_ROFF = 1; | ||
| 486 | break; | ||
| 487 | |||
| 488 | default: | ||
| 489 | Fatal(BAD_PARM); | ||
| 490 | |||
| 491 | } | ||
| 492 | if(*cptr != '\0') /* must be at end of argument */ | ||
| 493 | Fatal(BAD_PARM); | ||
| 494 | ++argv; /* next argument */ | ||
| 495 | } | ||
| 496 | |||
| 497 | /* Open the device */ | ||
| 498 | |||
| 499 | if((handle = IOCTLOpen("SMARTAAR")) == -1) | ||
| 500 | Fatal(NO_DEV_MESS); | ||
| 501 | |||
| 502 | /* Perform the actions indicated by the arguments */ | ||
| 503 | |||
| 504 | if(switches.SWITCH_I) { | ||
| 505 | if(IOCTLWrite(handle,"\x01",1) == -1) | ||
| 506 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 507 | } | ||
| 508 | |||
| 509 | if(switches.SWITCH_F) { | ||
| 510 | if(IOCTLWrite(handle,"\x00",1) == -1) | ||
| 511 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 512 | } | ||
| 513 | |||
| 514 | if(switches.SWITCH_WTON) { | ||
| 515 | if(IOCTLWrite(handle,"\x04\x01",2) == -1) | ||
| 516 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 517 | } | ||
| 518 | else if(switches.SWITCH_WTOFF) { | ||
| 519 | if(IOCTLWrite(handle,"\x04\x00",2) == -1) | ||
| 520 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 521 | } | ||
| 522 | |||
| 523 | if(switches.SWITCH_WCON) { | ||
| 524 | if(IOCTLWrite(handle,"\x04\x03",2) == -1) | ||
| 525 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 526 | } | ||
| 527 | else if(switches.SWITCH_WCOFF) { | ||
| 528 | if(IOCTLWrite(handle,"\x04\x02",2) == -1) | ||
| 529 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 530 | } | ||
| 531 | |||
| 532 | if(switches.SWITCH_L) { | ||
| 533 | if(IOCTLWrite(handle,"\x06",1) == -1) | ||
| 534 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 535 | } | ||
| 536 | else if(switches.SWITCH_U) { | ||
| 537 | if(IOCTLWrite(handle,"\x07",1) == -1) | ||
| 538 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 539 | } | ||
| 540 | |||
| 541 | if(switches.SWITCH_T) { | ||
| 542 | if(IOCTLWrite(handle,&tickpacket.Tchar,3) == -1) | ||
| 543 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 544 | } | ||
| 545 | |||
| 546 | if(switches.SWITCH_RON) { | ||
| 547 | if(IOCTLWrite(handle,"\x08\x01",2) == -1) | ||
| 548 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 549 | } | ||
| 550 | else if(switches.SWITCH_ROFF) { | ||
| 551 | if(IOCTLWrite(handle,"\x08\x00",2) == -1) | ||
| 552 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 553 | } | ||
| 554 | |||
| 555 | if(switches.SWITCH_CON) { | ||
| 556 | if(IOCTLWrite(handle,"\x0A\x01",2) == -1) | ||
| 557 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 558 | } | ||
| 559 | else if(switches.SWITCH_COFF) { | ||
| 560 | if(IOCTLWrite(handle,"\x0A\x00",2) == -1) | ||
| 561 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 562 | } | ||
| 563 | |||
| 564 | if(switches.SWITCH_E) { | ||
| 565 | if(IOCTLWrite(handle,"\x03",1) == -1) | ||
| 566 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 567 | } | ||
| 568 | else if(switches.SWITCH_D) { | ||
| 569 | if(IOCTLWrite(handle,"\x02",1) == -1) | ||
| 570 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 571 | } | ||
| 572 | |||
| 573 | if(switches.SWITCH_S || switches.SWITCH_SR || switches.SWITCH_SX) { | ||
| 574 | if(IOCTLRead(handle,&config,sizeof(config)) == -1) | ||
| 575 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 576 | if(config.nuldev != 0) | ||
| 577 | printf(STATUS_MES1); | ||
| 578 | else { | ||
| 579 | printf(STATUS_MES2); | ||
| 580 | if(config.enable_13 != 0) | ||
| 581 | printf(CACHE_MES,ENSTRING); | ||
| 582 | else | ||
| 583 | printf(CACHE_MES,DISSTRING); | ||
| 584 | if(config.lock_cache != 0) | ||
| 585 | printf(L_MES,LOCKSTRING); | ||
| 586 | else | ||
| 587 | printf(L_MES,UNLSTRING); | ||
| 588 | |||
| 589 | if(config.write_buff != 0) | ||
| 590 | printf(WB_MES,ONSTRING); | ||
| 591 | else | ||
| 592 | printf(WB_MES,OFFSTRING); | ||
| 593 | if(config.reboot_flush != 0) | ||
| 594 | printf(REBOOT_MES,ONSTRING); | ||
| 595 | else | ||
| 596 | printf(REBOOT_MES,OFFSTRING); | ||
| 597 | |||
| 598 | if(config.all_cache != 0) | ||
| 599 | printf(C_MES,ONSTRING); | ||
| 600 | else | ||
| 601 | printf(C_MES,OFFSTRING); | ||
| 602 | if(config.write_through != 0) | ||
| 603 | printf(WT_MES,ONSTRING); | ||
| 604 | else | ||
| 605 | printf(WT_MES,OFFSTRING); | ||
| 606 | |||
| 607 | if(config.ticksetting == 0) { | ||
| 608 | minutes = 60; | ||
| 609 | seconds = 1; | ||
| 610 | } | ||
| 611 | else { | ||
| 612 | seconds = ((unsigned long)config.ticksetting * 10) / 182; | ||
| 613 | minutes = seconds / 60; | ||
| 614 | seconds = seconds % 60; | ||
| 615 | } | ||
| 616 | printf(T_MES,minutes,seconds,config.ticksetting); | ||
| 617 | |||
| 618 | if(switches.SWITCH_SR) { | ||
| 619 | if(IOCTLWrite(handle,"\x09",1) == -1) | ||
| 620 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 621 | /* get the status again so that the extended status has the reset */ | ||
| 622 | if(IOCTLRead(handle,&config,sizeof(config)) == -1) | ||
| 623 | FatalC(handle,IOCTL_BAD_MESS); | ||
| 624 | } | ||
| 625 | if(switches.SWITCH_SX || switches.SWITCH_SR) { | ||
| 626 | if(config.total_writes == 0) | ||
| 627 | printf(STATUS_3W,config.write_hits,config.total_writes,(unsigned int) 0); | ||
| 628 | else | ||
| 629 | printf(STATUS_3W,config.write_hits,config.total_writes,(unsigned int)(config.write_hits*100/config.total_writes)); | ||
| 630 | if(config.total_reads == 0) | ||
| 631 | printf(STATUS_3R,config.read_hits,config.total_reads,(unsigned int) 0); | ||
| 632 | else | ||
| 633 | printf(STATUS_3R,config.read_hits,config.total_reads,(unsigned int)(config.read_hits*100/config.total_reads)); | ||
| 634 | total_ops = config.total_reads + config.total_writes; | ||
| 635 | total_hits = config.read_hits + config.write_hits; | ||
| 636 | if(total_ops == 0) | ||
| 637 | printf(STATUS_3T,total_hits,total_ops,(unsigned int) 0); | ||
| 638 | else | ||
| 639 | printf(STATUS_3T,total_hits,total_ops,(unsigned int)(total_hits*100/total_ops)); | ||
| 640 | printf(STATUS_4,config.ttracks,config.total_used,config.total_locked,config.total_dirty); | ||
| 641 | printf(STATUS_5,config.current_size,config.initial_size,config.minimum_size); | ||
| 642 | } | ||
| 643 | } | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Close the device, and done */ | ||
| 647 | |||
| 648 | IOCTLClose(handle); | ||
| 649 | exit(0); | ||
| 650 | } | ||
| 651 | |||
| 652 | /* | ||
| 653 | * Fatal -- Fatal (to flush13) error | ||
| 654 | * | ||
| 655 | * ENTRY: p is pointer to error message to print | ||
| 656 | * | ||
| 657 | * NOTES: | ||
| 658 | * | ||
| 659 | * EXIT: exit(-1) | ||
| 660 | * | ||
| 661 | */ | ||
| 662 | Fatal(p) | ||
| 663 | char *p; | ||
| 664 | { | ||
| 665 | fprintf(stderr,"\n%s\n",p); | ||
| 666 | exit(-1); | ||
| 667 | } | ||
| 668 | |||
| 669 | /* | ||
| 670 | * FatalC -- Fatal (to flush13) error, and close open handle | ||
| 671 | * | ||
| 672 | * ENTRY: p is pointer to error message to print | ||
| 673 | * hand is handle number of open device channel to close | ||
| 674 | * | ||
| 675 | * NOTES: | ||
| 676 | * | ||
| 677 | * EXIT: To Fatal | ||
| 678 | * | ||
| 679 | */ | ||
| 680 | FatalC(hand,p) | ||
| 681 | int hand; | ||
| 682 | char *p; | ||
| 683 | { | ||
| 684 | IOCTLClose(hand); | ||
| 685 | Fatal(p); | ||
| 686 | } | ||
diff --git a/v4.0/src/DEV/SMARTDRV/FLUSH13.LNK b/v4.0/src/DEV/SMARTDRV/FLUSH13.LNK new file mode 100644 index 0000000..16fb1dd --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/FLUSH13.LNK | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | flush13.obj fl13.obj flmes.obj | ||
| 2 | flush13.exe /m | ||
| 3 | |||
| 4 | |||
diff --git a/v4.0/src/DEV/SMARTDRV/INT13.DOC b/v4.0/src/DEV/SMARTDRV/INT13.DOC new file mode 100644 index 0000000..3e1917b --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/INT13.DOC | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | mINT13.SYS is an MS-DOS device driver which implements a memory cache | ||
| 2 | for data referenced on IBM-PC XT/AT Hard disks. It caches at the | ||
| 3 | "INT 13H" level and caches tracks. | ||
| 4 | |||
| 5 | NOTE WARNING: There is a "re-boot" bug in RAMDrive version 1.16. When | ||
| 6 | INT13 and RAMDrive are both installed, it is possible | ||
| 7 | that Ctrl-Alt-Del will not work. This problem is "fixed" | ||
| 8 | by updating your RAMDrive to version 1.17 or later. | ||
| 9 | |||
| 10 | IN CONFIG.SYS: | ||
| 11 | |||
| 12 | device = [d:][path]int13.sys [bbbb] [/e | /a] [/d] [/wt:on] [/wc:off] | ||
| 13 | [/t:nnnnn] [/r:on] [/c:on] | ||
| 14 | |||
| 15 | bbbb First numeric argument, if present, is cache size | ||
| 16 | in K bytes. Default value is 256. Min is 128. Max | ||
| 17 | is 4096 (4 Meg). | ||
| 18 | |||
| 19 | /e Specifies that PC AT Extended Memory is to be used. | ||
| 20 | It is an error if /E is specified on a machine other | ||
| 21 | than an IBM PC AT. /E is the default. | ||
| 22 | |||
| 23 | NOTE: There is 1k of INT13 overhead. That is to say, | ||
| 24 | if there are 512k bytes of extended memory, there | ||
| 25 | will be 511k bytes available for assignment to INT13. | ||
| 26 | |||
| 27 | /a Specifies that Above Board memory is to be used. It | ||
| 28 | is an error if the above board device driver is not | ||
| 29 | present. | ||
| 30 | |||
| 31 | Neither /A or /E Specifies /E | ||
| 32 | |||
| 33 | NOTE: THESE ARE THE ONLY CONFIGURATIONS. You must either have an | ||
| 34 | Above Board (or compatible), or you must have extended memory | ||
| 35 | on an IBM PC-AT (or compatible). | ||
| 36 | |||
| 37 | /d Disable caching. Causes INT13 to come up with caching | ||
| 38 | disabled (default is enabled). | ||
| 39 | |||
| 40 | /wt:on Enable write through. When INT13 is | ||
| 41 | caching write information, it is a good idea to imply | ||
| 42 | a flush of the cache on some operations so that in | ||
| 43 | case of a crash or power failure the information in | ||
| 44 | the cache which is not on the disk will not be lost. | ||
| 45 | /wt:on enables write through on full track INT 13s which | ||
| 46 | are to tracks not currently in the cache. /wt:off | ||
| 47 | disables it. INT13 is faster with write through | ||
| 48 | disabled, at the expense of there being a bigger risk of | ||
| 49 | loosing data. /wt:on IS NOT a substitute for flushing | ||
| 50 | before a re-boot!!!! The write through mechanism is far | ||
| 51 | from perfect, all it is is a risk REDUCER, not a risk | ||
| 52 | eliminator. Write through is off by default. | ||
| 53 | |||
| 54 | /wc:off - Disable write caching. There is risk when | ||
| 55 | caching "dirty" information that the system will crash, | ||
| 56 | or be re-booted, or be turned off before this | ||
| 57 | information can be written to the disk. This may | ||
| 58 | corrupt the disk. This risk can be ELIMINATED, at the | ||
| 59 | expense of cache performance, by NOT caching any dirty | ||
| 60 | information. /wc:off disables the caching of dirty | ||
| 61 | information, eliminating the risk. Write caching is | ||
| 62 | on by default. | ||
| 63 | |||
| 64 | /t:nnnnn - Set the auto flush interval. INT13 listens on the | ||
| 65 | system timer to note the passage of time and "age" the | ||
| 66 | dirty information in the cache. Every nnnnn ticks, | ||
| 67 | the cache is flushed. The timer ticks 18.2 times a | ||
| 68 | second. | ||
| 69 | |||
| 70 | nnnnn | | ||
| 71 | =========================================== | ||
| 72 | 18 | Flush every second | ||
| 73 | 1092 | Flush every minute | ||
| 74 | 5460 | Flush every 5 minutes | ||
| 75 | 10920 | Flush every 10 minutes | ||
| 76 | 21840 | Flush every 20 minutes | ||
| 77 | 32760 | Flush every 30 minutes | ||
| 78 | 65520 | Flush every hour | ||
| 79 | |||
| 80 | The default setting of nnnnn is 1092 or every minute. | ||
| 81 | nnnnn = 0 causes a wait for 65536 ticks which is a | ||
| 82 | little over an hour. The max value for nnnnn is 65535. | ||
| 83 | |||
| 84 | /r:on - Enable re-boot flush. | ||
| 85 | This enables the flush on re-boot logic. The default | ||
| 86 | is /r:off. This enables a flush in the Ctrl-Alt-Del | ||
| 87 | keyboard re-boot logic. NOTE WARNING DANGER!!!!!!!! | ||
| 88 | Enabling this feature can cause strange system behavior. | ||
| 89 | You will have to type Ctrl-Alt-Del twice at least. This | ||
| 90 | can adversly effect other software in the system. | ||
| 91 | The result of this can be very unpredictable. | ||
| 92 | |||
| 93 | /c:on - Enable all cache on reads. | ||
| 94 | Normally INT13 does not cache EVERY I/O. Whenever | ||
| 95 | it sees a full track I/O which is not currently in | ||
| 96 | the cache, it DOES NOT cache that track. This is | ||
| 97 | an optimization for "typical" operation, and actually | ||
| 98 | increases performance. This is the default setting | ||
| 99 | (/c:off). There may be some cases where it is desirable | ||
| 100 | that ALL reads be cached. One example is that you are | ||
| 101 | "loading" the cache prior to locking it with FLUSH13 /l. | ||
| 102 | With /c:off, some pieces of what you're trying to load | ||
| 103 | may not get into the cache. Another example is that | ||
| 104 | you continually access in a sequential manner (like | ||
| 105 | program load) some large file which happens to be | ||
| 106 | contiguous on the disk. Again, there may be some "piece" | ||
| 107 | of the file which does not get into the cache with | ||
| 108 | /c:off. /c:on enables the caching of ALL reads. | ||
| 109 | NOTE: The same "don't bother caching operations which | ||
| 110 | are full track and not in the cache" applies | ||
| 111 | to writes as well. /c has NO EFFECT on this | ||
| 112 | behavior however. /c only effects read operations. | ||
| 113 | |||
| 114 | |||
| 115 | |||
| 116 | MESSAGES: | ||
| 117 | |||
| 118 | |||
| 119 | INT13: Above Board Memory Manager not present | ||
| 120 | |||
| 121 | The /A switch was given but INT13 could not detect the presence of the | ||
| 122 | Above Board memory manager. You need to have a | ||
| 123 | |||
| 124 | device = EMM.SYS | ||
| 125 | |||
| 126 | line in your CONFIG.SYS file before you have any device = int13.sys | ||
| 127 | lines. INT13 will install a driver, but it will be non-functional. | ||
| 128 | |||
| 129 | |||
| 130 | INT13: Above Board Memory Status shows error | ||
| 131 | |||
| 132 | During the process of trying to set up the cache in Above Board memory | ||
| 133 | an error was detected. Run the Above Board Confidence test to test | ||
| 134 | your Above Board memory. INT13 will install a driver, but it will be | ||
| 135 | non-functional. | ||
| 136 | |||
| 137 | |||
| 138 | INT13: Computer must be PC-AT, or PC-AT compatible | ||
| 139 | |||
| 140 | The /E switch can only be given on an IBM PC AT or an IBM PC AT | ||
| 141 | compatible computer that has the FCH model byte (byte at FFFF:000E). | ||
| 142 | INT13 will install a driver, but it will be non-functional. | ||
| 143 | |||
| 144 | |||
| 145 | INT13: No extended memory available | ||
| 146 | |||
| 147 | Your system has NO memory for RAMDrive drives. | ||
| 148 | INT13 will install a driver, but it will be non-functional. | ||
| 149 | |||
| 150 | |||
| 151 | INT13: Insufficient memory | ||
| 152 | |||
| 153 | Your system has some memory available for INT13 cache, but not enough | ||
| 154 | to set up a driver. INT13 will install a driver, but it will be non-functional. | ||
| 155 | |||
| 156 | |||
| 157 | INT13: Invalid parameter | ||
| 158 | |||
| 159 | You specified too many parameters, your numeric parameter is not | ||
| 160 | valid, you specified conflicting or too many switches. Edit your CONFIG.SYS | ||
| 161 | file and fix the INT13 line. INT13 will install a driver, but it will | ||
| 162 | be non-functional. | ||
| 163 | |||
| 164 | |||
| 165 | INT13: Incorrect DOS version | ||
| 166 | |||
| 167 | INT13 only runs on 2.X and 3.X versions of DOS. | ||
| 168 | INT13 will install a driver, but it will be non-functional. | ||
| 169 | |||
| 170 | |||
| 171 | INT13: I/O error accessing cache memory | ||
| 172 | |||
| 173 | During the set up of the INT13 cache, an error was detected trying to | ||
| 174 | access the cache memory. Run any memory tests you have that will | ||
| 175 | exercise your extended or expanded memory. | ||
| 176 | INT13 will install a driver, but it will be non-functional. | ||
| 177 | |||
| 178 | |||
| 179 | INT13: No hardfiles on system | ||
| 180 | |||
| 181 | INT13 could not find any hardfiles on your system. Only hardfiles | ||
| 182 | which are compatible with IBM hardfiles at the ROM BIOS INT 13H | ||
| 183 | level can be supported. INT13 will install a driver, but it will | ||
| 184 | be non-functional. | ||
| 185 | |||
| 186 | |||
| 187 | INT13: Too many bytes per track on hardfile | ||
| 188 | |||
| 189 | One of the hardfiles on your system defined a very large track. | ||
| 190 | This track is too large for INT13 to be able to cache it. | ||
| 191 | INT13 will install a driver, but it will be non-functional. | ||
| 192 | |||
| 193 | |||
| 194 | Microsoft INT13 Cache version Y.YY | ||
| 195 | |||
| 196 | INT13 Header message, Y.YY is the version of INT13. | ||
| 197 | |||
| 198 | |||
| 199 | Cache size: nnnnk in UUUUUU Memory | ||
| 200 | Room for tttt tracks of ssss sectors each | ||
| 201 | |||
| 202 | This is an informational message from INT13 telling you how many Kilo Bytes | ||
| 203 | of memory were assigned to the cache and what type of memory it is, how many | ||
| 204 | tracks this allows to be buffered and how many sectors there are per track. | ||
| 205 | |||
| 206 | NOTE: There is nothing to "prevent" you from having two device = INT13.SYS | ||
| 207 | lines in your CONFIG.SYS file, but you should not do this. Very | ||
| 208 | unpredictable behavior will occur, and FLUSH13 will only "talk" to | ||
| 209 | one of them. | ||
| 210 | |||
| 211 | INT13 has several behavior aspects that can be changed. This is done | ||
| 212 | with the FLUSH13 utility. | ||
| 213 | |||
| 214 | FLUSH13 [/s|/sx|/sr] [/d|/e] [/l|/u] [/i] [/f] [/wt:on|/wt:off] | ||
| 215 | [/wc:on|/wc:off] [/t:nnnnn] [/r:on|/r:off] [/c:on|/c:off] | ||
| 216 | |||
| 217 | No arguments - This causes FLUSH13 to flush out any "dirty" | ||
| 218 | tracks in the INT13 cache. A "dirty" track is one | ||
| 219 | which has been written into the cache, but not yet | ||
| 220 | written to the disk. This invokation causes all dirty tracks | ||
| 221 | to be written out to the disk so that the system can | ||
| 222 | be re-booted or turned off. NOTE: FAILURE TO FLUSH | ||
| 223 | THE CACHE BEFORE A RE-BOOT OR POWER OFF CAN CAUSE THE | ||
| 224 | INFORMATION ON THE HARDFILE TO BE CORRUPTED. | ||
| 225 | |||
| 226 | /f - Flush. Same as the no arguments case, but allows you to | ||
| 227 | perform the flush and do something else (like /s). | ||
| 228 | |||
| 229 | /i - Flush and invalidate. This is the same as the no argument | ||
| 230 | case except that all of the information in the cache | ||
| 231 | is also discarded. This makes the cache EMPTY. | ||
| 232 | |||
| 233 | /d - Disable caching. This causes all dirty cache information | ||
| 234 | to be flushed and all caching to stop. | ||
| 235 | |||
| 236 | /e - Enable caching. This causes caching to be enabled after | ||
| 237 | a previous /d disable. When INT13 is started it is enabled. | ||
| 238 | |||
| 239 | /l - Lock the cache. This causes all dirty information to be | ||
| 240 | flushed, and the cache contents to be locked in the cache. | ||
| 241 | When in this mode the locked elements will not be discarded | ||
| 242 | to make room for new tracks. This can be used | ||
| 243 | to "load" the cache with desired things. For instance if | ||
| 244 | you use the "foobar" program a lot, you can run foobar, | ||
| 245 | causing it to be loaded into the cache, then lock the cache. | ||
| 246 | This causes the foobar program to always be in the cache. | ||
| 247 | You may lock the cache as many times as you want. Each lock | ||
| 248 | causes the current information (including any previously | ||
| 249 | locked information) to be locked. | ||
| 250 | NOTE: Information in a locked cache is READ ONLY!! Any write | ||
| 251 | operation on information in a locked cache causes the | ||
| 252 | information to be unlocked. | ||
| 253 | |||
| 254 | /u - Unlock the cache. This undoes a previous /l and returns | ||
| 255 | the cache to normal operation. | ||
| 256 | |||
| 257 | /s - Print status. This displays the settings of the setable | ||
| 258 | device parameters. | ||
| 259 | /sx - Print extended status. Same as /s, only additional | ||
| 260 | Statistical information is also given. | ||
| 261 | /sr - Reset statistics. Same as /sx, only the additional | ||
| 262 | Statistical information is reset to 0. | ||
| 263 | |||
| 264 | /wt:on off - Enable or Disable write through. When INT13 is caching | ||
| 265 | write information, it is a good idea to imply a flush of | ||
| 266 | the cache on some operations so that in case of a crash or | ||
| 267 | power failure the information in the cache which is not on | ||
| 268 | the disk will not be lost. /wt:on enables write through on full | ||
| 269 | track INT 13s which are to tracks not currently in the cache. | ||
| 270 | /wt:off disables it. INT13 is faster with write through | ||
| 271 | off, at the expense of there being a bigger risk of | ||
| 272 | loosing data. /wt:on IS NOT a substitute for flushing before | ||
| 273 | a re-boot!!!! This write through mechanism is far from perfect, | ||
| 274 | all it is is a risk REDUCER, not a risk eliminator. /wt:off | ||
| 275 | is the setting when INT13 is started. | ||
| 276 | |||
| 277 | /wc:on off - Enable or Disable write caching. There is risk when | ||
| 278 | caching "dirty" information that the system will crash, | ||
| 279 | or be re-booted, or be turned off before this information | ||
| 280 | can be written to the disk. This may corrupt the disk. | ||
| 281 | This risk can be ELIMINATED, at the expense of cache | ||
| 282 | performance, by NOT caching any dirty information. | ||
| 283 | /wc:off disables the caching of dirty information, | ||
| 284 | eliminating the risk. /wc:on enables the caching of dirty | ||
| 285 | information. /wc:on is the default when INT13 is started. | ||
| 286 | |||
| 287 | WARNING: You must be careful to flush the cache before | ||
| 288 | re-booting the system, or turning it off if /wc:on is selected. | ||
| 289 | You should also be careful to disable the cache (/d), or do | ||
| 290 | /wc:off before running any program under development which | ||
| 291 | has a chance of crashing due to bugs. | ||
| 292 | |||
| 293 | NOTE: When /wc:off is selected, write info CAN get into | ||
| 294 | the cache (when the write is to a track which is currently | ||
| 295 | in the cache). The difference is that this "dirty" information | ||
| 296 | is IMMEDIATELY written out to the disk instead of being | ||
| 297 | held in the cache in the "dirty" state. When the write is | ||
| 298 | to a track that is not in the cache, it will be passed | ||
| 299 | through to the disk without being cached. | ||
| 300 | |||
| 301 | /t:nnnnn - Set the auto flush interval. INT13 listens on the system | ||
| 302 | timer to note the passage of time and "age" the dirty | ||
| 303 | information in the cache. Every nnnnn ticks, the cache is | ||
| 304 | flushed. The timer ticks 18.2 times a second. | ||
| 305 | |||
| 306 | nnnnn | | ||
| 307 | =========================================== | ||
| 308 | 18 | Flush every second | ||
| 309 | 1092 | Flush every minute | ||
| 310 | 5460 | Flush every 5 minutes | ||
| 311 | 10920 | Flush every 10 minutes | ||
| 312 | 21840 | Flush every 20 minutes | ||
| 313 | 32760 | Flush every 30 minutes | ||
| 314 | 65520 | Flush every hour | ||
| 315 | |||
| 316 | The default setting of nnnnn is 1092 or every minute. | ||
| 317 | NOTE: There is no way to "disable" this tick aging. Setting | ||
| 318 | nnnnn = 0 causes a wait for 65536 ticks which is a | ||
| 319 | little over an hour. The max value for nnnnn is 65535. | ||
| 320 | Disabling the cache (/d), or turning write caching | ||
| 321 | off (/wc:off) effectively prevents the aging from | ||
| 322 | doing anything as there is never anything to flush | ||
| 323 | in these cases. Setting very low values of nnnnn | ||
| 324 | should be avoided as it places a lot of overhead into | ||
| 325 | the timer interrupt service. Rather than set low values, | ||
| 326 | it is better to just turn off write caching (/wc:off). | ||
| 327 | NOTE: As stated above, the max value for nnnnn is 65535. It | ||
| 328 | should be noted however that FLUSH13 DOES NOT object if | ||
| 329 | you specify a number larger than this! It will simply | ||
| 330 | use only the low 16 bits of the number. | ||
| 331 | |||
| 332 | /r:on off - En/Disable reboot flush. | ||
| 333 | INT13 has a provision for detecting Ctrl-Alt-Del user | ||
| 334 | reboots. /r:on enables a flush of the cache at this time | ||
| 335 | to prevent the disks from being corrupted. The default | ||
| 336 | setting is /r:off. NOTE WARNING DANGER!!!!! Enabling | ||
| 337 | this feature can prevent disks from being damaged BUT | ||
| 338 | the mechanism has flaws. For one, you will have to hit | ||
| 339 | Ctrl-Alt-Del a second time to get the system to reboot. | ||
| 340 | YOU MUST NOT POUND ON THE KEY. You will crash the system if | ||
| 341 | you do. Hit the key ONCE, if the system re-boots, fine. If | ||
| 342 | there is info to flush out of the cache, the drive light | ||
| 343 | will come on and the system will probably NOT reboot. WAIT | ||
| 344 | until the drive light is OFF before hitting Ctrl-Alt-Del | ||
| 345 | again. This feature of INT13 MAY NOT WORK with other | ||
| 346 | software in the system. USER BEWARE!!!!!!!!!!!!!!!!!!! | ||
| 347 | |||
| 348 | /c:on off - En/Disable all cache on reads. | ||
| 349 | Normally INT13 does not cache EVERY I/O. Whenever | ||
| 350 | it sees a full track I/O which is not currently in | ||
| 351 | the cache, it DOES NOT cache that track. This is | ||
| 352 | an optimization for "typical" operation, and actually | ||
| 353 | increases performance. This is the default setting | ||
| 354 | (/c:off). There may be some cases where it is desirable | ||
| 355 | that ALL reads be cached. One example is that you are | ||
| 356 | "loading" the cache prior to locking it with FLUSH13 /l. | ||
| 357 | With /c:off, some pieces of what you're trying to load | ||
| 358 | may not get into the cache. Another example is that | ||
| 359 | you continually access in a sequential manner (like | ||
| 360 | program load) some large file which happens to be | ||
| 361 | contiguous on the disk. Again, there may be some "piece" | ||
| 362 | of the file which does not get into the cache with | ||
| 363 | /c:off. /c:on enables the caching of ALL reads. | ||
| 364 | NOTE: The same "don't bother caching operations which | ||
| 365 | are full track and not in the cache" applies | ||
| 366 | to writes as well. /c has NO EFFECT on this | ||
| 367 | behavior however. /c only effects read operations. | ||
| 368 | |||
| 369 | If invalid or conflicting arguments are given, FLUSH13 prints a usage line. | ||
diff --git a/v4.0/src/DEV/SMARTDRV/LOADALL.ASM b/v4.0/src/DEV/SMARTDRV/LOADALL.ASM new file mode 100644 index 0000000..0476acd --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/LOADALL.ASM | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | BREAK <LOADALL descriptor caches> | ||
| 2 | |||
| 3 | DEF_ACCESS EQU 92H | ||
| 4 | DEF_LIMIT EQU 0FFFFH | ||
| 5 | |||
| 6 | SEGREG_DESCRIPTOR STRUC | ||
| 7 | SEG_BASE DW ? | ||
| 8 | DB ? | ||
| 9 | SEG_ACCESS DB DEF_ACCESS | ||
| 10 | SEG_LIMIT DW DEF_LIMIT | ||
| 11 | SEGREG_DESCRIPTOR ENDS | ||
| 12 | |||
| 13 | DTR_DESCRIPTOR STRUC | ||
| 14 | DTR_BASE DW ? | ||
| 15 | DB ? | ||
| 16 | DB 0 | ||
| 17 | DTR_LIMIT DW ? | ||
| 18 | DTR_DESCRIPTOR ENDS | ||
| 19 | ; | ||
| 20 | ; 386 Descriptor template | ||
| 21 | ; | ||
| 22 | desc struc | ||
| 23 | lim_0_15 dw 0 ; limit bits (0..15) | ||
| 24 | bas_0_15 dw 0 ; base bits (0..15) | ||
| 25 | bas_16_23 db 0 ; base bits (16..23) | ||
| 26 | access db 0 ; access byte | ||
| 27 | gran db 0 ; granularity byte | ||
| 28 | bas_24_31 db 0 ; base bits (24..31) | ||
| 29 | desc ends | ||
| 30 | |||
| 31 | gdt_descriptor struc | ||
| 32 | gdt_limit dw ? | ||
| 33 | gdt_base_0 dw ? | ||
| 34 | gdt_base_2 dw ? | ||
| 35 | gdt_descriptor ends | ||
diff --git a/v4.0/src/DEV/SMARTDRV/MAKEFILE b/v4.0/src/DEV/SMARTDRV/MAKEFILE new file mode 100644 index 0000000..80b7706 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/MAKEFILE | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | # rules and dependencies follow | ||
| 2 | # | ||
| 3 | # use microsoft make to build | ||
| 4 | # | ||
| 5 | # set up build environment - include and library for c | ||
| 6 | # | ||
| 7 | |||
| 8 | all: smartdrv.sys | ||
| 9 | |||
| 10 | smartdrv.obj: smartdrv.asm mi.asm loadall.asm \ | ||
| 11 | syscall.asm emm.asm above.asm \ | ||
| 12 | devsym.asm | ||
| 13 | masm smartdrv.asm; | ||
| 14 | |||
| 15 | smartdrv.exe: smartdrv.obj | ||
| 16 | link smartdrv,,smartdrv/M; | ||
| 17 | |||
| 18 | smartdrv.sys: smartdrv.exe | ||
| 19 | exe2bin smartdrv smartdrv.sys | ||
diff --git a/v4.0/src/DEV/SMARTDRV/MI.ASM b/v4.0/src/DEV/SMARTDRV/MI.ASM new file mode 100644 index 0000000..9d8efed --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/MI.ASM | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | BREAK <Machine instruction, flag definitions and character types> | ||
| 2 | |||
| 3 | mi_INT EQU 0CDh | ||
| 4 | mi_Long_JMP EQU 0EAh | ||
| 5 | mi_Long_CALL EQU 09Ah | ||
| 6 | mi_Long_RET EQU 0CBh | ||
| 7 | mi_Near_RET EQU 0C3h | ||
| 8 | |||
| 9 | ; xxxxoditszxaxpxc | ||
| 10 | f_Overflow EQU 0000100000000000B | ||
| 11 | f_Direction EQU 0000010000000000B | ||
| 12 | f_Interrupt EQU 0000001000000000B | ||
| 13 | f_Trace EQU 0000000100000000B | ||
| 14 | f_Sign EQU 0000000010000000B | ||
| 15 | f_Zero EQU 0000000001000000B | ||
| 16 | f_Aux EQU 0000000000010000B | ||
| 17 | f_Parity EQU 0000000000000100B | ||
| 18 | f_Carry EQU 0000000000000001B | ||
diff --git a/v4.0/src/DEV/SMARTDRV/OLI.CMP b/v4.0/src/DEV/SMARTDRV/OLI.CMP new file mode 100644 index 0000000..8a9a767 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/OLI.CMP | |||
| @@ -0,0 +1,464 @@ | |||
| 1 | CMP V2.13 Copyright (C) 1984, 1985 by White Heron Corporation | ||
| 2 | All rights reserved | ||
| 3 | |||
| 4 | old: smartdrv.asm (on the left) Note: < marks old lines. | ||
| 5 | new: a:smartdrv.asm (on the right) > marks new lines. | ||
| 6 | |||
| 7 | =============================================================================== | ||
| 8 | |||
| 9 | 6<; Will use IBM extended memory on PC-AT or | ||
| 10 | 7<; use Above Board on PC, XT, or AT | ||
| 11 | 8<; | ||
| 12 | 9<; | ||
| 13 | 10<; device = SMARTDRV.sys [bbbb] [/a] | ||
| 14 | |||
| 15 | ----> changed to the following: | ||
| 16 | |||
| 17 | 6>;; Will use IBM extended memory on PC-AT or | ||
| 18 | 7>;; use Above Board on PC, XT, or AT, and | ||
| 19 | 8>;; use extended, expanded, or upper extended memory on AT&T 6300 PLUS | ||
| 20 | 9>; | ||
| 21 | 10>; | ||
| 22 | 11>;; device = SMARTDRV.sys [bbbb] [/a] [/u] | ||
| 23 | |||
| 24 | =============================================================================== | ||
| 25 | |||
| 26 | 40<; | ||
| 27 | |||
| 28 | ----> changed to the following: | ||
| 29 | |||
| 30 | 41>;; /u Specifies that upper extended memory will be used | ||
| 31 | 42>;; on the AT&T 6300 PLUS. Upper extended memory | ||
| 32 | 43>;; is the memory beginning at FA0000. It is used | ||
| 33 | 44>;; to hold the UNIX kernel when the machine is running | ||
| 34 | 45>;; Simul-Task. However, when operating as a pure | ||
| 35 | 46>;; MS-DOS machine, this 384K of memory is available | ||
| 36 | 47>;; for SMARTDRIVE. | ||
| 37 | 48>;; Note that it is an error to specify this switch | ||
| 38 | 49>;; if the machine is not a 6300 PLUS. | ||
| 39 | |||
| 40 | =============================================================================== | ||
| 41 | |||
| 42 | 102>;; ?.?? 7/24/87 WSH Added 6300 PLUS support. This code is marked by | ||
| 43 | 103>;; the use of double semi-colons to make it easy to | ||
| 44 | 104>;; find. | ||
| 45 | |||
| 46 | ----> inserted before the following old file line: | ||
| 47 | |||
| 48 | 93< | ||
| 49 | |||
| 50 | =============================================================================== | ||
| 51 | |||
| 52 | 125> | ||
| 53 | 126>;; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is | ||
| 54 | 127>;; necessary to use the special OS-MERGE hardware to activate lines | ||
| 55 | 128>;; A20 to A23. However, these lines can be disabled only by resetting | ||
| 56 | 129>;; the processor. The return address offset and segment can be found | ||
| 57 | 130>;; at 40:a2, noted here as RealLoc1. | ||
| 58 | 131>;; | ||
| 59 | 132>BiosSeg segment at 40h ;; Used to locate 6300 PLUS reset address | ||
| 60 | 133> org 00a2h | ||
| 61 | 134>RealLoc1 dd 0 | ||
| 62 | 135>BiosSeg ends | ||
| 63 | |||
| 64 | ----> inserted before the following old file line: | ||
| 65 | |||
| 66 | 113< | ||
| 67 | |||
| 68 | =============================================================================== | ||
| 69 | |||
| 70 | 147>;; The /U configuration using upper extended memory on the | ||
| 71 | 148>;; 6300 PLUS is a special case of the type 1 configuration. | ||
| 72 | |||
| 73 | ----> inserted before the following old file line: | ||
| 74 | |||
| 75 | 124<; | ||
| 76 | |||
| 77 | =============================================================================== | ||
| 78 | |||
| 79 | 327>;; The internal name of the device driver has been changed from SMARTDRV | ||
| 80 | 328>;; to SMARTAAR to avoid DOS name conflicts with files named SMARTDRV.* | ||
| 81 | 329>;; | ||
| 82 | |||
| 83 | ----> inserted before the following old file line: | ||
| 84 | |||
| 85 | 302<INT13DEV LABEL WORD | ||
| 86 | |||
| 87 | =============================================================================== | ||
| 88 | |||
| 89 | 307< DB "SMARTDRV" ;Name of device | ||
| 90 | |||
| 91 | ----> changed to the following: | ||
| 92 | |||
| 93 | 335> DB "SMARTAAR" ;Name of device | ||
| 94 | |||
| 95 | =============================================================================== | ||
| 96 | |||
| 97 | 387>;; Data peculiar to AT&T 6300 PLUS. | ||
| 98 | 388> | ||
| 99 | 389>S5_FLAG DB 0 ;; If set, computer is a 6300 PLUS | ||
| 100 | |||
| 101 | ----> inserted before the following old file line: | ||
| 102 | |||
| 103 | 359< | ||
| 104 | |||
| 105 | =============================================================================== | ||
| 106 | |||
| 107 | 3074>;; NOTE: The value at BASE_ADDR is patched during initialization when | ||
| 108 | 3075>;; loading a RAMDrive into upper extended memory on a PLUS | ||
| 109 | 3076>;; | ||
| 110 | |||
| 111 | ----> inserted before the following old file line: | ||
| 112 | |||
| 113 | 3043<BASE_ADDR LABEL DWORD ; 24 bit address of start of this RAMDRV | ||
| 114 | |||
| 115 | =============================================================================== | ||
| 116 | |||
| 117 | 3190< MOV AH,0DFH | ||
| 118 | |||
| 119 | ----> changed to the following: | ||
| 120 | |||
| 121 | 3224> | ||
| 122 | 3225>;; | ||
| 123 | 3226>;; Enable address line 20 on the PC AT or activate A20-A23 on the 6300 PLUS. | ||
| 124 | 3227>;; The former can be done by placing 0dfh in AH and activating the keyboard | ||
| 125 | 3228>;; processor. On the PLUS, 90h goes in AL and the port at 03f20h is written. | ||
| 126 | 3229>;; So the combined value of 0df90h can be used for both machines with | ||
| 127 | 3230>;; appropriate coding of the called routine A20. | ||
| 128 | 3231>;; | ||
| 129 | 3232> | ||
| 130 | 3233>;; MOV AH,0DFH | ||
| 131 | 3234> mov ax,0df90h ;; set up for PLUS or AT | ||
| 132 | |||
| 133 | =============================================================================== | ||
| 134 | |||
| 135 | 3248< MOV AH,0DDH | ||
| 136 | 3249< CALL A20 ; Disable address line 20 | ||
| 137 | |||
| 138 | ----> changed to the following: | ||
| 139 | |||
| 140 | 3292> | ||
| 141 | 3293>;; | ||
| 142 | 3294>;; Reset of line A20 on the PC AT requires writing 0ddh to the keyboard | ||
| 143 | 3295>;; processor. On the PLUS, the appropriate value is 00. | ||
| 144 | 3296>;; | ||
| 145 | 3297> | ||
| 146 | 3298>;; MOV AH,0DDH | ||
| 147 | 3299> mov ax,0DD00h ;; setup for PLUS or AT. ah for IBM, al for PLUS | ||
| 148 | 3300> CALL A20 ; Disable address line 20 | ||
| 149 | |||
| 150 | =============================================================================== | ||
| 151 | |||
| 152 | 3331>;; CS override needed on S5_FLAG to avoid phase errors on | ||
| 153 | 3332>;; forward declaration of this variable. | ||
| 154 | 3333> cmp cs:[S5_FLAG],0 ;; test for 6300 PLUS | ||
| 155 | 3334> jnz A20S5 ;; yes, do this code | ||
| 156 | |||
| 157 | ----> inserted before the following old file line: | ||
| 158 | |||
| 159 | 3280< CLI | ||
| 160 | |||
| 161 | =============================================================================== | ||
| 162 | |||
| 163 | 3376> | ||
| 164 | 3377>;;* A20S5 - Address enable/disable routine for the 6300 PLUS. | ||
| 165 | 3378>;; | ||
| 166 | 3379>;; This routine enables lines A20-A23 on the PLUS by writing | ||
| 167 | 3380>;; to port 03f20h. Bit 7 turns the lines on, and bit 4 sets | ||
| 168 | 3381>;; the power-up bit. To disable the lines, the processor | ||
| 169 | 3382>;; must be reset. This is done by saving the world and | ||
| 170 | 3383>;; jumping to the ROM 80286 reset code. Since the power-up bit | ||
| 171 | 3384>;; is set, the data segment is set to the BiosSeg at 40h | ||
| 172 | 3385>;; and a jump is then made to the address at RealLoc1. | ||
| 173 | 3386>;; At RealLoc1, one can find the CS:IP where the code | ||
| 174 | 3387>;; is to continue. | ||
| 175 | 3388>;; | ||
| 176 | 3389>;; Uses ax, flags. | ||
| 177 | 3390>;; Returns with zero flag set. | ||
| 178 | 3391>;; | ||
| 179 | 3392>A20S5: | ||
| 180 | 3393> cli | ||
| 181 | 3394> or al,al ;; if zero, then resetting processor | ||
| 182 | 3395> jnz A20S5Next | ||
| 183 | 3396> call RSet ;; must return with entry value of ax | ||
| 184 | 3397>A20S5Next: | ||
| 185 | 3398> push dx ;; set/reset port | ||
| 186 | 3399> mov dx,3f20h | ||
| 187 | 3400> out dx,al | ||
| 188 | 3401> pop dx | ||
| 189 | 3402> xor al,al | ||
| 190 | 3403> STI | ||
| 191 | 3404> RET | ||
| 192 | 3405> | ||
| 193 | 3406>;;* a20S5BOOT - This code bypasses the processor reset on a reboot | ||
| 194 | 3407>;; of the 6300 PLUS. Otherwise the machine hangs. | ||
| 195 | 3408>a20s5BOOT: ;; use this code before reboot | ||
| 196 | 3409> cli | ||
| 197 | 3410> jmp short a20s5next | ||
| 198 | 3411> | ||
| 199 | 3412>OldStackSeg dw 0 ;; used during PLUS processor reset | ||
| 200 | 3413> ;; to save the stack segment | ||
| 201 | 3414> | ||
| 202 | 3415>;;* Rset - Reset the 80286 in order to turn off the address lines | ||
| 203 | 3416>;; on the 6300 PLUS. Only way to do this on the | ||
| 204 | 3417>;; current hardware. The processor itself can be | ||
| 205 | 3418>;; reset by reading or writing prot 03f00h | ||
| 206 | 3419>;; | ||
| 207 | 3420>;; Uses flags. | ||
| 208 | 3421>;; | ||
| 209 | 3422>RSet: | ||
| 210 | 3423> pusha ;; save world | ||
| 211 | 3424> push ds ;; save segments | ||
| 212 | 3425> push es | ||
| 213 | 3426> mov ax,BiosSeg ;; point to the bios segment | ||
| 214 | 3427> mov ds,ax ;; ds -> 40h | ||
| 215 | 3428>assume ds:BiosSeg | ||
| 216 | 3429> push word ptr [RealLoc1] ;; save what might have been here | ||
| 217 | 3430> push word ptr [RealLoc1+2] | ||
| 218 | 3431> mov word ptr [RealLoc1],cs:[offset ReturnBack] ;; load our return address | ||
| 219 | 3432> mov word ptr [RealLoc1+2],cs | ||
| 220 | 3433>assume ds:nothing | ||
| 221 | 3434> mov [OldStackSeg],ss ;; save the stack segment, too | ||
| 222 | 3435> mov dx,03f00h ;; reset the processor | ||
| 223 | 3436> in ax,dx | ||
| 224 | 3437> nop | ||
| 225 | 3438> nop | ||
| 226 | 3439> nop | ||
| 227 | 3440> cli | ||
| 228 | 3441> hlt ;; should never get here | ||
| 229 | 3442>ReturnBack: | ||
| 230 | 3443> mov ss,[OldStackSeg] ;; start the recovery | ||
| 231 | 3444>assume ds:BiosSeg | ||
| 232 | 3445> pop word ptr [RealLoc1+2] | ||
| 233 | 3446> pop word ptr [RealLoc1] | ||
| 234 | 3447> pop es | ||
| 235 | 3448> pop ds | ||
| 236 | 3449> popa | ||
| 237 | 3450> ret | ||
| 238 | |||
| 239 | ----> inserted before the following old file line: | ||
| 240 | |||
| 241 | 3321< | ||
| 242 | |||
| 243 | =============================================================================== | ||
| 244 | |||
| 245 | 3530<; out any dirty tracks take a LONG time, so long that we loose | ||
| 246 | |||
| 247 | ----> changed to the following: | ||
| 248 | |||
| 249 | 3660>; out any dirty tracks take a LONG time, so long that we lose | ||
| 250 | |||
| 251 | =============================================================================== | ||
| 252 | |||
| 253 | 3652< ; Reset INT 1C vector to trun cache off | ||
| 254 | |||
| 255 | ----> changed to the following: | ||
| 256 | |||
| 257 | 3782> ; Reset INT 1C vector to turn cache off | ||
| 258 | |||
| 259 | =============================================================================== | ||
| 260 | |||
| 261 | 3732< MOV AH,0DFH | ||
| 262 | |||
| 263 | ----> changed to the following: | ||
| 264 | |||
| 265 | 3862>;; MOV AH,0DFH | ||
| 266 | 3863> mov ax,0df90h ;; set up for PLUS or AT | ||
| 267 | |||
| 268 | =============================================================================== | ||
| 269 | |||
| 270 | 3775< MOV AH,0DDH ; Disable adress line 20 | ||
| 271 | 3776< CALL A20 | ||
| 272 | |||
| 273 | ----> changed to the following: | ||
| 274 | |||
| 275 | 3906>;; MOV AH,0DDH ; Disable adress line 20 | ||
| 276 | 3907> mov ax,0DD00h ;; setup for PLUS or AT. ah for IBM, al for PLUS | ||
| 277 | 3908> cmp [S5_FLAG],0 | ||
| 278 | 3909> jz OFF20A | ||
| 279 | 3910> call a20s5boot ;; Don't reset the processor on PLUS, this time | ||
| 280 | 3911> jmp short off20b | ||
| 281 | 3912>off20a: | ||
| 282 | 3913> CALL A20 | ||
| 283 | 3914>off20b: | ||
| 284 | |||
| 285 | =============================================================================== | ||
| 286 | |||
| 287 | 4078> | ||
| 288 | 4079>U_SWITCH db 0 ;; upper extended memory requested on 6300 PLUS | ||
| 289 | |||
| 290 | ----> inserted before the following old file line: | ||
| 291 | |||
| 292 | 3940< | ||
| 293 | |||
| 294 | =============================================================================== | ||
| 295 | |||
| 296 | 4274> | ||
| 297 | 4275>;; | ||
| 298 | 4276>;; 2.5 Check here for 6300 PLUS machine. First look for Olivetti copyright, | ||
| 299 | 4277>;; and if found, check id byte at f000:fffd. | ||
| 300 | 4278>;; | ||
| 301 | 4279> | ||
| 302 | 4280> push es ;; Olivetti Machine? | ||
| 303 | 4281> mov ax,0fc00h ;; Look for 'OL' at fc00:50 | ||
| 304 | 4282> mov es,ax | ||
| 305 | 4283> cmp es:[0050h],'LO' | ||
| 306 | 4284> jnz notS5 ;; not found | ||
| 307 | 4285> mov ax,0f000h | ||
| 308 | 4286> mov es,ax | ||
| 309 | 4287> cmp word ptr es:[0fffdh],0fc00h ;; look for 6300 plus | ||
| 310 | 4288> jnz notS5 | ||
| 311 | 4289> dec [S5_FLAG] ;; yep, set flag | ||
| 312 | 4290>notS5: | ||
| 313 | 4291> pop es | ||
| 314 | 4292> | ||
| 315 | |||
| 316 | ----> inserted before the following old file line: | ||
| 317 | |||
| 318 | 4134<; | ||
| 319 | |||
| 320 | =============================================================================== | ||
| 321 | |||
| 322 | 4411>;; Added for /u switch | ||
| 323 | 4412> cmp al,'u' ;; Look for U switch for PLUS | ||
| 324 | 4413> jnz A_TEST | ||
| 325 | 4414> cmp [S5_FLAG],0 ;; No good unless PLUS | ||
| 326 | 4415> jz bad_parm | ||
| 327 | 4416> TEST [GOTSWITCH],SWITCH_A ;; Already have switch A ? | ||
| 328 | 4417> JNZ BAD_PARM | ||
| 329 | 4418> cmp [U_SWITCH],0 | ||
| 330 | 4419> jne bad_parm | ||
| 331 | 4420> dec [U_SWITCH] | ||
| 332 | 4421> jmp scan_loop | ||
| 333 | 4422>A_TEST: | ||
| 334 | 4423>;; | ||
| 335 | |||
| 336 | ----> inserted before the following old file line: | ||
| 337 | |||
| 338 | 4252< CMP AL,"a" | ||
| 339 | |||
| 340 | =============================================================================== | ||
| 341 | |||
| 342 | 4435>;; added for /u switch | ||
| 343 | 4436> cmp [U_SWITCH],0 | ||
| 344 | 4437> jne bad_parm | ||
| 345 | 4438>;; | ||
| 346 | |||
| 347 | ----> inserted before the following old file line: | ||
| 348 | |||
| 349 | 4263< OR [GOTSWITCH],SWITCH_A | ||
| 350 | |||
| 351 | =============================================================================== | ||
| 352 | |||
| 353 | 4847>;; Note: When using upper extended memory on the PLUS, the value | ||
| 354 | 4848>;; at BASE_RESET + 2 is patched to FA during initialization. | ||
| 355 | 4849>;; | ||
| 356 | |||
| 357 | ----> inserted before the following old file line: | ||
| 358 | |||
| 359 | 4671<BASE_RESET LABEL DWORD ; RESMEM driver must patch this value | ||
| 360 | |||
| 361 | =============================================================================== | ||
| 362 | |||
| 363 | 5312> cmp U_SWITCH,0 ;; don't do this for at&t 6300 plus | ||
| 364 | 5313> jnz ret005 | ||
| 365 | |||
| 366 | ----> inserted before the following old file line: | ||
| 367 | |||
| 368 | 5133< PUSH AX | ||
| 369 | |||
| 370 | =============================================================================== | ||
| 371 | |||
| 372 | 5394> | ||
| 373 | 5395>;; If upper extended memory is used on the PLUS, it is necessary to | ||
| 374 | 5396>;; patch the values of base_reset and base_addr to get the addressing right. | ||
| 375 | 5397>;; | ||
| 376 | 5398> cmp [U_SWITCH],0 ;; patch the code for /U option | ||
| 377 | 5399> jz AT001A | ||
| 378 | 5400> mov ax,00fah | ||
| 379 | 5401> mov word ptr [base_reset+2],ax ;; patching upper address | ||
| 380 | 5402> mov word ptr [base_addr+2],ax ;; to FA from 10 | ||
| 381 | 5403>AT001A: | ||
| 382 | 5404> | ||
| 383 | |||
| 384 | ----> inserted before the following old file line: | ||
| 385 | |||
| 386 | 5213< MOV AX,8800H | ||
| 387 | |||
| 388 | =============================================================================== | ||
| 389 | |||
| 390 | 5214< INT 15H ; Get extended memory size | ||
| 391 | |||
| 392 | ----> changed to the following: | ||
| 393 | |||
| 394 | 5406> INT 15H ; Get extended memory size | ||
| 395 | |||
| 396 | =============================================================================== | ||
| 397 | |||
| 398 | 5410> | ||
| 399 | 5411>;; If running on a 6300 PLUS, it is necessary to subtract any upper extended | ||
| 400 | 5412>;; memory from the value obtained by int 15 to determine the correct memory | ||
| 401 | 5413>;; available for a type /E RAMDrive. If loading a /U RAMDrive, it is necessary | ||
| 402 | 5414>;; to find out if there IS any upper extended memory. | ||
| 403 | 5415> | ||
| 404 | 5416> cmp [U_SWITCH],0 ;; did we ask for upper extended memory | ||
| 405 | 5417> jz olstuff ;; no | ||
| 406 | 5418> call UpperMemCheck ;; yes, see if anything there | ||
| 407 | 5419> jc ERR_RET ;; no, quit | ||
| 408 | 5420> mov ax,384 ;; yes, but max allowed is 384K | ||
| 409 | 5421> jmp short at001b | ||
| 410 | 5422>olstuff: | ||
| 411 | 5423> cmp [S5_FLAG],0 ;; if not 6300 PLUS, go on | ||
| 412 | 5424> jz at001b | ||
| 413 | 5425> call UpperMemCheck ;; yes, see if 384K is there | ||
| 414 | 5426> jc at001b ;; no, so int 15h is right | ||
| 415 | 5427> sub ax,384 ;; yes, subtract 384K | ||
| 416 | 5428>AT001B: | ||
| 417 | 5429> | ||
| 418 | |||
| 419 | ----> inserted before the following old file line: | ||
| 420 | |||
| 421 | 5218< MOV DX,OFFSET ERRMSG2 | ||
| 422 | |||
| 423 | =============================================================================== | ||
| 424 | |||
| 425 | 5466> | ||
| 426 | 5467>;;* UpperMemCheck - Called by 6300 PLUS to verify existence of | ||
| 427 | 5468>;; upper extended memory of 384K at FA0000h | ||
| 428 | 5469>;; | ||
| 429 | 5470>;; Returns carry set if no upper extended memory. | ||
| 430 | 5471>;; | ||
| 431 | 5472>;; This routine is called only by a 6300 PLUS, and | ||
| 432 | 5473>;; it reads the hardware switch DSW2 to do the job. | ||
| 433 | 5474>;; | ||
| 434 | 5475>UpperMemCheck: | ||
| 435 | 5476> push ax | ||
| 436 | 5477> in al,66h | ||
| 437 | 5478> and al,00001111b | ||
| 438 | 5479> cmp al,00001011b | ||
| 439 | 5480> pop ax | ||
| 440 | 5481> jnz nomem | ||
| 441 | 5482> clc | ||
| 442 | 5483> ret | ||
| 443 | 5484>nomem: | ||
| 444 | 5485> stc | ||
| 445 | 5486> ret | ||
| 446 | |||
| 447 | ----> inserted before the following old file line: | ||
| 448 | |||
| 449 | 5254< | ||
| 450 | |||
| 451 | =============================================================================== | ||
| 452 | |||
| 453 | 6301>s5flagmsg db " = S5 flag",13,10,"$" | ||
| 454 | 6302>U_msg db " = U Switch", 13,10,'$' | ||
| 455 | |||
| 456 | ----> inserted before the following old file line: | ||
| 457 | |||
| 458 | 6068<ENDIF | ||
| 459 | |||
| 460 | =============================================================================== | ||
| 461 | |||
| 462 | 28 discrepancies. | ||
| 463 | File smartdrv.asm has 6075 lines. | ||
| 464 | File a:smartdrv.asm has 6310 lines. | ||
diff --git a/v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM b/v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM new file mode 100644 index 0000000..3efe7c1 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM | |||
| @@ -0,0 +1,7587 @@ | |||
| 1 | TITLE EXTENDED/EXPANDED MEMORY DISK CACHE | ||
| 2 | |||
| 3 | PAGE 58,132 | ||
| 4 | |||
| 5 | ; | ||
| 6 | ;; Will use IBM extended memory on PC-AT or | ||
| 7 | ;; use Above Board on PC, XT, or AT, and | ||
| 8 | ;; use extended, expanded, or upper extended memory on AT&T 6300 PLUS | ||
| 9 | ; | ||
| 10 | ; | ||
| 11 | ;; device = SMARTDRV.sys [bbbb] [/a] [/u] | ||
| 12 | ; | ||
| 13 | ; bbbb First numeric argument, if present, is memory size | ||
| 14 | ; in K bytes. Default value is 256. Min is 128. Max | ||
| 15 | ; is 8192 (8 Meg). | ||
| 16 | ; | ||
| 17 | ; By default PC AT Extended Memory is to be used. | ||
| 18 | ; It is an error if /E is specified on a machine other | ||
| 19 | ; than an IBM PC AT. /E is the default. | ||
| 20 | ; NOTE: Information in cache in PC AT extended memory | ||
| 21 | ; will be lost at system re-boot (warm or cold). This is | ||
| 22 | ; due to the fact that the IBM PC AT ROM bootstrap code | ||
| 23 | ; zeroes all of memory. | ||
| 24 | ; NOTE: There is 1k of memory overhead. That is to say, | ||
| 25 | ; if there are 512k bytes of extended memory, there | ||
| 26 | ; will be 511k bytes available for assignment to int13. | ||
| 27 | ; This 1k overhead is fixed and makes int13 compatible | ||
| 28 | ; with RAMDRive. | ||
| 29 | ; NOTE: The same allocation strategy as is used in RAMDrive | ||
| 30 | ; is used. This allows RAMDrive and INT13 to coexist on | ||
| 31 | ; the same system. Mixing with IBM VDISK is NOT supported. | ||
| 32 | ; | ||
| 33 | ; /a Specifies that Above Board memory is to be used. It | ||
| 34 | ; is an error if the above board device driver is not | ||
| 35 | ; present. | ||
| 36 | ; NOTE: Information in cache in Above Board memory | ||
| 37 | ; will be lost at system re-boot (warm or cold). This is | ||
| 38 | ; due to the fact that the EMM device driver performs a | ||
| 39 | ; destructive test when it is installed which zeros all | ||
| 40 | ; of the Above Board memory. | ||
| 41 | ;; /u Specifies that upper extended memory will be used | ||
| 42 | ;; on the AT&T 6300 PLUS. Upper extended memory | ||
| 43 | ;; is the memory beginning at FA0000. It is used | ||
| 44 | ;; to hold the UNIX kernel when the machine is running | ||
| 45 | ;; Simul-Task. However, when operating as a pure | ||
| 46 | ;; MS-DOS machine, this 384K of memory is available | ||
| 47 | ;; for SMARTDRIVE. | ||
| 48 | ;; Note that it is an error to specify this switch | ||
| 49 | ;; if the machine is not a 6300 PLUS. | ||
| 50 | ; | ||
| 51 | ; NOTE WARNING: ALL OF THIS CODE ASSUMES THAT ALL HARDFILES ARE 512 BYTES | ||
| 52 | ; PER SECTOR!!! All other hardfile parameters are read via INT 13, but | ||
| 53 | ; Bytes/sector MUST be IBM standard 512. | ||
| 54 | ; | ||
| 55 | ; MODIFICATION HISTORY | ||
| 56 | ; | ||
| 57 | ; 1.00 5/10/86 ARR Initial version based on RAMDrive 1.16. | ||
| 58 | ; 1.01 5/20/86 ARR Slight re-organization of places where FLUSH_CACHE | ||
| 59 | ; is called to discard a track to make sure | ||
| 60 | ; TRACK_BUFFER is invalidated correctly. | ||
| 61 | ; 1.10 5/26/86 ARR Added Timer Int to flush cache after passage | ||
| 62 | ; of user setable time. | ||
| 63 | ; 1.20 5/27/86 ARR Additions at request of Neilk. /t:nnnnn /d /wb:on | ||
| 64 | ; /wb:off /wt:on /wt:off can be on device = line. | ||
| 65 | ; Lock cache function added. | ||
| 66 | ; 1.21 5/29/86 ARR Lock code made more intelligent. | ||
| 67 | ; 1.22 5/30/86 ARR /r reboot flush code added | ||
| 68 | ; 1.23 6/03/86 ARR Cache statistics added | ||
| 69 | ; 1.24 6/05/86 ARR Added /a "all cache" code | ||
| 70 | ; 1.25 6/10/86 ARR Added total used, total locked to status | ||
| 71 | ; 1.26 6/12/86 ARR /wb changed to /wc to align with docs. Discard | ||
| 72 | ; of track when write to locked track changed to | ||
| 73 | ; unlock. Discard of track when write with /wc:off | ||
| 74 | ; changed to immediate write through. | ||
| 75 | ; 1.27 6/17/86 ARR Bug regarding the INT 13 error which is not | ||
| 76 | ; an error (error 11H, ECC error corrected). | ||
| 77 | ; changed error handling logic to handle this | ||
| 78 | ; correctly (ignore it). | ||
| 79 | ; 1.28 7/31/86 ARR Default seg reg access byte changed from | ||
| 80 | ; 82H to 92H. This was needed for 80386 functionality. | ||
| 81 | ; Change to LOADALL.ASM, also RAMDrive problem. | ||
| 82 | ; 1.30 8/04/86 ARR Default cache size uped to 256K | ||
| 83 | ; Min cache size uped to 128K | ||
| 84 | ; 1.31 8/07/86 ARR Moved SMSW SIDT SGDT set into BLKMOV code for | ||
| 85 | ; problem with CEMM | ||
| 86 | ; 1.32 8/27/86 ARR Added code to A20 routine to provide approp | ||
| 87 | ; settle time for A20 switch to occur. This will | ||
| 88 | ; help us on Compaq machines and faster ATs and | ||
| 89 | ; 80386 machines. Thanks to CC of Compaq for fix. | ||
| 90 | ; 1.33 9/22/86 ARR Added more info to startup header, in particular, | ||
| 91 | ; tells you whether /A or /E cache. | ||
| 92 | ; | ||
| 93 | ; SMARTDRV | ||
| 94 | ; ------ | ||
| 95 | ; | ||
| 96 | ; 1.00 5/13/87 SUNILP, GREGH, DAVIDW: | ||
| 97 | ; Modified INT13 to take care of multi track caching | ||
| 98 | ; Reduced functionality | ||
| 99 | ; Added two new IOCTL calls to increase/decrease | ||
| 100 | ; cache size, dynamically | ||
| 101 | ; | ||
| 102 | ; | ||
| 103 | ;; 7/24/87 WSH Added 6300 PLUS support. This code is marked by | ||
| 104 | ;; the use of double semi-colons to make it easy to | ||
| 105 | ;; find. | ||
| 106 | ; | ||
| 107 | ; 8/31/87 SUNILP | ||
| 108 | ; New extended memory allocation scheme. 386 support. | ||
| 109 | ; Support for new ps/2 systems. better 286 loadall | ||
| 110 | ; transfer. more complete expanded memory access. | ||
| 111 | ; several bug fixes. | ||
| 112 | ; | ||
| 113 | ; 1.01 9/17/87 SUNILP | ||
| 114 | ; Removed check that was limiting tracks to 32k bytes | ||
| 115 | ; Tracks can be upto 64k bytes now | ||
| 116 | ; | ||
| 117 | ; 1.02 10/22/87 SUNILP | ||
| 118 | ; Reduced statically allocated track buffer size to | ||
| 119 | ; minimum required | ||
| 120 | ; | ||
| 121 | ; 1.03 10/29/87 SUNILP | ||
| 122 | ; Changed name reported in messages to SMARTDrive | ||
| 123 | ; | ||
| 124 | ; 1/08/88 GREGH | ||
| 125 | ; Added support for OMTI controller. This code | ||
| 126 | ; is ifdef'd in with the OMTI keyword. | ||
| 127 | ; | ||
| 128 | ; 1.04 3/02/88 SUNILP | ||
| 129 | ; fix for recognition of 20MHz model 80. | ||
| 130 | ; fix for READ DASD int 13 dispatch. | ||
| 131 | ; | ||
| 132 | ; 1.05 5/13/88 SUNILP | ||
| 133 | ; fixed version checking to include dos 4.00 | ||
| 134 | ; | ||
| 135 | ; 2.10 6/13/88 CHIPA Merged in these changes for HP Vectra | ||
| 136 | ; 11/20/87 RCP | ||
| 137 | ; Fixed a20 enabling/disabling problems on | ||
| 138 | ; Vectra machines. | ||
| 139 | ; 8/24/88 MRW Merged changes from Windows tree into DOS tree | ||
| 140 | ; | ||
| 141 | |||
| 142 | BREAK MACRO subtitle | ||
| 143 | SUBTTL subtitle | ||
| 144 | PAGE | ||
| 145 | ENDM | ||
| 146 | |||
| 147 | .286p ; Use some 286 instructions in /E code | ||
| 148 | |||
| 149 | DEBUG EQU 0 | ||
| 150 | S_OLIVETTI EQU 1 ; Flag for olivetti 6300 plus machine | ||
| 151 | S_VECTRA EQU 2 ; Flag for HP Vectra machines | ||
| 152 | WINDOWS_SWITCHES EQU 1 ; 1 = uses switches for windows, 0 = all switches | ||
| 153 | ;OMTI EQU 1 ; Used for code specific to the OMTI Controller | ||
| 154 | |||
| 155 | MAX_HARD_FILES EQU 16 ; Max number of hardfiles our data structures support | ||
| 156 | |||
| 157 | MIN_CACHE_SIZE_K EQU 128 ; Minimum size for cache in K (multiple of 16) | ||
| 158 | |||
| 159 | IF1 | ||
| 160 | IFDEF OMTI | ||
| 161 | %out OMTI Controller release | ||
| 162 | ENDIF | ||
| 163 | ENDIF | ||
| 164 | |||
| 165 | IF1 | ||
| 166 | IF DEBUG | ||
| 167 | %out DEBUG VERSION!!!!!! | ||
| 168 | ENDIF | ||
| 169 | ENDIF | ||
| 170 | |||
| 171 | ;; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is | ||
| 172 | ;; necessary to use the special OS-MERGE hardware to activate lines | ||
| 173 | ;; A20 to A23. However, these lines can be disabled only by resetting | ||
| 174 | ;; the processor. The return address offset and segment can be found | ||
| 175 | ;; at 40:a2, noted here as RealLoc1. | ||
| 176 | ;; | ||
| 177 | BiosSeg segment at 40h ;; Used to locate 6300 PLUS reset address | ||
| 178 | org 00a2h | ||
| 179 | RealLoc1 dd 0 | ||
| 180 | BiosSeg ends | ||
| 181 | ; | ||
| 182 | R_Mode_IDT segment at 0h | ||
| 183 | R_mode_IDT ends | ||
| 184 | ; | ||
| 185 | .xlist | ||
| 186 | include devsym.asm | ||
| 187 | include syscall.asm | ||
| 188 | include mi.asm | ||
| 189 | .list | ||
| 190 | |||
| 191 | ; The INT13 device driver has 2 basic configurations. | ||
| 192 | ; | ||
| 193 | ; TYPE 1 - /E configuration using PC-AT extended memory and the LOADALL | ||
| 194 | ; instruction. | ||
| 195 | ;; The /U configuration using upper extended memory on the | ||
| 196 | ;; 6300 PLUS is a special case of the type 1 configuration. | ||
| 197 | ; | ||
| 198 | ; TYPE 2 - /A configuration using Above Board memory and EMM device | ||
| 199 | ; driver. | ||
| 200 | ; | ||
| 201 | ; The TYPE 2 driver uses the Above Board EMM device driver via INT 67H | ||
| 202 | ; to control access to, and to access the available memory. | ||
| 203 | ; | ||
| 204 | ; The TYPE 1 configuration uses the EMM control sector to | ||
| 205 | ; control access to the available memory | ||
| 206 | ; | ||
| 207 | |||
| 208 | include emm.asm | ||
| 209 | |||
| 210 | include loadall.asm | ||
| 211 | |||
| 212 | include above.asm | ||
| 213 | |||
| 214 | include ab_macro.asm | ||
| 215 | |||
| 216 | BREAK <I/O Packet offset declarations> | ||
| 217 | |||
| 218 | ; | ||
| 219 | ; Define I/O packet offsets for useful values. | ||
| 220 | ; | ||
| 221 | ; SEE ALSO | ||
| 222 | ; MS-DOS Technical Reference manual section on Installable Device Drivers | ||
| 223 | ; | ||
| 224 | |||
| 225 | ; READ/WRITE PACKET OFFSETS | ||
| 226 | RW_COUNT EQU WORD PTR (SIZE SRHEAD) + 5 | ||
| 227 | RW_TRANS EQU DWORD PTR (SIZE SRHEAD) + 1 | ||
| 228 | RW_START EQU WORD PTR (SIZE SRHEAD) + 7 | ||
| 229 | |||
| 230 | ; MEDIA CHECK PACKET OFFSETS | ||
| 231 | MCH_RETVAL EQU BYTE PTR (SIZE SRHEAD) + 1 | ||
| 232 | MCH_MEDIA EQU BYTE PTR (SIZE SRHEAD) + 0 | ||
| 233 | |||
| 234 | ; BUILD BPB PACKET OFFSETS | ||
| 235 | BPB_BUFFER EQU DWORD PTR (SIZE SRHEAD) + 1 | ||
| 236 | BPB_MEDIA EQU BYTE PTR (SIZE SRHEAD) + 0 | ||
| 237 | BPB_BPB EQU DWORD PTR (SIZE SRHEAD) + 5 | ||
| 238 | |||
| 239 | ; INIT PACKET OFFSETS | ||
| 240 | INIT_NUM EQU BYTE PTR (SIZE SRHEAD) + 0 | ||
| 241 | INIT_BREAK EQU DWORD PTR (SIZE SRHEAD) + 1 | ||
| 242 | INIT_BPB EQU DWORD PTR (SIZE SRHEAD) + 5 | ||
| 243 | INIT_DOSDEV EQU BYTE PTR (SIZE SRHEAD) + 9 | ||
| 244 | |||
| 245 | BREAK <Cache control structure> | ||
| 246 | |||
| 247 | ; | ||
| 248 | ; The cache control structure is the "management" data associated | ||
| 249 | ; with all of the data in the cache. The cache structures are | ||
| 250 | ; part of the device driver and they contain pointers to the | ||
| 251 | ; actual cache memory where the data is. This is more efficient | ||
| 252 | ; than putting the structures with the data as there is more overhead | ||
| 253 | ; to access stuff in the data area. The structures form a double | ||
| 254 | ; linked list in LRU order. The head points to the MRU element. The | ||
| 255 | ; tail points to the LRU element. Scans start at MRU as this is the | ||
| 256 | ; highest probability of a hit. Selection for bump is at LRU. All of | ||
| 257 | ; the links are short pointers. This limits the size of the cache | ||
| 258 | ; as the cache structures together with the device code must all | ||
| 259 | ; fit in 64K. This is more efficient than FAR links. Each cache element | ||
| 260 | ; contains one complete track of one of the INT 13 hard files (INT 13 | ||
| 261 | ; floppy drives are NOT cached). Cache "read ahead" is obtained by | ||
| 262 | ; reading complete tracks into the cache even though the INT 13 user | ||
| 263 | ; may have only requested one sector. Write behind is accomplished | ||
| 264 | ; (if enabled) by holding tracks for a while allowing user writes | ||
| 265 | ; on that track to "accumulate". | ||
| 266 | ; | ||
| 267 | ; The original INT 13 caching algorithm (Aaronr) is sumarized as follows: | ||
| 268 | ; | ||
| 269 | ; If user read is in cache | ||
| 270 | ; Perform user read from cache | ||
| 271 | ; Else | ||
| 272 | ; If read is full track | ||
| 273 | ; Perform write through (if enabled) | ||
| 274 | ; Pass Read to old INT 13 handler (no cache operation) | ||
| 275 | ; Else | ||
| 276 | ; Read track into cache using old INT 13 handler | ||
| 277 | ; Perform user read out of cache | ||
| 278 | ; | ||
| 279 | ; If user write is in cache | ||
| 280 | ; If write buffering is enabled | ||
| 281 | ; Perform user write into cache | ||
| 282 | ; Else | ||
| 283 | ; Discard cache for this track | ||
| 284 | ; Pass write through to old INT 13 handler | ||
| 285 | ; Else | ||
| 286 | ; If write is full track | ||
| 287 | ; Perform write through (if enabled) | ||
| 288 | ; Pass Write to old INT 13 handler (no cache operation) | ||
| 289 | ; Else | ||
| 290 | ; If write buffering is enabled | ||
| 291 | ; Read track into cache using old INT 13 handler | ||
| 292 | ; Perform user write into cache | ||
| 293 | ; Else | ||
| 294 | ; Pass write through to old INT 13 handler | ||
| 295 | ; | ||
| 296 | ; SMARTDRV modifications: | ||
| 297 | ; | ||
| 298 | ; 1. Write through always. | ||
| 299 | ; 2. Multi track I/O capability support. | ||
| 300 | ; 3. Direct transfer between cache and user buffer address for | ||
| 301 | ; full tracks. | ||
| 302 | ; | ||
| 303 | ; | ||
| 304 | ; | ||
| 305 | |||
| 306 | CACHE_CONTROL STRUC | ||
| 307 | FWD_LRU_LNK DW ? ; Link to next CACHE_CONTROL, -1 if last | ||
| 308 | BACK_LRU_LNK DW ? ; Link to previous CACHE_CONTROL, -1 if first | ||
| 309 | BASE_OFFSET DD ? ; Offset releative to start of cache | ||
| 310 | ; memory of start of this track buffer | ||
| 311 | TRACK_FLAGS DW ? ; Flags | ||
| 312 | ; | ||
| 313 | ; NOTE: The next two bytes are refed as a word. | ||
| 314 | ; MOV DX,WORD PTR STRC.TRACK_DRIVE | ||
| 315 | ; OR DH,80H | ||
| 316 | ; Puts the INT 13 drive in DL, and the head in DH which is correct | ||
| 317 | ; for an INT 13 | ||
| 318 | ; | ||
| 319 | TRACK_DRIVE DB ? ; INT 13 drive with high bit = 0 | ||
| 320 | TRACK_HEAD DB ? ; INT 13 head | ||
| 321 | TRACK_CYLN DW ? ; INT 13 cylinder | ||
| 322 | ; High byte is low byte of cylinder # | ||
| 323 | ; High two bits of Low byte are high | ||
| 324 | ; two bits of cylinder #. Other bits | ||
| 325 | ; are 0. This makes it easy to load the | ||
| 326 | ; CX register for an INT 13 for this | ||
| 327 | ; track: | ||
| 328 | ; MOV CX,STRC.CACHE_CYLN | ||
| 329 | ; OR CL,1 | ||
| 330 | CACHE_CONTROL ENDS | ||
| 331 | |||
| 332 | ; | ||
| 333 | ; TRACK_FLAGS bits | ||
| 334 | ; | ||
| 335 | TRACK_FREE EQU 0000000000000001B ; Track buffer is free | ||
| 336 | TRACK_DIRTY EQU 0000000000000010B ; Track needs to be written | ||
| 337 | TRACK_LOCKED EQU 0000000000000100B ; Track is locked | ||
| 338 | |||
| 339 | BREAK <Device header> | ||
| 340 | |||
| 341 | INT13CODE SEGMENT | ||
| 342 | ASSUME CS:INT13CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 343 | |||
| 344 | IF DEBUG | ||
| 345 | public strategy,int13$in,cmderr,err$cnt,err$exit,devexit | ||
| 346 | public INT13$IOCTL_Read,INT13$Read_St,INT13$Write_St,INT13$IOCTL_Write | ||
| 347 | public int_1C_handler,int_13_handler,POP_NO_PROC,INVALIDATE_CACHE | ||
| 348 | public CACHE_READ,CACHE_WRITE,FLUSH_PASS,FLUSH_INVALID_PASS | ||
| 349 | public FLUSH_WHOLE_CACHE_SAV,FLUSH_WHOLE_CACHE,FLUSH_CACHE | ||
| 350 | public WRITE_FROM_CACHE | ||
| 351 | public Cache_hit | ||
| 352 | public blkmov,INT_9,INT_19,RESET_SYSTEM,DO_INIT,SETBPB | ||
| 353 | public PRINT,ITOA,INT13$INIT,DRIVEPARMS,GETNUM,DISK_ABORT | ||
| 354 | public CTRL_IO,MM_SETDRIVE,FIND_VDRIVE,SET_RESET | ||
| 355 | public AT_EXT_INIT,FIX_DESCRIPTOR,ABOVE_INIT | ||
| 356 | public process_read_partial,process_block_read,pr_acc_trks | ||
| 357 | public pr_acc_trks,pr_cur_trk,process_write_partial,process_block_write | ||
| 358 | public check_parameters,process_regions,bytes_in_trk,sect_in_trk | ||
| 359 | public not_in_mem,read_disk | ||
| 360 | public not_in_memw,rd_partw,rd_part | ||
| 361 | public region | ||
| 362 | public SECTRKARRAY | ||
| 363 | ENDIF | ||
| 364 | |||
| 365 | ;** | ||
| 366 | ; | ||
| 367 | ; INT13 DEVICE HEADER | ||
| 368 | ; | ||
| 369 | ; COMMON TO TYPE 1, 2 drivers | ||
| 370 | ; | ||
| 371 | ; SEE ALSO | ||
| 372 | ; MS-DOS Technical Reference manual section on | ||
| 373 | ; Installable Device Drivers | ||
| 374 | ; | ||
| 375 | |||
| 376 | ;; The internal name of the device driver has been changed from SMARTDRV | ||
| 377 | ;; to SMARTAAR to avoid DOS name conflicts with files named SMARTDRV.* | ||
| 378 | ;; | ||
| 379 | INT13DEV LABEL WORD | ||
| 380 | DW -1,-1 | ||
| 381 | DEVATS DW DEVOPCL + CharDev + DevIOCtl | ||
| 382 | DW STRATEGY | ||
| 383 | DW INT13$IN | ||
| 384 | DB "SMARTAAR" ;Name of device | ||
| 385 | |||
| 386 | |||
| 387 | BREAK <Command dispatch table> | ||
| 388 | |||
| 389 | ;** | ||
| 390 | ; | ||
| 391 | ; This is the device driver command dispatch table. | ||
| 392 | ; | ||
| 393 | ; The first byte indicates the size of the table and therefore defines | ||
| 394 | ; which device function codes are valid. | ||
| 395 | ; | ||
| 396 | ; The entries in the table are NEAR word addresses of the appropriate | ||
| 397 | ; device routine. Thus the address of the routine to handle device function | ||
| 398 | ; 3 is: | ||
| 399 | ; WORD at ((INT13TBL + 1) + (2 * 3)) | ||
| 400 | ; | ||
| 401 | ; COMMON TO TYPE 1, 2 drivers | ||
| 402 | ; | ||
| 403 | ; | ||
| 404 | |||
| 405 | INT13TBL LABEL WORD | ||
| 406 | DB 15 ; Max allowed command code | ||
| 407 | DW INT13$INIT ; Init | ||
| 408 | DW CMDERR ; Media check | ||
| 409 | DW CMDERR ; Build BPB | ||
| 410 | DW INT13$IOCTL_Read ; IOCTL input | ||
| 411 | DW CMDERR ; Read | ||
| 412 | DW CMDERR ; Non-des read no-wait | ||
| 413 | DW INT13$Read_St ; Read status | ||
| 414 | DW CMDERR ; Read flush | ||
| 415 | DW CMDERR ; Write | ||
| 416 | DW CMDERR ; Write with verify | ||
| 417 | DW INT13$Write_St ; Output status | ||
| 418 | DW CMDERR ; Output flush | ||
| 419 | DW INT13$IOCTL_Write ; IOCTL output | ||
| 420 | DW DEVEXIT ; Open | ||
| 421 | DW DEVEXIT ; Close | ||
| 422 | DW CMDERR ; Rem media? | ||
| 423 | |||
| 424 | BREAK <Device Control data> | ||
| 425 | |||
| 426 | STATISTICS_SIZE EQU 40 | ||
| 427 | |||
| 428 | DRIVER_SEL DB 0 ; 0 if /E (TYPE 1), 1 if /A (TYPE 2), | ||
| 429 | |||
| 430 | DEV_SIZE DW 256 ; Size in K of the cache | ||
| 431 | |||
| 432 | SECTRACK DW ? ; Sectors per track | ||
| 433 | |||
| 434 | current_dev_size dw ? ; Current size in K of cache | ||
| 435 | |||
| 436 | ;; Data peculiar to AT&T 6300 PLUS. | ||
| 437 | |||
| 438 | S5_FLAG DB 0 ;; = S_OLIVETTI if 6300 plus machine | ||
| 439 | ;; = S_VECTRA if HP Vectra machine | ||
| 440 | |||
| 441 | db ? ; Spacer | ||
| 442 | |||
| 443 | A20On dw 0DF90h | ||
| 444 | A20Off dw 0DD00h | ||
| 445 | |||
| 446 | special_mem dw 0 | ||
| 447 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 448 | ; Unfortunately the code in smartdrv is very machine dependent | ||
| 449 | ; necessitating the use of a system flag to store the machine | ||
| 450 | ; configuration. The system flag is initialised during init time | ||
| 451 | ; and used when the caching services are requested. One bit which | ||
| 452 | ; is set and tested during caching is the state of the a20 line | ||
| 453 | ; when the cache code is entered. This is used because there are | ||
| 454 | ; applications which enable the a20 line and leave it enabled | ||
| 455 | ; throughout the duration of execution. Since smartdrv is a device | ||
| 456 | ; driver it shouldn't change the state of the environment. | ||
| 457 | ; | ||
| 458 | ; The system flag bit assignments are: | ||
| 459 | ; | ||
| 460 | ; ------------------------------------------------- | ||
| 461 | ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | ||
| 462 | ; ------------------------------------------------- | ||
| 463 | ; |-----|-----| | | | | | | ||
| 464 | ; | | | | | -----286 (and AT) | ||
| 465 | ; | | | | -----------386 (later than B0) | ||
| 466 | ; not | | -----------------PS/2 machine | ||
| 467 | ; used | -----------------------Olivetti (not used) | ||
| 468 | ; -----------------------------A20 state (enabled ?) | ||
| 469 | ; | ||
| 470 | ; The Olivetti guys have defined a flag of their own. This should be removed | ||
| 471 | ; and the bit assigned out here for them should be used. | ||
| 472 | ; | ||
| 473 | sys_flg db ? | ||
| 474 | ; | ||
| 475 | ; equates used for the system flag | ||
| 476 | ; | ||
| 477 | M_286 equ 00000001B | ||
| 478 | M_386 equ 00000010B | ||
| 479 | M_PS2 equ 00000100B | ||
| 480 | M_OLI equ 00001000B | ||
| 481 | A20_ST equ 00010000B | ||
| 482 | ifdef OMTI | ||
| 483 | OMTI_EXT equ 00100000B | ||
| 484 | endif | ||
| 485 | |||
| 486 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 487 | ; flag to indicate that reset code is being executed | ||
| 488 | reboot_flg db 0 | ||
| 489 | ; | ||
| 490 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 491 | ; emm ctrl address, needed for the reset code | ||
| 492 | emm_ctrl_addr dw EXTMEM_LOW | ||
| 493 | dw EXTMEM_HIGH | ||
| 494 | ; | ||
| 495 | ; | ||
| 496 | ; | ||
| 497 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 498 | ; A20 address line state determination addresses | ||
| 499 | ; | ||
| 500 | low_mem label dword | ||
| 501 | dw 20h*4 | ||
| 502 | dw 0 | ||
| 503 | |||
| 504 | high_mem label dword | ||
| 505 | dw 20h*4 + 10h | ||
| 506 | dw 0ffffh | ||
| 507 | |||
| 508 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 509 | ; A20 PS2 equates | ||
| 510 | ; | ||
| 511 | PS2_PORTA equ 0092h | ||
| 512 | GATE_A20 equ 010b | ||
| 513 | |||
| 514 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 515 | ; 386 working areas | ||
| 516 | start_gdt label byte | ||
| 517 | nul_des desc <> | ||
| 518 | cs_des desc <0FFFFh,0,0,09Fh,0,0> | ||
| 519 | ss_des desc <0FFFFh,0,0,093h,0,0> | ||
| 520 | ds_des desc <0FFFFh,0,0,093h,0,0> | ||
| 521 | es_des desc <0FFFFh,0,0,093h,0,0> | ||
| 522 | end_gdt label byte | ||
| 523 | |||
| 524 | emm_gdt gdt_descriptor <end_gdt-start_gdt,0,0> | ||
| 525 | ; | ||
| 526 | ; int 15 gdt | ||
| 527 | ; | ||
| 528 | int15_gdt label byte | ||
| 529 | desc <> ;dummy descriptor | ||
| 530 | desc <> ;descriptor for gdt itself | ||
| 531 | src desc <0ffffh,,,93h,,> | ||
| 532 | tgt desc <0ffffh,,,93h,,> | ||
| 533 | desc <> ;bios cs descriptor | ||
| 534 | desc <> ;stack segment descriptor | ||
| 535 | |||
| 536 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 537 | ; 0 if device is valid | ||
| 538 | ; Non-0 if device install failed (device non-functional) | ||
| 539 | ; | ||
| 540 | ; We need this state because there is no way to "un-install" | ||
| 541 | ; a character device as there is with block devices | ||
| 542 | ; | ||
| 543 | NULDEV DB 0 | ||
| 544 | |||
| 545 | ; | ||
| 546 | ; 0 if caching is off | ||
| 547 | ; Non-0 if caching is on | ||
| 548 | ; | ||
| 549 | ENABLE_13 DB 1 ; 0 for debug | ||
| 550 | |||
| 551 | ; | ||
| 552 | ; 0 if no write through | ||
| 553 | ; Non-0 if write through | ||
| 554 | ; | ||
| 555 | WRITE_THROUGH DB 0 | ||
| 556 | |||
| 557 | ; | ||
| 558 | ; 0 if no write buffering | ||
| 559 | ; Non-0 if write buffering enabled | ||
| 560 | ; | ||
| 561 | WRITE_BUFF DB 0 | ||
| 562 | |||
| 563 | ; | ||
| 564 | ; 0 if cache is unlocked | ||
| 565 | ; Non-0 if cache is locked | ||
| 566 | ; | ||
| 567 | LOCK_CACHE DB 0 | ||
| 568 | |||
| 569 | ; | ||
| 570 | ; 0 if full track I/O to tracks not in cache is not cached. | ||
| 571 | ; Non-0 if ALL I/O is to be cached | ||
| 572 | ; | ||
| 573 | ALL_CACHE DB 1 | ||
| 574 | |||
| 575 | ; | ||
| 576 | ; 0 if reboot flush is disabled | ||
| 577 | ; Non-0 if reboot flush is enabled | ||
| 578 | ; | ||
| 579 | REBOOT_FLUSH DB 0 | ||
| 580 | |||
| 581 | ; | ||
| 582 | ; An exclusion sem so that the INT 13 handler and the timer interact | ||
| 583 | ; without re-entrancy problems | ||
| 584 | ; | ||
| 585 | INT_13_BUSY DB 0 ; Exclusion sem | ||
| 586 | |||
| 587 | EVEN ; Force word data to word align | ||
| 588 | ; | ||
| 589 | ; Statistics counters | ||
| 590 | ; | ||
| 591 | ; WARNING!!!! Do not disturb the order of these!!!! See IOCTL_READ code. | ||
| 592 | ; | ||
| 593 | TOTAL_WRITES DD 0 | ||
| 594 | WRITE_HITS DD 0 | ||
| 595 | TOTAL_READS DD 0 | ||
| 596 | READ_HITS DD 0 | ||
| 597 | TTRACKS DW ? ; Total number of track buffers that fit | ||
| 598 | ; in DEV_SIZE K (number of cache elements) | ||
| 599 | TOTAL_USED DW 0 | ||
| 600 | TOTAL_LOCKED DW 0 | ||
| 601 | TOTAL_DIRTY DW 0 | ||
| 602 | |||
| 603 | ; | ||
| 604 | ; Tick counters | ||
| 605 | ; | ||
| 606 | TICK_SETTING DW 1092 ; Approx 1 minute | ||
| 607 | TICK_CNT DW 1092 | ||
| 608 | |||
| 609 | ; | ||
| 610 | ; Non-zero if there are dirty buffers in the cache | ||
| 611 | ; | ||
| 612 | DIRTY_CACHE DW 0 ; 0 if no dirty elements in cache | ||
| 613 | |||
| 614 | BREAK <Common Device code> | ||
| 615 | |||
| 616 | ; INT13 DEVICE ENTRY POINTS - STRATEGY, INT13$IN | ||
| 617 | ; | ||
| 618 | ; This code is standard DOS device driver function dispatch | ||
| 619 | ; code. STRATEGY is the device driver strategy routine, INT13$IN | ||
| 620 | ; is the driver interrupt routine. | ||
| 621 | ; | ||
| 622 | ; INT13$IN uses INT13TBL to dispatch to the appropriate handler | ||
| 623 | ; for each device function. It also does standard packet | ||
| 624 | ; unpacking. | ||
| 625 | ; | ||
| 626 | ; SEE ALSO | ||
| 627 | ; MS-DOS Technical Reference manual section on | ||
| 628 | ; Installable Device Drivers | ||
| 629 | ; | ||
| 630 | |||
| 631 | ASSUME CS:INT13CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 632 | |||
| 633 | PTRSAV DD 0 ; Storage location for packet addr | ||
| 634 | |||
| 635 | ;** STRATEGY - Device strategy routine | ||
| 636 | ; | ||
| 637 | ; Standard DOS 2.X 3.X device driver strategy routine. All it does | ||
| 638 | ; is save the packet address in PTRSAV. | ||
| 639 | ; | ||
| 640 | ; ENTRY ES:BX -> Device packet | ||
| 641 | ; EXIT NONE | ||
| 642 | ; USES NONE | ||
| 643 | ; | ||
| 644 | ; COMMON TO TYPE 1, 2 drivers | ||
| 645 | ; | ||
| 646 | ; | ||
| 647 | |||
| 648 | STRATP PROC FAR | ||
| 649 | |||
| 650 | STRATEGY: | ||
| 651 | MOV WORD PTR [PTRSAV],BX ; Save packet addr | ||
| 652 | MOV WORD PTR [PTRSAV+2],ES | ||
| 653 | RET | ||
| 654 | |||
| 655 | STRATP ENDP | ||
| 656 | |||
| 657 | ;** INT13$IN - Device interrupt routine | ||
| 658 | ; | ||
| 659 | ; Standard DOS 2.X 3.X device driver interrupt routine. | ||
| 660 | ; | ||
| 661 | ; | ||
| 662 | ; ENTRY PTRSAV has packet address saved by previous STRATEGY call. | ||
| 663 | ; EXIT Dispatch to appropriate function handler | ||
| 664 | ; CX = Packet RW_COUNT | ||
| 665 | ; DX = Packet RW_START | ||
| 666 | ; ES:DI = Packet RW_TRANS | ||
| 667 | ; DS = INT13CODE | ||
| 668 | ; STACK has saved values of all regs but FLAGS | ||
| 669 | ; All function handlers must return through one of | ||
| 670 | ; the standard exit points | ||
| 671 | ; USES FLAGS | ||
| 672 | ; | ||
| 673 | ; COMMON TO TYPE 1, 2 drivers | ||
| 674 | ; | ||
| 675 | ; | ||
| 676 | |||
| 677 | INT13$IN: | ||
| 678 | PUSH SI | ||
| 679 | PUSH AX | ||
| 680 | PUSH CX | ||
| 681 | PUSH DX | ||
| 682 | PUSH DI | ||
| 683 | PUSH BP | ||
| 684 | PUSH DS | ||
| 685 | PUSH ES | ||
| 686 | PUSH BX | ||
| 687 | |||
| 688 | LDS BX,[PTRSAV] ;GET POINTER TO I/O PACKET | ||
| 689 | ; | ||
| 690 | ; Set up registers for READ or WRITE since this is the most common case | ||
| 691 | ; | ||
| 692 | MOV CX,DS:[BX.RW_COUNT] ;CX = COUNT | ||
| 693 | MOV DX,DS:[BX.RW_START] ;DX = START SECTOR | ||
| 694 | MOV AL,DS:[BX.REQFUNC] ; Command code | ||
| 695 | MOV AH,BYTE PTR [INT13TBL] ; Valid range | ||
| 696 | CMP AL,AH | ||
| 697 | JA CMDERR ; Out of range command code | ||
| 698 | MOV SI,OFFSET INT13TBL + 1 ; Table of routines | ||
| 699 | CBW ; Make command code a word | ||
| 700 | ADD SI,AX ; Add it twice since one word in | ||
| 701 | ADD SI,AX ; table per command. | ||
| 702 | |||
| 703 | LES DI,DS:[BX.RW_TRANS] ; ES:DI transfer address | ||
| 704 | |||
| 705 | PUSH CS | ||
| 706 | POP DS | ||
| 707 | |||
| 708 | ASSUME DS:INT13CODE | ||
| 709 | |||
| 710 | JMP WORD PTR [SI] ; GO DO COMMAND | ||
| 711 | |||
| 712 | ;** EXIT - ALL ROUTINES RETURN THROUGH ONE OF THESE PATHS | ||
| 713 | ; | ||
| 714 | ; Exit code entry points: | ||
| 715 | ; | ||
| 716 | ; SEE ALSO | ||
| 717 | ; MS-DOS Technical Reference manual section on | ||
| 718 | ; Installable Device Drivers | ||
| 719 | ; | ||
| 720 | ; GENERAL ENTRY for all entry points | ||
| 721 | ; All packet values appropriate to the specific device function | ||
| 722 | ; filled in except for the status word in the static request | ||
| 723 | ; header. | ||
| 724 | ; | ||
| 725 | ; CMDERR - Used when an invalid device command is detected | ||
| 726 | ; | ||
| 727 | ; ENTRY Stack has frame set up by INT13$IN | ||
| 728 | ; EXIT Standard Device driver with error 3 | ||
| 729 | ; USES FLAGS | ||
| 730 | ; | ||
| 731 | ; ERR$CNT - Used when READ or WRITE wants to return with error code. | ||
| 732 | ; The packet RW_COUNT field is zeroed | ||
| 733 | ; | ||
| 734 | ; ENTRY AL is error code for low byte of packet status word | ||
| 735 | ; Stack has frame set up by INT13$IN | ||
| 736 | ; EXIT Standard Device driver with error AL | ||
| 737 | ; USES FLAGS | ||
| 738 | ; | ||
| 739 | ; ERR$EXIT - Used when a function other that READ or WRITE wants to | ||
| 740 | ; return an error | ||
| 741 | ; | ||
| 742 | ; ENTRY AL is error code for low byte of packet status word | ||
| 743 | ; Stack has frame set up by INT13$IN | ||
| 744 | ; EXIT Standard Device driver with error AL | ||
| 745 | ; USES FLAGS | ||
| 746 | ; | ||
| 747 | ; DEVEXIT - Used when a function wants to return with no error | ||
| 748 | ; | ||
| 749 | ; ENTRY AL is value for low byte of packet status word | ||
| 750 | ; NOTE: Typically there is no meaningful value | ||
| 751 | ; in the AL register when EXITing through here. | ||
| 752 | ; This is OK as the low 8 bits of the status word | ||
| 753 | ; have no meaning unless an error occured. | ||
| 754 | ; Stack has frame set up by INT13$IN | ||
| 755 | ; EXIT Standard Device driver with no error | ||
| 756 | ; USES FLAGS | ||
| 757 | ; | ||
| 758 | ; ERR1 - Used when a function wants to return with a value | ||
| 759 | ; for the whole status word | ||
| 760 | ; | ||
| 761 | ; ENTRY AX is value for packet status word | ||
| 762 | ; Stack has frame set up by INT13$IN | ||
| 763 | ; EXIT Standard Device driver with or without error | ||
| 764 | ; USES FLAGS | ||
| 765 | ; | ||
| 766 | ; COMMON TO TYPE 1, 2 drivers | ||
| 767 | ; | ||
| 768 | ; | ||
| 769 | |||
| 770 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 771 | |||
| 772 | CMDERR: | ||
| 773 | MOV AL,3 ;UNKNOWN COMMAND ERROR | ||
| 774 | JMP SHORT ERR$EXIT | ||
| 775 | |||
| 776 | ERR$CNT: | ||
| 777 | LDS BX,[PTRSAV] | ||
| 778 | MOV [BX.RW_COUNT],0 ; NO sectors transferred | ||
| 779 | ERR$EXIT: ; Error in AL | ||
| 780 | MOV AH,(STERR + STDON) SHR 8 ;MARK ERROR RETURN | ||
| 781 | JMP SHORT ERR1 | ||
| 782 | |||
| 783 | EXITP PROC FAR | ||
| 784 | |||
| 785 | DEVEXIT: | ||
| 786 | MOV AH,STDON SHR 8 | ||
| 787 | ERR1: | ||
| 788 | LDS BX,[PTRSAV] | ||
| 789 | MOV [BX.REQSTAT],AX ; Set return status | ||
| 790 | |||
| 791 | POP BX | ||
| 792 | POP ES | ||
| 793 | POP DS | ||
| 794 | POP BP | ||
| 795 | POP DI | ||
| 796 | POP DX | ||
| 797 | POP CX | ||
| 798 | POP AX | ||
| 799 | POP SI | ||
| 800 | RET ;RESTORE REGS AND RETURN | ||
| 801 | EXITP ENDP | ||
| 802 | |||
| 803 | ; | ||
| 804 | ; The following functions are not supported at this time. | ||
| 805 | ; | ||
| 806 | INT13$Read_St: | ||
| 807 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 808 | INT13$Write_St: | ||
| 809 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 810 | JMP CMDERR | ||
| 811 | |||
| 812 | BREAK <IOCTL Read function (get device control parms)> | ||
| 813 | |||
| 814 | SET_ZRJ3: | ||
| 815 | JMP SET_ZR | ||
| 816 | |||
| 817 | INT13$IOCTL_Read: | ||
| 818 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 819 | CLD | ||
| 820 | CMP CX,STATISTICS_SIZE ; Must have room to transfer data. | ||
| 821 | JB SET_ZRJ3 ; Not enough room from user | ||
| 822 | MOV [TOTAL_USED],0 | ||
| 823 | MOV [TOTAL_LOCKED],0 | ||
| 824 | MOV [TOTAL_DIRTY],0 | ||
| 825 | ; | ||
| 826 | ; Count all occupied, dirty and locked elements | ||
| 827 | ; | ||
| 828 | MOV [INT_13_BUSY],1 | ||
| 829 | MOV SI,[CACHE_HEAD] | ||
| 830 | INC SI | ||
| 831 | NEXTCC: | ||
| 832 | DEC SI | ||
| 833 | TEST [SI.TRACK_FLAGS],TRACK_FREE | ||
| 834 | JNZ SKIPCC | ||
| 835 | INC [TOTAL_USED] | ||
| 836 | TEST [SI.TRACK_FLAGS],TRACK_LOCKED | ||
| 837 | JZ TEST_DIRTY | ||
| 838 | INC [TOTAL_LOCKED] | ||
| 839 | TEST_DIRTY: | ||
| 840 | TEST [SI.TRACK_FLAGS],TRACK_DIRTY | ||
| 841 | JZ SKIPCC | ||
| 842 | INC [TOTAL_DIRTY] | ||
| 843 | SKIPCC: | ||
| 844 | MOV SI,[SI.FWD_LRU_LNK] | ||
| 845 | INC SI | ||
| 846 | JNZ NEXTCC | ||
| 847 | MOV [INT_13_BUSY],0 | ||
| 848 | MOV AL,[WRITE_THROUGH] | ||
| 849 | MOV AH,[WRITE_BUFF] | ||
| 850 | STOSW | ||
| 851 | MOV AL,[ENABLE_13] | ||
| 852 | MOV AH,[NULDEV] | ||
| 853 | STOSW | ||
| 854 | MOV AX,[TICK_SETTING] | ||
| 855 | STOSW | ||
| 856 | MOV AL,[LOCK_CACHE] | ||
| 857 | MOV AH,[REBOOT_FLUSH] | ||
| 858 | STOSW | ||
| 859 | MOV AL,[ALL_CACHE] | ||
| 860 | XOR AH,AH ; Unused currently | ||
| 861 | STOSW | ||
| 862 | MOV SI,OFFSET TOTAL_WRITES | ||
| 863 | MOV CX,12 | ||
| 864 | REP MOVSW | ||
| 865 | ; | ||
| 866 | ; Transfer Above Board Information | ||
| 867 | ; | ||
| 868 | xor dx,dx | ||
| 869 | mov es:[di][0],dx | ||
| 870 | mov es:[di][2],dx | ||
| 871 | mov es:[di][4],dx | ||
| 872 | cmp [driver_sel],dl ; is it expanded memory? | ||
| 873 | jz no_ems ; no, info already set | ||
| 874 | mov cx,16 | ||
| 875 | mov ax,[current_dev_size] | ||
| 876 | div cx | ||
| 877 | or dx,dx | ||
| 878 | jz no_remain | ||
| 879 | inc ax | ||
| 880 | xor dx,dx | ||
| 881 | no_remain: | ||
| 882 | stosw | ||
| 883 | mov ax,[dev_size] | ||
| 884 | div cx | ||
| 885 | or dx,dx | ||
| 886 | jz no_remaind | ||
| 887 | inc ax | ||
| 888 | no_remaind: | ||
| 889 | stosw | ||
| 890 | mov ax,MIN_CACHE_SIZE_K / 16 | ||
| 891 | stosw | ||
| 892 | no_ems: | ||
| 893 | LDS BX,[PTRSAV] | ||
| 894 | ASSUME DS:NOTHING | ||
| 895 | MOV [BX.RW_COUNT],STATISTICS_SIZE ; transfer amount | ||
| 896 | JMP DEVEXIT | ||
| 897 | |||
| 898 | BREAK <IOCTL Write functions (set device control parms and do flushes)> | ||
| 899 | |||
| 900 | ; | ||
| 901 | ; Command table for IOCTL Write functions. The first byte of the written | ||
| 902 | ; data contains the "function" code which is dispatched via this | ||
| 903 | ; table. The first byte is the maximum legal function code, then the word | ||
| 904 | ; addresses of the handlers for each function. | ||
| 905 | ; | ||
| 906 | IOCTLTBL DB 0Ch | ||
| 907 | DW IOCTL_FLUSH ; Function 0h | ||
| 908 | DW IOCTL_FLUSH_INVALID ; Function 1h | ||
| 909 | DW IOCTL_DISABLE ; Function 2h | ||
| 910 | DW IOCTL_ENABLE ; Function 3h | ||
| 911 | DW IOCTL_WRITE_MOD ; Function 4h | ||
| 912 | DW IOCTL_SET_TICK ; Function 5h | ||
| 913 | DW IOCTL_LOCK ; Function 6h | ||
| 914 | DW IOCTL_UNLOCK ; Function 7h | ||
| 915 | DW IOCTL_REBOOT ; Function 8h | ||
| 916 | DW IOCTL_STAT_RESET ; Function 9h | ||
| 917 | DW IOCTL_ALL_CACHE ; Function Ah | ||
| 918 | dw ioctl_reduce_cache_size ; Function Bh | ||
| 919 | dw ioctl_increase_cache_size ; Function Ch | ||
| 920 | |||
| 921 | SET_ZR: | ||
| 922 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 923 | LDS BX,[PTRSAV] | ||
| 924 | ASSUME DS:NOTHING | ||
| 925 | MOV [BX.RW_COUNT],0 ; NO bytes transferred | ||
| 926 | JMP DEVEXIT | ||
| 927 | |||
| 928 | SET_ERR_CNT: | ||
| 929 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 930 | MOV AL,3 ;UNKNOWN COMMAND ERROR | ||
| 931 | JMP ERR$CNT | ||
| 932 | |||
| 933 | INT13$IOCTL_Write: | ||
| 934 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 935 | CMP [NULDEV],0 ; Is the device valid? | ||
| 936 | JNZ SET_ZR ; No, you get an error | ||
| 937 | MOV AL,ES:[DI] ; Get command byte | ||
| 938 | MOV AH,BYTE PTR [IOCTLTBL] ; Valid range | ||
| 939 | CMP AL,AH ; In range? | ||
| 940 | JA SET_ERR_CNT ; No | ||
| 941 | MOV SI,OFFSET IOCTLTBL + 1 ; Table of routines | ||
| 942 | CBW ; Make command code a word | ||
| 943 | ADD SI,AX ; Add it twice since one word in | ||
| 944 | ADD SI,AX ; table per command. | ||
| 945 | JMP WORD PTR [SI] ; GO DO COMMAND | ||
| 946 | |||
| 947 | ;** IOCTL_FLUSH -- Flush the cache, but keep the data | ||
| 948 | ; | ||
| 949 | ; ENTRY: | ||
| 950 | ; ES:DI is transfer address | ||
| 951 | ; CX is transfer count | ||
| 952 | ; EXIT: | ||
| 953 | ; Through one of the device exit paths | ||
| 954 | ; USES: | ||
| 955 | ; ALL | ||
| 956 | ; | ||
| 957 | IOCTL_FLUSH: | ||
| 958 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 959 | MOV [INT_13_BUSY],1 | ||
| 960 | CALL FLUSH_WHOLE_CACHE | ||
| 961 | MOV [INT_13_BUSY],0 | ||
| 962 | JMP DEVEXIT | ||
| 963 | |||
| 964 | ;** IOCTL_FLUSH_INVALIDATE -- Flush the cache, and discard the data | ||
| 965 | ; | ||
| 966 | ; ENTRY: | ||
| 967 | ; ES:DI is transfer address | ||
| 968 | ; CX is transfer count | ||
| 969 | ; EXIT: | ||
| 970 | ; Through one of the device exit paths | ||
| 971 | ; USES: | ||
| 972 | ; ALL | ||
| 973 | ; | ||
| 974 | IOCTL_FLUSH_INVALID: | ||
| 975 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 976 | MOV [INT_13_BUSY],1 | ||
| 977 | CALL FLUSH_WHOLE_CACHE | ||
| 978 | CALL INVALIDATE_CACHE | ||
| 979 | MOV [INT_13_BUSY],0 | ||
| 980 | JMP DEVEXIT | ||
| 981 | |||
| 982 | ;** IOCTL_DISABLE -- Disable the caching for both reads and writes | ||
| 983 | ; | ||
| 984 | ; Also flush and invalidate the cache | ||
| 985 | ; | ||
| 986 | ; ENTRY: | ||
| 987 | ; ES:DI is transfer address | ||
| 988 | ; CX is transfer count | ||
| 989 | ; EXIT: | ||
| 990 | ; Through one of the device exit paths | ||
| 991 | ; USES: | ||
| 992 | ; ALL | ||
| 993 | ; | ||
| 994 | IOCTL_DISABLE: | ||
| 995 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 996 | MOV [INT_13_BUSY],1 | ||
| 997 | CALL FLUSH_WHOLE_CACHE | ||
| 998 | CALL INVALIDATE_CACHE | ||
| 999 | MOV [ENABLE_13],0 | ||
| 1000 | MOV [INT_13_BUSY],0 | ||
| 1001 | JMP DEVEXIT | ||
| 1002 | |||
| 1003 | ;** IOCTL_ENABLE -- Enable the caching for reads (and possibly writes) | ||
| 1004 | ; | ||
| 1005 | ; ENTRY: | ||
| 1006 | ; ES:DI is transfer address | ||
| 1007 | ; CX is transfer count | ||
| 1008 | ; EXIT: | ||
| 1009 | ; Through one of the device exit paths | ||
| 1010 | ; USES: | ||
| 1011 | ; ALL | ||
| 1012 | ; | ||
| 1013 | IOCTL_ENABLE: | ||
| 1014 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1015 | MOV [ENABLE_13],1 | ||
| 1016 | JMP DEVEXIT | ||
| 1017 | |||
| 1018 | ;** IOCTL_WRITE_MOD -- En/Disable Write through and write caching | ||
| 1019 | ; | ||
| 1020 | ; ENTRY: | ||
| 1021 | ; ES:DI is transfer address | ||
| 1022 | ; CX is transfer count | ||
| 1023 | ; Second byte of data indicates what to set | ||
| 1024 | ; 0 Turn off Write through | ||
| 1025 | ; 1 Turn on Write through | ||
| 1026 | ; 2 Turn off Write buffering (also flush) | ||
| 1027 | ; 3 Turn on Write buffering (also flush) | ||
| 1028 | ; EXIT: | ||
| 1029 | ; Through one of the device exit paths | ||
| 1030 | ; USES: | ||
| 1031 | ; ALL | ||
| 1032 | ; | ||
| 1033 | IOCTL_WRITE_MOD: | ||
| 1034 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1035 | CMP CX,2 ; Did user write enough? | ||
| 1036 | JB SET_ZR ; No, error | ||
| 1037 | MOV AL,ES:[DI.1] ; Get second byte | ||
| 1038 | CMP AL,3 ; In range? | ||
| 1039 | JA SET_ZR ; No, error | ||
| 1040 | CMP AL,2 ; WT or WB? | ||
| 1041 | JB SET_WRITE_TH ; WT | ||
| 1042 | DEC AL | ||
| 1043 | DEC AL ; 2 = 0, 3 = 1 | ||
| 1044 | MOV [INT_13_BUSY],1 | ||
| 1045 | MOV [WRITE_BUFF],AL | ||
| 1046 | CALL FLUSH_WHOLE_CACHE | ||
| 1047 | MOV [INT_13_BUSY],0 | ||
| 1048 | JMP DEVEXIT | ||
| 1049 | |||
| 1050 | SET_WRITE_TH: | ||
| 1051 | MOV [WRITE_THROUGH],AL | ||
| 1052 | JMP DEVEXIT | ||
| 1053 | |||
| 1054 | ;** IOCTL_SET_TICK -- Set tick count for auto flush | ||
| 1055 | ; | ||
| 1056 | ; ENTRY: | ||
| 1057 | ; ES:DI is transfer address | ||
| 1058 | ; CX is transfer count | ||
| 1059 | ; Second byte and third byte of data is value to set | ||
| 1060 | ; EXIT: | ||
| 1061 | ; Through one of the device exit paths | ||
| 1062 | ; USES: | ||
| 1063 | ; ALL | ||
| 1064 | ; | ||
| 1065 | IOCTL_SET_TICK: | ||
| 1066 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1067 | CMP CX,3 ; Did user write enough? | ||
| 1068 | JB SET_ZRJ ; No, error | ||
| 1069 | MOV AX,ES:[DI.1] ; Get second byte and third byte as word | ||
| 1070 | MOV [TICK_SETTING],AX | ||
| 1071 | JMP DEVEXIT | ||
| 1072 | |||
| 1073 | SET_ZRJ: | ||
| 1074 | JMP SET_ZR | ||
| 1075 | |||
| 1076 | ;** IOCTL_LOCK -- Lock the current cache | ||
| 1077 | ; | ||
| 1078 | ; Also flush the cache | ||
| 1079 | ; | ||
| 1080 | ; ENTRY: | ||
| 1081 | ; ES:DI is transfer address | ||
| 1082 | ; CX is transfer count | ||
| 1083 | ; EXIT: | ||
| 1084 | ; Through one of the device exit paths | ||
| 1085 | ; USES: | ||
| 1086 | ; ALL | ||
| 1087 | ; | ||
| 1088 | IOCTL_LOCK: | ||
| 1089 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1090 | MOV [INT_13_BUSY],1 | ||
| 1091 | CALL FLUSH_WHOLE_CACHE | ||
| 1092 | MOV [LOCK_CACHE],1 | ||
| 1093 | ; | ||
| 1094 | ; Lock all cache elements that have something in them | ||
| 1095 | ; | ||
| 1096 | MOV SI,[CACHE_HEAD] | ||
| 1097 | INC SI | ||
| 1098 | NEXTCS: | ||
| 1099 | DEC SI | ||
| 1100 | TEST [SI.TRACK_FLAGS],TRACK_FREE | ||
| 1101 | JNZ SKIPCS | ||
| 1102 | OR [SI.TRACK_FLAGS],TRACK_LOCKED | ||
| 1103 | SKIPCS: | ||
| 1104 | MOV SI,[SI.FWD_LRU_LNK] | ||
| 1105 | INC SI | ||
| 1106 | JNZ NEXTCS | ||
| 1107 | MOV [INT_13_BUSY],0 | ||
| 1108 | JMP DEVEXIT | ||
| 1109 | |||
| 1110 | ;** IOCTL_UNLOCK -- Unlock the cache | ||
| 1111 | ; | ||
| 1112 | ; ENTRY: | ||
| 1113 | ; ES:DI is transfer address | ||
| 1114 | ; CX is transfer count | ||
| 1115 | ; EXIT: | ||
| 1116 | ; Through one of the device exit paths | ||
| 1117 | ; USES: | ||
| 1118 | ; ALL | ||
| 1119 | ; | ||
| 1120 | IOCTL_UNLOCK: | ||
| 1121 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1122 | MOV [INT_13_BUSY],1 | ||
| 1123 | MOV [LOCK_CACHE],0 | ||
| 1124 | ; | ||
| 1125 | ; UnLock all cache elements | ||
| 1126 | ; | ||
| 1127 | MOV SI,[CACHE_HEAD] | ||
| 1128 | INC SI | ||
| 1129 | NEXTCX: | ||
| 1130 | DEC SI | ||
| 1131 | AND [SI.TRACK_FLAGS],NOT TRACK_LOCKED | ||
| 1132 | MOV SI,[SI.FWD_LRU_LNK] | ||
| 1133 | INC SI | ||
| 1134 | JNZ NEXTCX | ||
| 1135 | MOV [INT_13_BUSY],0 | ||
| 1136 | JMP DEVEXIT | ||
| 1137 | |||
| 1138 | ;** IOCTL_REBOOT -- En/Disable Reboot flush | ||
| 1139 | ; | ||
| 1140 | ; ENTRY: | ||
| 1141 | ; ES:DI is transfer address | ||
| 1142 | ; CX is transfer count | ||
| 1143 | ; Second byte of data indicates what to set | ||
| 1144 | ; 0 Turn off reboot flush | ||
| 1145 | ; 1 Turn on reboot flush | ||
| 1146 | ; EXIT: | ||
| 1147 | ; Through one of the device exit paths | ||
| 1148 | ; USES: | ||
| 1149 | ; ALL | ||
| 1150 | ; | ||
| 1151 | IOCTL_REBOOT: | ||
| 1152 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1153 | CMP CX,2 ; Did user write enough? | ||
| 1154 | JB SET_ZRJ ; No, error | ||
| 1155 | MOV AL,ES:[DI.1] ; Get second byte | ||
| 1156 | CMP AL,1 ; In range? | ||
| 1157 | JA SET_ZRJ ; No, error | ||
| 1158 | MOV [REBOOT_FLUSH],AL | ||
| 1159 | JMP DEVEXIT | ||
| 1160 | |||
| 1161 | |||
| 1162 | ;** IOCTL_STAT_RESET -- Reset the INT 13 statistics counters | ||
| 1163 | ; | ||
| 1164 | ; ENTRY: | ||
| 1165 | ; ES:DI is transfer address | ||
| 1166 | ; CX is transfer count | ||
| 1167 | ; EXIT: | ||
| 1168 | ; Through one of the device exit paths | ||
| 1169 | ; USES: | ||
| 1170 | ; ALL | ||
| 1171 | ; | ||
| 1172 | IOCTL_STAT_RESET: | ||
| 1173 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1174 | XOR AX,AX | ||
| 1175 | MOV WORD PTR [TOTAL_WRITES],AX | ||
| 1176 | MOV WORD PTR [TOTAL_WRITES + 2],AX | ||
| 1177 | MOV WORD PTR [WRITE_HITS],AX | ||
| 1178 | MOV WORD PTR [WRITE_HITS + 2],AX | ||
| 1179 | MOV WORD PTR [TOTAL_READS],AX | ||
| 1180 | MOV WORD PTR [TOTAL_READS + 2],AX | ||
| 1181 | MOV WORD PTR [READ_HITS],AX | ||
| 1182 | MOV WORD PTR [READ_HITS + 2],AX | ||
| 1183 | JMP DEVEXIT | ||
| 1184 | |||
| 1185 | ;** IOCTL_ALL_CACHE -- En/Disable All cache | ||
| 1186 | ; | ||
| 1187 | ; ENTRY: | ||
| 1188 | ; ES:DI is transfer address | ||
| 1189 | ; CX is transfer count | ||
| 1190 | ; Second byte of data indicates what to set | ||
| 1191 | ; 0 Turn off all cache | ||
| 1192 | ; 1 Turn on all cache | ||
| 1193 | ; EXIT: | ||
| 1194 | ; Through one of the device exit paths | ||
| 1195 | ; USES: | ||
| 1196 | ; ALL | ||
| 1197 | ; | ||
| 1198 | IOCTL_ALL_CACHE: | ||
| 1199 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1200 | CMP CX,2 ; Did user write enough? | ||
| 1201 | JB SET_ZRJ2 ; No, error | ||
| 1202 | MOV AL,ES:[DI.1] ; Get second byte | ||
| 1203 | CMP AL,1 ; In range? | ||
| 1204 | JA SET_ZRJ2 ; No, error | ||
| 1205 | MOV [ALL_CACHE],AL | ||
| 1206 | JMP DEVEXIT | ||
| 1207 | |||
| 1208 | SET_ZRJ2: | ||
| 1209 | JMP SET_ZR | ||
| 1210 | |||
| 1211 | ;** ioctl_reduce_cache_size Dynamically reduce the size of the cache | ||
| 1212 | ; | ||
| 1213 | ; This routine dynamically reduces the size of an Above Board memory (/A) | ||
| 1214 | ; cache. The routine is passed the number of pages that the cache should | ||
| 1215 | ; be reduced by. The minimum size for a cache is 64K or 4 pages. In | ||
| 1216 | ; removing the tracks from the cache, the memory is returned to the EMM | ||
| 1217 | ; and then the cache control structures for that memory are taken off the | ||
| 1218 | ; LRU list, and set to free. | ||
| 1219 | ; | ||
| 1220 | ; NOTE: In this version of INT13, only reads are cached, so that when | ||
| 1221 | ; a cached track is "removed" from memory, it's contents are not | ||
| 1222 | ; updated to disk. | ||
| 1223 | ; | ||
| 1224 | ; ENTRY: | ||
| 1225 | ; ES:DI is transfer address | ||
| 1226 | ; EXIT: | ||
| 1227 | ; Through one of the device exit paths | ||
| 1228 | ; USES: | ||
| 1229 | ; ALL | ||
| 1230 | ; | ||
| 1231 | error_reduce_exitj: | ||
| 1232 | jmp error_reduce_exit | ||
| 1233 | |||
| 1234 | ioctl_reduce_cache_size: | ||
| 1235 | assume ds:Int13Code | ||
| 1236 | assume es:nothing | ||
| 1237 | assume ss:nothing | ||
| 1238 | |||
| 1239 | cmp byte ptr [driver_sel],1 ; Make sure using Above Board | ||
| 1240 | jnz error_reduce_exitj | ||
| 1241 | mov ax,es:[di.1] ; Get second byte | ||
| 1242 | or ax,ax ; Reduce by a non-0 amount? | ||
| 1243 | jnz do_it | ||
| 1244 | jmp devexit | ||
| 1245 | do_it: mov cl,4 ; Multiply by 16 to get # of K bytes | ||
| 1246 | shl ax,cl ; AX has requested reduction in K | ||
| 1247 | mov bx,word ptr [current_dev_size] | ||
| 1248 | mov si,bx ; Save current_dev_size in SI for error | ||
| 1249 | sub bx,ax ; BX now has remaining cache memory in K | ||
| 1250 | cmp bx,MIN_CACHE_SIZE_K ; Compare BX with min cache in K bytes | ||
| 1251 | jl error_reduce_exitj | ||
| 1252 | mov word ptr [current_dev_size],bx | ||
| 1253 | shr bx,cl ; BX has new cache size in pages | ||
| 1254 | mov byte ptr [int_13_busy],1 | ||
| 1255 | ; | ||
| 1256 | ; Request Reallocation of Pages from EMM | ||
| 1257 | ; | ||
| 1258 | push ax | ||
| 1259 | mov dx,word ptr [above_pid] | ||
| 1260 | mov ah,ABOVE_REALLOCATE_PID | ||
| 1261 | int 67h | ||
| 1262 | or ah,ah | ||
| 1263 | jnz real_fail | ||
| 1264 | ; | ||
| 1265 | ; Determine how many cache tracks will be lost | ||
| 1266 | ; | ||
| 1267 | mov bx,word ptr [sectrack] ; Init code checked for too large track | ||
| 1268 | mov cl,9 | ||
| 1269 | shl bx,cl ; BX has bytes/track | ||
| 1270 | mov ax,word ptr [ttracks] | ||
| 1271 | mul bx ; AX:DX has bytes used by tracks | ||
| 1272 | xchg ax,si | ||
| 1273 | mov di,dx | ||
| 1274 | mov cx,1024 | ||
| 1275 | mul cx ; AX:DX has total bytes allocated | ||
| 1276 | sub ax,si ; Find difference in allocated and used | ||
| 1277 | sbb dx,di | ||
| 1278 | xchg ax,si | ||
| 1279 | xchg dx,di | ||
| 1280 | pop ax ; AX still has requested reduction in K | ||
| 1281 | mul cx ; DX:AX has requested reduction in byte | ||
| 1282 | |||
| 1283 | ; | ||
| 1284 | ; Make sure the we have to free up tracks in order to satisfy the request | ||
| 1285 | ; HACK! HACK! HACK! Smartdrv should only allocate as many pages as it needs. | ||
| 1286 | ; ChipA 14-Mar-1988 | ||
| 1287 | ; | ||
| 1288 | cmp dx,di | ||
| 1289 | ja free_tracks | ||
| 1290 | jb no_need_to_free_tracks | ||
| 1291 | cmp ax,si | ||
| 1292 | ja free_tracks | ||
| 1293 | no_need_to_free_tracks: | ||
| 1294 | sub ax,ax | ||
| 1295 | mov dx,ax | ||
| 1296 | jmp all_freed | ||
| 1297 | |||
| 1298 | free_tracks: | ||
| 1299 | sub ax,si ; Account for part not used | ||
| 1300 | sbb dx,di | ||
| 1301 | div bx ; AX has number of tracks being "lost" | ||
| 1302 | or dx,dx | ||
| 1303 | jz no_remainder | ||
| 1304 | inc ax ; Add one more track if remainder | ||
| 1305 | ; | ||
| 1306 | ; Determine which cache control structures we are to remove | ||
| 1307 | ; | ||
| 1308 | no_remainder: | ||
| 1309 | mov si,ax | ||
| 1310 | mov cx,SIZE CACHE_CONTROL | ||
| 1311 | mul cx | ||
| 1312 | xchg ax,bx ; BX has backward offset into CCS's | ||
| 1313 | mov ax,word ptr [ttracks] | ||
| 1314 | sub word ptr [ttracks],si | ||
| 1315 | mul cx ; AX has end of Cache Control | ||
| 1316 | sub ax,bx ; AX has start offset of CCS's to remove | ||
| 1317 | mov cx,si ; CX has number of CCS's to remove | ||
| 1318 | mov si,word ptr [cache_control_ptr] | ||
| 1319 | add si,ax ; SI points to first CCS to modify | ||
| 1320 | ; | ||
| 1321 | ; Loop through each cache control structure, removing from LRU list | ||
| 1322 | ; | ||
| 1323 | remove_cache_entries: | ||
| 1324 | mov word ptr [si].track_flags,TRACK_FREE | ||
| 1325 | call unlink_cache | ||
| 1326 | add si,SIZE CACHE_CONTROL | ||
| 1327 | loop remove_cache_entries | ||
| 1328 | |||
| 1329 | all_freed: | ||
| 1330 | mov byte ptr [int_13_busy],0 | ||
| 1331 | jmp devexit | ||
| 1332 | |||
| 1333 | real_fail: | ||
| 1334 | pop ax | ||
| 1335 | mov [current_dev_size],si ; Restore former dev size | ||
| 1336 | mov byte ptr [int_13_busy],0 | ||
| 1337 | error_reduce_exit: | ||
| 1338 | mov al,0Ch ; General failure | ||
| 1339 | jmp err$cnt | ||
| 1340 | |||
| 1341 | |||
| 1342 | ;** ioctl_increase_cache_size Dynamically increase the size of the cache | ||
| 1343 | ; | ||
| 1344 | ; This routine dynamically increases the size of an Above Board memory (/A) | ||
| 1345 | ; cache. The routine is passed the number of pages that the cache should | ||
| 1346 | ; be increased by. The maximum size allowed is the size specified from the | ||
| 1347 | ; INT13.SYS command line. The cache control structures for the memory added | ||
| 1348 | ; to the cache are placed on the LRU list at the LRU position, so that they | ||
| 1349 | ; will be immediately available for incoming tracks. | ||
| 1350 | ; | ||
| 1351 | ; ENTRY: | ||
| 1352 | ; ES:DI is transfer address | ||
| 1353 | ; EXIT: | ||
| 1354 | ; Through one of the device exit paths | ||
| 1355 | ; USES: | ||
| 1356 | ; ALL | ||
| 1357 | ; | ||
| 1358 | error_increase_exitj: | ||
| 1359 | jmp error_increase_exit | ||
| 1360 | |||
| 1361 | ioctl_increase_cache_size: | ||
| 1362 | assume ds:Int13Code | ||
| 1363 | assume es:nothing | ||
| 1364 | assume ss:nothing | ||
| 1365 | |||
| 1366 | cmp [driver_sel],1 ; Make sure using Above Board | ||
| 1367 | jnz error_increase_exitj | ||
| 1368 | mov ax,es:[di.1] ; Get second byte | ||
| 1369 | mov cl,4 ; Multiply by 16 to get # of K bytes | ||
| 1370 | shl ax,cl ; AX has requested addition in K | ||
| 1371 | mov bx,word ptr [current_dev_size] | ||
| 1372 | mov si,bx ; Save current dev size for error | ||
| 1373 | add bx,ax ; BX now has new cache memory size in K | ||
| 1374 | cmp bx,[dev_size] ; Compare BX with largest size in K bytes | ||
| 1375 | jbe increase_size_ok | ||
| 1376 | mov bx, [dev_size] ; Go to MAX size | ||
| 1377 | mov ax, bx | ||
| 1378 | sub ax, si ; Correct increase | ||
| 1379 | increase_size_ok: | ||
| 1380 | mov word ptr [current_dev_size],bx | ||
| 1381 | shr bx,cl ; BX has new cache size in pages | ||
| 1382 | mov [int_13_busy],1 | ||
| 1383 | ; | ||
| 1384 | ; Request Reallocation of Pages from EMM | ||
| 1385 | ; | ||
| 1386 | push ax | ||
| 1387 | mov dx,[above_pid] | ||
| 1388 | mov ah,ABOVE_REALLOCATE_PID | ||
| 1389 | int 67h | ||
| 1390 | or ah,ah | ||
| 1391 | jnz realloc_fail | ||
| 1392 | ; | ||
| 1393 | ; Determine how many cache tracks will be gained | ||
| 1394 | ; | ||
| 1395 | mov bx,word ptr [sectrack] ; Init code checked for too large track | ||
| 1396 | mov cl,9 | ||
| 1397 | shl bx,cl ; BX has bytes/track | ||
| 1398 | mov ax,word ptr [ttracks] | ||
| 1399 | mul bx ; AX:DX has bytes used by tracks | ||
| 1400 | xchg ax,si | ||
| 1401 | mov di,dx | ||
| 1402 | mov cx,1024 | ||
| 1403 | mul cx ; AX:DX has total bytes allocated | ||
| 1404 | sub ax,si ; Find difference in allocated and used | ||
| 1405 | sbb dx,di | ||
| 1406 | xchg ax,si | ||
| 1407 | xchg dx,di | ||
| 1408 | pop ax ; AX still has requested reduction in K | ||
| 1409 | mul cx ; DX:AX has requested reduction in byte | ||
| 1410 | add ax,si ; Account for part not used | ||
| 1411 | adc dx,di | ||
| 1412 | div bx ; AX has number of tracks being "gained" | ||
| 1413 | or ax, ax ; DIV trashes flags | ||
| 1414 | jz nothing_to_gain | ||
| 1415 | ; | ||
| 1416 | ; Determine which cache control structures we are to add | ||
| 1417 | ; | ||
| 1418 | mov si,ax | ||
| 1419 | mov cx,SIZE CACHE_CONTROL | ||
| 1420 | mov ax,[ttracks] | ||
| 1421 | add [ttracks],si ; Update TTRACKS | ||
| 1422 | mul cx ; AX has end of Cache Control | ||
| 1423 | mov cx,si ; CX has number of CCS's to add | ||
| 1424 | mov si,[cache_control_ptr] | ||
| 1425 | add si,ax ; SI points to first CCS to modify | ||
| 1426 | ; | ||
| 1427 | ; Loop through each cache control structure, adding to LRU list | ||
| 1428 | ; | ||
| 1429 | add_cache_entries: | ||
| 1430 | mov di,si ; Place element at LRU position | ||
| 1431 | xchg di,[cache_tail] | ||
| 1432 | mov [di].fwd_lru_lnk,si | ||
| 1433 | mov [si].back_lru_lnk,di | ||
| 1434 | mov [si].fwd_lru_lnk,-1 | ||
| 1435 | mov [si].track_flags,TRACK_FREE | ||
| 1436 | |||
| 1437 | add si,SIZE CACHE_CONTROL | ||
| 1438 | loop add_cache_entries | ||
| 1439 | nothing_to_gain: | ||
| 1440 | mov [int_13_busy],0 | ||
| 1441 | jmp devexit | ||
| 1442 | |||
| 1443 | realloc_fail: | ||
| 1444 | pop ax | ||
| 1445 | mov [current_dev_size],si ; Restore to original size | ||
| 1446 | mov [int_13_busy],0 | ||
| 1447 | error_increase_exit: | ||
| 1448 | mov al,0Ch ; General failure | ||
| 1449 | jmp err$cnt | ||
| 1450 | |||
| 1451 | |||
| 1452 | ; | ||
| 1453 | ; If the device errors out during install, we set the break address here. | ||
| 1454 | ; | ||
| 1455 | ERROR_END LABEL BYTE | ||
| 1456 | |||
| 1457 | BREAK <INT 1C (timer) handler> | ||
| 1458 | |||
| 1459 | EVEN ; Force word align | ||
| 1460 | ; | ||
| 1461 | ; Storage for the INT 1C vector BEFORE cache installed | ||
| 1462 | ; | ||
| 1463 | OLD_1C DD ? | ||
| 1464 | |||
| 1465 | ;** INT_1C_HANDLER - Handler for INT 1C timer ticks | ||
| 1466 | ; | ||
| 1467 | ; ENTRY | ||
| 1468 | ; None | ||
| 1469 | ; | ||
| 1470 | ; EXIT | ||
| 1471 | ; To next 1C handler, EOI may be sent | ||
| 1472 | ; | ||
| 1473 | ; USES | ||
| 1474 | ; None | ||
| 1475 | ; | ||
| 1476 | ; SEE ALSO | ||
| 1477 | ; IBM PC TECH REF MANUAL section on INT 1C | ||
| 1478 | ; DOS PRINT utility (most of this is stolen from there) | ||
| 1479 | ; | ||
| 1480 | INT_1C_HANDLER PROC FAR | ||
| 1481 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 1482 | PUSH AX | ||
| 1483 | DEC [TICK_CNT] | ||
| 1484 | JNZ CHAIN_1C | ||
| 1485 | CMP [INT_13_BUSY],0 | ||
| 1486 | JZ TRY_FLSH | ||
| 1487 | RE_TRIGGER: | ||
| 1488 | INC [TICK_CNT] ; Set it back to 1 so next tick triggers | ||
| 1489 | CHAIN_1C: | ||
| 1490 | POP AX | ||
| 1491 | JMP [OLD_1C] | ||
| 1492 | |||
| 1493 | TRY_FLSH: | ||
| 1494 | mov al,00001011b ; Select ISR in 8259 | ||
| 1495 | out 20H,al | ||
| 1496 | jmp short yyyy | ||
| 1497 | yyyy: | ||
| 1498 | jmp short zzzz | ||
| 1499 | zzzz: | ||
| 1500 | in al,20H ; Get ISR register | ||
| 1501 | and al,0FEH ; Mask timer int | ||
| 1502 | jnz RE_TRIGGER ; Another int is in progress | ||
| 1503 | INC [INT_13_BUSY] ; Exclude | ||
| 1504 | CMP [DIRTY_CACHE],0 ; Anything to do? | ||
| 1505 | JZ SKIP_FLSH ; No | ||
| 1506 | STI | ||
| 1507 | mov al,20H | ||
| 1508 | out 20H,al | ||
| 1509 | CALL FLUSH_WHOLE_CACHE_SAV | ||
| 1510 | SKIP_FLSH: | ||
| 1511 | MOV AX,[TICK_SETTING] | ||
| 1512 | CLI | ||
| 1513 | MOV [TICK_CNT],AX | ||
| 1514 | MOV [INT_13_BUSY],0 | ||
| 1515 | JMP CHAIN_1C | ||
| 1516 | |||
| 1517 | INT_1C_HANDLER ENDP | ||
| 1518 | |||
| 1519 | BREAK <INT 13 handler> | ||
| 1520 | |||
| 1521 | |||
| 1522 | ; INT 13 stack frame | ||
| 1523 | ; | ||
| 1524 | STACK_FRAME STRUC | ||
| 1525 | USER_OFF DW ? ; added for user transfer address | ||
| 1526 | USER_ES DW ? | ||
| 1527 | USER_DS DW ? | ||
| 1528 | USER_DI DW ? | ||
| 1529 | USER_SI DW ? | ||
| 1530 | USER_BP DW ? | ||
| 1531 | DW ? | ||
| 1532 | USER_BX DW ? | ||
| 1533 | USER_DX DW ? | ||
| 1534 | USER_CX DW ? | ||
| 1535 | USER_AX DW ? | ||
| 1536 | USER_IP DW ? | ||
| 1537 | USER_CS DW ? | ||
| 1538 | USER_FL DW ? | ||
| 1539 | STACK_FRAME ENDS | ||
| 1540 | |||
| 1541 | EVEN ; Force word align | ||
| 1542 | ; | ||
| 1543 | ; Storage for the INT 13 vector BEFORE cache installed | ||
| 1544 | ; | ||
| 1545 | OLD_13 DD ? | ||
| 1546 | |||
| 1547 | ; | ||
| 1548 | ; Array of sec/track for all hardfiles on system. First element cooresponds | ||
| 1549 | ; to first hard file. | ||
| 1550 | ; Value = 0 indicates no hardfile | ||
| 1551 | ; | ||
| 1552 | SECTRKARRAY DB MAX_HARD_FILES DUP (0) | ||
| 1553 | ; | ||
| 1554 | ; ARRAY OF MAXIMUM USEABLE HEADS FOR ALL THE HARDFILES IN THE SYSTEM. FIRST | ||
| 1555 | ; ELEMENT CORRESPONDS TO FIRST HARDFILE. | ||
| 1556 | ; VALUE = FF INDICATES NO HARDFILE (SUNILP) | ||
| 1557 | ; | ||
| 1558 | HDARRAY DB MAX_HARD_FILES DUP (0FFH) | ||
| 1559 | |||
| 1560 | ifdef OMTI | ||
| 1561 | OMTI_SET_CYL EQU 0EEh | ||
| 1562 | OMTI_GET_CYL EQU 0FEh | ||
| 1563 | OMTI_GET_REV EQU 0F9h | ||
| 1564 | endif ;OMTI | ||
| 1565 | ; | ||
| 1566 | ; INT 13 function dispatch | ||
| 1567 | ; Addresses of routines for AH INT 13 functions | ||
| 1568 | ; | ||
| 1569 | INT13DISPATCH LABEL WORD | ||
| 1570 | DW POP_NO_PROC ; 0, reset | ||
| 1571 | DW POP_NO_PROC ; 1, Read status | ||
| 1572 | DW CACHE_READ ; 2, read | ||
| 1573 | DW CACHE_WRITE ; 3, write | ||
| 1574 | DW POP_NO_PROC ; 4, verify | ||
| 1575 | DW INVALID_PASS ; 5, format | ||
| 1576 | DW INVALID_PASS ; 6, format | ||
| 1577 | DW INVALID_PASS ; 7, format | ||
| 1578 | DW POP_NO_PROC ; 8, drive parms | ||
| 1579 | DW INVALID_PASS ; 9, Init drive characteristic | ||
| 1580 | DW INVALID_PASS ; A, Read long | ||
| 1581 | DW INVALID_PASS ; B, Write long | ||
| 1582 | DW POP_NO_PROC ; C, Seek | ||
| 1583 | DW POP_NO_PROC ; D, Alt reset | ||
| 1584 | DW INVALID_PASS ; E, Read buffer | ||
| 1585 | DW INVALID_PASS ; F, Write buffer | ||
| 1586 | DW POP_NO_PROC ; 10, Test drive rdy | ||
| 1587 | DW POP_NO_PROC ; 11, Recalibrate | ||
| 1588 | DW POP_NO_PROC ; 12, Controller diag | ||
| 1589 | DW INVALID_PASS ; 13, Drive diag | ||
| 1590 | DW POP_NO_PROC ; 14, Controller diag internal | ||
| 1591 | DW POP_NO_PROC ; 15, READ DASD | ||
| 1592 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 1593 | ; | ||
| 1594 | ; MODIFICATIONS TO DATA STRUCT TO SUPPORT MULTI-TRACK I/O | ||
| 1595 | ; | ||
| 1596 | ; sunilp | ||
| 1597 | ; | ||
| 1598 | ; extra declarations needed | ||
| 1599 | ; | ||
| 1600 | max_hd db ? ;maximum useable head number for curr. drive | ||
| 1601 | sect_in_trk db ? ;maximum sector number in trk for curr drive | ||
| 1602 | bytes_in_trk dw ? ;numb of bytes in trk for current drive | ||
| 1603 | int13err db ? | ||
| 1604 | ; | ||
| 1605 | TRUE = 0ffH | ||
| 1606 | FALSE = NOT TRUE | ||
| 1607 | REG1_P = 001B | ||
| 1608 | REG2_P = 010B | ||
| 1609 | REG3_P = 100B | ||
| 1610 | ; | ||
| 1611 | REG1t struc | ||
| 1612 | START_H db ? ;start head | ||
| 1613 | START_T dw ? ;start track | ||
| 1614 | COUNT dw ? ;number of words | ||
| 1615 | START_S dw ? ;start sector | ||
| 1616 | REG1t ends | ||
| 1617 | ; | ||
| 1618 | REG2t struc | ||
| 1619 | db ? ;start head | ||
| 1620 | dw ? ;start track | ||
| 1621 | TRACKS db ? ;number of tracks | ||
| 1622 | REG2t ends | ||
| 1623 | ; | ||
| 1624 | REG3t struc | ||
| 1625 | db ? ;start head | ||
| 1626 | dw ? ;start track | ||
| 1627 | dw ? ;number of words | ||
| 1628 | REG3t ends | ||
| 1629 | ; | ||
| 1630 | REGIONt struc | ||
| 1631 | FLAG db 0 | ||
| 1632 | REG1 db size REG1t dup(?) | ||
| 1633 | REG2 db size REG2t dup(?) | ||
| 1634 | REG3 db size REG3t dup(?) | ||
| 1635 | REGIONt ends | ||
| 1636 | ; | ||
| 1637 | ; | ||
| 1638 | REGION db size REGIONt dup(?) | ||
| 1639 | ; | ||
| 1640 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 1641 | ; | ||
| 1642 | ; INT_13_HANDLER - Handler for INT 13 requests | ||
| 1643 | ; | ||
| 1644 | ; ENTRY | ||
| 1645 | ; All regs as for INT 13 | ||
| 1646 | ; | ||
| 1647 | ; EXIT | ||
| 1648 | ; To old INT 13 handler with regs unchanged if cache not involved | ||
| 1649 | ; Else return in AH and flags as per INT 13. | ||
| 1650 | ; | ||
| 1651 | ; USES | ||
| 1652 | ; AH and carry bit of FLAGS | ||
| 1653 | ; | ||
| 1654 | ; SEE ALSO | ||
| 1655 | ; IBM PC TECH REF MANUAL section on INT 13 | ||
| 1656 | ; | ||
| 1657 | INT_13_HANDLER PROC FAR | ||
| 1658 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 1659 | MOV [INT_13_BUSY],1 ; Exclude | ||
| 1660 | TEST DL,80H ; Hard file? | ||
| 1661 | JNZ IS_HARD ; Yes | ||
| 1662 | NO_PROC: | ||
| 1663 | PUSHF | ||
| 1664 | CLI | ||
| 1665 | CALL [OLD_13] ; Let old handler do it | ||
| 1666 | MOV [INT_13_BUSY],0 ; Clear sem | ||
| 1667 | RET 2 ; "IRET" chucking flags | ||
| 1668 | |||
| 1669 | ; | ||
| 1670 | ; Pop off the stack frame and pass to old handler | ||
| 1671 | ; | ||
| 1672 | POP_NO_PROC: | ||
| 1673 | POP BX | ||
| 1674 | POP ES | ||
| 1675 | POP DS | ||
| 1676 | ; Simulate POPA | ||
| 1677 | POP DI | ||
| 1678 | POP SI | ||
| 1679 | POP BP | ||
| 1680 | POP BX ; Dummy for pop sp | ||
| 1681 | POP BX | ||
| 1682 | POP DX | ||
| 1683 | POP CX | ||
| 1684 | POP AX | ||
| 1685 | ; | ||
| 1686 | JMP NO_PROC | ||
| 1687 | |||
| 1688 | IS_HARD: | ||
| 1689 | STI ; INTs ok now | ||
| 1690 | ; | ||
| 1691 | ; Set up standard stack frame | ||
| 1692 | ; | ||
| 1693 | ; Simulate PUSHA | ||
| 1694 | PUSH AX | ||
| 1695 | PUSH CX | ||
| 1696 | PUSH DX | ||
| 1697 | PUSH BX | ||
| 1698 | PUSH BX ; dummy for push sp | ||
| 1699 | PUSH BP | ||
| 1700 | PUSH SI | ||
| 1701 | PUSH DI | ||
| 1702 | ; | ||
| 1703 | PUSH DS | ||
| 1704 | PUSH ES | ||
| 1705 | push bx | ||
| 1706 | ; Set frame pointer | ||
| 1707 | MOV BP,SP | ||
| 1708 | MOV BL,AH | ||
| 1709 | XOR BH,BH ; Command in BX | ||
| 1710 | PUSH CS | ||
| 1711 | POP DS | ||
| 1712 | ASSUME DS:INT13CODE | ||
| 1713 | CMP [ENABLE_13],0 ; Are we enabled? | ||
| 1714 | JZ POP_NO_PROC ; No, ignore | ||
| 1715 | |||
| 1716 | ifdef OMTI | ||
| 1717 | ; | ||
| 1718 | ; The following code is used to handle the extended cylinder access method | ||
| 1719 | ; used by the OMTI controller. This controller has a modified INT13 routine | ||
| 1720 | ; that uses a unique function number to tell the controller that the next | ||
| 1721 | ; access to INT13 is for an extended cylinder. | ||
| 1722 | ; | ||
| 1723 | test sys_flg,OMTI_EXT ; Are we in extended state? | ||
| 1724 | jnz in_extended_state | ||
| 1725 | cmp bx,OMTI_SET_CYL ; Is this the OMTI extended function? | ||
| 1726 | jnz check_command_range | ||
| 1727 | or sys_flg,OMTI_EXT | ||
| 1728 | jmp pop_no_proc | ||
| 1729 | in_extended_state: | ||
| 1730 | ; | ||
| 1731 | ; If we are in the extended state, we want to make sure that this call | ||
| 1732 | ; does not go through into the cache. Therefore, we will check to see | ||
| 1733 | ; if this is a read or write function, and will return to the old INT13 | ||
| 1734 | ; routine if so. | ||
| 1735 | ; | ||
| 1736 | and sys_flg,NOT OMTI_EXT ; Clear the extended flag | ||
| 1737 | cmp bx,2h ; READ | ||
| 1738 | jz pop_no_proc | ||
| 1739 | cmp bx,3h ; WRITE | ||
| 1740 | jz pop_no_proc | ||
| 1741 | check_command_range: | ||
| 1742 | ; | ||
| 1743 | ; Allow the other OMTI functions to pass through | ||
| 1744 | ; | ||
| 1745 | cmp bx,OMTI_GET_CYL | ||
| 1746 | jz pop_no_proc | ||
| 1747 | cmp bx,OMTI_GET_REV | ||
| 1748 | jz pop_no_proc | ||
| 1749 | endif ; OMTI | ||
| 1750 | |||
| 1751 | CMP BX,15H ; Command in range? | ||
| 1752 | JA INVALID_PASS ; No, throw out cache | ||
| 1753 | SHL BX,1 ; Times two bytes per table entry | ||
| 1754 | JMP [BX.INT13DISPATCH] ; Dispatch to handler | ||
| 1755 | |||
| 1756 | ;** FLUSH_INVALID_PASS -- Discard cache and pass through | ||
| 1757 | ; | ||
| 1758 | ; ENTRY: | ||
| 1759 | ; INT 13 regs except for BP,BX and DS | ||
| 1760 | ; EXIT: | ||
| 1761 | ; To old INT13 handler | ||
| 1762 | ; | ||
| 1763 | FLUSH_INVALID_PASS: | ||
| 1764 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1765 | CALL FLUSH_WHOLE_CACHE | ||
| 1766 | CALL INVALIDATE_CACHE | ||
| 1767 | JMP POP_NO_PROC | ||
| 1768 | |||
| 1769 | ;** INVALID_PASS -- DISCARD CACHE, NO NEED TO FLUSH, PASS THROUGH | ||
| 1770 | ; | ||
| 1771 | ;** SUNIL PAI | ||
| 1772 | ; | ||
| 1773 | ; ENTRY: | ||
| 1774 | ; INT 13 regs except for BP,BX and DS | ||
| 1775 | ; EXIT: | ||
| 1776 | ; To old INT 13 handler | ||
| 1777 | ; | ||
| 1778 | INVALID_PASS: | ||
| 1779 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1780 | CALL INVALIDATE_CACHE | ||
| 1781 | JMP POP_NO_PROC | ||
| 1782 | |||
| 1783 | ;** FLUSH_PASS -- Flush cache (but retain data) and pass through | ||
| 1784 | ; | ||
| 1785 | ; ENTRY: | ||
| 1786 | ; INT 13 regs except for BP,BX and DS | ||
| 1787 | ; EXIT: | ||
| 1788 | ; To old INT13 handler | ||
| 1789 | ; | ||
| 1790 | FLUSH_PASS: | ||
| 1791 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1792 | CALL FLUSH_WHOLE_CACHE | ||
| 1793 | JMP POP_NO_PROC | ||
| 1794 | |||
| 1795 | BREAK <CACHE_READ -- Read via cache> | ||
| 1796 | |||
| 1797 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 1798 | ; | ||
| 1799 | cache_read: | ||
| 1800 | ; | ||
| 1801 | ; inputs: int13 regs except for bp - user stack frame | ||
| 1802 | ; bx - function (read,write) | ||
| 1803 | ; ds - int13code segment | ||
| 1804 | ; | ||
| 1805 | ; exits: to user success routine | ||
| 1806 | ; to user error routine | ||
| 1807 | ; to old int13 handler call | ||
| 1808 | ; | ||
| 1809 | ; uses: all but bp | ||
| 1810 | ; | ||
| 1811 | ; written by: sunil pai | ||
| 1812 | ; | ||
| 1813 | call check_parameters ; check user params | ||
| 1814 | jc pop_no_proc ; if error go to old int 13 handler | ||
| 1815 | ; | ||
| 1816 | call process_regions ; for multi-track business find the | ||
| 1817 | ; initial partial track, middle block | ||
| 1818 | ; and final partial track | ||
| 1819 | ; sets up REGION struct | ||
| 1820 | ; | ||
| 1821 | ; mov [int13err],FALSE ; clear int 13 error flag | ||
| 1822 | ; | ||
| 1823 | test [REGION.FLAG],REG1_P ; is region1 present | ||
| 1824 | je cr$2 ; if not present try region2 | ||
| 1825 | ; | ||
| 1826 | mov dh,[REGION.REG1.START_H] ;start head | ||
| 1827 | mov cx,[REGION.REG1.START_T] ;get start track | ||
| 1828 | mov bx,[REGION.REG1.START_S] ;start sector | ||
| 1829 | mov ax,[REGION.REG1.COUNT] ;number of words | ||
| 1830 | call process_read_partial ; | ||
| 1831 | jc error ;go to process error | ||
| 1832 | ; | ||
| 1833 | cr$2: test [REGION.FLAG],REG2_P ; is region2 present | ||
| 1834 | je cr$3 ; if not present try region3 | ||
| 1835 | ; | ||
| 1836 | mov dh,[REGION.REG2.START_H] ; get start head | ||
| 1837 | mov cx,[REGION.REG2.START_T] ; get start track | ||
| 1838 | mov al,[REGION.REG2.TRACKS] ; get number of tracks | ||
| 1839 | call process_block_read ; multi track capability | ||
| 1840 | jc error ; fouled? | ||
| 1841 | ; | ||
| 1842 | cr$3: test [REGION.FLAG],REG3_P ; is region3 present | ||
| 1843 | je suc ; if not we are done | ||
| 1844 | ; | ||
| 1845 | mov dh,[REGION.REG3.START_H] ; start head | ||
| 1846 | mov cx,[REGION.REG3.START_T] ; start track | ||
| 1847 | mov bx,1 ; start sector is 1 | ||
| 1848 | mov ax,[REGION.REG3.COUNT] ; number of words | ||
| 1849 | call process_read_partial ; | ||
| 1850 | jc error ; just as we were about to fin! | ||
| 1851 | ; | ||
| 1852 | ; exit points - suc and error. | ||
| 1853 | ; | ||
| 1854 | suc: and [bp.USER_FL],NOT f_Carry ; | ||
| 1855 | mov byte ptr [bp.USER_AX.1],0 ; | ||
| 1856 | ; | ||
| 1857 | operation_done: | ||
| 1858 | mov cs:[int_13_busy],0 ;clear semaphore | ||
| 1859 | pop bx ;user offset | ||
| 1860 | ; | ||
| 1861 | ; simulate popa | ||
| 1862 | ; | ||
| 1863 | pop es | ||
| 1864 | pop ds | ||
| 1865 | pop di | ||
| 1866 | pop si | ||
| 1867 | pop bp | ||
| 1868 | pop bx | ||
| 1869 | pop bx | ||
| 1870 | pop dx | ||
| 1871 | pop cx | ||
| 1872 | pop ax | ||
| 1873 | ; | ||
| 1874 | iret | ||
| 1875 | ; | ||
| 1876 | error: | ||
| 1877 | ; | ||
| 1878 | ; the next two instructions were removed because of the way Compaq | ||
| 1879 | ; handles bad sectors. they mark sectors bad not tracks. so in a | ||
| 1880 | ; track there may be good and bad sectors. However our int13 caching | ||
| 1881 | ; system does i/o from disk in tracks and will not get any track with | ||
| 1882 | ; bad sectors. to take care of this, we pass the read to the old int13 | ||
| 1883 | ; handler even when there is an int 13 error | ||
| 1884 | ; | ||
| 1885 | ; test [int13err],TRUE | ||
| 1886 | ; jne er$1 ;if not int13 error go to call | ||
| 1887 | ;int13 | ||
| 1888 | jmp pop_no_proc | ||
| 1889 | ;er$1: or [bp.USER_FL],f_Carry ; | ||
| 1890 | ; mov byte ptr [bp.USER_AX.1],AL ;int13 error code | ||
| 1891 | ; jmp operation_done | ||
| 1892 | ; | ||
| 1893 | pop_no_procw: | ||
| 1894 | call invalidate_cache | ||
| 1895 | jmp pop_no_proc | ||
| 1896 | ; | ||
| 1897 | cache_write: | ||
| 1898 | ; | ||
| 1899 | ; inputs: int13 regs except for bp - user stack frame | ||
| 1900 | ; bx - function (read,write) | ||
| 1901 | ; ds - int13code segment | ||
| 1902 | ; | ||
| 1903 | ; uses: all but bp | ||
| 1904 | ; | ||
| 1905 | ; written by: sunil pai | ||
| 1906 | ; | ||
| 1907 | call check_parameters ;check user params | ||
| 1908 | jc pop_no_procw ;error | ||
| 1909 | ; | ||
| 1910 | call process_regions ;for multi-track business find the | ||
| 1911 | ;initial partial track, middle block | ||
| 1912 | ;and final partial track | ||
| 1913 | ;sets up REGION struct | ||
| 1914 | ; | ||
| 1915 | ; writes always update disk, i.e., write through always operational | ||
| 1916 | ; | ||
| 1917 | mov ax,[bp.user_ax] ; restore int13 registers | ||
| 1918 | mov cx,[bp.user_cx] ; | ||
| 1919 | mov dx,[bp.user_dx] ; | ||
| 1920 | mov bx,[bp.user_bx] ; | ||
| 1921 | mov es,[bp.user_es] ; | ||
| 1922 | pushf ; since interrupt routine being called | ||
| 1923 | cli | ||
| 1924 | call [old_13] ; call old int 13 handler | ||
| 1925 | jnc cw$1 ; no error in writing to disk, continue | ||
| 1926 | ; | ||
| 1927 | or [bp.user_fl],f_Carry ; error then set carry | ||
| 1928 | mov byte ptr [bp.user_ax.1],ah ; and error code | ||
| 1929 | jmp short errorw ; and take error exit | ||
| 1930 | ; | ||
| 1931 | ; int 13 was successful, now we have to update cache as well | ||
| 1932 | ; | ||
| 1933 | cw$1: and [bp.user_fl],not f_Carry ; int 13 success | ||
| 1934 | mov byte ptr [bp.user_ax.1],0 ; | ||
| 1935 | ; | ||
| 1936 | and dl,not 80h | ||
| 1937 | ; | ||
| 1938 | test [REGION.FLAG],REG1_P ; is region1 present | ||
| 1939 | je cw$2 ; if not present try region2 | ||
| 1940 | ; | ||
| 1941 | mov dh,[REGION.REG1.START_H] ; get start head | ||
| 1942 | mov cx,[REGION.REG1.START_T] ; get start track | ||
| 1943 | mov bx,[REGION.REG1.START_S] ; start sector | ||
| 1944 | mov ax,[REGION.REG1.COUNT] ; number of words | ||
| 1945 | call process_write_partial ; partial write | ||
| 1946 | jc errorw ; go to process error | ||
| 1947 | ; | ||
| 1948 | cw$2: test [REGION.FLAG],REG2_P ; is region2 present | ||
| 1949 | je cw$3 ; if not present try region3 | ||
| 1950 | ; | ||
| 1951 | mov dh,[REGION.REG2.START_H] ; get start head | ||
| 1952 | mov cx,[REGION.REG2.START_T] ; get start track | ||
| 1953 | mov al,[REGION.REG2.TRACKS] ; get number of tracks | ||
| 1954 | call process_block_write ; | ||
| 1955 | jc errorw ; fouled? | ||
| 1956 | ; | ||
| 1957 | cw$3: test [REGION.FLAG],REG3_P ; is region3 present | ||
| 1958 | je operation_donew ; if not we are done | ||
| 1959 | ; | ||
| 1960 | mov dh,[REGION.REG3.START_H] ; start head | ||
| 1961 | mov cx,[REGION.REG3.START_T] ; start track | ||
| 1962 | mov bx,1 ; start sector is 1 | ||
| 1963 | mov ax,[REGION.REG3.COUNT] ; number of words | ||
| 1964 | call process_write_partial ; | ||
| 1965 | jnc operation_donew ; no error - finish | ||
| 1966 | ; | ||
| 1967 | errorw: call invalidate_cache ; we are not sure of the | ||
| 1968 | operation_donew: | ||
| 1969 | jmp operation_done | ||
| 1970 | ; | ||
| 1971 | ; | ||
| 1972 | INT_13_HANDLER endp | ||
| 1973 | ; | ||
| 1974 | process_read_partial proc near | ||
| 1975 | ; | ||
| 1976 | ; is used to read a partial track | ||
| 1977 | ; | ||
| 1978 | ; inputs: dx: head and drive (8th bit stripped) | ||
| 1979 | ; cx: track | ||
| 1980 | ; bx: start sector | ||
| 1981 | ; ax: number of words | ||
| 1982 | ; | ||
| 1983 | ; outputs:cy set if error | ||
| 1984 | ; clear if success | ||
| 1985 | ; | ||
| 1986 | ; strategy: | ||
| 1987 | ; if (track in cache) then { | ||
| 1988 | ; if (track in track_buffer) then | ||
| 1989 | ; perform user read from track buffer; | ||
| 1990 | ; else | ||
| 1991 | ; perform user read from cache; | ||
| 1992 | ; } | ||
| 1993 | ; else { | ||
| 1994 | ; read track into track buffer; | ||
| 1995 | ; read track buffer into cache; | ||
| 1996 | ; perform user read from track buffer; | ||
| 1997 | ; } | ||
| 1998 | ; | ||
| 1999 | ; cache transfers handled by freeing cache element if possible | ||
| 2000 | ; and making it lru | ||
| 2001 | ; | ||
| 2002 | ; uses: only dx assumed unchanged | ||
| 2003 | ; | ||
| 2004 | call track_in_cache ; is track in cache | ||
| 2005 | jc read_disk ; if not we have to read from disk | ||
| 2006 | ; | ||
| 2007 | cmp cx,[track_buffer_cyln] ; is it in the track buffer | ||
| 2008 | jnz not_in_mem ; no | ||
| 2009 | cmp dx,[track_buffer_hddr] ; | ||
| 2010 | jz read_bufferj ; yes | ||
| 2011 | ; | ||
| 2012 | ; read buffer from cache | ||
| 2013 | ; | ||
| 2014 | not_in_mem: | ||
| 2015 | push dx | ||
| 2016 | xchg ax,bx ;get number of words in bx and start sect in ax | ||
| 2017 | dec ax ;0 based number | ||
| 2018 | mov cl,9 ; | ||
| 2019 | shl ax,cl ;byte offset | ||
| 2020 | xor dx,dx ; | ||
| 2021 | ; | ||
| 2022 | mov cx,bx ;number of words | ||
| 2023 | mov es,[bp.user_es] ; | ||
| 2024 | mov di,[bp.user_off]; | ||
| 2025 | shl bx,1 ; number of bytes | ||
| 2026 | add [bp.user_off],bx ; update user offset | ||
| 2027 | ; | ||
| 2028 | add ax,word ptr [si.base_offset] | ||
| 2029 | adc dx,word ptr [si.base_offset.2] | ||
| 2030 | xor bh,bh | ||
| 2031 | push si | ||
| 2032 | push ds | ||
| 2033 | push bp | ||
| 2034 | call blkmov | ||
| 2035 | pop bp | ||
| 2036 | pop ds | ||
| 2037 | pop si | ||
| 2038 | pop dx | ||
| 2039 | jc err_cache | ||
| 2040 | call cache_is_mru | ||
| 2041 | clc | ||
| 2042 | ret | ||
| 2043 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2044 | ; | ||
| 2045 | ; track not in cache. see if free cache available to initiate transfer | ||
| 2046 | ; | ||
| 2047 | read_disk: | ||
| 2048 | cmp di,-1 ;free cache | ||
| 2049 | jnz rd_part ;if present we can initiate read | ||
| 2050 | stc ; else error exit | ||
| 2051 | ret | ||
| 2052 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2053 | ; | ||
| 2054 | read_bufferj: | ||
| 2055 | jmp short read_buffer | ||
| 2056 | ; | ||
| 2057 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2058 | ; | ||
| 2059 | ; cache element available. we can start by transferring track from disk | ||
| 2060 | ; to track buffer. | ||
| 2061 | ; | ||
| 2062 | rd_part: | ||
| 2063 | mov si,di ;get element in si | ||
| 2064 | mov [track_buffer_cyln],-1 ;invalidate present track buffer | ||
| 2065 | mov [track_buffer_hddr],-1 | ||
| 2066 | mov [si.track_flags],track_free ;if read fails | ||
| 2067 | push dx | ||
| 2068 | push cx | ||
| 2069 | push bx | ||
| 2070 | push ax | ||
| 2071 | or cl,1 | ||
| 2072 | or dl,80h | ||
| 2073 | mov al,[sect_in_trk] | ||
| 2074 | mov ah,2 ; read | ||
| 2075 | push cs | ||
| 2076 | pop es | ||
| 2077 | mov bx,[track_buffer_ptr] | ||
| 2078 | pushf | ||
| 2079 | cli | ||
| 2080 | call [old_13] | ||
| 2081 | jnc rd$1 | ||
| 2082 | cmp ah,11h ;the int13 error which is not an error | ||
| 2083 | je rd$1 | ||
| 2084 | mov [int13err],TRUE | ||
| 2085 | add sp,8 | ||
| 2086 | mov al,ah | ||
| 2087 | stc | ||
| 2088 | ret | ||
| 2089 | ; | ||
| 2090 | ; transfer track buffer to cache | ||
| 2091 | ; | ||
| 2092 | rd$1: | ||
| 2093 | mov di,[track_buffer_ptr] ;es:di is transfer address | ||
| 2094 | mov cx,[bytes_in_trk] | ||
| 2095 | shr cx,1 ; cx is number words in track | ||
| 2096 | mov bh,1 ;write | ||
| 2097 | mov ax,word ptr [si.base_offset] ;address of cache | ||
| 2098 | mov dx,word ptr [si.base_offset.2] ; | ||
| 2099 | push ds | ||
| 2100 | push si | ||
| 2101 | push bp | ||
| 2102 | call blkmov | ||
| 2103 | pop bp | ||
| 2104 | pop si | ||
| 2105 | pop ds | ||
| 2106 | pop ax | ||
| 2107 | pop bx | ||
| 2108 | pop cx | ||
| 2109 | pop dx | ||
| 2110 | jnc rd$2 | ||
| 2111 | ; | ||
| 2112 | ; error in transferring info to cache. invalidate cache element and | ||
| 2113 | ; make it lru | ||
| 2114 | ; | ||
| 2115 | err_cache: | ||
| 2116 | mov [si.track_flags],track_free | ||
| 2117 | call cache_is_lru ; make cache element lru | ||
| 2118 | stc | ||
| 2119 | ret | ||
| 2120 | ; | ||
| 2121 | ; info transfer to cache successful. fill in track, head and drive | ||
| 2122 | ; info into cache control element and track buffer control element | ||
| 2123 | ; | ||
| 2124 | if debug | ||
| 2125 | rd_2: | ||
| 2126 | endif | ||
| 2127 | rd$2: | ||
| 2128 | mov word ptr [si.track_cyln],cx | ||
| 2129 | mov word ptr [si.track_drive],dx | ||
| 2130 | and [si.track_flags], not track_free | ||
| 2131 | mov word ptr [track_buffer_cyln],cx | ||
| 2132 | mov word ptr [track_buffer_hddr],dx | ||
| 2133 | ; | ||
| 2134 | ; perform user i/o from track buffer | ||
| 2135 | ; | ||
| 2136 | read_buffer: | ||
| 2137 | call cache_is_mru | ||
| 2138 | ; | ||
| 2139 | mov si,bx ; start sector | ||
| 2140 | dec si ; 0 based number | ||
| 2141 | mov cl,9 ; | ||
| 2142 | shl si,cl ; byte offset in si | ||
| 2143 | add si,[track_buffer_ptr] | ||
| 2144 | mov cx,ax | ||
| 2145 | mov es,[bp.user_es] | ||
| 2146 | mov di,[bp.user_off] | ||
| 2147 | cld | ||
| 2148 | rep movsw | ||
| 2149 | mov [bp.user_off],di | ||
| 2150 | clc | ||
| 2151 | ret | ||
| 2152 | ; | ||
| 2153 | process_read_partial endp | ||
| 2154 | ; | ||
| 2155 | process_block_read proc near | ||
| 2156 | ; | ||
| 2157 | ; inputs: ax = number of tracks | ||
| 2158 | ; dx = drive and head (8th bit stripped) | ||
| 2159 | ; cx = start track | ||
| 2160 | ; bp = user stack frame | ||
| 2161 | ; | ||
| 2162 | ; outputs: cy set if error | ||
| 2163 | ; cy clear if okay | ||
| 2164 | ; | ||
| 2165 | ; algorithm: | ||
| 2166 | ; | ||
| 2167 | ; repeat | ||
| 2168 | ; if (cur_trk in cache) then | ||
| 2169 | ; transfer track from cache to user buffer; | ||
| 2170 | ; no_of_trks = no_of_trks - 1 | ||
| 2171 | ; else | ||
| 2172 | ; accumulate tracks which are not in cache | ||
| 2173 | ; read these in one disk operation | ||
| 2174 | ; transfer these from user buffer to cache | ||
| 2175 | ; no_of_trks = no_of_trks - accumulated_trks | ||
| 2176 | ; until no_of_trks == 0 | ||
| 2177 | ; | ||
| 2178 | pbr$1: | ||
| 2179 | ; | ||
| 2180 | ; since we are going to look ahead and see how many tracks can | ||
| 2181 | ; be dealt with together, we have to save start head and track | ||
| 2182 | ; | ||
| 2183 | push cx ; save start head | ||
| 2184 | push dx ; save start track | ||
| 2185 | xor ah,ah ;number of accumulated tracks | ||
| 2186 | pbr$2: call track_in_cache ; | ||
| 2187 | jnc pbr$4 ; if current track in cache start processing | ||
| 2188 | inc dh ; go to next track | ||
| 2189 | call adj_hd_trk ; | ||
| 2190 | inc ah ;accumulate the tracks | ||
| 2191 | dec al ;are we done | ||
| 2192 | jne pbr$2 ;go to see next track | ||
| 2193 | pop dx ;restore start head and track | ||
| 2194 | pop cx ; | ||
| 2195 | call pr_acc_trks ;process the accumulated tracks | ||
| 2196 | ret ;we are done | ||
| 2197 | pbr$4: | ||
| 2198 | pop dx ;restore start head and track | ||
| 2199 | pop cx | ||
| 2200 | or ah,ah ;are there any accumulated | ||
| 2201 | je pbr$5 | ||
| 2202 | call pr_acc_trks ;process the accumulated tracks | ||
| 2203 | jc pbr$7 ;if carry set finish with error | ||
| 2204 | add dh,ah ;adjust track and head | ||
| 2205 | call adj_hd_trk | ||
| 2206 | jmp pbr$1 | ||
| 2207 | ; | ||
| 2208 | pbr$5: call pr_cur_trk ;process current track which is in cache | ||
| 2209 | jc pbr$7 ;if carry set finish with error | ||
| 2210 | inc dh | ||
| 2211 | call adj_hd_trk | ||
| 2212 | pbr$6: | ||
| 2213 | dec al ;are we done? | ||
| 2214 | jne pbr$1 ; | ||
| 2215 | clc | ||
| 2216 | pbr$7: ret | ||
| 2217 | ; | ||
| 2218 | process_block_read endp | ||
| 2219 | ; | ||
| 2220 | pr_acc_trks proc near | ||
| 2221 | ; | ||
| 2222 | ; inputs: cx = start track | ||
| 2223 | ; dh = start head | ||
| 2224 | ; ah = number of accumulated tracks | ||
| 2225 | ; | ||
| 2226 | ; outputs: if success :- cy clear, [bp.user_off] modified | ||
| 2227 | ; if failure :- cy set | ||
| 2228 | ; | ||
| 2229 | ; regs to be preserved: al,cx,si | ||
| 2230 | ; | ||
| 2231 | ; algorithm: | ||
| 2232 | ; | ||
| 2233 | ; read buffer from disk; | ||
| 2234 | ; for (cur_trk=start_trk,transfer_off=user_off; no_of_trks-- > 0; | ||
| 2235 | ; transfer_off=transfer_off+size_of_trk) do | ||
| 2236 | ; if ((cache=get_cache())!=-1) then | ||
| 2237 | ; transfer_trk_to_cache; | ||
| 2238 | ; else | ||
| 2239 | ; exit with error; | ||
| 2240 | ; | ||
| 2241 | ; | ||
| 2242 | push si | ||
| 2243 | push dx | ||
| 2244 | push cx | ||
| 2245 | push ax ; stack:- {ax,cx,dx,si} | ||
| 2246 | ; | ||
| 2247 | ; initialise int13 registers for reading the accumulated tracks into | ||
| 2248 | ; user memory. | ||
| 2249 | ; | ||
| 2250 | mov al,ah ;number of tracks | ||
| 2251 | xor ah,ah ;in ax | ||
| 2252 | ; | ||
| 2253 | mul [sect_in_trk] ;get number of sectors in ax | ||
| 2254 | ; | ||
| 2255 | mov ah,2 | ||
| 2256 | or cx,1 ;start sector | ||
| 2257 | ; | ||
| 2258 | or dl,80h ;set hard disk bit | ||
| 2259 | mov bx,[bp.user_off]; | ||
| 2260 | mov es,[bp.user_es] ; | ||
| 2261 | ; | ||
| 2262 | pushf | ||
| 2263 | cli | ||
| 2264 | call [old_13] ;perform multi track read | ||
| 2265 | ; | ||
| 2266 | ; check for int 13 error | ||
| 2267 | ; | ||
| 2268 | jnc pat$1 ;if okay proceed | ||
| 2269 | ; | ||
| 2270 | add sp,8 ;clear stack | ||
| 2271 | mov al,ah | ||
| 2272 | mov [int13err],TRUE ; | ||
| 2273 | stc | ||
| 2274 | ret ;error exit | ||
| 2275 | ; | ||
| 2276 | ; we have succesfully read al tracks into user memory. now these have | ||
| 2277 | ; to transfer these to cache. | ||
| 2278 | ; | ||
| 2279 | pat$1: and dl,not 80h ;clear off 8th bit | ||
| 2280 | pop ax ;restore ax | ||
| 2281 | pop cx ; | ||
| 2282 | push cx ; | ||
| 2283 | push ax | ||
| 2284 | ; | ||
| 2285 | mov di,[bp.user_off];initialise transfer offset | ||
| 2286 | ; | ||
| 2287 | ; ah has number of tracks still left to be transferred | ||
| 2288 | ; di has transfer offset | ||
| 2289 | ; cx has current track number | ||
| 2290 | ; dx has current drive and head | ||
| 2291 | ; | ||
| 2292 | pat$2: | ||
| 2293 | call get_cache ;get free cache element | ||
| 2294 | ; | ||
| 2295 | ; si = cache element | ||
| 2296 | ; | ||
| 2297 | cmp si,-1 ;was there an element | ||
| 2298 | je pat$5 ;cache saturated exit | ||
| 2299 | ; | ||
| 2300 | ; check if track is in track buffer | ||
| 2301 | ; | ||
| 2302 | cmp cx,[track_buffer_cyln] | ||
| 2303 | jne pat$21 | ||
| 2304 | cmp dx,[track_buffer_hddr] | ||
| 2305 | jne pat$21 | ||
| 2306 | ; | ||
| 2307 | ; track is in track buffer. to avoid two transfers invalidate | ||
| 2308 | ; track buffer | ||
| 2309 | ; | ||
| 2310 | mov [track_buffer_cyln],-1 | ||
| 2311 | mov [track_buffer_hddr],-1 | ||
| 2312 | ; | ||
| 2313 | ; transfer track from user buffer to cache | ||
| 2314 | ; | ||
| 2315 | pat$21: mov [si.track_flags],track_free ;if write fails | ||
| 2316 | push cx | ||
| 2317 | push ax | ||
| 2318 | push ds | ||
| 2319 | push si | ||
| 2320 | push bp | ||
| 2321 | push di | ||
| 2322 | push dx | ||
| 2323 | ; | ||
| 2324 | mov es,[bp.user_es] | ||
| 2325 | mov cx,[bytes_in_trk] | ||
| 2326 | shr cx,1 ;words | ||
| 2327 | mov ax,word ptr [si.base_offset] | ||
| 2328 | mov dx,word ptr [si.base_offset.2] | ||
| 2329 | mov bh,1 ;write | ||
| 2330 | call blkmov | ||
| 2331 | ; | ||
| 2332 | pop dx | ||
| 2333 | pop di | ||
| 2334 | pop bp | ||
| 2335 | pop si | ||
| 2336 | pop ds | ||
| 2337 | pop ax | ||
| 2338 | pop cx | ||
| 2339 | ; | ||
| 2340 | jnc pat$3 | ||
| 2341 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2342 | ; error in transferring information to cache. make it lru | ||
| 2343 | ; | ||
| 2344 | ; | ||
| 2345 | call cache_is_lru | ||
| 2346 | pat$5: | ||
| 2347 | add sp,8 | ||
| 2348 | stc | ||
| 2349 | ret ;cache error exit | ||
| 2350 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 2351 | ; | ||
| 2352 | ; successfully transferred information to cache. fill in track and | ||
| 2353 | ; drive and head information into cache control element | ||
| 2354 | ; | ||
| 2355 | pat$3: mov word ptr [si.track_cyln],cx | ||
| 2356 | mov word ptr [si.track_drive],dx | ||
| 2357 | and [si.track_flags],not track_free | ||
| 2358 | call cache_is_mru | ||
| 2359 | |||
| 2360 | ; | ||
| 2361 | add di,[bytes_in_trk] ;advance pointer in user transfer buffer to | ||
| 2362 | ;next track | ||
| 2363 | ; | ||
| 2364 | inc dh ;advance track | ||
| 2365 | call adj_hd_trk | ||
| 2366 | ; | ||
| 2367 | pat$4: dec ah ;have we processed all the accumulated trks | ||
| 2368 | jne pat$2 | ||
| 2369 | mov [bp.user_off],di ;update user transfer address to beyond | ||
| 2370 | ;this accumulated block | ||
| 2371 | pop ax | ||
| 2372 | pop cx | ||
| 2373 | pop dx | ||
| 2374 | pop si | ||
| 2375 | clc | ||
| 2376 | ret ;success exit | ||
| 2377 | ; | ||
| 2378 | pr_acc_trks endp | ||
| 2379 | ; | ||
| 2380 | pr_cur_trk proc near | ||
| 2381 | ; | ||
| 2382 | ; inputs: | ||
| 2383 | ; si = cache element | ||
| 2384 | ; cx = current track | ||
| 2385 | ; dx = drive and head | ||
| 2386 | ; | ||
| 2387 | ; outputs: | ||
| 2388 | ; cy = set if error | ||
| 2389 | ; = clear if success | ||
| 2390 | ; | ||
| 2391 | ; algorithm: | ||
| 2392 | ; transfer track from cache to user memory | ||
| 2393 | ; | ||
| 2394 | push ax | ||
| 2395 | push cx | ||
| 2396 | push dx | ||
| 2397 | push si | ||
| 2398 | push ds | ||
| 2399 | push bp | ||
| 2400 | ; | ||
| 2401 | mov cx,[bytes_in_trk] | ||
| 2402 | shr cx,1 | ||
| 2403 | mov ax,word ptr [si.base_offset] | ||
| 2404 | mov dx,word ptr [si.base_offset.2] | ||
| 2405 | mov es,[bp.user_es] | ||
| 2406 | mov di,[bp.user_off] | ||
| 2407 | xor bh,bh ;read | ||
| 2408 | call blkmov | ||
| 2409 | ; | ||
| 2410 | pop bp | ||
| 2411 | pop ds | ||
| 2412 | pop si | ||
| 2413 | pop dx | ||
| 2414 | pop cx | ||
| 2415 | pop ax | ||
| 2416 | ; | ||
| 2417 | jnc pct$1 | ||
| 2418 | ; | ||
| 2419 | mov [si.track_flags],track_free | ||
| 2420 | call cache_is_lru | ||
| 2421 | stc | ||
| 2422 | ret ;error exit | ||
| 2423 | ; | ||
| 2424 | pct$1: call cache_is_mru | ||
| 2425 | mov di,[bytes_in_trk] | ||
| 2426 | add [bp.user_off],di | ||
| 2427 | clc | ||
| 2428 | ret | ||
| 2429 | ; | ||
| 2430 | pr_cur_trk endp | ||
| 2431 | ; | ||
| 2432 | process_write_partial proc near | ||
| 2433 | ; | ||
| 2434 | ; is used to write a partial track | ||
| 2435 | ; | ||
| 2436 | ; inputs: dx: int13 dx with high bit of dl set off | ||
| 2437 | ; cx: track | ||
| 2438 | ; bx: start sector | ||
| 2439 | ; ax: number of words | ||
| 2440 | ; | ||
| 2441 | ; outputs:cy set if error | ||
| 2442 | ; clear if success | ||
| 2443 | ; | ||
| 2444 | ; strategy: | ||
| 2445 | ; if (track in cache) then { | ||
| 2446 | ; if (track in track_buffer) then | ||
| 2447 | ; invalidate track buffer; | ||
| 2448 | ; perform user write into cache; | ||
| 2449 | ; } | ||
| 2450 | ; else { | ||
| 2451 | ; read track into track buffer; | ||
| 2452 | ; write track buffer into cache; | ||
| 2453 | ; } | ||
| 2454 | ; | ||
| 2455 | ; | ||
| 2456 | call track_in_cache ;is track in cache | ||
| 2457 | jc read_diskw ;if not we have to read from disk | ||
| 2458 | ; | ||
| 2459 | cmp cx,[track_buffer_cyln] ;is it in the track buffer | ||
| 2460 | jnz not_in_memw ;no | ||
| 2461 | cmp dx,[track_buffer_hddr] ; | ||
| 2462 | jnz not_in_memw ;no | ||
| 2463 | ;yes | ||
| 2464 | ; | ||
| 2465 | mov [track_buffer_cyln],-1 ;invalidate trk buf | ||
| 2466 | mov [track_buffer_hddr],-1 ;to avoid two transfers | ||
| 2467 | ; | ||
| 2468 | ; update cache element from user buffer | ||
| 2469 | ; | ||
| 2470 | not_in_memw: | ||
| 2471 | push dx | ||
| 2472 | xchg ax,bx ;get number of words in bx and start sect in ax | ||
| 2473 | dec ax ;0 based number | ||
| 2474 | mov cl,9 ; | ||
| 2475 | shl ax,cl ;byte offset | ||
| 2476 | xor dx,dx ; | ||
| 2477 | ; | ||
| 2478 | mov cx,bx ;number of words | ||
| 2479 | mov es,[bp.user_es] ; | ||
| 2480 | mov di,[bp.user_off]; | ||
| 2481 | shl bx,1 | ||
| 2482 | add [bp.user_off],bx | ||
| 2483 | ; | ||
| 2484 | add ax,word ptr [si.base_offset] | ||
| 2485 | adc dx,word ptr [si.base_offset.2] | ||
| 2486 | mov bh,1 ;write | ||
| 2487 | push si | ||
| 2488 | push ds | ||
| 2489 | push bp | ||
| 2490 | call blkmov | ||
| 2491 | pop bp | ||
| 2492 | pop ds | ||
| 2493 | pop si | ||
| 2494 | pop dx | ||
| 2495 | jc err_cw | ||
| 2496 | call cache_is_mru | ||
| 2497 | clc | ||
| 2498 | ret | ||
| 2499 | ; | ||
| 2500 | ; cache error | ||
| 2501 | ; | ||
| 2502 | err_cw: mov [si.track_flags],track_free | ||
| 2503 | call cache_is_lru | ||
| 2504 | stc | ||
| 2505 | ret | ||
| 2506 | ; | ||
| 2507 | ; track not in cache. see if free cache element available | ||
| 2508 | ; | ||
| 2509 | read_diskw: | ||
| 2510 | cmp di,-1 ;free cache | ||
| 2511 | jnz rd_partw ;if present we can initiate read | ||
| 2512 | stc | ||
| 2513 | ret | ||
| 2514 | ; | ||
| 2515 | ; free cache element available. read track from disk into track buffer | ||
| 2516 | ; | ||
| 2517 | rd_partw: | ||
| 2518 | mov si,di ;get element in si | ||
| 2519 | mov [track_buffer_cyln],-1 | ||
| 2520 | mov [track_buffer_hddr],-1 | ||
| 2521 | mov [si.track_flags],track_free | ||
| 2522 | push dx | ||
| 2523 | push cx | ||
| 2524 | push bx | ||
| 2525 | push ax | ||
| 2526 | or cl,1 | ||
| 2527 | or dl,80h | ||
| 2528 | mov al,[sect_in_trk] | ||
| 2529 | mov ah,2 | ||
| 2530 | push cs | ||
| 2531 | pop es | ||
| 2532 | mov bx,[track_buffer_ptr] | ||
| 2533 | pushf | ||
| 2534 | cli | ||
| 2535 | call [old_13] | ||
| 2536 | jnc wr$1 | ||
| 2537 | cmp ah,11h ;the int13 error which is not an error | ||
| 2538 | je wr$1 | ||
| 2539 | mov [int13err],TRUE | ||
| 2540 | add sp,8 | ||
| 2541 | mov al,ah | ||
| 2542 | stc | ||
| 2543 | ret | ||
| 2544 | ; | ||
| 2545 | ; since we have already updated disk, the track read doesn't need | ||
| 2546 | ; to be updated from user buffer. transfer track from track buffer | ||
| 2547 | ; into cache | ||
| 2548 | ; | ||
| 2549 | wr$1: mov di,[track_buffer_ptr] ;es:di is transfer address | ||
| 2550 | mov al,[sect_in_trk] | ||
| 2551 | xor ah,ah | ||
| 2552 | mov cl,8 | ||
| 2553 | shl ax,cl | ||
| 2554 | mov cx,ax | ||
| 2555 | mov bh,1 ;write | ||
| 2556 | mov ax,word ptr [si.base_offset] | ||
| 2557 | mov dx,word ptr [si.base_offset.2] | ||
| 2558 | push ds | ||
| 2559 | push si | ||
| 2560 | push bp | ||
| 2561 | call blkmov | ||
| 2562 | pop bp | ||
| 2563 | pop si | ||
| 2564 | pop ds | ||
| 2565 | pop ax | ||
| 2566 | pop bx | ||
| 2567 | pop cx | ||
| 2568 | pop dx | ||
| 2569 | jnc wr$2 | ||
| 2570 | ret | ||
| 2571 | ; | ||
| 2572 | ; information successfully transferred to cache. fill in cache | ||
| 2573 | ; control element with the info on head, drive and track | ||
| 2574 | ; | ||
| 2575 | wr$2: | ||
| 2576 | mov word ptr [si.track_cyln],cx | ||
| 2577 | mov word ptr [si.track_drive],dx | ||
| 2578 | and [si.track_flags], not track_free | ||
| 2579 | mov word ptr [track_buffer_cyln],cx | ||
| 2580 | mov word ptr [track_buffer_hddr],dx | ||
| 2581 | ; | ||
| 2582 | call cache_is_mru | ||
| 2583 | ; | ||
| 2584 | shl ax,1 | ||
| 2585 | add [bp.user_off],ax | ||
| 2586 | clc | ||
| 2587 | ret | ||
| 2588 | ; | ||
| 2589 | process_write_partial endp | ||
| 2590 | ; | ||
| 2591 | ; | ||
| 2592 | process_block_write proc near | ||
| 2593 | ; | ||
| 2594 | ; al = number of tracks | ||
| 2595 | ; cx = start track | ||
| 2596 | ; dx = drive and start head | ||
| 2597 | ; bp = user stack frame | ||
| 2598 | ; | ||
| 2599 | ; cy set if error | ||
| 2600 | ; cy clear if success | ||
| 2601 | ; | ||
| 2602 | ; algorithm: for (cur_trk=st_trk; trks-- > 0; ) | ||
| 2603 | ; if (cur_trk in cache) then | ||
| 2604 | ; write cur_trk from user buffer into cache; | ||
| 2605 | ; else { | ||
| 2606 | ; get a free cache element; | ||
| 2607 | ; write cur_trk from user buffer into this cache elem | ||
| 2608 | ; } | ||
| 2609 | ; | ||
| 2610 | mov di,[bp.user_off] | ||
| 2611 | ; | ||
| 2612 | pbw$1: push di ;save it because next call destroys di | ||
| 2613 | call track_in_cache ;is the track in cache | ||
| 2614 | jnc pbw$2 | ||
| 2615 | ; | ||
| 2616 | cmp di,-1 ;no free cache | ||
| 2617 | je pbw$4 ;error exit | ||
| 2618 | ; | ||
| 2619 | mov si,di ;track was not in cache. now there will be one | ||
| 2620 | mov [si.track_flags],track_free | ||
| 2621 | mov word ptr [si.track_cyln],cx | ||
| 2622 | mov word ptr [si.track_drive],dx | ||
| 2623 | ; | ||
| 2624 | pbw$2: pop di | ||
| 2625 | ; | ||
| 2626 | ; check if it is in track buffer also in which case invalidate trk buffer | ||
| 2627 | ; | ||
| 2628 | cmp cx,[track_buffer_cyln] | ||
| 2629 | jne pbw$21 | ||
| 2630 | cmp dx,[track_buffer_hddr] | ||
| 2631 | jne pbw$21 | ||
| 2632 | ; | ||
| 2633 | ; invalidate track buffer to avoid two transfers | ||
| 2634 | ; | ||
| 2635 | mov [track_buffer_cyln],-1 | ||
| 2636 | mov [track_buffer_hddr],-1 | ||
| 2637 | ; | ||
| 2638 | ; update cache from user buffer | ||
| 2639 | pbw$21: | ||
| 2640 | push cx ; | ||
| 2641 | push ax | ||
| 2642 | push ds | ||
| 2643 | push si | ||
| 2644 | push bp | ||
| 2645 | push di | ||
| 2646 | push dx | ||
| 2647 | ; | ||
| 2648 | mov es,[bp.user_es] | ||
| 2649 | mov cx,[bytes_in_trk] | ||
| 2650 | shr cx,1 | ||
| 2651 | mov ax,word ptr [si.base_offset] | ||
| 2652 | mov dx,word ptr [si.base_offset.2] | ||
| 2653 | mov bh,1 | ||
| 2654 | call blkmov | ||
| 2655 | ; | ||
| 2656 | pop dx | ||
| 2657 | pop di | ||
| 2658 | pop bp | ||
| 2659 | pop si | ||
| 2660 | pop ds | ||
| 2661 | pop ax | ||
| 2662 | pop cx | ||
| 2663 | ; | ||
| 2664 | jnc pbw$22 | ||
| 2665 | jmp err_cw | ||
| 2666 | ; | ||
| 2667 | pbw$22: and [si.track_flags],not track_free | ||
| 2668 | ; | ||
| 2669 | inc dh ;go to next track | ||
| 2670 | call adj_hd_trk | ||
| 2671 | pbw$3: add di,[bytes_in_trk] | ||
| 2672 | call cache_is_mru | ||
| 2673 | ; | ||
| 2674 | dec al ; are we done | ||
| 2675 | jne pbw$1 | ||
| 2676 | ; | ||
| 2677 | ; success exit | ||
| 2678 | mov [bp.user_off],di | ||
| 2679 | clc | ||
| 2680 | ret | ||
| 2681 | ; | ||
| 2682 | ; error exit | ||
| 2683 | ; | ||
| 2684 | pbw$4: pop di | ||
| 2685 | stc | ||
| 2686 | ret | ||
| 2687 | ; | ||
| 2688 | process_block_write endp | ||
| 2689 | ; | ||
| 2690 | check_parameters proc near | ||
| 2691 | ; | ||
| 2692 | ; inputs: same as int13 registers except for | ||
| 2693 | ; BP - user_stack_frame | ||
| 2694 | ; BX - function (either read or write) | ||
| 2695 | ; DS - int13code segment | ||
| 2696 | ; | ||
| 2697 | ; outputs: carry set if params invalid | ||
| 2698 | ; carry clear if params okay | ||
| 2699 | ; | ||
| 2700 | ; if parameters okay : | ||
| 2701 | ; dl - drive with high bit off | ||
| 2702 | ; bx - sector number | ||
| 2703 | ; cl - cleared of the sector number | ||
| 2704 | ; | ||
| 2705 | ; | ||
| 2706 | ; check for number of drives | ||
| 2707 | ; | ||
| 2708 | and dl, not 80H ; turn off high bit of drive | ||
| 2709 | cmp dl,MAX_HARD_FILES ; more than allowed drives? | ||
| 2710 | jae bad_parmx ; error. | ||
| 2711 | ; | ||
| 2712 | ; check for number of sectors | ||
| 2713 | ; | ||
| 2714 | or al,al ; zero sectors ? | ||
| 2715 | je bad_parmx ; error. | ||
| 2716 | ; | ||
| 2717 | cmp al,80h ; more than 80h sectors ? | ||
| 2718 | ja bad_parmx ; error. | ||
| 2719 | ; | ||
| 2720 | ; check for wrap in user transfer address | ||
| 2721 | ; | ||
| 2722 | mov di,[bp.user_bx] ; es:di is transfer address | ||
| 2723 | xor ah,ah ; ax has number of sectors | ||
| 2724 | mov si,ax ; get it into si | ||
| 2725 | push cx ; | ||
| 2726 | mov cl,9 | ||
| 2727 | shl si,cl ; convert number of sectors into | ||
| 2728 | ; number of bytes | ||
| 2729 | dec si ; convert into zero based number | ||
| 2730 | pop cx ; | ||
| 2731 | add di,si ; add to transfer address offset | ||
| 2732 | jc bad_parmx ; if exceeds 64k offset then wrap | ||
| 2733 | ; | ||
| 2734 | ; get drive number into di to use as offset into sect / trk table | ||
| 2735 | ; | ||
| 2736 | mov di,dx ; drive number | ||
| 2737 | and di,0000000011111111B ; just get the relevant bits | ||
| 2738 | ; | ||
| 2739 | ; form sector number in bx and compare against allowed number of sectors | ||
| 2740 | ; in track on the drive indicated | ||
| 2741 | ; | ||
| 2742 | mov bx,cx ; | ||
| 2743 | and bx,0000000000111111B ; bl will then have sector number | ||
| 2744 | or bx,bx ; zero sector number | ||
| 2745 | je bad_parmx ; is bad | ||
| 2746 | cmp bl, [di.sectrkarray] ; is it more than number of sectors | ||
| 2747 | ; allowed | ||
| 2748 | ja bad_parmx ; | ||
| 2749 | ; | ||
| 2750 | ; check head parameter | ||
| 2751 | ; | ||
| 2752 | cmp dh,[di.hdarray] ; is it more than max useable val for drive | ||
| 2753 | ja bad_parmx ; | ||
| 2754 | ; | ||
| 2755 | ; do we need some code to check if read exceeds tracks in system ? | ||
| 2756 | ; should we also put a limit on the number of sectors that could | ||
| 2757 | ; be looked up in cache ? | ||
| 2758 | ; | ||
| 2759 | ; | ||
| 2760 | ; clear off sector number from cl to leave just trk number in cx | ||
| 2761 | ; | ||
| 2762 | and cl,11000000B ; clear off sector number | ||
| 2763 | ; | ||
| 2764 | ; store sectors in track for current drive and bytes in track for | ||
| 2765 | ; current drive in memory | ||
| 2766 | ; | ||
| 2767 | push bx | ||
| 2768 | push cx | ||
| 2769 | mov bl,[di.hdarray] | ||
| 2770 | mov [max_hd],bl ; maximum head number for cur. drive | ||
| 2771 | mov bl,[di.sectrkarray] ; number of sectors in trk | ||
| 2772 | mov [sect_in_trk],bl ; store this | ||
| 2773 | mov cl,9 | ||
| 2774 | shl bx,cl ; bytes in track | ||
| 2775 | mov [bytes_in_trk],bx ; store this | ||
| 2776 | pop cx | ||
| 2777 | pop bx | ||
| 2778 | clc | ||
| 2779 | ret ;return with no error | ||
| 2780 | ; | ||
| 2781 | bad_parmx: | ||
| 2782 | stc | ||
| 2783 | ret | ||
| 2784 | ; | ||
| 2785 | check_parameters endp | ||
| 2786 | ; | ||
| 2787 | process_regions proc near | ||
| 2788 | ; | ||
| 2789 | ; inputs: bx - start sector | ||
| 2790 | ; al - number of sectors | ||
| 2791 | ; cx - start track | ||
| 2792 | ; | ||
| 2793 | ; outputs: none | ||
| 2794 | ; | ||
| 2795 | ; action: initialise regions struct | ||
| 2796 | ; | ||
| 2797 | mov byte ptr [REGION.FLAG],0 ; clear regions flag | ||
| 2798 | cmp bx,1 ; if start sector is one | ||
| 2799 | je pr$2 ; might as well start with region2 | ||
| 2800 | ; | ||
| 2801 | ; process region1 | ||
| 2802 | ; | ||
| 2803 | or [REGION.FLAG],REG1_P ; mark region1 present | ||
| 2804 | mov ah,[sect_in_trk] ; get sectors in track | ||
| 2805 | sub ah,bl ; remaining number of sectors in track | ||
| 2806 | inc ah ; adjust 0 based numb to one based numb | ||
| 2807 | cmp ah,al | ||
| 2808 | jbe pr$1 ; if below or equal ah has number of sectors | ||
| 2809 | ; in region1 | ||
| 2810 | mov ah,al ; else all the sectors are in region1 | ||
| 2811 | pr$1: sub al,ah ; adjust number of sectors | ||
| 2812 | mov [REGION.REG1.START_H],dh | ||
| 2813 | mov [REGION.REG1.START_T],cx | ||
| 2814 | mov [REGION.REG1.START_S],bx | ||
| 2815 | push cx ; save these registers | ||
| 2816 | push ax ; | ||
| 2817 | mov al,ah ; | ||
| 2818 | xor ah,ah ; ax has number of sectors now | ||
| 2819 | mov cl,8 ; | ||
| 2820 | shl ax,cl ; multiply by 256 to get number of words | ||
| 2821 | mov [REGION.REG1.COUNT],ax ; store this count | ||
| 2822 | pop ax ; | ||
| 2823 | pop cx | ||
| 2824 | inc dh | ||
| 2825 | call adj_hd_trk | ||
| 2826 | ; | ||
| 2827 | ; process region2 | ||
| 2828 | ; | ||
| 2829 | pr$2: or al,al ; are we done | ||
| 2830 | je pr$end ; | ||
| 2831 | xor ah,ah ; ax has number of sectors | ||
| 2832 | div [sect_in_trk] ; find number of tracks | ||
| 2833 | or al,al ; al will have number of full tracks | ||
| 2834 | ; ah will have number of sectors left | ||
| 2835 | je pr$3 ; if no full tracks no region2 | ||
| 2836 | ; | ||
| 2837 | or [REGION.FLAG],REG2_P ; mark region2 present | ||
| 2838 | mov [REGION.REG2.START_H],dh | ||
| 2839 | mov [REGION.REG2.START_T],cx; store start track | ||
| 2840 | mov [REGION.REG2.TRACKS],al ; and number of tracks | ||
| 2841 | add dh,al ; adjust track number | ||
| 2842 | call adj_hd_trk | ||
| 2843 | ; | ||
| 2844 | ; process region3 | ||
| 2845 | ; | ||
| 2846 | pr$3: or ah,ah ; are we done (no sectors left) | ||
| 2847 | je pr$end ; if yes go to fin | ||
| 2848 | or [REGION.FLAG],REG3_P ; else mark region3 present | ||
| 2849 | mov [REGION.REG3.START_H],dh | ||
| 2850 | mov [REGION.REG3.START_T],cx ;store track number | ||
| 2851 | mov cl,8 | ||
| 2852 | mov al,ah | ||
| 2853 | xor ah,ah ; convert number of sectors into number of | ||
| 2854 | shl ax,cl ; words | ||
| 2855 | mov [REGION.REG3.COUNT],ax ; store this | ||
| 2856 | pr$end: | ||
| 2857 | ; | ||
| 2858 | ret | ||
| 2859 | ; | ||
| 2860 | process_regions endp | ||
| 2861 | ; | ||
| 2862 | ; Support Routines: | ||
| 2863 | ; | ||
| 2864 | ; | ||
| 2865 | track_in_cache proc near | ||
| 2866 | ; | ||
| 2867 | ; input: dl = drive number with bit 8 set off | ||
| 2868 | ; cx = cylinder number | ||
| 2869 | ; | ||
| 2870 | mov di,-1 ; di will return lru item nearest to matching | ||
| 2871 | ; element, -1 if none | ||
| 2872 | mov si,[cache_head] ; start with mru cache entry | ||
| 2873 | inc si ; to counter next instruction | ||
| 2874 | nexte: | ||
| 2875 | dec si ; to counter last instruction in the loop | ||
| 2876 | test [si.track_flags],track_locked ; is the track locked? | ||
| 2877 | jnz no_set ; | ||
| 2878 | mov di,si ; if not locked update di to this element | ||
| 2879 | no_set: | ||
| 2880 | test [si.track_flags],track_free ; is element free | ||
| 2881 | jnz skipe ; if free we need not check this one | ||
| 2882 | cmp dx,word ptr [si.track_drive] ; if not free check drive+head | ||
| 2883 | jnz skipe ; | ||
| 2884 | cmp cx,[si.track_cyln] ; and cylinder number | ||
| 2885 | jz tic$1 ; if found exit routine | ||
| 2886 | skipe: | ||
| 2887 | mov si,[si.fwd_lru_lnk] ; else go to check next cache element | ||
| 2888 | inc si ; if last element was end then si = -1 | ||
| 2889 | jnz nexte ; and incrementing it will set zero flag | ||
| 2890 | stc | ||
| 2891 | ret | ||
| 2892 | tic$1: clc | ||
| 2893 | ret | ||
| 2894 | ; | ||
| 2895 | track_in_cache endp | ||
| 2896 | ; | ||
| 2897 | get_cache proc near | ||
| 2898 | ; | ||
| 2899 | ; inputs: none | ||
| 2900 | ; outputs: si = lru cache element not locked | ||
| 2901 | ; = -1 if all elems locked | ||
| 2902 | ; | ||
| 2903 | mov si,[cache_tail] ;start with lru element | ||
| 2904 | inc si ;to counter next instruction | ||
| 2905 | gc$1: | ||
| 2906 | dec si ; to counter last instruction in loop | ||
| 2907 | test [si.track_flags],track_locked ; is the element locked | ||
| 2908 | jz gc$2 ; if not locked this is the lucky(?) guy | ||
| 2909 | ; | ||
| 2910 | mov si,[si.back_lru_lnk] ; else go back in chain to check the | ||
| 2911 | ; next recently used cache element | ||
| 2912 | inc si ; as before -1 is the end of chain | ||
| 2913 | jnz gc$1 ; incrementing it will set zero flag | ||
| 2914 | ; | ||
| 2915 | dec si ; no element found, si = -1 | ||
| 2916 | ; | ||
| 2917 | gc$2: ret | ||
| 2918 | ; | ||
| 2919 | get_cache endp | ||
| 2920 | ; | ||
| 2921 | adj_hd_trk proc near | ||
| 2922 | ; | ||
| 2923 | ; inputs: ch,cl track number | ||
| 2924 | ; dh changed head number to be checked and adjusted | ||
| 2925 | ; | ||
| 2926 | ; outputs: cx and dh updated | ||
| 2927 | ; | ||
| 2928 | pushf | ||
| 2929 | aht$1: cmp dh,[max_hd] ;is the head number > heads on drive | ||
| 2930 | jbe aht$2 | ||
| 2931 | sub dh,[max_hd] ;if so decrease head number by number of | ||
| 2932 | ;heads on drive | ||
| 2933 | dec dh ;by one more | ||
| 2934 | add ch,1 ;and step to next track | ||
| 2935 | jnc aht$1 | ||
| 2936 | add cl,40h | ||
| 2937 | jmp aht$1 | ||
| 2938 | aht$2: popf | ||
| 2939 | ret | ||
| 2940 | ; | ||
| 2941 | adj_hd_trk endp | ||
| 2942 | |||
| 2943 | CACHE_HIT PROC NEAR | ||
| 2944 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 2945 | CACHE_HIT ENDP | ||
| 2946 | |||
| 2947 | |||
| 2948 | ;** INVALIDATE_CACHE -- Discard all cache info | ||
| 2949 | ; | ||
| 2950 | ; ENTRY | ||
| 2951 | ; Cache is flushed (If it is not, all dirty info will simply be chucked) | ||
| 2952 | ; EXIT | ||
| 2953 | ; All elements of cache are marked free | ||
| 2954 | ; USES | ||
| 2955 | ; BX,FLAGS | ||
| 2956 | ; | ||
| 2957 | INVALIDATE_CACHE PROC NEAR | ||
| 2958 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 2959 | MOV BX,[CACHE_HEAD] | ||
| 2960 | INC BX ; Counter next instruction | ||
| 2961 | NEXTC: | ||
| 2962 | DEC BX | ||
| 2963 | MOV [BX.TRACK_FLAGS],TRACK_FREE | ||
| 2964 | MOV BX,[BX.FWD_LRU_LNK] | ||
| 2965 | INC BX | ||
| 2966 | JNZ NEXTC | ||
| 2967 | ; | ||
| 2968 | ; Track buffer invalid too | ||
| 2969 | ; | ||
| 2970 | MOV [TRACK_BUFFER_CYLN],-1 | ||
| 2971 | MOV [TRACK_BUFFER_HDDR],-1 | ||
| 2972 | MOV [DIRTY_CACHE],0 | ||
| 2973 | ret | ||
| 2974 | |||
| 2975 | INVALIDATE_CACHE ENDP | ||
| 2976 | |||
| 2977 | ;** CACHE_IS_MRU -- Put cache element in LRU chain at MRU position | ||
| 2978 | ; | ||
| 2979 | ; ENTRY | ||
| 2980 | ; SI points cache element to place at MRU position | ||
| 2981 | ; EXIT | ||
| 2982 | ; SI is at MRU position (head) | ||
| 2983 | ; USES | ||
| 2984 | ; DI,FLAGS | ||
| 2985 | ; | ||
| 2986 | CACHE_IS_MRU PROC NEAR | ||
| 2987 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 2988 | push di | ||
| 2989 | CMP SI,[CACHE_HEAD] | ||
| 2990 | JZ RET444 | ||
| 2991 | CALL UNLINK_CACHE | ||
| 2992 | MOV DI,SI | ||
| 2993 | XCHG DI,[CACHE_HEAD] | ||
| 2994 | MOV [DI.BACK_LRU_LNK],SI | ||
| 2995 | MOV [SI.FWD_LRU_LNK],DI | ||
| 2996 | MOV [SI.BACK_LRU_LNK],-1 | ||
| 2997 | RET444: pop di | ||
| 2998 | RET | ||
| 2999 | |||
| 3000 | CACHE_IS_MRU ENDP | ||
| 3001 | |||
| 3002 | ;** CACHE_IS_LRU -- Put cache element in LRU chain at LRU position | ||
| 3003 | ; | ||
| 3004 | ; ENTRY | ||
| 3005 | ; SI points to cache element to place at LRU position | ||
| 3006 | ; EXIT | ||
| 3007 | ; SI is at LRU position (tail) | ||
| 3008 | ; USES | ||
| 3009 | ; DI,FLAGS | ||
| 3010 | ; | ||
| 3011 | CACHE_IS_LRU PROC NEAR | ||
| 3012 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3013 | push di | ||
| 3014 | CMP SI,[CACHE_TAIL] | ||
| 3015 | JZ RET555 | ||
| 3016 | CALL UNLINK_CACHE | ||
| 3017 | MOV DI,SI | ||
| 3018 | XCHG DI,[CACHE_TAIL] | ||
| 3019 | MOV [DI.FWD_LRU_LNK],SI | ||
| 3020 | MOV [SI.BACK_LRU_LNK],DI | ||
| 3021 | MOV [SI.FWD_LRU_LNK],-1 | ||
| 3022 | RET555: pop di | ||
| 3023 | RET | ||
| 3024 | |||
| 3025 | CACHE_IS_LRU ENDP | ||
| 3026 | |||
| 3027 | ;** UNLINK_CACHE -- Unlink cache element from LRU chain | ||
| 3028 | ; | ||
| 3029 | ; ENTRY | ||
| 3030 | ; SI points to element to unlink | ||
| 3031 | ; EXIT | ||
| 3032 | ; SI is unlinked | ||
| 3033 | ; USES | ||
| 3034 | ; DI,FLAGS | ||
| 3035 | ; | ||
| 3036 | UNLINK_CACHE PROC NEAR | ||
| 3037 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3038 | PUSH BX | ||
| 3039 | MOV DI,[SI.BACK_LRU_LNK] ; Get prev guy | ||
| 3040 | INC DI ; Guy First? | ||
| 3041 | JZ NEW_HEAD ; Yes | ||
| 3042 | DEC DI | ||
| 3043 | MOV BX,[SI.FWD_LRU_LNK] ; Get next guy | ||
| 3044 | MOV [DI.FWD_LRU_LNK],BX ; Prev fwd is my fwd | ||
| 3045 | INC BX ; Is that guy last? | ||
| 3046 | JZ NEW_TAIL ; Yes | ||
| 3047 | DEC BX | ||
| 3048 | MOV [BX.BACK_LRU_LNK],DI ; Next back is my back | ||
| 3049 | NULL_CACHE: | ||
| 3050 | POP BX | ||
| 3051 | RET | ||
| 3052 | |||
| 3053 | NEW_HEAD: | ||
| 3054 | MOV DI,[SI.FWD_LRU_LNK] ; Is head also tail? | ||
| 3055 | INC DI | ||
| 3056 | JZ NULL_CACHE ; Yes | ||
| 3057 | DEC DI | ||
| 3058 | MOV [CACHE_HEAD],DI ; New head | ||
| 3059 | MOV [DI.BACK_LRU_LNK],-1 ; New head has no back link | ||
| 3060 | POP BX | ||
| 3061 | RET | ||
| 3062 | |||
| 3063 | NEW_TAIL: | ||
| 3064 | MOV [CACHE_TAIL],DI ; New tail | ||
| 3065 | POP BX | ||
| 3066 | RET | ||
| 3067 | UNLINK_CACHE ENDP | ||
| 3068 | |||
| 3069 | RETRY_CNT DB ? | ||
| 3070 | |||
| 3071 | ;** WRITE_FROM_CACHE -- Write out cache element to disk | ||
| 3072 | ; | ||
| 3073 | ; ENTRY | ||
| 3074 | ; SI -> cache element to write | ||
| 3075 | ; EXIT | ||
| 3076 | ; Carry Clear | ||
| 3077 | ; Written OK | ||
| 3078 | ; Track buffer is set to this track | ||
| 3079 | ; Carry Set | ||
| 3080 | ; Error, AL is error code | ||
| 3081 | ; Track buffer is set to empty | ||
| 3082 | ; USES | ||
| 3083 | ; AX,BX,CX,DX,ES,DI,FLAGS | ||
| 3084 | ; | ||
| 3085 | WRITE_FROM_CACHE PROC NEAR | ||
| 3086 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3087 | ; | ||
| 3088 | ; First transfer track down to track buffer because we can't write | ||
| 3089 | ; direct to extended or expanded mem with INT 13 | ||
| 3090 | ; | ||
| 3091 | PUSH CS | ||
| 3092 | POP ES | ||
| 3093 | MOV DI,[TRACK_BUFFER_PTR] ; ES:DI is transfer addr for BLKMOV | ||
| 3094 | MOV BX,WORD PTR [SI.TRACK_DRIVE] | ||
| 3095 | XOR BH,BH | ||
| 3096 | MOV AL,[BX.SECTRKARRAY] | ||
| 3097 | XOR AH,AH | ||
| 3098 | PUSH AX | ||
| 3099 | MOV CL,8 | ||
| 3100 | SHL AX,CL ; AX is words in track | ||
| 3101 | MOV CX,AX | ||
| 3102 | XOR BH,BH ; Read | ||
| 3103 | MOV AX,WORD PTR [SI.BASE_OFFSET] | ||
| 3104 | MOV DX,WORD PTR [SI.BASE_OFFSET.2] ; DX:AX is address in mem | ||
| 3105 | PUSH DS | ||
| 3106 | PUSH SI | ||
| 3107 | PUSH BP | ||
| 3108 | CALL BLKMOV ; Track buffer contents to track buffer | ||
| 3109 | POP BP | ||
| 3110 | POP SI | ||
| 3111 | POP DS | ||
| 3112 | JC ERR_FLP | ||
| 3113 | POP AX ; AL is sec/trk | ||
| 3114 | ; | ||
| 3115 | ; Now write it out to drive from the track buffer | ||
| 3116 | ; | ||
| 3117 | MOV CX,[SI.TRACK_CYLN] | ||
| 3118 | MOV DX,WORD PTR [SI.TRACK_DRIVE] | ||
| 3119 | MOV [TRACK_BUFFER_CYLN],CX ; Set track buffer currency | ||
| 3120 | MOV [TRACK_BUFFER_HDDR],DX | ||
| 3121 | OR CL,1 | ||
| 3122 | OR DL,80H | ||
| 3123 | MOV AH,3 | ||
| 3124 | PUSH CS | ||
| 3125 | POP ES | ||
| 3126 | MOV BX,[TRACK_BUFFER_PTR] | ||
| 3127 | PUSH AX | ||
| 3128 | MOV [RETRY_CNT],5 | ||
| 3129 | RETRY_WRITE: | ||
| 3130 | PUSHF | ||
| 3131 | CALL [OLD_13] ; Write it out | ||
| 3132 | JC ERR_RETRY | ||
| 3133 | NO_ERR1: | ||
| 3134 | POP AX | ||
| 3135 | ERR_FL: | ||
| 3136 | ret | ||
| 3137 | |||
| 3138 | ERR_RETRY: | ||
| 3139 | CMP AH,11H ; The error that is not an error? | ||
| 3140 | JZ NO_ERR1 ; Yes, cmp cleared carry | ||
| 3141 | PUSH AX ; Save error in AH | ||
| 3142 | MOV AH,0 ; Reset | ||
| 3143 | INT 13H | ||
| 3144 | POP AX ; Get error back | ||
| 3145 | DEC [RETRY_CNT] | ||
| 3146 | JZ SET_ERR ; Return error | ||
| 3147 | POP AX ; Recover correct AX for INT 13 | ||
| 3148 | PUSH AX | ||
| 3149 | JMP RETRY_WRITE | ||
| 3150 | |||
| 3151 | SET_ERR: | ||
| 3152 | MOV AL,AH ; INT 13 error to AL | ||
| 3153 | ERR_FLP: | ||
| 3154 | ADD SP,2 | ||
| 3155 | STC | ||
| 3156 | MOV [TRACK_BUFFER_CYLN],-1 ; Zap the track buffer | ||
| 3157 | MOV [TRACK_BUFFER_HDDR],-1 | ||
| 3158 | JMP ERR_FL | ||
| 3159 | |||
| 3160 | WRITE_FROM_CACHE ENDP | ||
| 3161 | |||
| 3162 | ;** FLUSH_CACHE -- Flush specific cache element if it's dirty | ||
| 3163 | ; | ||
| 3164 | ; ENTRY | ||
| 3165 | ; SI points to element to flush | ||
| 3166 | ; EXIT | ||
| 3167 | ; Carry Clear | ||
| 3168 | ; SI is flushed if it was dirty | ||
| 3169 | ; SI.TRACK_FLAGS dirty bit clear | ||
| 3170 | ; Track buffer set to this track | ||
| 3171 | ; Carry Set | ||
| 3172 | ; SI could not be flushed | ||
| 3173 | ; SI.TRACK_FLAGS = free | ||
| 3174 | ; AL is error code | ||
| 3175 | ; Track buffer set to empty | ||
| 3176 | ; USES | ||
| 3177 | ; AX,BX,CX,DX,ES,DI,FLAGS | ||
| 3178 | ; | ||
| 3179 | FLUSH_CACHE PROC NEAR | ||
| 3180 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3181 | TEST [SI.TRACK_FLAGS],TRACK_FREE ; Clears carry | ||
| 3182 | JNZ IGNORE_TRK | ||
| 3183 | TEST [SI.TRACK_FLAGS],TRACK_DIRTY ; Clears carry | ||
| 3184 | JZ IGNORE_TRK | ||
| 3185 | CALL WRITE_FROM_CACHE | ||
| 3186 | DEC [DIRTY_CACHE] ; Doesn't effect carry | ||
| 3187 | JC FLUSH_ERRX | ||
| 3188 | AND [SI.TRACK_FLAGS],NOT TRACK_DIRTY ; Clears carry | ||
| 3189 | IGNORE_TRK: | ||
| 3190 | ret | ||
| 3191 | |||
| 3192 | FLUSH_ERRX: | ||
| 3193 | MOV [SI.TRACK_FLAGS],TRACK_FREE ; Track gone, unlocked | ||
| 3194 | RET | ||
| 3195 | |||
| 3196 | FLUSH_CACHE ENDP | ||
| 3197 | |||
| 3198 | ;** FLUSH_WHOLE_CACHE_SAV -- Flush all dirty cache elements saving regs | ||
| 3199 | ; | ||
| 3200 | ; ENTRY | ||
| 3201 | ; None | ||
| 3202 | ; EXIT | ||
| 3203 | ; Cache flushed | ||
| 3204 | ; USES | ||
| 3205 | ; FLAGS | ||
| 3206 | ; | ||
| 3207 | FLUSH_WHOLE_CACHE_SAV PROC NEAR | ||
| 3208 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 3209 | ; Simulate PUSHA | ||
| 3210 | PUSH AX | ||
| 3211 | PUSH CX | ||
| 3212 | PUSH DX | ||
| 3213 | PUSH BX | ||
| 3214 | PUSH BX ; dummy for push sp | ||
| 3215 | PUSH BP | ||
| 3216 | PUSH SI | ||
| 3217 | PUSH DI | ||
| 3218 | ; | ||
| 3219 | PUSH DS | ||
| 3220 | PUSH ES | ||
| 3221 | PUSH CS | ||
| 3222 | POP DS | ||
| 3223 | ASSUME DS:INT13CODE | ||
| 3224 | CALL FLUSH_WHOLE_CACHE | ||
| 3225 | POP ES | ||
| 3226 | POP DS | ||
| 3227 | ; Simulate POPA | ||
| 3228 | POP DI | ||
| 3229 | POP SI | ||
| 3230 | POP BP | ||
| 3231 | POP BX ; Dummy for pop sp | ||
| 3232 | POP BX | ||
| 3233 | POP DX | ||
| 3234 | POP CX | ||
| 3235 | POP AX | ||
| 3236 | ; | ||
| 3237 | ret | ||
| 3238 | FLUSH_WHOLE_CACHE_SAV ENDP | ||
| 3239 | |||
| 3240 | ;** FLUSH_WHOLE_CACHE -- Flush all dirty cache elements | ||
| 3241 | ; | ||
| 3242 | ; ENTRY | ||
| 3243 | ; None | ||
| 3244 | ; EXIT | ||
| 3245 | ; Cache flushed | ||
| 3246 | ; USES | ||
| 3247 | ; AX,BX,CX,DX,ES,SI,DI,FLAGS | ||
| 3248 | ; | ||
| 3249 | FLUSH_WHOLE_CACHE PROC NEAR | ||
| 3250 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3251 | MOV SI,[CACHE_HEAD] | ||
| 3252 | INC SI ; Counter next instruction | ||
| 3253 | FLSH_LP: | ||
| 3254 | DEC SI | ||
| 3255 | CALL FLUSH_CACHE | ||
| 3256 | MOV SI,[SI.FWD_LRU_LNK] | ||
| 3257 | INC SI | ||
| 3258 | JNZ FLSH_LP | ||
| 3259 | FLUSH_DONE: | ||
| 3260 | MOV [DIRTY_CACHE],0 ; No dirty guys in cache | ||
| 3261 | ret | ||
| 3262 | |||
| 3263 | FLUSH_WHOLE_CACHE ENDP | ||
| 3264 | |||
| 3265 | BREAK <Drive code for /E driver> | ||
| 3266 | |||
| 3267 | ; | ||
| 3268 | ; The following label defines the start of the I/O code which is driver type | ||
| 3269 | ; specific. | ||
| 3270 | ; | ||
| 3271 | ; THE TYPE 2 driver must REPLACE this code with code appropriate | ||
| 3272 | ; to the driver type. | ||
| 3273 | ; | ||
| 3274 | EVEN ; Force start of drive code to word boundary | ||
| 3275 | |||
| 3276 | DRIVE_CODE LABEL WORD | ||
| 3277 | |||
| 3278 | EXTMEM_LOW EQU 0000H ; 24 bit addr of start of extended memory | ||
| 3279 | EXTMEM_HIGH EQU 0010H | ||
| 3280 | |||
| 3281 | ;** BASE_ADDR data element | ||
| 3282 | ; | ||
| 3283 | ; The next value defines the 24 bit address of the start of the memory for | ||
| 3284 | ; the cache. It is equal to the EMM_BASE value in the | ||
| 3285 | ; EMM_REC structure for the cache. | ||
| 3286 | ; | ||
| 3287 | ; NOTE THAT IT IS INITIALIZED TO THE START OF EXTENDED MEMORY. This is | ||
| 3288 | ; because BLKMOV is used to read the EMM_CTRL sector during initialization | ||
| 3289 | ; of a TYPE 1 driver. | ||
| 3290 | ; | ||
| 3291 | ; NOTE: This data element is shared by TYPE 1, 2 drivers, but | ||
| 3292 | ; its meaning and correct initial value are driver type specific. | ||
| 3293 | ; | ||
| 3294 | |||
| 3295 | ;; NOTE: The value at BASE_ADDR is patched during initialization when | ||
| 3296 | ;; loading a RAMDrive into upper extended memory on a PLUS | ||
| 3297 | ;; | ||
| 3298 | BASE_ADDR LABEL DWORD ; 24 bit address of start of this RAMDRV | ||
| 3299 | DW EXTMEM_LOW | ||
| 3300 | DW EXTMEM_HIGH | ||
| 3301 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3302 | ;** BLKMOV - Perform transfer for TYPE 1 driver | ||
| 3303 | ; | ||
| 3304 | ; This routine is the transfer routine for moving bytes | ||
| 3305 | ; to and from the AT extended memory in real mode using | ||
| 3306 | ; the LOADALL instruction. The LOADALL instruction is used | ||
| 3307 | ; to set up a segment descriptor which has a 24 bit address. | ||
| 3308 | ; During the time the LOADALL 24 bit segment descriptor is | ||
| 3309 | ; in effect we must have interrupts disabled. If a real mode | ||
| 3310 | ; 8086 interrupt handler was given control it might perform | ||
| 3311 | ; a segment register operation which would destroy the special | ||
| 3312 | ; segment descriptor set up by LOADALL. This is prevented by | ||
| 3313 | ; doing a CLI during the "LOADALL time". | ||
| 3314 | ; | ||
| 3315 | ; WARNING NUMBER ONE: | ||
| 3316 | ; THIS CODE WILL NOT WORK ON ANY 80286 MACHINE WHERE THE NMI | ||
| 3317 | ; INTERRUPT IS ANYTHING BUT A FATAL, SYSTEM HALTING ERROR. | ||
| 3318 | ; | ||
| 3319 | ; Since it is bad to leave interrupts disabled for a long | ||
| 3320 | ; time, the I/O is performed 256 words at a time enabling | ||
| 3321 | ; interrupts between each 256 word piece. This keeps the time | ||
| 3322 | ; interrupts are disabled down to a reasonable figure in the 100mSec | ||
| 3323 | ; range. | ||
| 3324 | ; | ||
| 3325 | ; To use the LOADALL instruction 102 bytes at location 80:0 must | ||
| 3326 | ; be used. INT13 copies the contents of 80:0 into its own buffer, | ||
| 3327 | ; copies in the LOADALL info, performs the LOADALL, and then copies | ||
| 3328 | ; back the previous contents of 80:0. These operations are all | ||
| 3329 | ; performed during the time interrupts are disabled for each 256 word | ||
| 3330 | ; block. This must be done with interrupts disabled because this area | ||
| 3331 | ; on DOS 2.X and 3.X contains variable BIOS data. | ||
| 3332 | ; | ||
| 3333 | ; In order to gain full 24 bit addressing it is also required | ||
| 3334 | ; that address line 20 be enabled. This effects 8086 compatibility | ||
| 3335 | ; on 80286 systems. This code leaves address line 20 enabled | ||
| 3336 | ; for the ENTIRE duration of the I/O because it is too time | ||
| 3337 | ; expensive to disable/enable it for each 256 word block. | ||
| 3338 | ; | ||
| 3339 | ; WARNING NUMBER TWO: | ||
| 3340 | ; IF A MULTITASKING PRE-EMPTIVE SYSTEM SCHEDULES AND RUNS | ||
| 3341 | ; AN APPLICATION WHICH RELIES ON THE 1 MEG ADDRESS WRAP | ||
| 3342 | ; PROPERTY OF THE 8086 AND 8088 DURING THE TIME INT13 | ||
| 3343 | ; IS IN THE MIDDLE OF DOING AN I/O WITH ADDRESS LINE 20 ENABLED, | ||
| 3344 | ; THE APPLICATION WILL NOT RUN PROPERLY AND MAY DESTRUCT THE | ||
| 3345 | ; INT13 MEMORY. | ||
| 3346 | ; | ||
| 3347 | ; METHOD: | ||
| 3348 | ; Perform various LOADALL setup operations | ||
| 3349 | ; Enable address line 20 | ||
| 3350 | ; While there is I/O to perform | ||
| 3351 | ; Do "per 256 word block" LOADALL setup operations | ||
| 3352 | ; Set up copy of 80:0 to INT13 buffer | ||
| 3353 | ; CLI | ||
| 3354 | ; copy 80:0 to INT13 buffer | ||
| 3355 | ; copy LOADALL info to 80:0 | ||
| 3356 | ; LOADALL | ||
| 3357 | ; do 256 word transfer | ||
| 3358 | ; copy INT13 80:0 buffer back to 80:0 | ||
| 3359 | ; STI | ||
| 3360 | ; Disable address line 20 | ||
| 3361 | ; | ||
| 3362 | ; SEE ALSO | ||
| 3363 | ; INTEL special documentation of LOADALL instruction | ||
| 3364 | ; | ||
| 3365 | ; ENTRY: | ||
| 3366 | ; ES:DI is packet transfer address. | ||
| 3367 | ; CX is number of words to transfer. | ||
| 3368 | ; DX:AX is 32 bit start byte offset (0 = start of cache) | ||
| 3369 | ; BH is 1 for WRITE, 0 for READ | ||
| 3370 | ; | ||
| 3371 | ; BASE_ADDR set to point to start of cache memory | ||
| 3372 | ; This "input" is not the responsibility of the caller. It | ||
| 3373 | ; is up to the initialization code to set it up when the | ||
| 3374 | ; device is installed | ||
| 3375 | ; | ||
| 3376 | ; EXIT: | ||
| 3377 | ; Carry Clear | ||
| 3378 | ; OK, operation performed successfully | ||
| 3379 | ; Carry Set | ||
| 3380 | ; Error during operation, AL is error number (INT 13 error) | ||
| 3381 | ; | ||
| 3382 | ; USES: | ||
| 3383 | ; ALL | ||
| 3384 | ; | ||
| 3385 | ; This routine is specific to TYPE 1 driver | ||
| 3386 | ; | ||
| 3387 | ; sunilp - incorporated blkmov_386 (thanks to gregh) | ||
| 3388 | ; incorporated loadall_286 trick (thanks to scottra) | ||
| 3389 | ; added new a20 functionality | ||
| 3390 | ; ideally the code should be all relocatable abd the 386 | ||
| 3391 | ; blkmov should be relocated on the 286 blkmov for the | ||
| 3392 | ; 386 case. Also the A20 routines for the Olivetti or PS/2 | ||
| 3393 | ; should also ideally be relocated on top of the normal A20 | ||
| 3394 | |||
| 3395 | BLKMOV: | ||
| 3396 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 3397 | test [sys_flg],M_386 | ||
| 3398 | je blkmov_286 | ||
| 3399 | jmp blkmov_386 | ||
| 3400 | ; | ||
| 3401 | ; Compute 32 bit address of start of I/O | ||
| 3402 | ; | ||
| 3403 | blkmov_286: | ||
| 3404 | ADD AX,WORD PTR [BASE_ADDR] | ||
| 3405 | ADC DX,WORD PTR [BASE_ADDR + 2] | ||
| 3406 | ; | ||
| 3407 | ; Dispatch on function | ||
| 3408 | ; | ||
| 3409 | OR BH,BH | ||
| 3410 | JZ READ_IT | ||
| 3411 | ; | ||
| 3412 | ; Write | ||
| 3413 | ; | ||
| 3414 | MOV WORD PTR [ESDES.SEG_BASE],AX | ||
| 3415 | MOV BYTE PTR [ESDES.SEG_BASE + 2],DL | ||
| 3416 | ; MOV [LSI],DI | ||
| 3417 | mov [lbx],di ;sp | ||
| 3418 | MOV [LDI],0 | ||
| 3419 | MOV SI,OFFSET DSDES | ||
| 3420 | JMP SHORT SET_TRANS | ||
| 3421 | |||
| 3422 | READ_IT: | ||
| 3423 | MOV WORD PTR [DSDES.SEG_BASE],AX | ||
| 3424 | MOV BYTE PTR [DSDES.SEG_BASE + 2],DL | ||
| 3425 | MOV [LDI],DI | ||
| 3426 | ; MOV [LSI],0 ;sp | ||
| 3427 | mov [lbx],0 | ||
| 3428 | MOV SI,OFFSET ESDES | ||
| 3429 | SET_TRANS: | ||
| 3430 | MOV AX,ES | ||
| 3431 | CALL SEG_SET ; Set ES or DS segreg | ||
| 3432 | ; | ||
| 3433 | ; Set stack descriptor | ||
| 3434 | ; | ||
| 3435 | MOV AX,SS | ||
| 3436 | MOV [LSSS],AX | ||
| 3437 | MOV SI,OFFSET SSDES | ||
| 3438 | CALL SEG_SET | ||
| 3439 | MOV [LSP],SP | ||
| 3440 | ; SUB [LSP],2 ; CX is on stack at LOADALL | ||
| 3441 | ; | ||
| 3442 | ; the loadall kludge | ||
| 3443 | ; | ||
| 3444 | mov ax,cs ;sp | ||
| 3445 | inc ax ;sp | ||
| 3446 | mov [lcss],ax ;sp | ||
| 3447 | mov si,offset CSDES ;sp | ||
| 3448 | mov ax,cs ;sp | ||
| 3449 | call seg_set ;sp | ||
| 3450 | ; | ||
| 3451 | ; Set Other LOADALL stuff | ||
| 3452 | ; | ||
| 3453 | SMSW [LDSW] | ||
| 3454 | SIDT FWORD PTR [IDTDES] | ||
| 3455 | SGDT FWORD PTR [GDTDES] | ||
| 3456 | ; | ||
| 3457 | ; NOW The damn SXXX instructions store the desriptors in a | ||
| 3458 | ; different order than LOADALL wants | ||
| 3459 | ; | ||
| 3460 | MOV SI,OFFSET IDTDES | ||
| 3461 | CALL FIX_DESCRIPTOR | ||
| 3462 | MOV SI,OFFSET GDTDES | ||
| 3463 | CALL FIX_DESCRIPTOR | ||
| 3464 | ; | ||
| 3465 | ; Enable address line 20 | ||
| 3466 | ; | ||
| 3467 | |||
| 3468 | ;; | ||
| 3469 | ;; Enable address line 20 on the PC AT or activate A20-A23 on the 6300 PLUS. | ||
| 3470 | ;; The former can be done by placing 0dfh in AH and activating the keyboard | ||
| 3471 | ;; processor. On the PLUS, 90h goes in AL and the port at 03f20h is written. | ||
| 3472 | ;; So the combined value of 0df90h can be used for both machines with | ||
| 3473 | ;; appropriate coding of the called routine A20. | ||
| 3474 | ;; | ||
| 3475 | |||
| 3476 | ;; MOV AH,0DFH | ||
| 3477 | mov ax,cs:[A20On] ;; set up for PLUS or AT | ||
| 3478 | CALL A20 | ||
| 3479 | Jc NR_ERR | ||
| 3480 | ; JMP SHORT IO_START ;sp | ||
| 3481 | jmp short move_main_loop ;sp | ||
| 3482 | |||
| 3483 | NR_ERR: | ||
| 3484 | MOV AL,0AAH ; Drive not ready error | ||
| 3485 | STC | ||
| 3486 | RET | ||
| 3487 | |||
| 3488 | ;IOLOOP: ;sp | ||
| 3489 | ; PUSH CX ;sp | ||
| 3490 | |||
| 3491 | move_main_loop: ;sp | ||
| 3492 | assume ds:nothing ;sp | ||
| 3493 | jcxz io_done ;sp | ||
| 3494 | mov cs:[ldx],cx ;sp | ||
| 3495 | MOV AX,80H | ||
| 3496 | MOV DS,AX | ||
| 3497 | PUSH CS | ||
| 3498 | POP ES | ||
| 3499 | XOR SI,SI | ||
| 3500 | MOV DI,OFFSET cs:[SWAP_80] | ||
| 3501 | MOV CX,102/2 | ||
| 3502 | mov cs:[ssSave],ss | ||
| 3503 | CLD | ||
| 3504 | CLI ; Un interruptable | ||
| 3505 | REP MOVSW ; Save contents of 80:0 | ||
| 3506 | PUSH DS | ||
| 3507 | PUSH ES | ||
| 3508 | POP DS | ||
| 3509 | POP ES | ||
| 3510 | XOR DI,DI | ||
| 3511 | MOV SI,OFFSET cs:LOADALL_TBL | ||
| 3512 | MOV CX,102/2 | ||
| 3513 | REP MOVSW ; Transfer in LOADALL info | ||
| 3514 | DW 050FH ; LOADALL INSTRUCTION | ||
| 3515 | AFTER_LOADALL: | ||
| 3516 | ; set up stack for moving 80:0 information back again | ||
| 3517 | ; | ||
| 3518 | xor bp,bp | ||
| 3519 | mov ss,ax | ||
| 3520 | mov si,offset cs:[swap_80] | ||
| 3521 | mov cx,102/2 | ||
| 3522 | move_loop: | ||
| 3523 | lods word ptr cs:[si] | ||
| 3524 | mov ss:[bp],ax | ||
| 3525 | inc bp | ||
| 3526 | inc bp | ||
| 3527 | loop move_loop | ||
| 3528 | mov ss,cs:[ssSave] | ||
| 3529 | mov cx,dx | ||
| 3530 | mov si,bx | ||
| 3531 | ;critical code | ||
| 3532 | sti | ||
| 3533 | rep movsw | ||
| 3534 | cli ; bugfix sunilp | ||
| 3535 | mov ax,cs | ||
| 3536 | dec ax | ||
| 3537 | push ax | ||
| 3538 | mov ax,offset io_done | ||
| 3539 | push ax | ||
| 3540 | db 0cbh | ||
| 3541 | ; | ||
| 3542 | db 16 dup (0fah) ; bugfix sunilp | ||
| 3543 | mov ax,cs | ||
| 3544 | dec ax | ||
| 3545 | push ax | ||
| 3546 | mov ax,offset resume_int | ||
| 3547 | push ax | ||
| 3548 | db 0cbh | ||
| 3549 | ; | ||
| 3550 | resume_int: | ||
| 3551 | mov cs:[ldi],di | ||
| 3552 | mov cs:[lbx],si | ||
| 3553 | jmp move_main_loop | ||
| 3554 | |||
| 3555 | ; REP MOVSW ; Move data | ||
| 3556 | ;IO_START: | ||
| 3557 | ; JCXZ IODN | ||
| 3558 | ; MOV WORD PTR [LCX],256 ; ASSUME full block | ||
| 3559 | ; SUB CX,256 | ||
| 3560 | ; JNC IOLOOP ; OK | ||
| 3561 | ; ADD [LCX],CX ; OOPs, partial block | ||
| 3562 | ; XOR CX,CX ; This is the last block | ||
| 3563 | ; JMP IOLOOP | ||
| 3564 | |||
| 3565 | ;IODN: | ||
| 3566 | io_done: | ||
| 3567 | sti ; bugfix sunilp | ||
| 3568 | MOV CX,800H ; Retry this many times | ||
| 3569 | OFFLP: | ||
| 3570 | |||
| 3571 | ;; | ||
| 3572 | ;; Reset of line A20 on the PC AT requires writing 0ddh to the keyboard | ||
| 3573 | ;; processor. On the PLUS, the appropriate value is 00. | ||
| 3574 | ;; | ||
| 3575 | |||
| 3576 | ;; MOV AH,0DDH | ||
| 3577 | mov ax,cs:[A20Off] ;; setup for PLUS or AT. ah for IBM, al for PLUS | ||
| 3578 | CALL A20 ; Disable address line 20 | ||
| 3579 | jnc dis_done | ||
| 3580 | LOOP OFFLP | ||
| 3581 | dis_done: | ||
| 3582 | CLC | ||
| 3583 | RET | ||
| 3584 | |||
| 3585 | ;** A20 - ENABLE/DISABLE ADDRESS LINE 20 ON IBM PC-AT | ||
| 3586 | ; | ||
| 3587 | ; This routine enables/disables address line 20 by twiddling bits | ||
| 3588 | ; in one of the keyboard controller registers. | ||
| 3589 | ; | ||
| 3590 | ; SEE ALSO | ||
| 3591 | ; IBM Technical Reference Personal Computer AT Manual #1502243 | ||
| 3592 | ; Page 5-155 | ||
| 3593 | ; | ||
| 3594 | ; ENTRY | ||
| 3595 | ; AH = 0DDH to disable A20 | ||
| 3596 | ; AH = 0DFH to enable A20 | ||
| 3597 | ; EXIT | ||
| 3598 | ; CY Failed | ||
| 3599 | ; NC Succeeded | ||
| 3600 | ; USES | ||
| 3601 | ; AL, FLAGS | ||
| 3602 | ; | ||
| 3603 | ; WARNING If this routine is called in a CLI state this routine has | ||
| 3604 | ; the side effect of enabling interrupts. | ||
| 3605 | ; | ||
| 3606 | ; This routine is specific to TYPE 1 driver | ||
| 3607 | ; | ||
| 3608 | |||
| 3609 | A20: | ||
| 3610 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 3611 | ;; CS override needed on S5_FLAG to avoid phase errors on | ||
| 3612 | ;; forward declaration of this variable. | ||
| 3613 | cmp cs:[S5_FLAG],S_OLIVETTI ;; test for 6300 PLUS | ||
| 3614 | jne test_vec ;; yes, do this code | ||
| 3615 | jmp a20s5 | ||
| 3616 | test_vec: | ||
| 3617 | cmp cs:[S5_FLAG],S_VECTRA | ||
| 3618 | jne test_ps2 | ||
| 3619 | jmp VecA20 | ||
| 3620 | test_ps2: | ||
| 3621 | test cs:[sys_flg],M_PS2 ; is it a ps2 machine | ||
| 3622 | jne a20ps2 ; if yes it has separate a20 routine | ||
| 3623 | old_a20: | ||
| 3624 | CLI | ||
| 3625 | call check_a20 ; check to see if it can be enb /disb | ||
| 3626 | jc a20suc ; no it may not be toggled | ||
| 3627 | CALL E_8042 | ||
| 3628 | JNZ a20err | ||
| 3629 | MOV AL,0D1H | ||
| 3630 | OUT 64H,AL | ||
| 3631 | CALL E_8042 | ||
| 3632 | JNZ a20err | ||
| 3633 | MOV AL,AH | ||
| 3634 | OUT 60H,AL | ||
| 3635 | CALL E_8042 | ||
| 3636 | JNZ a20err | ||
| 3637 | ; | ||
| 3638 | ; We must wait for the a20 line to settle down, which (on an AT) | ||
| 3639 | ; may not happen until up to 20 usec after the 8042 has accepted | ||
| 3640 | ; the command. We make use of the fact that the 8042 will not | ||
| 3641 | ; accept another command until it is finished with the last one. | ||
| 3642 | ; The 0FFh command does a NULL 'Pulse Output Port'. Total execution | ||
| 3643 | ; time is on the order of 30 usec, easily satisfying the IBM 8042 | ||
| 3644 | ; settling requirement. (Thanks, CW!) | ||
| 3645 | ; | ||
| 3646 | mov al,0FFh ;* Pulse Output Port (pulse no lines) | ||
| 3647 | out 64H,al ;* send cmd to 8042 | ||
| 3648 | CALL E_8042 ;* wait for 8042 to accept cmd | ||
| 3649 | jnz A20Err | ||
| 3650 | |||
| 3651 | A20Suc: sti | ||
| 3652 | clc | ||
| 3653 | RET | ||
| 3654 | A20Err: sti | ||
| 3655 | stc | ||
| 3656 | ret | ||
| 3657 | ; | ||
| 3658 | ; Helper routine for A20. It waits for the keyboard controller to be "ready". | ||
| 3659 | ; | ||
| 3660 | E_8042: | ||
| 3661 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 3662 | PUSH CX | ||
| 3663 | XOR CX,CX | ||
| 3664 | E_LOOP: | ||
| 3665 | IN AL,64H | ||
| 3666 | AND AL,2 | ||
| 3667 | LOOPNZ E_LOOP | ||
| 3668 | POP CX | ||
| 3669 | RET | ||
| 3670 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3671 | ; A20 status checking. If request is to enable a20 we must check to | ||
| 3672 | ; see if it is already enabled. If so we just set the sys_flg to | ||
| 3673 | ; indicate this. On disabling the routine checks to see if disabling | ||
| 3674 | ; is allowed | ||
| 3675 | ; | ||
| 3676 | check_a20: | ||
| 3677 | assume ds:nothing,es:nothing,ss:nothing | ||
| 3678 | cmp ah,0ddh ; is it a disable operation | ||
| 3679 | jne check_a20_enable | ||
| 3680 | ; | ||
| 3681 | ; check if a20 disabling allowed | ||
| 3682 | ; | ||
| 3683 | test cs:[sys_flg],a20_st | ||
| 3684 | jne no_toggle | ||
| 3685 | toggle: clc | ||
| 3686 | ret | ||
| 3687 | ; | ||
| 3688 | ; a20 enabling, check if allowed | ||
| 3689 | ; | ||
| 3690 | check_a20_enable: | ||
| 3691 | and cs:[sys_flg], not A20_ST | ||
| 3692 | push cx | ||
| 3693 | push ds | ||
| 3694 | push si | ||
| 3695 | push es | ||
| 3696 | push di | ||
| 3697 | lds si,cs:low_mem | ||
| 3698 | les di,cs:high_mem | ||
| 3699 | mov cx,3 | ||
| 3700 | cld | ||
| 3701 | repe cmpsw | ||
| 3702 | pop di | ||
| 3703 | pop es | ||
| 3704 | pop si | ||
| 3705 | pop ds | ||
| 3706 | jcxz not_enabled | ||
| 3707 | pop cx | ||
| 3708 | or cs:[sys_flg],A20_ST | ||
| 3709 | no_toggle: | ||
| 3710 | stc | ||
| 3711 | ret | ||
| 3712 | not_enabled: | ||
| 3713 | pop cx | ||
| 3714 | clc | ||
| 3715 | ret | ||
| 3716 | |||
| 3717 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3718 | ; A20 routine for PS2s. The PS2 A20 hardware has shifted and toggling | ||
| 3719 | ; a bit in the system port is all that is required. | ||
| 3720 | A20PS2: | ||
| 3721 | assume ds:nothing,es:nothing,ss:nothing | ||
| 3722 | cli | ||
| 3723 | ; | ||
| 3724 | ; first separate disable operation from enable operation | ||
| 3725 | ; | ||
| 3726 | cmp ah,0ddh | ||
| 3727 | je disbl_PS2 | ||
| 3728 | ; | ||
| 3729 | ; enabling the a20 | ||
| 3730 | ; | ||
| 3731 | and cs:[sys_flg],not A20_ST | ||
| 3732 | in al,PS2_PORTA ; input a20 status | ||
| 3733 | test al,GATE_A20 ; is the a20 line set | ||
| 3734 | je set_it ; | ||
| 3735 | or cs:[sys_flg],A20_ST ; indicate that it was already set | ||
| 3736 | ps2a20suc: | ||
| 3737 | clc | ||
| 3738 | sti | ||
| 3739 | ret | ||
| 3740 | |||
| 3741 | set_it: push cx | ||
| 3742 | xor cx,cx | ||
| 3743 | or al,GATE_A20 | ||
| 3744 | out PS2_PORTA,al ; set it | ||
| 3745 | see_agn: | ||
| 3746 | in al,PS2_PORTA ; read status again | ||
| 3747 | test al,GATE_A20 | ||
| 3748 | loopz see_agn | ||
| 3749 | pop cx | ||
| 3750 | jz ps2err | ||
| 3751 | clc | ||
| 3752 | sti | ||
| 3753 | ret | ||
| 3754 | ; | ||
| 3755 | ; disabling the ps2 | ||
| 3756 | ; | ||
| 3757 | disbl_PS2: | ||
| 3758 | test cs:[sys_flg],A20_ST | ||
| 3759 | jne ps2a20suc | ||
| 3760 | ; | ||
| 3761 | push cx | ||
| 3762 | xor cx,cx | ||
| 3763 | in al,PS2_PORTA | ||
| 3764 | and al,not GATE_A20 | ||
| 3765 | out PS2_PORTA,al | ||
| 3766 | see_agn1: | ||
| 3767 | in al,PS2_PORTA | ||
| 3768 | test al,GATE_A20 | ||
| 3769 | loopnz see_agn1 | ||
| 3770 | pop cx | ||
| 3771 | jnz ps2err | ||
| 3772 | clc | ||
| 3773 | sti | ||
| 3774 | ret | ||
| 3775 | ; | ||
| 3776 | ps2err: | ||
| 3777 | stc | ||
| 3778 | sti | ||
| 3779 | ret | ||
| 3780 | |||
| 3781 | |||
| 3782 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3783 | ;;* VECA20 - Address enable/disable routine for Vectra family computers | ||
| 3784 | ;; | ||
| 3785 | ;; This routine does the same function as A20 for Vectra machines. | ||
| 3786 | ;; Vectra machines require writing single byte as opposed to | ||
| 3787 | ;; double byte commands to the 8041. This is due to a bug | ||
| 3788 | ;; in older versions in the Vectra 8041 controllers. IBM | ||
| 3789 | ;; machines must use double byte commands due to lack of | ||
| 3790 | ;; implementation of single byte commands in some of their machines. | ||
| 3791 | ;; | ||
| 3792 | ;; Uses al, flags | ||
| 3793 | ;; Has same results as A20 | ||
| 3794 | ;; | ||
| 3795 | VecA20: | ||
| 3796 | CLI | ||
| 3797 | call check_a20 | ||
| 3798 | jc VecA20Suc | ||
| 3799 | call E_8042 | ||
| 3800 | jnz VecA20Err | ||
| 3801 | mov al,ah ;sigle byte command is code passed | ||
| 3802 | out 64H,al | ||
| 3803 | call E_8042 | ||
| 3804 | jnz VecA20Err | ||
| 3805 | ; See A20 for a description of the following code. It simply makes | ||
| 3806 | ; sure that the previous command has been completed. We cannot | ||
| 3807 | ; pulse the command reg since there is a bug in some Vectra 8041s | ||
| 3808 | ; instead we write the byte again knowing that when this one is | ||
| 3809 | ; accepted the previous one has been processed. | ||
| 3810 | mov al,ah | ||
| 3811 | out 64H,al | ||
| 3812 | call E_8042 | ||
| 3813 | jnz VecA20Err | ||
| 3814 | VecA20Suc: | ||
| 3815 | sti | ||
| 3816 | clc | ||
| 3817 | ret | ||
| 3818 | VecA20Err: | ||
| 3819 | sti | ||
| 3820 | stc | ||
| 3821 | ret | ||
| 3822 | |||
| 3823 | |||
| 3824 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3825 | ;;* A20S5 - Address enable/disable routine for the 6300 PLUS. | ||
| 3826 | ;; | ||
| 3827 | ;; This routine enables lines A20-A23 on the PLUS by writing | ||
| 3828 | ;; to port 03f20h. Bit 7 turns the lines on, and bit 4 sets | ||
| 3829 | ;; the power-up bit. To disable the lines, the processor | ||
| 3830 | ;; must be reset. This is done by saving the world and | ||
| 3831 | ;; jumping to the ROM 80286 reset code. Since the power-up bit | ||
| 3832 | ;; is set, the data segment is set to the BiosSeg at 40h | ||
| 3833 | ;; and a jump is then made to the address at RealLoc1. | ||
| 3834 | ;; At RealLoc1, one can find the CS:IP where the code | ||
| 3835 | ;; is to continue. | ||
| 3836 | ;; | ||
| 3837 | ;; Uses ax, flags. | ||
| 3838 | ;; Returns with zero flag set. | ||
| 3839 | ;; | ||
| 3840 | A20S5: test [reboot_flg],0ffh ;; sunilp | ||
| 3841 | jne a20s5boot ;; sunilp | ||
| 3842 | cli | ||
| 3843 | or al,al ;; if zero, then resetting processor | ||
| 3844 | jnz A20S5Next | ||
| 3845 | call RSet ;; must return with entry value of ax | ||
| 3846 | A20S5Next: | ||
| 3847 | push dx ;; set/reset port | ||
| 3848 | mov dx,3f20h | ||
| 3849 | out dx,al | ||
| 3850 | pop dx | ||
| 3851 | clc ;; sunilp modification cy flag now important | ||
| 3852 | STI | ||
| 3853 | RET | ||
| 3854 | |||
| 3855 | ;;* a20S5BOOT - This code bypasses the processor reset on a reboot | ||
| 3856 | ;; of the 6300 PLUS. Otherwise the machine hangs. | ||
| 3857 | a20s5BOOT: ;; use this code before reboot | ||
| 3858 | cli | ||
| 3859 | jmp short a20s5next | ||
| 3860 | |||
| 3861 | OldStackSeg dw 0 ;; used during PLUS processor reset | ||
| 3862 | ;; to save the stack segment | ||
| 3863 | |||
| 3864 | ;;* Rset - Reset the 80286 in order to turn off the address lines | ||
| 3865 | ;; on the 6300 PLUS. Only way to do this on the | ||
| 3866 | ;; current hardware. The processor itself can be | ||
| 3867 | ;; reset by reading or writing prot 03f00h | ||
| 3868 | ;; | ||
| 3869 | ;; Uses flags. | ||
| 3870 | ;; | ||
| 3871 | RSet: | ||
| 3872 | pusha ;; save world | ||
| 3873 | push ds ;; save segments | ||
| 3874 | push es | ||
| 3875 | mov ax,BiosSeg ;; point to the bios segment | ||
| 3876 | mov ds,ax ;; ds -> 40h | ||
| 3877 | assume ds:BiosSeg | ||
| 3878 | push word ptr [RealLoc1] ;; save what might have been here | ||
| 3879 | push word ptr [RealLoc1+2] | ||
| 3880 | mov word ptr [RealLoc1],cs:[offset ReturnBack] ;; load our return address | ||
| 3881 | mov word ptr [RealLoc1+2],cs | ||
| 3882 | assume ds:nothing | ||
| 3883 | mov [OldStackSeg],ss ;; save the stack segment, too | ||
| 3884 | mov dx,03f00h ;; reset the processor | ||
| 3885 | in ax,dx | ||
| 3886 | nop | ||
| 3887 | nop | ||
| 3888 | nop | ||
| 3889 | cli | ||
| 3890 | hlt ;; should never get here | ||
| 3891 | ReturnBack: | ||
| 3892 | mov ss,[OldStackSeg] ;; start the recovery | ||
| 3893 | assume ds:BiosSeg | ||
| 3894 | pop word ptr [RealLoc1+2] | ||
| 3895 | pop word ptr [RealLoc1] | ||
| 3896 | pop es | ||
| 3897 | pop ds | ||
| 3898 | popa | ||
| 3899 | ret | ||
| 3900 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 3901 | blkmov_386: ;_protect: | ||
| 3902 | assume ds:int13code,es:nothing,ss:nothing | ||
| 3903 | ; | ||
| 3904 | ; Compute 32 bit address of start of I/O | ||
| 3905 | ; | ||
| 3906 | add ax,word ptr [base_addr] | ||
| 3907 | adc dx,word ptr [base_addr + 2] | ||
| 3908 | ; | ||
| 3909 | push cx | ||
| 3910 | ; | ||
| 3911 | ; Are we in virtual mode | ||
| 3912 | ; | ||
| 3913 | smsw cx | ||
| 3914 | test cx,01B ; is the pe bit set | ||
| 3915 | je pr_mode_tran | ||
| 3916 | |||
| 3917 | jmp int_15_tran | ||
| 3918 | ; | ||
| 3919 | ; Dispatch on function | ||
| 3920 | ; | ||
| 3921 | pr_mode_tran: | ||
| 3922 | or bh,bh | ||
| 3923 | jz read_it_1 | ||
| 3924 | ; | ||
| 3925 | ; Write | ||
| 3926 | ; | ||
| 3927 | ; Update ES descriptor with address of track in cache | ||
| 3928 | ; | ||
| 3929 | mov si,offset es_des | ||
| 3930 | mov [si].bas_0_15,ax | ||
| 3931 | mov [si].bas_16_23,dl | ||
| 3932 | mov [si].bas_24_31,dh | ||
| 3933 | ; | ||
| 3934 | ; Update DS descriptor with transfer address | ||
| 3935 | ; | ||
| 3936 | mov ax,es | ||
| 3937 | mov cx,16 | ||
| 3938 | mul cx | ||
| 3939 | mov si,offset ds_des | ||
| 3940 | mov [si].bas_0_15,ax | ||
| 3941 | mov [si].bas_16_23,dl | ||
| 3942 | mov [si].bas_24_31,dh | ||
| 3943 | |||
| 3944 | |||
| 3945 | ; Switch SI and DI for write transfer | ||
| 3946 | |||
| 3947 | mov si,di | ||
| 3948 | xor di,di | ||
| 3949 | |||
| 3950 | jmp short set_trans_1 | ||
| 3951 | |||
| 3952 | read_it_1: | ||
| 3953 | ; | ||
| 3954 | ; Update DS descriptor with address of track in cache | ||
| 3955 | ; | ||
| 3956 | mov si,offset ds_des | ||
| 3957 | mov [si].bas_0_15,ax | ||
| 3958 | mov [si].bas_16_23,dl | ||
| 3959 | mov [si].bas_24_31,dh | ||
| 3960 | ; | ||
| 3961 | ; Update ES descriptor with transfer address | ||
| 3962 | ; | ||
| 3963 | mov ax,es | ||
| 3964 | mov cx,16 | ||
| 3965 | mul cx | ||
| 3966 | mov si,offset es_des | ||
| 3967 | mov [si].bas_0_15,ax | ||
| 3968 | mov [si].bas_16_23,dl | ||
| 3969 | mov [si].bas_24_31,dh | ||
| 3970 | ; | ||
| 3971 | ; Keep SI and DI the same for read transfer | ||
| 3972 | ; | ||
| 3973 | xor si,si | ||
| 3974 | |||
| 3975 | set_trans_1: | ||
| 3976 | ; | ||
| 3977 | ; Restore Transfer Count | ||
| 3978 | ; | ||
| 3979 | pop cx | ||
| 3980 | |||
| 3981 | ; | ||
| 3982 | mov ax,cs:[A20On] | ||
| 3983 | call A20 | ||
| 3984 | jc nr_err_1 | ||
| 3985 | ; | ||
| 3986 | ; we shall do the transfer 1024 words at a time | ||
| 3987 | ; | ||
| 3988 | db 66h | ||
| 3989 | push ax | ||
| 3990 | mov bx,cx | ||
| 3991 | assume ds:nothing | ||
| 3992 | pr_io_agn_1: | ||
| 3993 | mov cx,1024 | ||
| 3994 | cmp bx,cx | ||
| 3995 | ja pr_strt_1 | ||
| 3996 | mov cx,bx | ||
| 3997 | pr_strt_1: | ||
| 3998 | sub bx,cx | ||
| 3999 | cli ; Un interruptable | ||
| 4000 | cld | ||
| 4001 | lgdt fword ptr emm_gdt | ||
| 4002 | |||
| 4003 | |||
| 4004 | ; | ||
| 4005 | ; Switch to protected mode | ||
| 4006 | ; | ||
| 4007 | db 66h,0Fh, 20h, 0 ;mov eax,cr0 | ||
| 4008 | or ax,1 | ||
| 4009 | db 66h,0Fh,22h, 0 ;mov cr0,eax | ||
| 4010 | ; | ||
| 4011 | ; Clear prefetch queue | ||
| 4012 | ; | ||
| 4013 | db 0eah ; far jump | ||
| 4014 | dw offset flush_prefetch | ||
| 4015 | dw cs_des - start_gdt | ||
| 4016 | ; | ||
| 4017 | flush_prefetch: | ||
| 4018 | assume cs:nothing | ||
| 4019 | ; | ||
| 4020 | ; Initialize segment registers | ||
| 4021 | ; | ||
| 4022 | mov ax,ds_des - start_gdt | ||
| 4023 | mov ds,ax | ||
| 4024 | assume ds:nothing | ||
| 4025 | mov ax,es_des - start_gdt | ||
| 4026 | mov es,ax | ||
| 4027 | assume es:nothing | ||
| 4028 | shr cx,1 ; convert word count to dword count | ||
| 4029 | db 0f3h,066h,0a5h ; rep movsd | ||
| 4030 | ; rep movsw ; Move data | ||
| 4031 | ; | ||
| 4032 | ; | ||
| 4033 | ; Return to Real Mode | ||
| 4034 | ; | ||
| 4035 | ; | ||
| 4036 | db 66h,0Fh, 20h, 0 ; mov eax,cr0 | ||
| 4037 | and ax,0FFFEh | ||
| 4038 | db 66h,0Fh, 22h, 0 ; mov cr0,eax | ||
| 4039 | ; | ||
| 4040 | ; Flush Prefetch Queue | ||
| 4041 | ; | ||
| 4042 | db 0EAh ; Far jump | ||
| 4043 | dw offset flushcs | ||
| 4044 | cod_seg dw ? ; Fixed up at initialization time | ||
| 4045 | assume cs:Int13Code | ||
| 4046 | flushcs: | ||
| 4047 | ; | ||
| 4048 | sti | ||
| 4049 | ; see if transfer done else go to do next block | ||
| 4050 | ; | ||
| 4051 | or bx,bx | ||
| 4052 | jne pr_io_agn_1 | ||
| 4053 | ; | ||
| 4054 | db 66h | ||
| 4055 | pop ax | ||
| 4056 | mov ax,cs | ||
| 4057 | mov es,ax | ||
| 4058 | assume es:nothing | ||
| 4059 | mov ds,ax | ||
| 4060 | assume ds:Int13Code | ||
| 4061 | |||
| 4062 | mov cx,800h ; Retry this many times | ||
| 4063 | offlp_1: | ||
| 4064 | mov ax,cs:[A20Off] | ||
| 4065 | call A20 ; Disable address line 20 | ||
| 4066 | jnc offlp1_out | ||
| 4067 | loop offlp_1 | ||
| 4068 | offlp1_out: | ||
| 4069 | clc | ||
| 4070 | ret | ||
| 4071 | |||
| 4072 | nr_err_1: | ||
| 4073 | |||
| 4074 | mov al,0AAh ; Drive not ready error | ||
| 4075 | stc | ||
| 4076 | ret | ||
| 4077 | ; | ||
| 4078 | int_15_tran: | ||
| 4079 | assume ds:int13code,es:nothing,ss:nothing | ||
| 4080 | or bh,bh | ||
| 4081 | jz read_it_2 | ||
| 4082 | ; | ||
| 4083 | ; Write | ||
| 4084 | ; | ||
| 4085 | ; Update tgt descriptor with address of track in cache | ||
| 4086 | ; | ||
| 4087 | mov si,offset tgt | ||
| 4088 | mov [si].bas_0_15,ax | ||
| 4089 | mov [si].bas_16_23,dl | ||
| 4090 | mov [si].bas_24_31,dh | ||
| 4091 | ; | ||
| 4092 | ; Update src descriptor with transfer address | ||
| 4093 | ; | ||
| 4094 | mov ax,es | ||
| 4095 | mov cx,16 | ||
| 4096 | mul cx | ||
| 4097 | add ax,di | ||
| 4098 | adc dx,0 | ||
| 4099 | mov si,offset src | ||
| 4100 | mov [si].bas_0_15,ax | ||
| 4101 | mov [si].bas_16_23,dl | ||
| 4102 | mov [si].bas_24_31,dh | ||
| 4103 | ; | ||
| 4104 | jmp short set_trans_2 | ||
| 4105 | |||
| 4106 | read_it_2: | ||
| 4107 | ; | ||
| 4108 | ; Update src descriptor with address of track in cache | ||
| 4109 | ; | ||
| 4110 | mov si,offset src | ||
| 4111 | mov [si].bas_0_15,ax | ||
| 4112 | mov [si].bas_16_23,dl | ||
| 4113 | mov [si].bas_24_31,dh | ||
| 4114 | ; | ||
| 4115 | ; Update tgt descriptor with transfer address | ||
| 4116 | ; | ||
| 4117 | mov ax,es | ||
| 4118 | mov cx,16 | ||
| 4119 | mul cx | ||
| 4120 | add ax,di | ||
| 4121 | adc dx,0 | ||
| 4122 | mov si,offset tgt | ||
| 4123 | mov [si].bas_0_15,ax | ||
| 4124 | mov [si].bas_16_23,dl | ||
| 4125 | mov [si].bas_24_31,dh | ||
| 4126 | ; | ||
| 4127 | set_trans_2: | ||
| 4128 | ; | ||
| 4129 | ; Restore Transfer Count | ||
| 4130 | ; | ||
| 4131 | pop bx | ||
| 4132 | |||
| 4133 | ; | ||
| 4134 | ; we shall do the transfer 1024 words at a time | ||
| 4135 | ; | ||
| 4136 | pr_io_agn_2: | ||
| 4137 | mov cx,1024 | ||
| 4138 | cmp bx,cx | ||
| 4139 | ja pr_strt_2 | ||
| 4140 | mov cx,bx | ||
| 4141 | pr_strt_2: | ||
| 4142 | sub bx,cx | ||
| 4143 | push cs | ||
| 4144 | pop es | ||
| 4145 | mov si,offset int15_gdt | ||
| 4146 | mov ax,emm_blkm shl 8 | ||
| 4147 | int emm_int | ||
| 4148 | jc nr_err_1 | ||
| 4149 | ; | ||
| 4150 | ; | ||
| 4151 | ; see if transfer done else fo to do next block | ||
| 4152 | ; | ||
| 4153 | or bx,bx | ||
| 4154 | je io_exit | ||
| 4155 | ; | ||
| 4156 | add [src.bas_0_15],2048 | ||
| 4157 | adc [src.bas_16_23],0 | ||
| 4158 | adc [src.bas_24_31],0 | ||
| 4159 | ; | ||
| 4160 | add [tgt.bas_0_15],2048 | ||
| 4161 | adc [tgt.bas_16_23],0 | ||
| 4162 | adc [tgt.bas_24_31],0 | ||
| 4163 | ; | ||
| 4164 | jmp pr_io_agn_2 | ||
| 4165 | io_exit: | ||
| 4166 | clc | ||
| 4167 | ret | ||
| 4168 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4169 | ;** SEG_SET - Set up a LOADALL segment descriptor as in REAL mode | ||
| 4170 | ; | ||
| 4171 | ; This routine sets the BASE value in the segment descriptor | ||
| 4172 | ; pointed to by DS:SI with the segment value in AX as the 80286 | ||
| 4173 | ; does in REAL mode. This routine is used to set a descriptor | ||
| 4174 | ; which DOES NOT have an extended 24 bit address. | ||
| 4175 | ; | ||
| 4176 | ; SEE ALSO | ||
| 4177 | ; INTEL special documentation of LOADALL instruction | ||
| 4178 | ; | ||
| 4179 | ; ENTRY: | ||
| 4180 | ; DS:SI -> Seg register descriptor | ||
| 4181 | ; AX is seg register value | ||
| 4182 | ; EXIT: | ||
| 4183 | ; NONE | ||
| 4184 | ; USES: | ||
| 4185 | ; AX | ||
| 4186 | ; | ||
| 4187 | ; This routine is specific to TYPE 1 driver | ||
| 4188 | ; | ||
| 4189 | |||
| 4190 | SEG_SET: | ||
| 4191 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 4192 | PUSH DX | ||
| 4193 | PUSH CX | ||
| 4194 | MOV CX,16 | ||
| 4195 | MUL CX ; Believe or not, this is faster than a 32 bit SHIFT | ||
| 4196 | MOV WORD PTR [SI.SEG_BASE],AX | ||
| 4197 | MOV BYTE PTR [SI.SEG_BASE + 2],DL | ||
| 4198 | POP CX | ||
| 4199 | POP DX | ||
| 4200 | RET | ||
| 4201 | |||
| 4202 | ;** FIX_DESCRIPTOR - Shuffle GTD IDT descriptors | ||
| 4203 | ; | ||
| 4204 | ; The segment descriptors for the IDT and GDT are stored | ||
| 4205 | ; by the SIDT instruction in a slightly different format | ||
| 4206 | ; than the LOADALL instruction wants them. This routine | ||
| 4207 | ; performs the transformation by PUSHing the contents | ||
| 4208 | ; of the descriptor, and then POPing them in a different | ||
| 4209 | ; order. | ||
| 4210 | ; | ||
| 4211 | ; SEE ALSO | ||
| 4212 | ; INTEL special documentation of LOADALL instruction | ||
| 4213 | ; INTEL 80286 processor handbook description of SIDT instruction | ||
| 4214 | ; | ||
| 4215 | ; ENTRY: | ||
| 4216 | ; DS:SI points to IDT or GDT descriptor in SIDT form | ||
| 4217 | ; EXIT: | ||
| 4218 | ; DS:SI points to IDT or GDT descriptor in LOADALL form | ||
| 4219 | ; USES: | ||
| 4220 | ; 6 words of stack | ||
| 4221 | ; | ||
| 4222 | ; NOTE: The transformation is reversable, so this routine | ||
| 4223 | ; will also work to transform a descriptor in LOADALL | ||
| 4224 | ; format to one in SIDT format. | ||
| 4225 | ; | ||
| 4226 | ; Specific to TYPE 1 driver | ||
| 4227 | ; | ||
| 4228 | |||
| 4229 | FIX_DESCRIPTOR: | ||
| 4230 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 4231 | PUSH WORD PTR [SI + 4] | ||
| 4232 | PUSH WORD PTR [SI + 2] | ||
| 4233 | PUSH WORD PTR [SI] | ||
| 4234 | POP WORD PTR [SI + 4] | ||
| 4235 | POP WORD PTR [SI] | ||
| 4236 | POP WORD PTR [SI + 2] | ||
| 4237 | RET | ||
| 4238 | |||
| 4239 | ;** DATA SPECIFIC TO THE LOADALL INSTRUCTION USAGE | ||
| 4240 | ; | ||
| 4241 | ; SWAP_80 and LOADALL_TBL are data elements specific to the use | ||
| 4242 | ; of the LOADALL instruction by TYPE 1 drivers. | ||
| 4243 | ; | ||
| 4244 | |||
| 4245 | ; | ||
| 4246 | ; Swap buffer for contents of 80:0 | ||
| 4247 | ; | ||
| 4248 | EVEN ; Force word alignment of SWAP_80 and LOADALL_TBL | ||
| 4249 | |||
| 4250 | SWAP_80 DB 102 DUP(?) | ||
| 4251 | ssSave dw ? | ||
| 4252 | |||
| 4253 | ; | ||
| 4254 | ; LOADALL data buffer placed at 80:0 | ||
| 4255 | ; | ||
| 4256 | LOADALL_TBL LABEL BYTE | ||
| 4257 | DB 6 DUP(0) | ||
| 4258 | LDSW DW ? | ||
| 4259 | DB 14 DUP (0) | ||
| 4260 | TR DW 0 | ||
| 4261 | FLAGS DW 0 ; High 4 bits 0, Int off, Direction clear | ||
| 4262 | ; Trace clear. Rest don't care. | ||
| 4263 | LIP DW OFFSET AFTER_LOADALL | ||
| 4264 | LDT DW 0 | ||
| 4265 | LDSS DW 8000h | ||
| 4266 | LSSS DW ? | ||
| 4267 | LCSS DW ? | ||
| 4268 | LESS DW ? | ||
| 4269 | LDI DW ? | ||
| 4270 | LSI DW ? | ||
| 4271 | LBP DW ? | ||
| 4272 | LSP DW ? | ||
| 4273 | LBX DW ? | ||
| 4274 | LDX DW ? | ||
| 4275 | LCX DW ? | ||
| 4276 | LAX DW 80H | ||
| 4277 | ESDES SEGREG_DESCRIPTOR <> | ||
| 4278 | CSDES SEGREG_DESCRIPTOR <> | ||
| 4279 | SSDES SEGREG_DESCRIPTOR <> | ||
| 4280 | DSDES SEGREG_DESCRIPTOR <> | ||
| 4281 | GDTDES DTR_DESCRIPTOR <> | ||
| 4282 | LDTDES DTR_DESCRIPTOR <0D000H,0,0FFH,0088H> | ||
| 4283 | IDTDES DTR_DESCRIPTOR <> | ||
| 4284 | TSSDES DTR_DESCRIPTOR <0C000H,0,0FFH,0800H> | ||
| 4285 | |||
| 4286 | ;** TRUE LOCATION OF ABOVE_PID | ||
| 4287 | ; | ||
| 4288 | ; Define the TRUE (runtime TYPE 2 driver) location of ABOVE_PID. | ||
| 4289 | ; This is the only piece of TYPE 2 specific data that we need | ||
| 4290 | ; in the resident image. We must define it HERE rather than down | ||
| 4291 | ; at ABOVE_BLKMOV so that we have its TRUE location after the | ||
| 4292 | ; TYPE 2 code is swapped in at initialization. If we defined | ||
| 4293 | ; it down at ABOVE_BLKMOV any instruction like: | ||
| 4294 | ; | ||
| 4295 | ; MOV DX,[ABOVE_PID] | ||
| 4296 | ; | ||
| 4297 | ; Would have to be "fixed up" when we moved the ABOVE_BLKMOV | ||
| 4298 | ; code into its final location. | ||
| 4299 | ; | ||
| 4300 | |||
| 4301 | ABOVE_PID EQU WORD PTR $ - 2 ; TRUE location of ABOVE_PID | ||
| 4302 | |||
| 4303 | ; | ||
| 4304 | ; The following label defines the end of the region where BLKMOV code | ||
| 4305 | ; may be swapped in. BLKMOV code to be swapped in MUST fit | ||
| 4306 | ; between DRIVE_CODE and DRIVE_END | ||
| 4307 | ; | ||
| 4308 | DRIVE_END LABEL WORD | ||
| 4309 | |||
| 4310 | |||
| 4311 | BREAK <INT 19/9 Handlers> | ||
| 4312 | |||
| 4313 | ; | ||
| 4314 | ; As discussed above in the documentation of the EMM_CTRL sector it | ||
| 4315 | ; is necessary to hear about system re-boots so that the EMM_ISDRIVER | ||
| 4316 | ; bits in the EMM_REC structure can be manipulated correctly. | ||
| 4317 | ; | ||
| 4318 | ; On the IBM PC family of machines there are two events which cause a | ||
| 4319 | ; "soft" system re-boot which we might expect the EMM_CTRL sector to | ||
| 4320 | ; survive through. One is software INT 19H, the other is the Ctrl-Alt-Del | ||
| 4321 | ; character sequence which can be detected by "listening" on INT 9 for | ||
| 4322 | ; it. The code below consists of a handler for INT 19H, a handler | ||
| 4323 | ; for INT 9, and a drive TYPE dependant piece of code. | ||
| 4324 | ; | ||
| 4325 | ; The drive TYPE dependant piece of code works as follows: | ||
| 4326 | ; | ||
| 4327 | ; TYPE 1 uses EMM_CTRL sector so it turnd off the | ||
| 4328 | ; EMM_ISDRIVER bit in the record indicated by MY_EMM_REC. | ||
| 4329 | ; EACH TYPE 1 driver in the system includes the INT 19/9 | ||
| 4330 | ; code. | ||
| 4331 | ; | ||
| 4332 | ; TYPE 2 DOES NOT use the EMM_CTRL sector but it still has | ||
| 4333 | ; a handler. What this handler does is issue an | ||
| 4334 | ; ABOVE_DEALLOC call to deallocate the Above Board | ||
| 4335 | ; memory allocated to INT13. In current versions | ||
| 4336 | ; of the EMM device driver this step is unnecessary | ||
| 4337 | ; as the EMM device driver is thrown away together | ||
| 4338 | ; with all of the allocation information when the system | ||
| 4339 | ; is re-booted. We do it anyway because some future version | ||
| 4340 | ; of the EMM device driver may be smarter and retain | ||
| 4341 | ; allocation information through a warm-boot. Currently, | ||
| 4342 | ; doing this doesn't hurt anything. Since this code cannot | ||
| 4343 | ; do a global ABOVE_DEALLOC for all TYPE 2 drivers in the | ||
| 4344 | ; system, it does an ABOVE_DEALLOC only for its memory | ||
| 4345 | ; and EACH TYPE 2 driver in the system includes the INT 19/9 | ||
| 4346 | ; code. | ||
| 4347 | ; | ||
| 4348 | |||
| 4349 | ; | ||
| 4350 | ; Storage locations for the "next" INT 19 and INT 9 vectors, the ones | ||
| 4351 | ; that were in the interrupt table when the device driver was loaded. | ||
| 4352 | ; They are initialized to -1 to indicate they contain no useful information. | ||
| 4353 | ; | ||
| 4354 | OLD_19 LABEL DWORD | ||
| 4355 | DW -1 | ||
| 4356 | DW -1 | ||
| 4357 | |||
| 4358 | OLD_9 LABEL DWORD | ||
| 4359 | DW -1 | ||
| 4360 | DW -1 | ||
| 4361 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4362 | ; modification to meet new memory allocation standard | ||
| 4363 | OLD_15 LABEL DWORD | ||
| 4364 | DW -1 | ||
| 4365 | DW -1 | ||
| 4366 | int15_size dw 0 | ||
| 4367 | ; | ||
| 4368 | ; | ||
| 4369 | INT_15: | ||
| 4370 | ASSUME DS:NOTHING,SS:NOTHING,ES:NOTHING | ||
| 4371 | ; | ||
| 4372 | ; This piece of code determines the size of extended memory | ||
| 4373 | ; which was allocated before this driver and then subtracts | ||
| 4374 | ; the amount it has allocated for itself | ||
| 4375 | ; | ||
| 4376 | ; inputs: ah = 88h is of interest | ||
| 4377 | ; outputs: ax = size of extended memory allocated by all before and | ||
| 4378 | ; including us | ||
| 4379 | ; regs used: flags | ||
| 4380 | ; | ||
| 4381 | pushf | ||
| 4382 | cmp ah,88h | ||
| 4383 | je mem_det | ||
| 4384 | popf | ||
| 4385 | jmp [old_15] | ||
| 4386 | mem_det: | ||
| 4387 | mov ax,[int15_size] | ||
| 4388 | popf | ||
| 4389 | clc | ||
| 4390 | sti | ||
| 4391 | iret | ||
| 4392 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4393 | ;** INT 9 Keyboard handler | ||
| 4394 | ; | ||
| 4395 | ; All this piece of code does is look for the Ctrl-Alt-Del event. | ||
| 4396 | ; If key is not Ctrl-Alt-Del, it jumps to OLD_9 without doing | ||
| 4397 | ; anything. If the Ctrl-Alt-Del key is detected it calls | ||
| 4398 | ; RESET_SYSTEM to perform driver TYPE specific re-boot code. | ||
| 4399 | ; It then resets INT 13H to disable the cache and then jumps to | ||
| 4400 | ; OLD_9 to pass on the event. | ||
| 4401 | ; | ||
| 4402 | ; NOTE THAT UNLIKE INT 19 THIS HANDLER DOES NOT NEED TO RESET | ||
| 4403 | ; THE INT 9 AND INT 19 VECTORS. This is because the Ctrl-Alt-Del | ||
| 4404 | ; IBM ROM re-boot code resets these vectors. | ||
| 4405 | ; | ||
| 4406 | ; We would LIKE to ALSO flush the cache, but we can't. For one the | ||
| 4407 | ; keyboard is at a higher IRQ than the disk. We could EOI the keyboard, | ||
| 4408 | ; but this doesn't fix the second problem. INT 13s to write | ||
| 4409 | ; out any dirty tracks take a LONG time, so long that we lose | ||
| 4410 | ; the key. In other words we see Ctrl-Alt-Del, but none of the | ||
| 4411 | ; INT 9 handlers after us will. | ||
| 4412 | ; | ||
| 4413 | ; | ||
| 4414 | ; SEE ALSO | ||
| 4415 | ; INT 9 IBM ROM code in ROM BIOS listing of | ||
| 4416 | ; IBM PC Technical Reference manual for any PC family member | ||
| 4417 | ; | ||
| 4418 | ; ENTRY | ||
| 4419 | ; NONE | ||
| 4420 | ; EXIT | ||
| 4421 | ; NONE, via OLD_9 | ||
| 4422 | ; USES | ||
| 4423 | ; FLAGS | ||
| 4424 | ; | ||
| 4425 | ; THIS CODE IS USED BY TYPE 1,2 drivers. | ||
| 4426 | ; | ||
| 4427 | |||
| 4428 | INT_9: | ||
| 4429 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 4430 | PUSH AX | ||
| 4431 | PUSH DS | ||
| 4432 | IN AL,60H | ||
| 4433 | CMP AL,83 ; DEL key? | ||
| 4434 | JNZ CHAIN ; No | ||
| 4435 | XOR AX,AX | ||
| 4436 | MOV DS,AX | ||
| 4437 | MOV AL,BYTE PTR DS:[417H] ; Get KB flag | ||
| 4438 | NOT AL | ||
| 4439 | TEST AL,0CH ; Ctrl Alt? | ||
| 4440 | JNZ CHAIN ; No | ||
| 4441 | MOV [INT_13_BUSY],1 ; Exclude | ||
| 4442 | ; | ||
| 4443 | ; We would LIKE to do this, always but we can't. For one the keyboard | ||
| 4444 | ; is at a higher IRQ than the disk. We can EOI the keyboard, | ||
| 4445 | ; but this doesn't fix the second problem. INT 13s to write | ||
| 4446 | ; out any dirty tracks take a LONG time, so long that we loose | ||
| 4447 | ; the key. In other words we see Ctrl-Alt-Del, but none of the | ||
| 4448 | ; INT 9 handlers after us will. | ||
| 4449 | ; | ||
| 4450 | CMP [REBOOT_FLUSH],0 ; Reboot flush enabled? | ||
| 4451 | JZ NO_REBOOT_FLUSH ; No | ||
| 4452 | CMP [DIRTY_CACHE],0 ; Anything to do? | ||
| 4453 | JZ NO_REBOOT_FLUSH ; No | ||
| 4454 | MOV AL,20H | ||
| 4455 | OUT 20H,AL ; EOI the keyboard int | ||
| 4456 | CALL FLUSH_WHOLE_CACHE_SAV ; Flush cache | ||
| 4457 | NO_REBOOT_FLUSH: | ||
| 4458 | ; | ||
| 4459 | CALL RESET_SYSTEM ; Ctrl Alt DEL | ||
| 4460 | ; | ||
| 4461 | ; Reset INT 13 vector to turn cache off | ||
| 4462 | ; | ||
| 4463 | MOV AX,WORD PTR [OLD_13] | ||
| 4464 | CLI | ||
| 4465 | MOV WORD PTR DS:[13H * 4],AX | ||
| 4466 | MOV AX,WORD PTR [OLD_13 + 2] | ||
| 4467 | MOV WORD PTR DS:[(13H * 4) + 2],AX | ||
| 4468 | ; | ||
| 4469 | ; Reset INT 1C vector to turn cache off | ||
| 4470 | ; | ||
| 4471 | ; MOV AX,WORD PTR [OLD_1C] | ||
| 4472 | ; MOV WORD PTR DS:[1CH * 4],AX | ||
| 4473 | ; MOV AX,WORD PTR [OLD_1C + 2] | ||
| 4474 | ; MOV WORD PTR DS:[(1CH * 4) + 2],AX | ||
| 4475 | MOV [INT_13_BUSY],0 | ||
| 4476 | CHAIN: | ||
| 4477 | POP DS | ||
| 4478 | POP AX | ||
| 4479 | JMP [OLD_9] | ||
| 4480 | |||
| 4481 | ;** INT 19 Software re-boot handler | ||
| 4482 | ; | ||
| 4483 | ; All this piece of code does is sit on INT 19 waiting for | ||
| 4484 | ; a re-boot to be signaled by being called. It calls | ||
| 4485 | ; FLUSH_WHOLE_CACHE_SAV to flush out any dirty cache info then | ||
| 4486 | ; RESET_SYSTEM to perform driver TYPE specific re-boot code, | ||
| 4487 | ; resets the INT 19, INT 13 and INT 9 vectors, | ||
| 4488 | ; and then jumps to OLD_19 to pass on the event. | ||
| 4489 | ; | ||
| 4490 | ; NOTE THAT UNLIKE INT 9 THIS HANDLER NEEDS TO RESET | ||
| 4491 | ; THE INT 9 AND INT 19 VECTORS. This is because the INT 19 | ||
| 4492 | ; IBM ROM re-boot code DOES NOT reset these vectors, and we | ||
| 4493 | ; don't want to leave them pointing to routines that are not | ||
| 4494 | ; protected from getting stomped on by the re-boot. | ||
| 4495 | ; | ||
| 4496 | ; SEE ALSO | ||
| 4497 | ; INT 19 IBM ROM code in ROM BIOS listing of | ||
| 4498 | ; IBM PC Technical Reference manual for any PC family member | ||
| 4499 | ; | ||
| 4500 | ; ENTRY | ||
| 4501 | ; NONE | ||
| 4502 | ; EXIT | ||
| 4503 | ; NONE, via OLD_19 | ||
| 4504 | ; USES | ||
| 4505 | ; FLAGS | ||
| 4506 | ; | ||
| 4507 | ; THIS CODE IS USED BY TYPE 1,2 drivers. | ||
| 4508 | ; | ||
| 4509 | |||
| 4510 | INT_19: | ||
| 4511 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 4512 | MOV [INT_13_BUSY],1 ; Exclude | ||
| 4513 | cmp [reboot_flush],0 ; | ||
| 4514 | je no_flush | ||
| 4515 | CALL FLUSH_WHOLE_CACHE_SAV ; Flush out the cache | ||
| 4516 | no_flush: | ||
| 4517 | CALL RESET_SYSTEM | ||
| 4518 | PUSH AX | ||
| 4519 | PUSH DS | ||
| 4520 | XOR AX,AX | ||
| 4521 | MOV DS,AX | ||
| 4522 | MOV AX,WORD PTR [OLD_13] | ||
| 4523 | CLI | ||
| 4524 | ; | ||
| 4525 | ; Reset INT 13 vector to trun cache off | ||
| 4526 | ; | ||
| 4527 | MOV WORD PTR DS:[13H * 4],AX | ||
| 4528 | MOV AX,WORD PTR [OLD_13 + 2] | ||
| 4529 | MOV WORD PTR DS:[(13H * 4) + 2],AX | ||
| 4530 | ; | ||
| 4531 | ; Reset INT 1C vector to turn cache off | ||
| 4532 | ; | ||
| 4533 | ; MOV AX,WORD PTR [OLD_1C] | ||
| 4534 | ; MOV WORD PTR DS:[1CH * 4],AX | ||
| 4535 | ; MOV AX,WORD PTR [OLD_1C + 2] | ||
| 4536 | ; MOV WORD PTR DS:[(1CH * 4) + 2],AX | ||
| 4537 | ; | ||
| 4538 | ; Since INT 19 DOES NOT reset any vectors (like INT 9 Ctrl Alt DEL does), | ||
| 4539 | ; we must replace those vectors we have mucked with. | ||
| 4540 | ; | ||
| 4541 | ; NOTE THAT WE RESET VECTORS DIRECTLY!!!!!!!!!!!!!!!!!! | ||
| 4542 | ; We are not sure that DOS is reliable enough to call. | ||
| 4543 | ; | ||
| 4544 | MOV AX,WORD PTR [OLD_19] | ||
| 4545 | MOV WORD PTR DS:[19H * 4],AX | ||
| 4546 | MOV AX,WORD PTR [OLD_19 + 2] | ||
| 4547 | MOV WORD PTR DS:[(19H * 4) + 2],AX | ||
| 4548 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4549 | ; removed from smartdrv | ||
| 4550 | ; MOV AX,WORD PTR [OLD_9] | ||
| 4551 | ; MOV WORD PTR DS:[9H * 4],AX | ||
| 4552 | ; MOV AX,WORD PTR [OLD_9 + 2] | ||
| 4553 | ; MOV WORD PTR DS:[(9H * 4) + 2],AX | ||
| 4554 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4555 | mov ax,word ptr [old_15] | ||
| 4556 | cmp ax,word ptr [old_15+2] | ||
| 4557 | jne res_15 | ||
| 4558 | cmp ax,-1 | ||
| 4559 | je skip_res | ||
| 4560 | res_15: | ||
| 4561 | mov word ptr ds:[15h*4],ax | ||
| 4562 | mov ax,word ptr [old_15+2] | ||
| 4563 | mov word ptr ds:[(15h*4) +2],ax | ||
| 4564 | ; | ||
| 4565 | skip_res: | ||
| 4566 | POP DS | ||
| 4567 | POP AX | ||
| 4568 | MOV [INT_13_BUSY],0 | ||
| 4569 | JMP [OLD_19] | ||
| 4570 | |||
| 4571 | ;** RESET_SYSTEM perform TYPE 1 (/E) driver specific reboot code | ||
| 4572 | ; | ||
| 4573 | ; This code performs the EMM_ISDRIVER reset function as described | ||
| 4574 | ; in EMM.ASM for all EMM_REC structure for this device (offset | ||
| 4575 | ; stored in MY_EMM_REC). We use the same LOADALL | ||
| 4576 | ; method described at BLKMOV to address the EMM_CTRL sector | ||
| 4577 | ; at the start of extended memory and perform our changes in | ||
| 4578 | ; place. | ||
| 4579 | ; | ||
| 4580 | ; NOTE: RESET_SYSTEM ALSO defines the start of ANOTHER piece of | ||
| 4581 | ; driver TYPE specific code that TYPE 2 drivers | ||
| 4582 | ; will have to swap in a different piece of code for. | ||
| 4583 | ; | ||
| 4584 | ; ENTRY | ||
| 4585 | ; NONE | ||
| 4586 | ; EXIT | ||
| 4587 | ; NONE | ||
| 4588 | ; USES | ||
| 4589 | ; NONE | ||
| 4590 | ; | ||
| 4591 | ; This code is specific to TYPE 1 drivers | ||
| 4592 | ; | ||
| 4593 | |||
| 4594 | RESET_SYSTEM: | ||
| 4595 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 4596 | JMP SHORT TRUE_START | ||
| 4597 | |||
| 4598 | MY_EMM_REC DW 0 ; Offset into 1K EMM_CTRL of my record | ||
| 4599 | |||
| 4600 | TRUE_START: | ||
| 4601 | PUSHA | ||
| 4602 | mov cs:[reboot_flg],0ffh ; set the reboot flag | ||
| 4603 | cmp cs:[my_emm_rec],0 ; was an emm record allocated? | ||
| 4604 | je reset_skip | ||
| 4605 | PUSH DS | ||
| 4606 | PUSH ES | ||
| 4607 | ; | ||
| 4608 | ; reset base_addr to be address of emm ctrl sector | ||
| 4609 | ; | ||
| 4610 | mov ax,cs:[emm_ctrl_addr] | ||
| 4611 | mov dx,cs:[emm_ctrl_addr+2] | ||
| 4612 | mov word ptr cs:[base_addr],ax | ||
| 4613 | mov word ptr cs:[base_addr+2],dx | ||
| 4614 | ; | ||
| 4615 | ; read 1k emm control sector into track buffer, I want to keep memory | ||
| 4616 | ; access methods separate from driver code. We end up wasting a lot of | ||
| 4617 | ; time here but is reboot code anyway so thats okay | ||
| 4618 | ; | ||
| 4619 | mov bx,cs | ||
| 4620 | mov es,bx ; | ||
| 4621 | mov di,cs:[track_buffer_ptr] | ||
| 4622 | mov cx,512 | ||
| 4623 | xor ax,ax | ||
| 4624 | xor dx,dx | ||
| 4625 | mov bh,0 ; read | ||
| 4626 | push es | ||
| 4627 | push di | ||
| 4628 | call blkmov | ||
| 4629 | pop di | ||
| 4630 | pop es | ||
| 4631 | jc finish_reset | ||
| 4632 | ; | ||
| 4633 | ; fix the flags for my emm record so that it is no longer in use | ||
| 4634 | ; | ||
| 4635 | mov bx,cs:[my_emm_rec] | ||
| 4636 | add bx,di | ||
| 4637 | and es:[bx.emm_flags],not emm_isdriver | ||
| 4638 | ; | ||
| 4639 | ; write out the modified emm record out to memory | ||
| 4640 | ; | ||
| 4641 | xor ax,ax | ||
| 4642 | xor dx,dx | ||
| 4643 | mov bh,1 ; write | ||
| 4644 | call blkmov | ||
| 4645 | finish_reset: | ||
| 4646 | POP ES | ||
| 4647 | POP DS | ||
| 4648 | reset_skip: | ||
| 4649 | POPA | ||
| 4650 | RET | ||
| 4651 | |||
| 4652 | ; | ||
| 4653 | ; The following label defines the end of the | ||
| 4654 | ; Driver TYPE specific RESET_SYSTEM code which will have to be replaced | ||
| 4655 | ; for different driver TYPEs as the code between RESET_SYSTEM and | ||
| 4656 | ; RESET_INCLUDE. Swapped in code MUST FIT between RESET_SYSTEM and | ||
| 4657 | ; RESET_INCLUDE. | ||
| 4658 | ; | ||
| 4659 | RESET_INCLUDE LABEL BYTE | ||
| 4660 | |||
| 4661 | ; | ||
| 4662 | ; This data is only used at INIT, but it must be protected from overwrite | ||
| 4663 | ; by the DO_INIT code. | ||
| 4664 | ; | ||
| 4665 | TERM_ADDR LABEL DWORD ; Address to return as break address in INIT packet | ||
| 4666 | DW ? ; Computed at INIT time | ||
| 4667 | DW ? ; INT13 CS filled in at INIT | ||
| 4668 | |||
| 4669 | ; | ||
| 4670 | ; THIS CODE MUST BE IN RESIDENT PORTION BECAUSE IT WRITES IN THE AREA | ||
| 4671 | ; OCCUPIED BY THE DISPOSABLE INIT CODE. | ||
| 4672 | ; | ||
| 4673 | |||
| 4674 | ;** DO_INIT - Initialize cache structures to "empty" | ||
| 4675 | ; | ||
| 4676 | DO_INIT: | ||
| 4677 | ASSUME DS:INT13CODE | ||
| 4678 | MOV AX,[SECTRACK] | ||
| 4679 | MOV CL,9 | ||
| 4680 | SHL AX,CL ; AX is bytes per track buffer | ||
| 4681 | MOV BX,[CACHE_CONTROL_PTR] | ||
| 4682 | MOV CX,[TTRACKS] | ||
| 4683 | MOV [CACHE_HEAD],BX | ||
| 4684 | MOV [BX.BACK_LRU_LNK],-1 | ||
| 4685 | MOV WORD PTR [BX.BASE_OFFSET],0 | ||
| 4686 | MOV WORD PTR [BX.BASE_OFFSET+2],0 | ||
| 4687 | MOV [BX.TRACK_FLAGS],TRACK_FREE | ||
| 4688 | MOV DI,BX | ||
| 4689 | ADD BX,SIZE CACHE_CONTROL ; Next structure | ||
| 4690 | DEC CX ; One less to do | ||
| 4691 | JCXZ SETDONE ; one buffer in cache | ||
| 4692 | SETLOOP: | ||
| 4693 | MOV [DI.FWD_LRU_LNK],BX | ||
| 4694 | MOV [BX.BACK_LRU_LNK],DI | ||
| 4695 | MOV [BX.TRACK_FLAGS],TRACK_FREE | ||
| 4696 | MOV DX,WORD PTR [DI.BASE_OFFSET] | ||
| 4697 | ADD DX,AX | ||
| 4698 | MOV WORD PTR [BX.BASE_OFFSET],DX | ||
| 4699 | MOV DX,WORD PTR [DI.BASE_OFFSET+2] | ||
| 4700 | ADC DX,0 | ||
| 4701 | MOV WORD PTR [BX.BASE_OFFSET+2],DX | ||
| 4702 | MOV DI,BX | ||
| 4703 | ADD BX,SIZE CACHE_CONTROL ; Next structure | ||
| 4704 | LOOP SETLOOP | ||
| 4705 | SETDONE: | ||
| 4706 | MOV [DI.FWD_LRU_LNK],-1 | ||
| 4707 | MOV [CACHE_TAIL],DI ; That is the tail | ||
| 4708 | ; | ||
| 4709 | ; NOTE FALL THROUGH!!!!!!! | ||
| 4710 | ; | ||
| 4711 | |||
| 4712 | ;** SETBPB - Set INIT packet I/O return values | ||
| 4713 | ; | ||
| 4714 | ; This entry is used to set the INIT packet Break address | ||
| 4715 | ; | ||
| 4716 | ; ENTRY | ||
| 4717 | ; TERM_ADDR set to device end | ||
| 4718 | ; EXIT | ||
| 4719 | ; through DEVEXIT | ||
| 4720 | ; USES | ||
| 4721 | ; DS, BX, CX | ||
| 4722 | ; | ||
| 4723 | ; COMMON TO TYPE 1, 2 drivers | ||
| 4724 | ; | ||
| 4725 | |||
| 4726 | SETBPB: | ||
| 4727 | ASSUME DS:NOTHING | ||
| 4728 | ; | ||
| 4729 | ; 7. Set the return INIT I/O packet values | ||
| 4730 | ; | ||
| 4731 | LDS BX,[PTRSAV] | ||
| 4732 | MOV CX,WORD PTR [TERM_ADDR] | ||
| 4733 | MOV WORD PTR [BX.INIT_BREAK],CX ;SET BREAK ADDRESS | ||
| 4734 | MOV CX,WORD PTR [TERM_ADDR + 2] | ||
| 4735 | MOV WORD PTR [BX.INIT_BREAK + 2],CX | ||
| 4736 | JMP DEVEXIT | ||
| 4737 | |||
| 4738 | |||
| 4739 | EVEN ; Make sure we get word alignment of the track | ||
| 4740 | ; buffer. | ||
| 4741 | |||
| 4742 | ; | ||
| 4743 | ; The following items define the "track buffer". When we want to I/O a track | ||
| 4744 | ; this is where we do it. We cannot I/O the track directly into extended | ||
| 4745 | ; memory because we have no way to specify a 24 bit address to INT 13. We | ||
| 4746 | ; Cannot I/O direct to expanded memory because DMA into the expanded memory | ||
| 4747 | ; window is not supported. This buffer also "holds" one track, so we keep | ||
| 4748 | ; track of the last track that was in here because it is faster to access | ||
| 4749 | ; it here than through extended/expanded memory. A value of -1 in the | ||
| 4750 | ; "currency" fields indicates that there is currently nothing interesting | ||
| 4751 | ; in the track buffer. NOTE: It is ASSUMED that the track buffer always | ||
| 4752 | ; represents a track that is IN the cache, therefore one must be sure to | ||
| 4753 | ; invalidate the track buffer when the cache element it represents is | ||
| 4754 | ; discarded. The offset of the track buffer is dynamic. Never talk about | ||
| 4755 | ; OFFSET TRACK_BUFFER. Always get the track buffer address out of | ||
| 4756 | ; TRACK_BUFFER_PTR. The initialization code "moves" the track buffer so | ||
| 4757 | ; that it does not cause a DMA Boundary error which would slow things | ||
| 4758 | ; down quite a bit. | ||
| 4759 | ; | ||
| 4760 | |||
| 4761 | ; | ||
| 4762 | ; Cylinder and hd/drv of track in track buffer | ||
| 4763 | ; | ||
| 4764 | TRACK_BUFFER_CYLN DW -1 | ||
| 4765 | TRACK_BUFFER_HDDR DW -1 | ||
| 4766 | |||
| 4767 | ; | ||
| 4768 | ; Pointer to track buffer. May be adjusted for DMA boundary error prevention. | ||
| 4769 | ; | ||
| 4770 | TRACK_BUFFER_PTR DW OFFSET TRACK_BUFFER | ||
| 4771 | |||
| 4772 | ; | ||
| 4773 | ; Cache structure pointers | ||
| 4774 | ; | ||
| 4775 | |||
| 4776 | ; | ||
| 4777 | ; Pointer to cache structures. This ends up being right after TRACK_BUFFER. | ||
| 4778 | ; | ||
| 4779 | CACHE_CONTROL_PTR DW ? | ||
| 4780 | |||
| 4781 | ; | ||
| 4782 | ; Cache head and tail pointers | ||
| 4783 | ; | ||
| 4784 | CACHE_HEAD DW ? | ||
| 4785 | CACHE_TAIL DW ? | ||
| 4786 | |||
| 4787 | ; | ||
| 4788 | ; This is the "in the 1Meg address space" track buffer. Its TRUE start | ||
| 4789 | ; may be adjusted for DMA boundary violation error prevention, and its | ||
| 4790 | ; Size may be adjusted depending on how many sectors per track there | ||
| 4791 | ; are. WARNING! This buffer must be AT LEAST 1024 bytes for /E driver | ||
| 4792 | ; init code (buffer for 1K EMM control sector). | ||
| 4793 | ; | ||
| 4794 | TRACK_BUFFER DB (512 * 2 + 16) DUP(0) | ||
| 4795 | ; we really don't need those 16 bytes, i | ||
| 4796 | ; am just paranoid | ||
| 4797 | ; | ||
| 4798 | ; The TERM_ADDR for the device will be set somewhere "around" here | ||
| 4799 | ; by the init code | ||
| 4800 | ; | ||
| 4801 | |||
| 4802 | BREAK <COMMON INIT CODE> | ||
| 4803 | |||
| 4804 | ;** DISPOSABLE INIT DATA | ||
| 4805 | ; | ||
| 4806 | ; INIT data which need not be part of resident image | ||
| 4807 | ; | ||
| 4808 | |||
| 4809 | U_SWITCH db 0 ;; upper extended memory requested on 6300 PLUS | ||
| 4810 | |||
| 4811 | EXT_K DW ? ; Size in K of Extended memory. | ||
| 4812 | |||
| 4813 | NUM_ARG DB 1 ; Counter for numeric | ||
| 4814 | ; arguments bbbb. | ||
| 4815 | |||
| 4816 | GOTSWITCH DB 0 ; Bit map of switches seen | ||
| 4817 | |||
| 4818 | SWITCH_E EQU 00000001B | ||
| 4819 | SWITCH_A EQU 00000010B ; Only switch allowed | ||
| 4820 | SWITCH_T EQU 00000100B | ||
| 4821 | SWITCH_D EQU 00001000B | ||
| 4822 | SWITCH_WT EQU 00010000B | ||
| 4823 | SWITCH_WC EQU 00100000B | ||
| 4824 | SWITCH_R EQU 01000000B | ||
| 4825 | SWITCH_C EQU 10000000B | ||
| 4826 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4827 | sys_det proc near | ||
| 4828 | ; | ||
| 4829 | ; author: sunilp, august 1, 1987. thanks to rickha for most of this | ||
| 4830 | ; routine. | ||
| 4831 | ; | ||
| 4832 | ; purpose: to determine whether extended memory cache can be installed | ||
| 4833 | ; on this system. also to determine and store in the system | ||
| 4834 | ; flag the machine identification. | ||
| 4835 | ; | ||
| 4836 | ; inputs: none | ||
| 4837 | ; | ||
| 4838 | ; outputs: CY set if this machine doesn't allow extended memory cache. | ||
| 4839 | ; CY clear if this machine allows extended memory cache and | ||
| 4840 | ; the system flag is set according to the machine type. | ||
| 4841 | ; | ||
| 4842 | ; registers used: ax,es,flags | ||
| 4843 | ;---------------------------------- | ||
| 4844 | ; Clear the state of the system flag | ||
| 4845 | ; | ||
| 4846 | assume ds:int13code,es:nothing,ss:nothing | ||
| 4847 | xor ax,ax ; 0000 into AX | ||
| 4848 | mov [sys_flg],al ; clear system flag | ||
| 4849 | ;---------------------------------- | ||
| 4850 | ; Determine if 8086/8088 system. If so we should abort immediately. | ||
| 4851 | ; | ||
| 4852 | push ax ; ax has 0 | ||
| 4853 | popf ; try to put that in the flags | ||
| 4854 | pushf | ||
| 4855 | pop ax ; look at what really went into flags | ||
| 4856 | and ax,0F000h ; mask off high flag bits | ||
| 4857 | cmp ax,0F000h ; Q: was high nibble all ones ? | ||
| 4858 | je cpu_err ; Y: it's an 8086 (or 8088) | ||
| 4859 | ;---------------------------------- | ||
| 4860 | ; Determine if 80286/80386 machine. | ||
| 4861 | ; | ||
| 4862 | mov ax,0F000h ; N: try to set the high bits | ||
| 4863 | push ax | ||
| 4864 | popf ; ... in the flags | ||
| 4865 | pushf | ||
| 4866 | pop ax ; look at actual flags | ||
| 4867 | and ax,0F000h ; Q: any high bits set ? | ||
| 4868 | je cpu_286 ; N: it's an 80286 | ||
| 4869 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 4870 | ; It is a 386 cpu. We should next try to determine if the ROM is | ||
| 4871 | ; B0 or earlier. We don't want these guys. | ||
| 4872 | ; | ||
| 4873 | cpu_386: | ||
| 4874 | pushf ; clear | ||
| 4875 | pop ax ; NT | ||
| 4876 | and ax,not 0F000h ; and | ||
| 4877 | push ax ; IOPL | ||
| 4878 | popf ; bits | ||
| 4879 | ;---------------------------------- | ||
| 4880 | ; the next three instructions were removed because we are loaded | ||
| 4881 | ; in real mode. So there is no need to check for virtual mode. | ||
| 4882 | ; | ||
| 4883 | ; smsw ax ;check for Virtual Mode | ||
| 4884 | ; test ax,0001 ; Q: Currently in Virtual Mode ? | ||
| 4885 | ; jnz cpu_exit ; Y: quit with error message | ||
| 4886 | ;---------------------------------- | ||
| 4887 | ; N: check 386 stepping for B0 | ||
| 4888 | call is_b0 ; Q: B0 ? | ||
| 4889 | jc cpu_err ; Y: abort | ||
| 4890 | ;---------------------------------- | ||
| 4891 | ; We have a valid 386 guy. Set the flag to indicate this. | ||
| 4892 | ; | ||
| 4893 | or [sys_flg],M_386 ; set 386 bit | ||
| 4894 | jmp short PS2Test | ||
| 4895 | |||
| 4896 | ;---------------------------------- | ||
| 4897 | ; This is a 286 guy. Check for AT model byte. We don't want non-ATs. | ||
| 4898 | ; Set 286 bit if AT type. Then check for PS/2 | ||
| 4899 | ; | ||
| 4900 | cpu_286: | ||
| 4901 | mov ax,0ffffh | ||
| 4902 | mov es,ax | ||
| 4903 | cmp byte ptr es:[0eh],0fch ; AT model byte | ||
| 4904 | jne cpu_err ; if not abort | ||
| 4905 | ; | ||
| 4906 | or [sys_flg],M_286 ; set 286 flag bit | ||
| 4907 | ; | ||
| 4908 | ; | ||
| 4909 | ; Determine if this is a PS/2 system | ||
| 4910 | ; | ||
| 4911 | PS2Test: | ||
| 4912 | call IsPS2Machine | ||
| 4913 | or ax,ax | ||
| 4914 | jz NCRTest | ||
| 4915 | or [sys_flg],M_PS2 | ||
| 4916 | |||
| 4917 | NCRTest: | ||
| 4918 | call IsNCRMachine | ||
| 4919 | or ax,ax | ||
| 4920 | jz cpu_suc | ||
| 4921 | |||
| 4922 | ; We're on an NCR machine, send D7 and D5 to the 8042 in order | ||
| 4923 | ; to toggle A20 instead of the DF and DD we usually send. | ||
| 4924 | ; ChipA 06-16-88 | ||
| 4925 | mov cs:[A20On],0D790h | ||
| 4926 | mov cs:[A20Off],0D500h | ||
| 4927 | |||
| 4928 | ;---------------------------------- | ||
| 4929 | ; success exit:-- | ||
| 4930 | cpu_suc: | ||
| 4931 | clc | ||
| 4932 | ret | ||
| 4933 | |||
| 4934 | ;---------------------------------- | ||
| 4935 | ; error exit:-- | ||
| 4936 | cpu_err: | ||
| 4937 | stc | ||
| 4938 | ret | ||
| 4939 | ; | ||
| 4940 | sys_det endp | ||
| 4941 | |||
| 4942 | |||
| 4943 | ;*--------------------------------------------------------------------------* | ||
| 4944 | ;* * | ||
| 4945 | ;* IsPS2Machine HARDWARE DEP. * | ||
| 4946 | ;* * | ||
| 4947 | ;* Check for PS/2 machine * | ||
| 4948 | ;* * | ||
| 4949 | ;* ARGS: None * | ||
| 4950 | ;* RETS: AX = 1 if we're on a valid PS/2 machine, 0 otherwise * | ||
| 4951 | ;* REGS: AX and Flags clobbered * | ||
| 4952 | ;* * | ||
| 4953 | ;*--------------------------------------------------------------------------* | ||
| 4954 | |||
| 4955 | IsPS2Machine proc near | ||
| 4956 | |||
| 4957 | mov ah,0C0h ; Get System Description Vector | ||
| 4958 | stc | ||
| 4959 | int 15h | ||
| 4960 | jc short IPMNoPS2 ; Error? Not a PS/2. | ||
| 4961 | |||
| 4962 | ; Are we on a PS/2 Model 35? | ||
| 4963 | cmp es:[bx+2],09FCh | ||
| 4964 | je short IPMFoundIt ; Yup, use the PS/2 method | ||
| 4965 | |||
| 4966 | ; Do we have a "Micro Channel" computer? | ||
| 4967 | mov al,byte ptr es:[bx+5] ; Get "Feature Information Byte 1" | ||
| 4968 | test al,00000010b ; Test the "Micro Channel Implemented" bit | ||
| 4969 | jz short IPMNoPS2 | ||
| 4970 | |||
| 4971 | IPMFoundIt: mov ax,1 | ||
| 4972 | ret | ||
| 4973 | |||
| 4974 | IPMNoPS2: xor ax,ax | ||
| 4975 | ret | ||
| 4976 | |||
| 4977 | IsPS2Machine endp | ||
| 4978 | |||
| 4979 | |||
| 4980 | ;*--------------------------------------------------------------------------* | ||
| 4981 | ;* * | ||
| 4982 | ;* IsNCRMachine HARDWARE DEP. * | ||
| 4983 | ;* * | ||
| 4984 | ;* Check for NCR machine * | ||
| 4985 | ;* * | ||
| 4986 | ;* ARGS: None * | ||
| 4987 | ;* RETS: AX = 1 if we're on a valid NCR machine, 0 otherwise * | ||
| 4988 | ;* REGS: AX and Flags clobbered * | ||
| 4989 | ;* * | ||
| 4990 | ;*--------------------------------------------------------------------------* | ||
| 4991 | |||
| 4992 | ; Look for 'NC' at F000:FFEA | ||
| 4993 | |||
| 4994 | IsNCRMachine proc near | ||
| 4995 | |||
| 4996 | mov ax,0F000h | ||
| 4997 | mov es,ax | ||
| 4998 | mov ax,word ptr es:[0FFEAh] | ||
| 4999 | cmp ax,'CN' | ||
| 5000 | je INMFoundIt | ||
| 5001 | xor ax,ax | ||
| 5002 | ret | ||
| 5003 | |||
| 5004 | INMFoundIt: mov ax,1 | ||
| 5005 | ret | ||
| 5006 | |||
| 5007 | IsNCRMachine endp | ||
| 5008 | |||
| 5009 | |||
| 5010 | ;****************************************************************************** | ||
| 5011 | ; IS_B0 - check for 386-B0 | ||
| 5012 | ; | ||
| 5013 | ; This routine takes advantage of the fact that the bit INSERT and | ||
| 5014 | ; EXTRACT instructions that existed in B0 and earlier versions of the | ||
| 5015 | ; 386 were removed in the B1 stepping. When executed on the B1, INSERT | ||
| 5016 | ; and EXTRACT cause an INT 6 (invalid opcode) exception. This routine | ||
| 5017 | ; can therefore discriminate between B1/later 386s and B0/earlier 386s. | ||
| 5018 | ; It is intended to be used in sequence with other checks to determine | ||
| 5019 | ; processor stepping by exercising specific bugs found in specific | ||
| 5020 | ; steppings of the 386. | ||
| 5021 | ; | ||
| 5022 | ; ENTRY: REAL MODE on 386 processor (CPU ID already performed) | ||
| 5023 | ; EXIT: CF = 0 if B1 or later | ||
| 5024 | ; CF = 1 if B0 or prior | ||
| 5025 | ; | ||
| 5026 | ; ENTRY: | ||
| 5027 | ; EXIT: | ||
| 5028 | ; USED: AX, flags | ||
| 5029 | ; STACK: | ||
| 5030 | ;------------------------------------------------------------------------------ | ||
| 5031 | is_b0 proc near | ||
| 5032 | push bx | ||
| 5033 | push cx | ||
| 5034 | push dx | ||
| 5035 | push ds | ||
| 5036 | |||
| 5037 | xor bx,bx | ||
| 5038 | mov ds,bx ; DS = 0000 (real mode IDT) | ||
| 5039 | assume ds:R_Mode_IDT | ||
| 5040 | push [bx+(6*4)] | ||
| 5041 | pop cs:[int6_save] ; save old INT 6 offset | ||
| 5042 | push [bx+(6*4)+2] | ||
| 5043 | pop cs:[int6_save+2] ; save old INT 6 segment | ||
| 5044 | |||
| 5045 | mov word ptr [bx+(6*4)],offset int6 | ||
| 5046 | mov [bx+(6*4)+2],cs ; set vector to new INT 6 handler | ||
| 5047 | ; | ||
| 5048 | ; Attempt execution of Extract Bit String instruction. Execution on | ||
| 5049 | ; B0 or earlier with length (CL) = 0 will return 0 into the destination | ||
| 5050 | ; (CX in this case). Execution on B1 or later will fail and dummy INT 6 | ||
| 5051 | ; handler will return execution to the instruction following the XBTS. | ||
| 5052 | ; CX will remain unchanged in this case. | ||
| 5053 | ; | ||
| 5054 | xor ax,ax | ||
| 5055 | mov dx,ax | ||
| 5056 | mov cx,0FF00h ; Extract length (CL)=0, CX=non-zero | ||
| 5057 | db 0Fh,0A6h,0CAh ; XBTS CX,DX,AX,CL | ||
| 5058 | |||
| 5059 | xor bx,bx | ||
| 5060 | mov ds,bx ; DS = 0000 (real mode IDT) | ||
| 5061 | push cs:[int6_save] ; restore original INT 6 offset | ||
| 5062 | pop [bx+(6*4)] ; | ||
| 5063 | push cs:[int6_save+2] ; restore original INT 6 segment | ||
| 5064 | pop [bx+(6*4)+2] | ||
| 5065 | |||
| 5066 | or cx,cx ; Q: CX = 0 (meaning <=B0) ? | ||
| 5067 | jz ib_exit ; Y: exit (carry clear) | ||
| 5068 | stc ; N: set carry to indicate >=B1 | ||
| 5069 | ib_exit: | ||
| 5070 | cmc ; flip carry tense | ||
| 5071 | pop ds | ||
| 5072 | pop dx | ||
| 5073 | pop cx | ||
| 5074 | pop bx | ||
| 5075 | ret ; *** RETURN *** | ||
| 5076 | is_b0 endp | ||
| 5077 | ; | ||
| 5078 | ; Temporary INT 6 handler - assumes the cause of the exception was the | ||
| 5079 | ; attempted execution of an XTBS instruction. | ||
| 5080 | ; | ||
| 5081 | int6 proc near | ||
| 5082 | push bp | ||
| 5083 | mov bp,sp | ||
| 5084 | add word ptr [bp+2],3 ; bump IP past faulting instruction | ||
| 5085 | pop bp | ||
| 5086 | iret ; *** RETURN *** | ||
| 5087 | int6_save dw 0000,0000 | ||
| 5088 | int6 endp | ||
| 5089 | ;*************************************************************************** | ||
| 5090 | |||
| 5091 | ;** PRINT - Print a "$" terminated message on stdout | ||
| 5092 | ; | ||
| 5093 | ; This routine prints "$" terminated messages on stdout. | ||
| 5094 | ; It may be called with only the DX part of the DS:DX message | ||
| 5095 | ; pointer set, the routine puts the correct value in DS to point | ||
| 5096 | ; at the INT13 messages. | ||
| 5097 | ; | ||
| 5098 | ; ENTRY: | ||
| 5099 | ; DX pointer to "$" terminated message (INT13CODE relative) | ||
| 5100 | ; EXIT: | ||
| 5101 | ; NONE | ||
| 5102 | ; USES: | ||
| 5103 | ; AX | ||
| 5104 | ; | ||
| 5105 | ; COMMON TO TYPE 1, 2, 3, 4 drivers | ||
| 5106 | ; | ||
| 5107 | |||
| 5108 | PRINT: | ||
| 5109 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 5110 | PUSH DS | ||
| 5111 | PUSH CS | ||
| 5112 | POP DS | ||
| 5113 | MOV AH,Std_Con_String_Output | ||
| 5114 | INT 21H | ||
| 5115 | POP DS | ||
| 5116 | RET | ||
| 5117 | |||
| 5118 | ;** ITOA - Print Decimal Integer on stdout | ||
| 5119 | ; | ||
| 5120 | ; Print an unsigned 16 bit value as a decimal integer on stdout | ||
| 5121 | ; with leading zero supression. Prints from 1 to 5 digits. Value | ||
| 5122 | ; 0 prints as "0". | ||
| 5123 | ; | ||
| 5124 | ; Routine uses divide instruction and a recursive call. Maximum | ||
| 5125 | ; recursion is four (five digit number) plus one word on stack | ||
| 5126 | ; for each level. | ||
| 5127 | ; | ||
| 5128 | ; ENTRY AX has binary value to be printed | ||
| 5129 | ; EXIT NONE | ||
| 5130 | ; USES AX,CX,DX,FLAGS | ||
| 5131 | ; | ||
| 5132 | ; COMMON TO TYPE 1, 2, 3, 4 drivers | ||
| 5133 | ; | ||
| 5134 | |||
| 5135 | ITOA: | ||
| 5136 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 5137 | |||
| 5138 | MOV CX,10 | ||
| 5139 | XOR DX,DX | ||
| 5140 | DIV CX ; DX is low digit, AX is higher digits | ||
| 5141 | OR AX,AX | ||
| 5142 | JZ PRINT_THIS_DIGIT ; No more higher digits | ||
| 5143 | PUSH DX ; Save this digit | ||
| 5144 | CALL ITOA ; Print higher digits first | ||
| 5145 | POP DX ; Recover this digit | ||
| 5146 | PRINT_THIS_DIGIT: | ||
| 5147 | ADD DL,"0" ; Convert to ASCII | ||
| 5148 | MOV AH,Std_CON_Output | ||
| 5149 | INT 21H | ||
| 5150 | RET | ||
| 5151 | |||
| 5152 | |||
| 5153 | ;** INT13$INIT - Device Driver Initialization routine | ||
| 5154 | ; | ||
| 5155 | ; INT13 Initialization routine. This is the COMMON initialization | ||
| 5156 | ; code used by ALL driver TYPEs. Its jobs are to: | ||
| 5157 | ; | ||
| 5158 | ; 1. Initialize various global values | ||
| 5159 | ; 2. Check for correct DOS version and do changes to the device | ||
| 5160 | ; based on the DOS version if needed. | ||
| 5161 | ; 3. Set OLD_13, OLD_1C and Parse the command line and set values accordingly | ||
| 5162 | ; 4. Set up the cache parameters and | ||
| 5163 | ; Call a TYPE specific INIT routine based on the Parse | ||
| 5164 | ; to set up a specific driver TYPE. | ||
| 5165 | ; 5. Print out report of INT13 parameters | ||
| 5166 | ; 6. Set the return INIT I/O packet values | ||
| 5167 | ; | ||
| 5168 | ; The first two lines perform step 1. Step two starts after and | ||
| 5169 | ; goes through VER_OK. Step 3 starts at VER_OK and goes through | ||
| 5170 | ; ARGS_DONE. Step 4 starts at ARGS_DONE and goes through I001. | ||
| 5171 | ; Step 5 starts at I001 and goes through DRIVE_SET. Step 6 starts | ||
| 5172 | ; at DRIVE_SET and goes through SETBPB. Step 7 starts at SETBPB | ||
| 5173 | ; and ends at the JMP DEVEXIT 10 lines later. | ||
| 5174 | ; | ||
| 5175 | ; At any time during the above steps an error may be detected. When | ||
| 5176 | ; this happens one of the error messages is printed and INT13 | ||
| 5177 | ; de-installs itself. It does this at DEVABORT_NOMES by changing | ||
| 5178 | ; the Device attributes to a BLOCK DEVICE and setting its size to NULL. | ||
| 5179 | ; All INT13 needs to do is make sure any INT vectors it changed | ||
| 5180 | ; (INT 9 and INT 19 and INT 13) get restored to what they were | ||
| 5181 | ; when INT13 first started. If an EMM_CTRL sector is being | ||
| 5182 | ; used (TYPE 1) and one of the EMM_REC structures has been | ||
| 5183 | ; marked EMM_ISDRIVER by this driver, it must turn that bit back off | ||
| 5184 | ; since the driver did not install. A TYPE 2 driver must make sure it | ||
| 5185 | ; ABOVE_DEALLOCs any memory it allocated from the EMM device. The duty | ||
| 5186 | ; of reclaiming EMM_CTRL or Above Board memory and re-setting vectors | ||
| 5187 | ; is done by the DISK_ABORT routine which may be called by either | ||
| 5188 | ; this COMMON INIT code, or the TYPE specific INIT code. | ||
| 5189 | ; | ||
| 5190 | ; Step 1 initializes the segment part of TERM_ADDR to the correct | ||
| 5191 | ; value for type 1, 2 drivers. | ||
| 5192 | ; | ||
| 5193 | ; Step 2 checks to make sure that we are running on a DOS in the | ||
| 5194 | ; 2.X or 3.X series which this driver is restricted to. If running | ||
| 5195 | ; on a 2.X series the device header attribute word and device command | ||
| 5196 | ; table are patched to exclude those device calls that don't exist | ||
| 5197 | ; on DOS 2.X. | ||
| 5198 | ; | ||
| 5199 | ; Step 3 uses the "DEVICE = xxxxxxxxx" line pointer provided by | ||
| 5200 | ; DOS to look for the various device parameters. NOTE: This pointer | ||
| 5201 | ; IS NOT DOCUMENTED in the DOS 2.X tech ref material, but it does | ||
| 5202 | ; exist in the same way as 3.X. This code is simple even though | ||
| 5203 | ; it looks rather long. First it skips over the device name field | ||
| 5204 | ; to get to the arguments. In then parses the arguments as they are | ||
| 5205 | ; encountered. All parameter errors are detected here. NOTE THAT | ||
| 5206 | ; THIS ROUTINE IS NOT RESPONSIBLE FOR SETTING DEFAULT VALUES OF | ||
| 5207 | ; PARAMETER VARIABLES. This is accomplished by static initialization | ||
| 5208 | ; of the parameter variables. | ||
| 5209 | ; | ||
| 5210 | ; Step 4 calls a device TYPE specific initialization routine based | ||
| 5211 | ; on the parse in step 3 (presence or absense of /E and /A switches). | ||
| 5212 | ; NOTE that one of the prime jobs of these device TYPE specific | ||
| 5213 | ; routines is to set all of the variables that are needed by Step | ||
| 5214 | ; 5 and 6 that haven't been set by the COMMON init code: | ||
| 5215 | ; | ||
| 5216 | ; DEV_SIZE set to TRUE size of device | ||
| 5217 | ; BASE_ADDR set to TRUE start of device so BLKMOV | ||
| 5218 | ; can be called | ||
| 5219 | ; BASE_RESET set so DISK_ABORT can be called | ||
| 5220 | ; TERM_ADDR set to correct end of device | ||
| 5221 | ; | ||
| 5222 | ; Step 5 makes the status report display of DEVICE SIZE and other info. | ||
| 5223 | ; | ||
| 5224 | ; Step 6 sets the INIT I/O packet return values for Break address. | ||
| 5225 | ; | ||
| 5226 | ; | ||
| 5227 | ; SEE ALSO | ||
| 5228 | ; MS-DOS Technical Reference manual section on | ||
| 5229 | ; Installable Device Drivers | ||
| 5230 | ; | ||
| 5231 | ; ENTRY from INT13$IN | ||
| 5232 | ; EXIT Through DEVEXIT | ||
| 5233 | ; USES ALL | ||
| 5234 | ; | ||
| 5235 | ; COMMON TO TYPE 1, 2 drivers | ||
| 5236 | ; | ||
| 5237 | |||
| 5238 | INT13$INIT: | ||
| 5239 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 5240 | ; | ||
| 5241 | ; 1. Initialize various global values | ||
| 5242 | ; | ||
| 5243 | MOV WORD PTR [TERM_ADDR + 2],CS | ||
| 5244 | ; | ||
| 5245 | ; 2. Check for correct DOS version and do changes to the device | ||
| 5246 | ; based on the DOS version if needed. | ||
| 5247 | ; | ||
| 5248 | CLD | ||
| 5249 | MOV AH,GET_VERSION | ||
| 5250 | INT 21H | ||
| 5251 | XCHG AH,AL | ||
| 5252 | CMP AX,(2 SHL 8) + 00 | ||
| 5253 | JB BADVER ; Below 2.00, BAD | ||
| 5254 | CMP AX,(3 SHL 8) + 00 | ||
| 5255 | JB VER2X ; 2.X requires some patches | ||
| 5256 | CMP AX,(4 SHL 8) + 00 | ||
| 5257 | JBE VER_OK ; 3.X or 4.0 OK | ||
| 5258 | BADVER: | ||
| 5259 | MOV DX,OFFSET BADVERMES | ||
| 5260 | JMP DEVABORT | ||
| 5261 | |||
| 5262 | VER2X: | ||
| 5263 | AND [DEVATS],NOT DEVOPCL ; No such bit in 2.X | ||
| 5264 | MOV BYTE PTR [INT13TBL],11 ; Fewer functions too | ||
| 5265 | VER_OK: | ||
| 5266 | |||
| 5267 | ;; | ||
| 5268 | ;; 2.5 Check here for 6300 PLUS machine. First look for Olivetti copyright, | ||
| 5269 | ;; and if found, check id byte at f000:fffd. | ||
| 5270 | ;; | ||
| 5271 | |||
| 5272 | push es ;; Olivetti Machine? | ||
| 5273 | mov ax,0fc00h ;; Look for 'OL' at fc00:50 | ||
| 5274 | mov es,ax | ||
| 5275 | cmp es:[0050h],'LO' | ||
| 5276 | jnz notS5 ;; not found | ||
| 5277 | mov ax,0f000h | ||
| 5278 | mov es,ax | ||
| 5279 | cmp word ptr es:[0fffdh],0fc00h ;; look for 6300 plus | ||
| 5280 | jnz notS5 | ||
| 5281 | mov [S5_FLAG],S_OLIVETTI ;; yep, set flag | ||
| 5282 | notS5: | ||
| 5283 | |||
| 5284 | ;; Check here for an HP Vectra machine. Look for HP id byte. | ||
| 5285 | ;; | ||
| 5286 | mov ax,0f000H | ||
| 5287 | mov es,ax | ||
| 5288 | cmp es:[0f8H],'PH' | ||
| 5289 | jnz notHP | ||
| 5290 | mov [S5_FLAG],S_VECTRA | ||
| 5291 | notHP: | ||
| 5292 | pop es | ||
| 5293 | |||
| 5294 | ; | ||
| 5295 | ; 3. Set OLD_13, OLD_1C and Parse the command line and set values accordingly | ||
| 5296 | ; | ||
| 5297 | MOV AX,(Get_Interrupt_Vector SHL 8) OR 13H | ||
| 5298 | INT 21H | ||
| 5299 | MOV WORD PTR [OLD_13],BX | ||
| 5300 | MOV WORD PTR [OLD_13 + 2],ES | ||
| 5301 | MOV AX,(Get_Interrupt_Vector SHL 8) OR 1CH | ||
| 5302 | INT 21H | ||
| 5303 | MOV WORD PTR [OLD_1C],BX | ||
| 5304 | MOV WORD PTR [OLD_1C + 2],ES | ||
| 5305 | LDS SI,[PTRSAV] | ||
| 5306 | ASSUME DS:NOTHING | ||
| 5307 | MOV DX,OFFSET HEADERMES | ||
| 5308 | CALL PRINT | ||
| 5309 | LDS SI,[SI.INIT_BPB] ; DS:SI points to config.sys | ||
| 5310 | SKIPLP1: ; Skip leading delims to start of name | ||
| 5311 | LODSB | ||
| 5312 | CMP AL," " | ||
| 5313 | JZ SKIPLP1 | ||
| 5314 | CMP AL,9 | ||
| 5315 | JZ SKIPLP1 | ||
| 5316 | CMP AL,"," | ||
| 5317 | JZ SKIPLP1 | ||
| 5318 | JMP SHORT SKIPNM | ||
| 5319 | |||
| 5320 | ARGS_DONEJ: | ||
| 5321 | JMP ARGS_DONE | ||
| 5322 | |||
| 5323 | SWITCHJ: | ||
| 5324 | JMP SWITCH | ||
| 5325 | |||
| 5326 | SKIPLP2: ; Skip over device name | ||
| 5327 | LODSB | ||
| 5328 | SKIPNM: | ||
| 5329 | CMP AL,13 | ||
| 5330 | JZ ARGS_DONEJ | ||
| 5331 | CMP AL,10 | ||
| 5332 | JZ ARGS_DONEJ | ||
| 5333 | CMP AL," " | ||
| 5334 | JZ FIRST_ARG | ||
| 5335 | CMP AL,9 | ||
| 5336 | JZ FIRST_ARG | ||
| 5337 | CMP AL,"," | ||
| 5338 | JZ FIRST_ARG | ||
| 5339 | CMP AL,0 ; Need this for 2.0 2.1 | ||
| 5340 | JNZ SKIPLP2 | ||
| 5341 | SCAN_LOOP: ; PROCESS arguments | ||
| 5342 | LODSB | ||
| 5343 | FIRST_ARG: | ||
| 5344 | OR AL,AL ; Need this for 2.0 2.1 | ||
| 5345 | JZ ARGS_DONEJ | ||
| 5346 | CMP AL,13 | ||
| 5347 | JZ ARGS_DONEJ | ||
| 5348 | CMP AL,10 | ||
| 5349 | JZ ARGS_DONEJ | ||
| 5350 | CMP AL," " | ||
| 5351 | JZ SCAN_LOOP | ||
| 5352 | CMP AL,9 | ||
| 5353 | JZ SCAN_LOOP | ||
| 5354 | CMP AL,"," | ||
| 5355 | JZ SCAN_LOOP | ||
| 5356 | CMP AL,"/" | ||
| 5357 | JZ SWITCHJ | ||
| 5358 | CMP AL,"0" | ||
| 5359 | JB BAD_PARMJ | ||
| 5360 | CMP AL,"9" | ||
| 5361 | JA BAD_PARMJ | ||
| 5362 | DEC SI | ||
| 5363 | CALL GETNUM | ||
| 5364 | CMP [NUM_ARG],1 | ||
| 5365 | JA BAD_PARMJ ; Only 1 numeric argument | ||
| 5366 | SET_SIZE: | ||
| 5367 | CMP BX,128 | ||
| 5368 | JB BAD_PARMJ | ||
| 5369 | CMP BX,8192 | ||
| 5370 | JA BAD_PARMJ | ||
| 5371 | MOV [DEV_SIZE],BX | ||
| 5372 | ;A | ||
| 5373 | mov [current_dev_size],bx | ||
| 5374 | ;A | ||
| 5375 | JMP SHORT NUM_DONE | ||
| 5376 | |||
| 5377 | BAD_PARMJ: | ||
| 5378 | JMP SHORT BAD_PARM | ||
| 5379 | |||
| 5380 | NUM_DONE: | ||
| 5381 | INC [NUM_ARG] ; Next numeric argument | ||
| 5382 | SCAN_LOOPJ: | ||
| 5383 | JMP SCAN_LOOP | ||
| 5384 | |||
| 5385 | BAD_PARM: | ||
| 5386 | MOV DX,OFFSET ERRMSG1 | ||
| 5387 | DEVABORT: | ||
| 5388 | CALL PRINT | ||
| 5389 | DEVABORT_NOMES: | ||
| 5390 | ; INC [NULDEV] ;Indicate NUL device | ||
| 5391 | ; MOV WORD PTR [TERM_ADDR],OFFSET ERROR_END ;Minimul null device | ||
| 5392 | ; JMP SETBPB ;and return | ||
| 5393 | LDS BX,[PTRSAV] | ||
| 5394 | MOV WORD PTR [BX].INIT_NUM,0 | ||
| 5395 | MOV WORD PTR [BX].INIT_BREAK[0],0 | ||
| 5396 | MOV WORD PTR [BX].INIT_BREAK[2],CS | ||
| 5397 | MOV [DEVATS],0 | ||
| 5398 | JMP DEVEXIT | ||
| 5399 | |||
| 5400 | SWITCH: | ||
| 5401 | LODSB | ||
| 5402 | OR AL,20H | ||
| 5403 | |||
| 5404 | if WINDOWS_SWITCHES eq 0 | ||
| 5405 | CMP AL,"e" | ||
| 5406 | JNZ ABOVE_TEST | ||
| 5407 | EXT_SET: | ||
| 5408 | TEST [GOTSWITCH],SWITCH_E + SWITCH_A | ||
| 5409 | JNZ BAD_PARM | ||
| 5410 | OR [GOTSWITCH],SWITCH_E | ||
| 5411 | MOV [DRIVER_SEL],0 | ||
| 5412 | JMP SCAN_LOOP | ||
| 5413 | |||
| 5414 | ABOVE_TEST: | ||
| 5415 | |||
| 5416 | endif ; WINDOWS_SWITCHES eq 0 | ||
| 5417 | |||
| 5418 | ;; Added for /u switch | ||
| 5419 | cmp al,'u' ;; Look for U switch for PLUS | ||
| 5420 | jnz A_TEST | ||
| 5421 | cmp [S5_FLAG],S_OLIVETTI ;; No good unless PLUS | ||
| 5422 | jne bad_parm | ||
| 5423 | TEST [GOTSWITCH],SWITCH_A ;; Already have switch A ? | ||
| 5424 | JNZ BAD_PARM | ||
| 5425 | cmp [U_SWITCH],0 | ||
| 5426 | jne bad_parm | ||
| 5427 | dec [U_SWITCH] | ||
| 5428 | jmp scan_loop | ||
| 5429 | A_TEST: | ||
| 5430 | ;; | ||
| 5431 | CMP AL,"a" | ||
| 5432 | |||
| 5433 | if WINDOWS_SWITCHES | ||
| 5434 | jnz bad_parm | ||
| 5435 | else | ||
| 5436 | JNZ DIS_TEST | ||
| 5437 | endif ;WINDOWS_SWITCHES | ||
| 5438 | |||
| 5439 | ABOVE_SET: | ||
| 5440 | TEST [GOTSWITCH],SWITCH_A ; Was SWITCH_E + SWITCH_A | ||
| 5441 | JNZ BAD_PARM | ||
| 5442 | ;; added for /u switch | ||
| 5443 | cmp [U_SWITCH],0 | ||
| 5444 | jne bad_parm | ||
| 5445 | ;; | ||
| 5446 | OR [GOTSWITCH],SWITCH_A | ||
| 5447 | MOV [DRIVER_SEL],1 | ||
| 5448 | JMP SCAN_LOOP | ||
| 5449 | |||
| 5450 | if WINDOWS_SWITCHES eq 0 | ||
| 5451 | |||
| 5452 | DIS_TEST: | ||
| 5453 | CMP AL,"d" | ||
| 5454 | JNZ W_TEST | ||
| 5455 | DIS_SET: | ||
| 5456 | TEST [GOTSWITCH],SWITCH_D | ||
| 5457 | JNZ BAD_PARM | ||
| 5458 | OR [GOTSWITCH],SWITCH_D | ||
| 5459 | MOV [ENABLE_13],0 | ||
| 5460 | JMP SCAN_LOOP | ||
| 5461 | |||
| 5462 | W_TEST: | ||
| 5463 | CMP AL,"w" | ||
| 5464 | JNZ T_TEST | ||
| 5465 | LODSW | ||
| 5466 | OR AL,20H | ||
| 5467 | CMP AX,":c" | ||
| 5468 | JNZ WT_TEST | ||
| 5469 | LODSW | ||
| 5470 | OR AX,2020H | ||
| 5471 | CMP AX,"fo" | ||
| 5472 | JNZ BAD_PARM | ||
| 5473 | LODSB | ||
| 5474 | OR AL,20H | ||
| 5475 | CMP AL,"f" | ||
| 5476 | JNZ BAD_PARMJX | ||
| 5477 | WC_SET: | ||
| 5478 | TEST [GOTSWITCH],SWITCH_WC | ||
| 5479 | JNZ BAD_PARMJX | ||
| 5480 | OR [GOTSWITCH],SWITCH_WC | ||
| 5481 | MOV [WRITE_BUFF],0 | ||
| 5482 | JMP SCAN_LOOP | ||
| 5483 | |||
| 5484 | WT_TEST: | ||
| 5485 | CMP AX,":t" | ||
| 5486 | JNZ BAD_PARMJX | ||
| 5487 | LODSW | ||
| 5488 | OR AX,2020H | ||
| 5489 | CMP AX,"no" | ||
| 5490 | JNZ BAD_PARMJX | ||
| 5491 | WT_SET: | ||
| 5492 | TEST [GOTSWITCH],SWITCH_WT | ||
| 5493 | JNZ BAD_PARMJX | ||
| 5494 | OR [GOTSWITCH],SWITCH_WT | ||
| 5495 | MOV [WRITE_THROUGH],1 | ||
| 5496 | JMP SCAN_LOOP | ||
| 5497 | |||
| 5498 | BAD_PARMJX: | ||
| 5499 | JMP BAD_PARM | ||
| 5500 | |||
| 5501 | T_TEST: | ||
| 5502 | CMP AL,"t" | ||
| 5503 | JNZ R_TEST | ||
| 5504 | LODSW | ||
| 5505 | CMP AL,":" | ||
| 5506 | JNZ BAD_PARMJX | ||
| 5507 | CMP AH,"0" | ||
| 5508 | JB BAD_PARMJX | ||
| 5509 | CMP AH,"9" | ||
| 5510 | JA BAD_PARMJX | ||
| 5511 | DEC SI | ||
| 5512 | CALL GETNUM | ||
| 5513 | T_SET: | ||
| 5514 | TEST [GOTSWITCH],SWITCH_T | ||
| 5515 | JNZ BAD_PARMJX | ||
| 5516 | OR [GOTSWITCH],SWITCH_T | ||
| 5517 | MOV [TICK_SETTING],BX | ||
| 5518 | JMP SCAN_LOOP | ||
| 5519 | |||
| 5520 | R_TEST: | ||
| 5521 | CMP AL,"r" | ||
| 5522 | JNZ C_TEST | ||
| 5523 | LODSW | ||
| 5524 | OR AH,20H | ||
| 5525 | CMP AX,"o:" | ||
| 5526 | JNZ BAD_PARMJX | ||
| 5527 | LODSB | ||
| 5528 | OR AL,20H | ||
| 5529 | CMP AL,"n" | ||
| 5530 | JNZ BAD_PARMJX | ||
| 5531 | TEST [GOTSWITCH],SWITCH_R | ||
| 5532 | JNZ BAD_PARMJX | ||
| 5533 | OR [GOTSWITCH],SWITCH_R | ||
| 5534 | MOV [REBOOT_FLUSH],1 | ||
| 5535 | JMP SCAN_LOOP | ||
| 5536 | |||
| 5537 | C_TEST: | ||
| 5538 | CMP AL,"c" | ||
| 5539 | JNZ BAD_PARMJX | ||
| 5540 | LODSW | ||
| 5541 | OR AH,20H | ||
| 5542 | CMP AX,"o:" | ||
| 5543 | JNZ BAD_PARMJX | ||
| 5544 | LODSB | ||
| 5545 | OR AL,20H | ||
| 5546 | CMP AL,"n" | ||
| 5547 | JNZ BAD_PARMJX | ||
| 5548 | TEST [GOTSWITCH],SWITCH_C | ||
| 5549 | JNZ BAD_PARMJX | ||
| 5550 | OR [GOTSWITCH],SWITCH_C | ||
| 5551 | MOV [ALL_CACHE],1 | ||
| 5552 | JMP SCAN_LOOP | ||
| 5553 | endif ;WINDOWS_SWITCHES eq 0 | ||
| 5554 | |||
| 5555 | ARGS_DONE: | ||
| 5556 | ; | ||
| 5557 | ; 4. Call a TYPE specific INIT routine based on the Parse | ||
| 5558 | ; to set up a specific driver TYPE. | ||
| 5559 | ; | ||
| 5560 | PUSH CS | ||
| 5561 | POP DS | ||
| 5562 | ASSUME DS:INT13CODE | ||
| 5563 | MOV AL,[DRIVER_SEL] ; Find out which init to call | ||
| 5564 | OR AL,AL | ||
| 5565 | JNZ NEXTV | ||
| 5566 | CALL AT_EXT_INIT | ||
| 5567 | JMP SHORT INI_RET | ||
| 5568 | |||
| 5569 | NEXTV: | ||
| 5570 | CALL ABOVE_INIT | ||
| 5571 | INI_RET: | ||
| 5572 | JNC I001 | ||
| 5573 | JMP DEVABORT_NOMES | ||
| 5574 | |||
| 5575 | I001: | ||
| 5576 | DRIVE_SET: | ||
| 5577 | ; | ||
| 5578 | ; update the current device size | ||
| 5579 | ; | ||
| 5580 | mov ax,[dev_size] | ||
| 5581 | mov [current_dev_size],ax | ||
| 5582 | ; | ||
| 5583 | ; 6. Print out report of INT13 parameters | ||
| 5584 | ; | ||
| 5585 | MOV DX,OFFSET STATMES1 | ||
| 5586 | CALL PRINT | ||
| 5587 | MOV AX,[DEV_SIZE] | ||
| 5588 | CALL ITOA | ||
| 5589 | MOV DX,OFFSET STATMES1E | ||
| 5590 | CMP [DRIVER_SEL],0 | ||
| 5591 | JZ PTYPX | ||
| 5592 | MOV DX,OFFSET STATMES1A | ||
| 5593 | PTYPX: | ||
| 5594 | CALL PRINT | ||
| 5595 | MOV DX,OFFSET STATMES2 | ||
| 5596 | CALL PRINT | ||
| 5597 | MOV AX,[TTRACKS] | ||
| 5598 | CALL ITOA | ||
| 5599 | MOV DX,OFFSET STATMES3 | ||
| 5600 | CALL PRINT | ||
| 5601 | MOV AX,[SECTRACK] | ||
| 5602 | CALL ITOA | ||
| 5603 | MOV DX,OFFSET STATMES4 | ||
| 5604 | CALL PRINT | ||
| 5605 | |||
| 5606 | ifdef OMTI | ||
| 5607 | mov dx,offset omti_msg | ||
| 5608 | call print | ||
| 5609 | endif | ||
| 5610 | IF DEBUG | ||
| 5611 | MOV DX,OFFSET STATMES5 | ||
| 5612 | CALL PRINT | ||
| 5613 | MOV AX,CS | ||
| 5614 | CALL ITOA | ||
| 5615 | MOV DX,OFFSET STATMES6 | ||
| 5616 | CALL PRINT | ||
| 5617 | ENDIF | ||
| 5618 | ; | ||
| 5619 | ; Turn on the cache by chaining INT 13, and INT 1C | ||
| 5620 | ; | ||
| 5621 | MOV DX,OFFSET INT_13_HANDLER | ||
| 5622 | MOV AX,(Set_Interrupt_Vector SHL 8) OR 13H | ||
| 5623 | INT 21H | ||
| 5624 | ; MOV DX,OFFSET INT_1C_HANDLER | ||
| 5625 | ; MOV AX,(Set_Interrupt_Vector SHL 8) OR 1CH | ||
| 5626 | ; INT 21H | ||
| 5627 | JMP DO_INIT | ||
| 5628 | |||
| 5629 | ;** DRIVEPARMS Initialize drive related cache parameters | ||
| 5630 | ; | ||
| 5631 | ; ENTRY | ||
| 5632 | ; Stuff set so that BLKMOV can be used to access cache memory | ||
| 5633 | ; DEV_SIZE set to TRUE cache size in K | ||
| 5634 | ; EXIT | ||
| 5635 | ; Carry Set | ||
| 5636 | ; Error, message already printed | ||
| 5637 | ; Carry clear | ||
| 5638 | ; TRACK_BUFFER_PTR adjusted for DMA error prevention | ||
| 5639 | ; CACHE_CONTROL_PTR set | ||
| 5640 | ; TERM_ADDR set | ||
| 5641 | ; TTRACKS set | ||
| 5642 | ; SECTRACK set | ||
| 5643 | ; SECTRKARRAY set | ||
| 5644 | ; HDARRAY set (SUNILP) | ||
| 5645 | ; USES | ||
| 5646 | ; ALL but DS | ||
| 5647 | ; | ||
| 5648 | ; COMMON TO TYPE 1, 2 drivers | ||
| 5649 | ; | ||
| 5650 | ; | ||
| 5651 | NO_HARDFILES: | ||
| 5652 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 5653 | MOV DX,OFFSET NOHARD | ||
| 5654 | PEER: | ||
| 5655 | CALL PRINT | ||
| 5656 | STC | ||
| 5657 | RET | ||
| 5658 | |||
| 5659 | TRACK_TOO_BIG: | ||
| 5660 | MOV DX,OFFSET BIGTRACK | ||
| 5661 | JMP PEER | ||
| 5662 | |||
| 5663 | DRIVEPARMS: | ||
| 5664 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 5665 | ; | ||
| 5666 | ; First figure out sec/track of any hardfiles | ||
| 5667 | ; | ||
| 5668 | MOV DL,80H | ||
| 5669 | MOV AH,8 | ||
| 5670 | INT 13H | ||
| 5671 | JC NO_HARDFILES | ||
| 5672 | OR DL,DL | ||
| 5673 | JZ NO_HARDFILES | ||
| 5674 | AND CL,00111111B | ||
| 5675 | MOV [SECTRKARRAY],CL | ||
| 5676 | mov [hdarray],dh | ||
| 5677 | XOR CH,CH | ||
| 5678 | MOV [SECTRACK],CX | ||
| 5679 | MOV CL,DL | ||
| 5680 | DEC CX | ||
| 5681 | JCXZ FINISHED | ||
| 5682 | CMP CX,MAX_HARD_FILES - 1 | ||
| 5683 | JBE DNUM_OK | ||
| 5684 | MOV CX,MAX_HARD_FILES - 1 | ||
| 5685 | DNUM_OK: | ||
| 5686 | MOV DL,81H | ||
| 5687 | PARMLOOP: | ||
| 5688 | PUSH CX | ||
| 5689 | PUSH DX | ||
| 5690 | MOV AH,8 | ||
| 5691 | INT 13H | ||
| 5692 | JC IGNORE_DRIVE | ||
| 5693 | AND CL,00111111B | ||
| 5694 | POP BX | ||
| 5695 | PUSH BX | ||
| 5696 | AND BX,0000000001111111B | ||
| 5697 | MOV [BX.SECTRKARRAY],CL | ||
| 5698 | mov [bx.hdarray],dh | ||
| 5699 | XOR CH,CH | ||
| 5700 | CMP CX,[SECTRACK] | ||
| 5701 | JBE IGNORE_DRIVE | ||
| 5702 | MOV [SECTRACK],CX | ||
| 5703 | IGNORE_DRIVE: | ||
| 5704 | POP DX | ||
| 5705 | INC DL | ||
| 5706 | POP CX | ||
| 5707 | LOOP PARMLOOP | ||
| 5708 | FINISHED: | ||
| 5709 | ; | ||
| 5710 | ; Figure out number of full tracks that fit in cache | ||
| 5711 | ; | ||
| 5712 | MOV AX,[SECTRACK] | ||
| 5713 | MOV CX,512 | ||
| 5714 | MUL CX ; DX:AX = Bytes per track | ||
| 5715 | OR DX,DX | ||
| 5716 | JNZ TRACK_TOO_BIG | ||
| 5717 | MOV BX,AX ; BX is bytes per track | ||
| 5718 | MOV AX,[DEV_SIZE] | ||
| 5719 | MOV CX,1024 | ||
| 5720 | MUL CX ; DX:AX = size of cache in bytes | ||
| 5721 | DIV BX ; AX is full tracks in cache | ||
| 5722 | MOV [TTRACKS],AX | ||
| 5723 | ; | ||
| 5724 | ; Figure out if we have a DMA boundary problem | ||
| 5725 | ; | ||
| 5726 | mov DX,DS ; Check for 64k boundary error | ||
| 5727 | shl DX,1 | ||
| 5728 | shl DX,1 | ||
| 5729 | shl DX,1 | ||
| 5730 | shl DX,1 ; Segment converted to absolute address | ||
| 5731 | add DX,[TRACK_BUFFER_PTR] ; Combine with offset | ||
| 5732 | add DX,511 ; simulate a one sector transfer | ||
| 5733 | ; And set next divide for round up | ||
| 5734 | ; | ||
| 5735 | ; If carry is set, then we are within 512 bytes of the end of the DMA segment. | ||
| 5736 | ; Adjust TRACK_BUFFER_PTR UP by 512 bytes. | ||
| 5737 | ; | ||
| 5738 | jnc NotWithin512 | ||
| 5739 | add [TRACK_BUFFER_PTR],512 ; adjust | ||
| 5740 | jmp short SetCachest | ||
| 5741 | |||
| 5742 | NotWithin512: | ||
| 5743 | ; | ||
| 5744 | ; DX is the physical low 16 bits of the proposed track buffer plus 511. | ||
| 5745 | ; See how many sectors fit up to boundary. | ||
| 5746 | ; | ||
| 5747 | shr DH,1 ; DH = number of sectors in DMA segment | ||
| 5748 | ; till start of buffer rounded up | ||
| 5749 | mov AH,128 ; AH = max number of sectors in DMA segment | ||
| 5750 | sub AH,DH | ||
| 5751 | ; | ||
| 5752 | ; AH is now the number of sectors that we can successfully transfer using this | ||
| 5753 | ; address without a DMA boundary problem. If this number is above or equal to | ||
| 5754 | ; the track buffer size, then buffer is OK. Otherwise, we adjust buffer UP | ||
| 5755 | ; till it is after the boundary by adding ((AH+1)*512) to the buffer address. | ||
| 5756 | ; | ||
| 5757 | mov al,ah | ||
| 5758 | xor ah,ah | ||
| 5759 | cmp AX,[SECTRACK] ; can we fit it in? | ||
| 5760 | jae SetCachest ; yes, buffer is OK | ||
| 5761 | inc ax ; Add 1 | ||
| 5762 | mov cl,9 ; Mult by 512 | ||
| 5763 | shl ax,cl | ||
| 5764 | add [TRACK_BUFFER_PTR],ax ; Adjust | ||
| 5765 | SetCachest: | ||
| 5766 | ; | ||
| 5767 | ; Set pointer to cache control structures | ||
| 5768 | ; | ||
| 5769 | mov bx,[SECTRACK] | ||
| 5770 | mov cl,9 ; Mult by 512 | ||
| 5771 | shl bx,cl ; AX is bytes in Track buffer | ||
| 5772 | add bx,[TRACK_BUFFER_PTR] ; First byte after track buffer | ||
| 5773 | mov [CACHE_CONTROL_PTR],bx | ||
| 5774 | mov cx,SIZE CACHE_CONTROL | ||
| 5775 | mov ax,[TTRACKS] | ||
| 5776 | MUL cx | ||
| 5777 | add bx,ax | ||
| 5778 | ; | ||
| 5779 | ; Set TERM_ADDR | ||
| 5780 | ; | ||
| 5781 | mov word ptr [TERM_ADDR],bx | ||
| 5782 | CLC | ||
| 5783 | RET | ||
| 5784 | |||
| 5785 | ;** GETNUM - Read an unsigned integer | ||
| 5786 | ; | ||
| 5787 | ; This routine looks at DS:SI for a decimal unsigned integer. | ||
| 5788 | ; It is up to the caller to make sure DS:SI points to the start | ||
| 5789 | ; of a number. If it is called without DS:SI pointing to a valid | ||
| 5790 | ; decimal digit the routine will return 0. Any non decimal digit | ||
| 5791 | ; defines the end of the number and SI is advanced over the | ||
| 5792 | ; digits which composed the number. Leading "0"s are OK. | ||
| 5793 | ; | ||
| 5794 | ; THIS ROUTINE DOES NOT CHECK FOR NUMBERS LARGER THAN WILL FIT | ||
| 5795 | ; IN 16 BITS. If it is passed a pointer to a number larger than | ||
| 5796 | ; 16 bits it will return the low 16 bits of the number. | ||
| 5797 | ; | ||
| 5798 | ; This routine uses the MUL instruction to multiply the running | ||
| 5799 | ; number by 10 (initial value is 0) and add the numeric value | ||
| 5800 | ; of the current digit. Any overflow on the MUL or ADD is ignored. | ||
| 5801 | ; | ||
| 5802 | ; ENTRY: | ||
| 5803 | ; DS:SI -> ASCII text of number | ||
| 5804 | ; EXIT: | ||
| 5805 | ; BX is binary for number | ||
| 5806 | ; SI advanced to point to char after number | ||
| 5807 | ; USES: | ||
| 5808 | ; AX,BX,DX,SI | ||
| 5809 | ; | ||
| 5810 | ; COMMON TO TYPE 1, 2, 3, 4 drivers | ||
| 5811 | ; | ||
| 5812 | |||
| 5813 | GETNUM: | ||
| 5814 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 5815 | |||
| 5816 | XOR BX,BX | ||
| 5817 | GETNUM1: | ||
| 5818 | LODSB | ||
| 5819 | SUB AL,"0" | ||
| 5820 | JB NUMRET | ||
| 5821 | CMP AL,9 | ||
| 5822 | JA NUMRET | ||
| 5823 | CBW | ||
| 5824 | XCHG AX,BX | ||
| 5825 | MOV DX,10 | ||
| 5826 | MUL DX | ||
| 5827 | ADD BX,AX | ||
| 5828 | JMP GETNUM1 | ||
| 5829 | |||
| 5830 | NUMRET: | ||
| 5831 | DEC SI | ||
| 5832 | RET | ||
| 5833 | |||
| 5834 | BREAK <INITIAL EMM control sector> | ||
| 5835 | |||
| 5836 | ;** flag to signify valid emm control record | ||
| 5837 | ; | ||
| 5838 | valid_emm db 0 | ||
| 5839 | |||
| 5840 | ;** INITIAL EMM_CTRL sector | ||
| 5841 | ; | ||
| 5842 | ; This is a datum which represents a correct initial EMM_CTRL | ||
| 5843 | ; sector as discussed in the EMM_CTRL documentation. It is used | ||
| 5844 | ; to check for the presense of a valid EMM_CTRL by comparing | ||
| 5845 | ; the signature strings, and for correctly initializing the | ||
| 5846 | ; EMM_CTRL sector if needed. | ||
| 5847 | ; | ||
| 5848 | ; The DWORD at BASE_RESET, which is the EMM_BASE of the NULL | ||
| 5849 | ; 0th EMM_REC structure, is used as a storage location of | ||
| 5850 | ; the address of the EMM_CTRL sector (PLUS 1024!!!!!!). | ||
| 5851 | ; This value can be used if it is necessary to re-address the | ||
| 5852 | ; EMM_CTRL sector during initialization. See the DISK_ABORT routine. | ||
| 5853 | ; NOTE THAT BASE_RESET CAN NOT BE USED AT RUNTIME AS THIS DATUM | ||
| 5854 | ; IS NOT PART OF THE RESIDENT IMAGE. | ||
| 5855 | ; | ||
| 5856 | ; This data is appropriate to TYPE 1 drivers | ||
| 5857 | ; | ||
| 5858 | |||
| 5859 | EMM_CONTROL LABEL BYTE | ||
| 5860 | DB "MICROSOFT EMM CTRL VERSION 1.00 CONTROL BLOCK " | ||
| 5861 | DW 0 | ||
| 5862 | DW 0 | ||
| 5863 | ; NULL 0th record | ||
| 5864 | DW EMM_ALLOC + EMM_ISDRIVER | ||
| 5865 | DW EMM_EMM | ||
| 5866 | ;; Note: When using upper extended memory on the PLUS, the value | ||
| 5867 | ;; at BASE_RESET + 2 is patched to FA during initialization. | ||
| 5868 | ;; | ||
| 5869 | BASE_RESET LABEL DWORD ; RESMEM driver must patch this value | ||
| 5870 | DW EXTMEM_LOW + 1024 | ||
| 5871 | DW EXTMEM_HIGH | ||
| 5872 | DW 0 | ||
| 5873 | |||
| 5874 | DB 950 DUP(0) | ||
| 5875 | DB "ARRARRARRA" | ||
| 5876 | |||
| 5877 | |||
| 5878 | BREAK <INT13 COMMON INIT ROUTINES> | ||
| 5879 | |||
| 5880 | ;** DISK_ABORT - De-install INT13 after init | ||
| 5881 | ; | ||
| 5882 | ; This routine MUST BE CALLED to de-install a INT13 cache | ||
| 5883 | ; if the de-installation takes place: | ||
| 5884 | ; | ||
| 5885 | ; AFTER INT 19/INT 9 vectors are replaced | ||
| 5886 | ; AFTER ABOVE_PID is valid for TYPE 2 | ||
| 5887 | ; AFTER an EMM_REC structure in the EMM_CTRL sector | ||
| 5888 | ; has been marked EMM_ISDRIVER for TYPE 1. | ||
| 5889 | ; | ||
| 5890 | ; In all cases the INT 9 and INT 19 vectors are replaced if the | ||
| 5891 | ; value of both words of OLD_19 is NOT -1. This is why the initial value | ||
| 5892 | ; of this datum is -1. In the event that the INT 9 and INT 19 | ||
| 5893 | ; vectors are replaced, this datum takes on some value other than -1. | ||
| 5894 | ; | ||
| 5895 | ; If this is a TYPE 1 driver the EMM_ISDRIVER bit is | ||
| 5896 | ; turned off in the EMM_REC pointed to by MY_EMM_REC. | ||
| 5897 | ; NOTE THAT A TYPE 1 DRIVER MAY USE THIS ROUTINE | ||
| 5898 | ; IF IT HAS NOT "TURNED ON" AN EMM_ISDRIVER BIT IN ONE OF THE EMM_REC | ||
| 5899 | ; STRUCTURES. This is OK because the initial 0 value of MY_EMM_REC | ||
| 5900 | ; is checked, and nothing is done if it is still 0. | ||
| 5901 | ; | ||
| 5902 | ; If this is a TYPE 2 driver, an ABOVE_DEALLOC call is made on | ||
| 5903 | ; ABOVE_PID. | ||
| 5904 | ; | ||
| 5905 | ; ENTRY: | ||
| 5906 | ; BASE_RESET valid if TYPE 1 | ||
| 5907 | ; ABOVE_PID valid if TYPE 2 | ||
| 5908 | ; EXIT: | ||
| 5909 | ; NONE | ||
| 5910 | ; USES: | ||
| 5911 | ; ALL but DS | ||
| 5912 | ; | ||
| 5913 | ; COMMON TO TYPE 1, 2 drivers | ||
| 5914 | ; | ||
| 5915 | |||
| 5916 | DISK_ABORT: | ||
| 5917 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 5918 | |||
| 5919 | CMP [DRIVER_SEL],1 | ||
| 5920 | JNZ NOT_ABOVE | ||
| 5921 | AGAIN: | ||
| 5922 | ; | ||
| 5923 | ; TYPE 2, De-alloc the Above Board memory | ||
| 5924 | ; | ||
| 5925 | MOV DX,[ABOVE_PID] | ||
| 5926 | MOV AH,ABOVE_DEALLOC | ||
| 5927 | INT 67H | ||
| 5928 | CMP AH,ABOVE_ERROR_BUSY | ||
| 5929 | JZ AGAIN | ||
| 5930 | JMP SHORT RET002 | ||
| 5931 | |||
| 5932 | NOT_ABOVE: | ||
| 5933 | CMP [MY_EMM_REC],0 ; Need to turn off bit? | ||
| 5934 | JZ RET002 ; No | ||
| 5935 | ; | ||
| 5936 | ; TYPE 1, turn off EMM_ISDRIVER at MY_EMM_REC | ||
| 5937 | ; | ||
| 5938 | MOV AX,WORD PTR [BASE_RESET] | ||
| 5939 | MOV DX,WORD PTR [BASE_RESET + 2] | ||
| 5940 | SUB AX,1024 ; Backup to EMM_CTRL | ||
| 5941 | SBB DX,0 | ||
| 5942 | MOV WORD PTR [BASE_ADDR],AX | ||
| 5943 | MOV WORD PTR [BASE_ADDR + 2],DX | ||
| 5944 | XOR BH,BH ; READ | ||
| 5945 | CALL CTRL_IO ; Get EMM_CTRL | ||
| 5946 | JC RET002 | ||
| 5947 | MOV DI,OFFSET TRACK_BUFFER | ||
| 5948 | ADD DI,[MY_EMM_REC] | ||
| 5949 | AND [DI.EMM_FLAGS],NOT EMM_ISDRIVER ; Undo install | ||
| 5950 | MOV BH,1 ; WRITE | ||
| 5951 | CALL CTRL_IO ; EMM_CTRL back out | ||
| 5952 | RET002: | ||
| 5953 | ; | ||
| 5954 | ; Reset INT 9, and/or INT 19 if OLD_19 is not -1 | ||
| 5955 | ; | ||
| 5956 | PUSH DS | ||
| 5957 | LDS DX,[OLD_19] | ||
| 5958 | ASSUME DS:NOTHING | ||
| 5959 | MOV AX,DS | ||
| 5960 | CMP AX,-1 | ||
| 5961 | JNZ RESET_VECS | ||
| 5962 | CMP AX,DX | ||
| 5963 | JZ NO_VECS | ||
| 5964 | RESET_VECS: | ||
| 5965 | MOV AX,(Set_Interrupt_Vector SHL 8) OR 19H | ||
| 5966 | INT 21H | ||
| 5967 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5968 | ; removed from smartdrv | ||
| 5969 | ; LDS DX,[OLD_9] | ||
| 5970 | ; MOV AX,(Set_Interrupt_Vector SHL 8) OR 9H | ||
| 5971 | ; INT 21H | ||
| 5972 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 5973 | lds dx,[old_15] | ||
| 5974 | cmp ax,-1 | ||
| 5975 | jne reset_15 | ||
| 5976 | cmp ax,dx | ||
| 5977 | je no_vecs | ||
| 5978 | reset_15: | ||
| 5979 | mov ax,(set_interrupt_vector shl 8) or 15h | ||
| 5980 | int 21h | ||
| 5981 | NO_VECS: | ||
| 5982 | POP DS | ||
| 5983 | RET | ||
| 5984 | |||
| 5985 | ;** CTRL_IO - Read/Write the first 1024 bytes at BASE_ADDR | ||
| 5986 | ; | ||
| 5987 | ; This routine is used at INIT time to read the first 1024 | ||
| 5988 | ; bytes at BASE_ADDR. If TYPE 1 and BASE_ADDR points | ||
| 5989 | ; to the EMM_CTRL address (initial value), the EMM_CTRL sector | ||
| 5990 | ; is read/written. If TYPE 1 and BASE_ADDR has been set | ||
| 5991 | ; to the start of the cache, the first 1024 bytes of the cache | ||
| 5992 | ; are read/written. If TYPE 2, the first 1024 bytes of | ||
| 5993 | ; the cache are read/written. All this routine does is | ||
| 5994 | ; set inputs to BLKMOV to transfer 1024 bytes at offset 0 to/from | ||
| 5995 | ; TRACK_BUFFER. | ||
| 5996 | ; | ||
| 5997 | ; ENTRY: | ||
| 5998 | ; BH = 0 for READ, 1 for WRITE | ||
| 5999 | ; EXIT: | ||
| 6000 | ; TRACK_BUFFER filled in with 1024 bytes at BASE_ADDR | ||
| 6001 | ; USES: | ||
| 6002 | ; ALL but DS | ||
| 6003 | ; | ||
| 6004 | ; COMMON TO TYPE 1, 2 drivers | ||
| 6005 | ; | ||
| 6006 | |||
| 6007 | CTRL_IO: | ||
| 6008 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6009 | XOR DX,DX | ||
| 6010 | MOV AX,DX ; Offset 0 | ||
| 6011 | MOV CX,512 ; 1024 bytes | ||
| 6012 | PUSH CS | ||
| 6013 | POP ES | ||
| 6014 | MOV DI,OFFSET TRACK_BUFFER | ||
| 6015 | PUSH DS | ||
| 6016 | CALL BLKMOV ; Read in EMM_CTRL | ||
| 6017 | POP DS | ||
| 6018 | RET | ||
| 6019 | |||
| 6020 | ;** MM_SETDRIVE - Look for/Init EMM_CTRL and DOS volume | ||
| 6021 | ; | ||
| 6022 | ; This routine is used by TYPE 1 drivers to check for/initialize | ||
| 6023 | ; the EMM_CTRL sector. | ||
| 6024 | ; | ||
| 6025 | ; This routine reads the EMM_CTRL sector in to TRACK_BUFFER | ||
| 6026 | ; CALLS FIND_VDRIVE to check out and alloc or find an EMM_REC | ||
| 6027 | ; Sets BASE_ADDR to point to the start of the INT13 cache memory | ||
| 6028 | ; Writes the updated EMM_CTRL back out from TRACK_BUFFER | ||
| 6029 | ; | ||
| 6030 | ; ENTRY: | ||
| 6031 | ; BASE_ADDR initialized to point at START of extended memory | ||
| 6032 | ; so that the EMM_CTRL sector can be accessed by | ||
| 6033 | ; doing I/O at offset 0. | ||
| 6034 | ; EXT_K is set to size of extended memory | ||
| 6035 | ; DEV_SIZE is set to user requested device size | ||
| 6036 | ; EXIT: | ||
| 6037 | ; CARRY SET - error, message already printed | ||
| 6038 | ; CARRY CLEAR | ||
| 6039 | ; BASE_ADDR set for this drive | ||
| 6040 | ; DEV_SIZE set to TRUE size | ||
| 6041 | ; | ||
| 6042 | ; USES | ||
| 6043 | ; ALL but DS | ||
| 6044 | ; | ||
| 6045 | ; Used by TYPE 1 drivers | ||
| 6046 | ; | ||
| 6047 | |||
| 6048 | MM_SETDRIVE: | ||
| 6049 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6050 | XOR BH,BH ; READ | ||
| 6051 | CALL CTRL_IO ; Get EMM_CTRL | ||
| 6052 | MOV DX,OFFSET INIT_IO_ERR | ||
| 6053 | JC ERR_RET2 | ||
| 6054 | CALL FIND_VDRIVE ; Snoop | ||
| 6055 | JC RET001 | ||
| 6056 | PUSH ES ; Save EMM_BASE from EMM_REC | ||
| 6057 | PUSH DI | ||
| 6058 | ; modification sunilp | ||
| 6059 | cmp [u_switch],0 ; we shall use ol' microsoft standard for this | ||
| 6060 | je mm_s$1 ; if we are using int15 scheme no need to write | ||
| 6061 | ; out emm control record | ||
| 6062 | ; end modification sp | ||
| 6063 | MOV BH,1 ; WRITE | ||
| 6064 | CALL CTRL_IO ; Write EMM_CTRL back out | ||
| 6065 | MOV DX,OFFSET INIT_IO_ERR | ||
| 6066 | JC ERR_RET2P | ||
| 6067 | mm_s$1: | ||
| 6068 | POP WORD PTR [BASE_ADDR] ; Set final correct BASE_ADDR | ||
| 6069 | POP WORD PTR [BASE_ADDR + 2] | ||
| 6070 | CLC | ||
| 6071 | RET001: | ||
| 6072 | RET | ||
| 6073 | |||
| 6074 | ERR_RET2P: | ||
| 6075 | ADD SP,4 | ||
| 6076 | ERR_RET2: | ||
| 6077 | CALL PRINT | ||
| 6078 | STC | ||
| 6079 | RET | ||
| 6080 | |||
| 6081 | ;** FIND_VDRIVE - Check out EMM_CTRL and alloc | ||
| 6082 | ; | ||
| 6083 | ; This code checks for a valid EMM_CTRL and sets up | ||
| 6084 | ; an initial one if there isn't. It then performs the | ||
| 6085 | ; algorithm described in the EMM_CTRL documentation | ||
| 6086 | ; to either allocate a NEW EMM_REC of type EMM_APPLICATION, | ||
| 6087 | ; or find an existing EMM_REC which is EMM_APPLICATION and has | ||
| 6088 | ; its EMM_ISDRIVER bit clear. In the later case it | ||
| 6089 | ; checks to see if DEV_SIZE is consistent with EMM_KSIZE | ||
| 6090 | ; and tries to make adjustments to EMM_KSIZE or DEV_SIZE | ||
| 6091 | ; if they are not consistent. | ||
| 6092 | ; | ||
| 6093 | ; First the EMM_CTRL signature strings are checked. | ||
| 6094 | ; If they are not valid we go to SETCTRL to set up a new | ||
| 6095 | ; empty EMM_CTRL in SECTOR_BUFFER. | ||
| 6096 | ; If the signatures are valid, EMM_TOTALK is checked | ||
| 6097 | ; against EXT_K. If they are the same, the EMM_CTRL sector is | ||
| 6098 | ; valid and we skip to SCAN_DEV. Otherwise we initialize the | ||
| 6099 | ; EMM_CTRL sector at SETCTRL. All we need to do to set up the initial | ||
| 6100 | ; EMM_CTRL sector is transfer the record at EMM_CONTROL into | ||
| 6101 | ; TRACK_BUFFER and set EMM_TOTALK and EMM_AVAILK to EXT_K - 1. | ||
| 6102 | ; | ||
| 6103 | ; In either case, finding a valid EMM_CTRL or setting up a correct | ||
| 6104 | ; initial one, we end up at SCAN_DEV. This code performs the | ||
| 6105 | ; scan of the EMM_REC structures looking for a "free" one | ||
| 6106 | ; or an allocated one which is EMM_APPLICATION and has its EMM_ISDRIVER | ||
| 6107 | ; bit clear as described in the EMM_CTRL sector documentation. | ||
| 6108 | ; | ||
| 6109 | ; If we find a "free" EMM_REC structure we go to GOT_FREE_REC | ||
| 6110 | ; and try to allocate some memory. This attempt will fail if | ||
| 6111 | ; EMM_AVAILK is less than 16K. We then call SET_RESET to do | ||
| 6112 | ; the INT 9/INT 19 setup. We adjust DEV_SIZE to equal the | ||
| 6113 | ; available memory if DEV_SIZE is > EMM_AVAILK. Then all we do | ||
| 6114 | ; is set EMM_AVAILK and all of the fields in the EMM_REC structure | ||
| 6115 | ; as described in the EMM_CTRL sector documentation. | ||
| 6116 | ; | ||
| 6117 | ; Call SET_RESET to do INT 9/INT 19 setup. | ||
| 6118 | ; IF the EMM_REC structure we found is the LAST EMM_REC structure | ||
| 6119 | ; we cannot edit any sizes and whatever the EMM_KSIZE | ||
| 6120 | ; is we stuff it into DEV_SIZE and set the EMM_ISDRIVER | ||
| 6121 | ; bit, and we're done. | ||
| 6122 | ; NOTE: We DO NOT check that EMM_KSIZE is at least | ||
| 6123 | ; 16K as we know this EMM_REC was created | ||
| 6124 | ; by some PREVIOUS INT13 program who | ||
| 6125 | ; DID make sure it was at least 16K | ||
| 6126 | ; ELSE | ||
| 6127 | ; IF EMM_KSIZE == DEV_SIZE | ||
| 6128 | ; set EMM_ISDRIVER and we're done | ||
| 6129 | ; IF EMM_KSIZE < DEV_SIZE | ||
| 6130 | ; either the user has edited his DEVICE = line since | ||
| 6131 | ; the last time the system was re-booted, or at the | ||
| 6132 | ; time we initially allocated this region EMM_AVAILK | ||
| 6133 | ; was less than DEV_SIZE and we had to trim the device | ||
| 6134 | ; size back. | ||
| 6135 | ; This case is handled at INSUFF_MEM. | ||
| 6136 | ; IF the next EMM_REC structure is not allocated | ||
| 6137 | ; IF EMM_AVAILK == 0 | ||
| 6138 | ; We can't do anything, so set DEV_SIZE | ||
| 6139 | ; to EMM_KSIZE and we're done. | ||
| 6140 | ; ELSE | ||
| 6141 | ; allocate appropriate amount off of EMM_AVAILK | ||
| 6142 | ; and add it to EMM_KSIZE and we're done. | ||
| 6143 | ; ELSE | ||
| 6144 | ; We can't do anything, so set DEV_SIZE | ||
| 6145 | ; to EMM_KSIZE and we're done. | ||
| 6146 | ; ELSE | ||
| 6147 | ; This is the EMM_KSIZE > DEV_SIZE case, it means the | ||
| 6148 | ; user MUST have edited his DEVICE = line. | ||
| 6149 | ; IF next EMM_REC is NOT free | ||
| 6150 | ; We can't shrink the allocation block, | ||
| 6151 | ; but we'll leave DEV_SIZE set to the user | ||
| 6152 | ; specification and let him waste memory. | ||
| 6153 | ; ELSE | ||
| 6154 | ; SHRINK the allocation block by adding | ||
| 6155 | ; the extra memory back onto EMM_AVAILK | ||
| 6156 | ; and subtracting it from EMM_KSIZE and | ||
| 6157 | ; we're done | ||
| 6158 | ; | ||
| 6159 | ; ENTRY: | ||
| 6160 | ; SECTOR_BUFFER containes POSSIBLE EMM_CTRL sector | ||
| 6161 | ; MUST BE CHECKED | ||
| 6162 | ; EXT_K is set to size of extended memory | ||
| 6163 | ; DEV_SIZE is set to user requested device size | ||
| 6164 | ; EXIT: | ||
| 6165 | ; CARRY SET | ||
| 6166 | ; Error, message already printed | ||
| 6167 | ; CARRY CLEAR | ||
| 6168 | ; ES:DI = BASE_ADDR for this drive from EMM_BASE of EMM_REC | ||
| 6169 | ; EMM_REC is marked EMM_ISDRIVER | ||
| 6170 | ; TRACK_BUFFER must be written out, it contains an updated | ||
| 6171 | ; EMM_CTRL sector | ||
| 6172 | ; DEV_SIZE set to TRUE size | ||
| 6173 | ; MY_EMM_REC is the offset in the 1k EMM_CTRL sector of the | ||
| 6174 | ; record we allocated. | ||
| 6175 | ; | ||
| 6176 | ; USES: | ||
| 6177 | ; ALL but DS | ||
| 6178 | ; | ||
| 6179 | ; Specific to TYPE 1 drivers | ||
| 6180 | ; | ||
| 6181 | ; substancial modification to this routine, would have totally changed | ||
| 6182 | ; if it weren't for the olivetti memory | ||
| 6183 | ; | ||
| 6184 | ; we are going to be int15 guys from now except for the olivetti memory | ||
| 6185 | ; | ||
| 6186 | FIND_VDRIVE: | ||
| 6187 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6188 | PUSH CS | ||
| 6189 | POP ES | ||
| 6190 | MOV DI,OFFSET TRACK_BUFFER | ||
| 6191 | MOV SI,OFFSET EMM_CONTROL | ||
| 6192 | MOV CX,50 | ||
| 6193 | CLD | ||
| 6194 | REPE CMPSB | ||
| 6195 | jnz no_emm_rec | ||
| 6196 | ; JNZ SETCTRL ; No EMM_CTRL | ||
| 6197 | ADD SI,EMM_TAIL_SIG - 50 | ||
| 6198 | ADD DI,EMM_TAIL_SIG - 50 | ||
| 6199 | MOV CX,10 | ||
| 6200 | REPE CMPSB | ||
| 6201 | jnz no_emm_rec | ||
| 6202 | ; JNZ SETCTRL ; No EMM_CTRL | ||
| 6203 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6204 | ; with int15 guys around this is not feasible | ||
| 6205 | ; MOV DI,OFFSET TRACK_BUFFER | ||
| 6206 | ; MOV AX,[EXT_K] | ||
| 6207 | ; DEC AX ; Size in EMM_CTRL doesn't include EMM_CTRL | ||
| 6208 | ; CMP AX,[DI.EMM_TOTALK] | ||
| 6209 | ; JZ SCAN_DEV ; EMM_CTRL is valid | ||
| 6210 | ;SETCTRL: | ||
| 6211 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6212 | ; | ||
| 6213 | ; modification sunilp | ||
| 6214 | ; | ||
| 6215 | dec [valid_emm] ; signal prescence of emm record | ||
| 6216 | no_emm_rec: | ||
| 6217 | cmp [u_switch],0h ; is it a u driver | ||
| 6218 | jne old_st ; if not go to install acc to new int15 | ||
| 6219 | jmp new_st ; standard | ||
| 6220 | ; | ||
| 6221 | ; for olivetti u memory we still have to install according to ol' microsoft st | ||
| 6222 | ; | ||
| 6223 | old_st: | ||
| 6224 | cmp [valid_emm],0h ; do we have a valid emm | ||
| 6225 | jne scan_dev ; if yes go to scan structures | ||
| 6226 | set_ctrl: ; else we have to install a new one | ||
| 6227 | MOV DI,OFFSET TRACK_BUFFER | ||
| 6228 | PUSH DI | ||
| 6229 | MOV SI,OFFSET EMM_CONTROL | ||
| 6230 | MOV CX,1024/2 | ||
| 6231 | REP MOVSW ; Move in initial EMM_CTRL | ||
| 6232 | POP DI | ||
| 6233 | MOV AX,[EXT_K] | ||
| 6234 | DEC AX ; Size in EMM_CTRL doesn't include EMM_CTRL | ||
| 6235 | MOV [DI.EMM_TOTALK],AX | ||
| 6236 | MOV [DI.EMM_AVAILK],AX | ||
| 6237 | SCAN_DEV: | ||
| 6238 | MOV SI,OFFSET TRACK_BUFFER ; DS:SI points to EMM_CTRL | ||
| 6239 | MOV DI,SI | ||
| 6240 | ADD DI,EMM_RECORD ; DS:DI points to EMM records | ||
| 6241 | MOV CX,EMM_NUMREC | ||
| 6242 | LOOK_REC: | ||
| 6243 | TEST [DI.EMM_FLAGS],EMM_ALLOC | ||
| 6244 | JNZ CHECK_SYS | ||
| 6245 | JMP GOT_FREE_REC ; Must alloc new region | ||
| 6246 | |||
| 6247 | CHECK_SYS: | ||
| 6248 | CMP [DI.EMM_SYSTEM],EMM_APPLICATION | ||
| 6249 | JNZ NEXTREC ; Not correct type | ||
| 6250 | TEST [DI.EMM_FLAGS],EMM_ISDRIVER | ||
| 6251 | JNZ NEXTRECI ; Driver already in | ||
| 6252 | CALL SET_RESET ; Set up INT 19,9 | ||
| 6253 | MOV AX,[DI.EMM_KSIZE] | ||
| 6254 | CMP CX,1 | ||
| 6255 | JBE OK_SET_DEV ; If this is last record, must | ||
| 6256 | ; select this size | ||
| 6257 | CMP AX,[DEV_SIZE] | ||
| 6258 | JZ OK_SET_DEV ; Exact match, Okay | ||
| 6259 | JB INSUFF_MEM ; User asked for more | ||
| 6260 | ; Size of found block is bigger than requested size. | ||
| 6261 | ; User MUST have edited CONFIG.SYS. | ||
| 6262 | PUSH DI | ||
| 6263 | ADD DI,SIZE EMM_REC | ||
| 6264 | TEST [DI.EMM_FLAGS],EMM_ALLOC | ||
| 6265 | POP DI | ||
| 6266 | JZ SHRINK_BLOCK ; Next block is free, shrink | ||
| 6267 | MOV AX,[DEV_SIZE] | ||
| 6268 | JMP SHORT SET_2 | ||
| 6269 | |||
| 6270 | SHRINK_BLOCK: | ||
| 6271 | SUB AX,[DEV_SIZE] ; AX is amount to shrink | ||
| 6272 | ADD [SI.EMM_AVAILK],AX | ||
| 6273 | MOV AX,[DEV_SIZE] | ||
| 6274 | MOV [DI.EMM_KSIZE],AX | ||
| 6275 | JMP SHORT SET_2 | ||
| 6276 | |||
| 6277 | INSUFF_MEM: ; Size of found block is smaller | ||
| 6278 | ; than requested size. | ||
| 6279 | PUSH DI | ||
| 6280 | ADD DI,SIZE EMM_REC | ||
| 6281 | TEST [DI.EMM_FLAGS],EMM_ALLOC | ||
| 6282 | POP DI | ||
| 6283 | JNZ OK_SET_DEV ; Next block is NOT free, can't grow | ||
| 6284 | TRY_TO_GROW_BLOCK: | ||
| 6285 | CMP [SI.EMM_AVAILK],0 | ||
| 6286 | JZ OK_SET_DEV ; Need SPECIAL check for this case | ||
| 6287 | SUB AX,[DEV_SIZE] | ||
| 6288 | NEG AX ; AX is amount we would like to grow | ||
| 6289 | SUB [SI.EMM_AVAILK],AX | ||
| 6290 | JNC GOT_THE_MEM | ||
| 6291 | ADD AX,[SI.EMM_AVAILK] ; AX is MAX we can grow | ||
| 6292 | MOV [SI.EMM_AVAILK],0 ; We take all that's left | ||
| 6293 | GOT_THE_MEM: | ||
| 6294 | ADD [DI.EMM_KSIZE],AX | ||
| 6295 | MOV AX,[DI.EMM_KSIZE] | ||
| 6296 | SET_2: | ||
| 6297 | OK_SET_DEV: | ||
| 6298 | MOV [DEV_SIZE],AX | ||
| 6299 | OR [DI.EMM_FLAGS],EMM_ISDRIVER | ||
| 6300 | MOV [MY_EMM_REC],DI | ||
| 6301 | SUB [MY_EMM_REC],OFFSET TRACK_BUFFER ; Make start of EMM_CTRL relative | ||
| 6302 | LES DI,[DI.EMM_BASE] | ||
| 6303 | XOR AX,AX ; Set zero, clear carry | ||
| 6304 | RET | ||
| 6305 | |||
| 6306 | NEXTRECI: | ||
| 6307 | NEXTREC: | ||
| 6308 | ADD DI,SIZE EMM_REC ; Next record | ||
| 6309 | LOOP LOOK_RECJ | ||
| 6310 | VERROR: | ||
| 6311 | MOV DX,OFFSET ERRMSG2 | ||
| 6312 | CALL PRINT | ||
| 6313 | STC | ||
| 6314 | RET | ||
| 6315 | |||
| 6316 | LOOK_RECJ: | ||
| 6317 | JMP LOOK_REC | ||
| 6318 | |||
| 6319 | GOT_FREE_REC: | ||
| 6320 | MOV AX,[SI.EMM_AVAILK] | ||
| 6321 | CMP AX,16 | ||
| 6322 | JB VERROR ; 16K is smallest device | ||
| 6323 | CALL SET_RESET ; Set INT 19,9 | ||
| 6324 | CMP AX,[DEV_SIZE] | ||
| 6325 | JBE GOTSIZE ; Not enough for user spec | ||
| 6326 | MOV AX,[DEV_SIZE] ; User size is OK | ||
| 6327 | GOTSIZE: | ||
| 6328 | MOV [DEV_SIZE],AX | ||
| 6329 | SUB [SI.EMM_AVAILK],AX | ||
| 6330 | MOV [DI.EMM_KSIZE],AX | ||
| 6331 | MOV [DI.EMM_SYSTEM],EMM_APPLICATION | ||
| 6332 | MOV [DI.EMM_FLAGS],EMM_ALLOC + EMM_ISDRIVER | ||
| 6333 | MOV [MY_EMM_REC],DI | ||
| 6334 | SUB [MY_EMM_REC],OFFSET TRACK_BUFFER ; Make start of EMM_CTRL relative | ||
| 6335 | PUSH DI | ||
| 6336 | SUB DI,SIZE EMM_REC ; Look at prev record to compute base | ||
| 6337 | MOV AX,[DI.EMM_KSIZE] | ||
| 6338 | LES BX,[DI.EMM_BASE] | ||
| 6339 | MOV DI,ES ; DI:BX is prev base | ||
| 6340 | MOV CX,1024 | ||
| 6341 | MUL CX ; Mult size by 1024 to get # bytes | ||
| 6342 | ADD AX,BX ; Add size onto base to get next base | ||
| 6343 | ADC DX,DI | ||
| 6344 | POP DI | ||
| 6345 | MOV WORD PTR [DI.EMM_BASE],AX | ||
| 6346 | MOV WORD PTR [DI.EMM_BASE + 2],DX | ||
| 6347 | LES DI,[DI.EMM_BASE] | ||
| 6348 | XOR AX,AX ; Set zero, clear carry | ||
| 6349 | INC AX ; RESET zero | ||
| 6350 | RET | ||
| 6351 | |||
| 6352 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6353 | ; the new int15 standard | ||
| 6354 | ; | ||
| 6355 | new_st: | ||
| 6356 | mov bx,[ext_k] ; contiguous memory reported by int15 | ||
| 6357 | cmp [valid_emm],0 ; is there a valid emm record | ||
| 6358 | je no_adjust ; if not there no need to adjust | ||
| 6359 | ; the memory available | ||
| 6360 | ; else we have to find how much memory is already allocated by the microsoft | ||
| 6361 | ; emm control block and subtract this from the amount that is available. the | ||
| 6362 | ; memory allocated is totalk - availk + 1 | ||
| 6363 | ; | ||
| 6364 | sub bx,1 ; subtract the emm ctrl record size | ||
| 6365 | mov di,offset track_buffer ; set up to address the ctrl record | ||
| 6366 | ; read in | ||
| 6367 | mov ax,[di.emm_totalk] ; ax <- totalk | ||
| 6368 | sub ax,[di.emm_availk] ; ax <- totalk - availk | ||
| 6369 | sub bx,ax ; adjust memory available | ||
| 6370 | jc verror ; if no memory go to abort | ||
| 6371 | ; | ||
| 6372 | cmp bx,128 ; is it the minimum required | ||
| 6373 | jb verror ; if less go to abort | ||
| 6374 | ; | ||
| 6375 | ; the memory available has been found and is in bx. now compare it with | ||
| 6376 | ; requested device size and take the minimum of the two | ||
| 6377 | ; | ||
| 6378 | no_adjust: | ||
| 6379 | cmp [dev_size],bx ; | ||
| 6380 | jb skip_adj_dev_size ; if enough space we don't need to adj | ||
| 6381 | ; dev_size | ||
| 6382 | mov [dev_size],bx ; else we have compromise on dev size | ||
| 6383 | skip_adj_dev_size: | ||
| 6384 | ; | ||
| 6385 | ; now that we have the correct dev size we should proceed with the installation | ||
| 6386 | ; of a new int 15 handler which will account for the memory grabbed by this guy | ||
| 6387 | ; | ||
| 6388 | mov bx,[ext_k] ; get memory which was reported by int15 | ||
| 6389 | add bx,[special_mem] ; account for olivetti guys | ||
| 6390 | sub bx,[dev_size] ; | ||
| 6391 | mov [int15_size],bx ; this is the size thaat will be reported | ||
| 6392 | ; by the int 15 handler | ||
| 6393 | ; now install the int15 handler | ||
| 6394 | ; | ||
| 6395 | push ax | ||
| 6396 | push dx | ||
| 6397 | push bx | ||
| 6398 | push es | ||
| 6399 | mov ax,(get_interrupt_vector shl 8) or 15h | ||
| 6400 | int 21h | ||
| 6401 | mov word ptr [old_15],bx | ||
| 6402 | mov word ptr [old_15+2],es | ||
| 6403 | mov dx,offset int_15 | ||
| 6404 | mov ax,(set_interrupt_vector shl 8) or 15h | ||
| 6405 | int 21h | ||
| 6406 | pop es | ||
| 6407 | pop bx | ||
| 6408 | pop dx | ||
| 6409 | pop ax | ||
| 6410 | ; | ||
| 6411 | ; set up int19 vector | ||
| 6412 | ; | ||
| 6413 | call set_reset | ||
| 6414 | ; | ||
| 6415 | ; now fill device base address in es:di | ||
| 6416 | ; | ||
| 6417 | mov ax,[ext_k] | ||
| 6418 | sub ax,[dev_size] ; this now has memory left | ||
| 6419 | mov cx,1024 ; we are going to find size in bytes | ||
| 6420 | mul cx ; dx:ax = ax * 1024 | ||
| 6421 | add ax,word ptr [base_addr] ; | ||
| 6422 | adc dx,word ptr [base_addr+2] ; | ||
| 6423 | mov es,dx ; | ||
| 6424 | mov di,ax ; | ||
| 6425 | ret | ||
| 6426 | |||
| 6427 | ;** SET_RESET - Set up INT 19/INT 9 vectors | ||
| 6428 | ; | ||
| 6429 | ; This routine will install the INT 9 and INT 19 | ||
| 6430 | ; code by saving the current INT 9 and INT 19 | ||
| 6431 | ; vectors in OLD_9 and OLD_19 (NOTE: the change in the value of OLD_19 | ||
| 6432 | ; to something other than -1 indicates that the vectors have been | ||
| 6433 | ; replaced), setting the vectors to point to INT_9 and INT_19. | ||
| 6434 | ; | ||
| 6435 | ; ENTRY: | ||
| 6436 | ; NONE | ||
| 6437 | ; EXIT: | ||
| 6438 | ; NONE | ||
| 6439 | ; USES: | ||
| 6440 | ; None | ||
| 6441 | ; | ||
| 6442 | ; COMMON TO TYPE 1, 2 drivers | ||
| 6443 | ; | ||
| 6444 | |||
| 6445 | SET_RESET: | ||
| 6446 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6447 | cmp U_SWITCH,0 ;; don't do this for at&t 6300 plus | ||
| 6448 | jnz ret005 | ||
| 6449 | PUSH AX | ||
| 6450 | PUSH DX | ||
| 6451 | PUSH BX | ||
| 6452 | PUSH ES | ||
| 6453 | MOV AX,(Get_Interrupt_Vector SHL 8) OR 19H | ||
| 6454 | INT 21H | ||
| 6455 | MOV WORD PTR [OLD_19],BX | ||
| 6456 | MOV WORD PTR [OLD_19 + 2],ES | ||
| 6457 | MOV DX,OFFSET INT_19 | ||
| 6458 | MOV AX,(Set_Interrupt_Vector SHL 8) OR 19H | ||
| 6459 | INT 21H | ||
| 6460 | MOV AX,(Get_Interrupt_Vector SHL 8) OR 9H | ||
| 6461 | INT 21H | ||
| 6462 | MOV WORD PTR [OLD_9],BX | ||
| 6463 | MOV WORD PTR [OLD_9 + 2],ES | ||
| 6464 | ; MOV DX,OFFSET INT_9 | ||
| 6465 | ; MOV AX,(Set_Interrupt_Vector SHL 8) OR 9H | ||
| 6466 | ; INT 21H | ||
| 6467 | POP ES | ||
| 6468 | POP BX | ||
| 6469 | POP DX | ||
| 6470 | POP AX | ||
| 6471 | RET005: | ||
| 6472 | RET | ||
| 6473 | |||
| 6474 | BREAK </E INIT Code> | ||
| 6475 | |||
| 6476 | ;** AT_EXT_INIT - Perform /E (TYPE 1) specific initialization | ||
| 6477 | ; | ||
| 6478 | ; This code does the drive TYPE specific initialization for TYPE 1 | ||
| 6479 | ; drivers. | ||
| 6480 | ; | ||
| 6481 | ; Make sure running on 80286 IBM PC-AT compatible system by | ||
| 6482 | ; making sure the model byte at FFFF:000E is FC. | ||
| 6483 | ; Get the size of extended memory by using 8800H call to INT 15. | ||
| 6484 | ; and make sure it is big enough to accomodate thr driver. | ||
| 6485 | ; Limit DEV_SIZE to the available memory found in the previous step | ||
| 6486 | ; by making DEV_SIZE smaller if necessary. | ||
| 6487 | ; Initialize the GLOBAL parts of the LOADALL information which | ||
| 6488 | ; are not set by each call to BLKMOV. | ||
| 6489 | ; CALL MM_SETDRIVE to look for EMM_CTRL and perform all the | ||
| 6490 | ; other initialization tasks. | ||
| 6491 | ; Call DRIVEPARMS to set TERM_ADDR and other drive specific cache parms | ||
| 6492 | ; | ||
| 6493 | ; ENTRY: | ||
| 6494 | ; Invokation line parameter values set. | ||
| 6495 | ; EXIT: | ||
| 6496 | ; CARRY SET | ||
| 6497 | ; Error, message already printed. Driver not installed. | ||
| 6498 | ; EMM_CTRL not marked (but MAY be initialized if | ||
| 6499 | ; a valid one was not found). | ||
| 6500 | ; CARRY CLEAR | ||
| 6501 | ; BASE_ADDR set for this drive from EMM_BASE of EMM_REC | ||
| 6502 | ; BASE_RESET set from BASE_ADDR | ||
| 6503 | ; TERM_ADDR set | ||
| 6504 | ; EMM_REC is marked EMM_ISDRIVER | ||
| 6505 | ; MY_EMM_REC set | ||
| 6506 | ; DEV_SIZE set to TRUE size | ||
| 6507 | ; RESET_SYSTEM code and INT 9/INT 19 code included, | ||
| 6508 | ; INT 19 and 9 vector patched. | ||
| 6509 | ; | ||
| 6510 | ; USES: | ||
| 6511 | ; ALL but DS | ||
| 6512 | ; | ||
| 6513 | ; Code is specific to TYPE 1 driver | ||
| 6514 | ; | ||
| 6515 | |||
| 6516 | AT_EXT_INIT: | ||
| 6517 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6518 | push ds | ||
| 6519 | call sys_det ; new routine to do more comprehensive | ||
| 6520 | pop ds | ||
| 6521 | jnc at001 ; checks than before | ||
| 6522 | MOV DX,OFFSET BAD_AT | ||
| 6523 | ERR_RET: | ||
| 6524 | CALL PRINT | ||
| 6525 | STC | ||
| 6526 | RET | ||
| 6527 | |||
| 6528 | AT001: | ||
| 6529 | |||
| 6530 | ;; If upper extended memory is used on the PLUS, it is necessary to | ||
| 6531 | ;; patch the values of base_reset and base_addr to get the addressing right. | ||
| 6532 | ;; | ||
| 6533 | cmp [U_SWITCH],0 ;; patch the code for /U option | ||
| 6534 | jz AT001A | ||
| 6535 | mov ax,00fah | ||
| 6536 | mov word ptr [emm_ctrl_addr+2],ax ;; in resident part for reset code | ||
| 6537 | mov word ptr [base_reset+2],ax ;; patching upper address | ||
| 6538 | mov word ptr [base_addr+2],ax ;; to FA from 10 | ||
| 6539 | AT001A: | ||
| 6540 | MOV AX,8800H | ||
| 6541 | INT 15H ; Get extended memory size | ||
| 6542 | MOV DX,OFFSET NO_MEM | ||
| 6543 | OR AX,AX | ||
| 6544 | JZ ERR_RET | ||
| 6545 | |||
| 6546 | ;; If running on a 6300 PLUS, it is necessary to subtract any upper extended | ||
| 6547 | ;; memory from the value obtained by int 15 to determine the correct memory | ||
| 6548 | ;; available for a type /E RAMDrive. If loading a /U RAMDrive, it is necessary | ||
| 6549 | ;; to find out if there IS any upper extended memory. | ||
| 6550 | |||
| 6551 | cmp [U_SWITCH],0 ;; did we ask for upper extended memory | ||
| 6552 | jz olstuff ;; no | ||
| 6553 | call UpperMemCheck ;; yes, see if anything there | ||
| 6554 | jc ERR_RET ;; no, quit | ||
| 6555 | mov ax,384 ;; yes, but max allowed is 384K | ||
| 6556 | jmp short at001b | ||
| 6557 | olstuff: | ||
| 6558 | cmp [S5_FLAG],S_OLIVETTI ;; if not 6300 PLUS, go on | ||
| 6559 | jne at001b | ||
| 6560 | call UpperMemCheck ;; yes, see if 384K is there | ||
| 6561 | jc at001b ;; no, so int 15h is right | ||
| 6562 | sub ax,384 ;; yes, subtract 384K | ||
| 6563 | mov [special_mem],384 ;; store special memory size | ||
| 6564 | AT001B: | ||
| 6565 | |||
| 6566 | MOV DX,OFFSET ERRMSG2 | ||
| 6567 | CMP AX,128 ; 128k min cache | ||
| 6568 | JB ERR_RET | ||
| 6569 | MOV [EXT_K],AX | ||
| 6570 | MOV BX,AX | ||
| 6571 | ; DEC BX ; BX is MAX possible cache size | ||
| 6572 | CMP [DEV_SIZE],BX | ||
| 6573 | JBE AT002 ; DEV_SIZE OK | ||
| 6574 | MOV [DEV_SIZE],BX ; Limit DEV_SIZE to available | ||
| 6575 | AT002: | ||
| 6576 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6577 | ; 386 modification | ||
| 6578 | test [sys_flg],M_386 | ||
| 6579 | je loadall_setup | ||
| 6580 | mov ax,cs | ||
| 6581 | mov word ptr [cod_seg],ax | ||
| 6582 | ; set cs descriptor | ||
| 6583 | mov cx,16 | ||
| 6584 | mul cx | ||
| 6585 | mov si,offset cs_des | ||
| 6586 | mov [si].bas_0_15,ax | ||
| 6587 | mov [si].bas_16_23,dl | ||
| 6588 | mov [si].bas_24_31,dh | ||
| 6589 | ; set gdt base | ||
| 6590 | mov si,offset emm_gdt | ||
| 6591 | add ax,offset start_gdt | ||
| 6592 | adc dx,0 | ||
| 6593 | mov [si].gdt_base_0,ax | ||
| 6594 | mov [si].gdt_base_2,dx | ||
| 6595 | jmp short common_setup | ||
| 6596 | ; | ||
| 6597 | ; Init various pieces of LOADALL info | ||
| 6598 | ; | ||
| 6599 | ;;;; SMSW [LDSW] | ||
| 6600 | ;;;; SIDT QWORD PTR [IDTDES] | ||
| 6601 | ;;;; SGDT QWORD PTR [GDTDES] | ||
| 6602 | ;;;; ; | ||
| 6603 | ;;;; ; NOW The damn SXXX instructions store the desriptors in a | ||
| 6604 | ;;;; ; different order than LOADALL wants | ||
| 6605 | ;;;; ; | ||
| 6606 | ;;;; MOV SI,OFFSET IDTDES | ||
| 6607 | ;;;; CALL FIX_DESCRIPTOR | ||
| 6608 | ;;;; MOV SI,OFFSET GDTDES | ||
| 6609 | ;;;; CALL FIX_DESCRIPTOR | ||
| 6610 | loadall_setup: | ||
| 6611 | MOV [LCSS],CS | ||
| 6612 | MOV SI,OFFSET CSDES | ||
| 6613 | MOV AX,CS | ||
| 6614 | CALL SEG_SET | ||
| 6615 | common_setup: | ||
| 6616 | CALL MM_SETDRIVE | ||
| 6617 | JC RETXXX | ||
| 6618 | CALL DRIVEPARMS | ||
| 6619 | JNC RETXXX | ||
| 6620 | CALL DISK_ABORT | ||
| 6621 | STC | ||
| 6622 | RETXXX: | ||
| 6623 | RET | ||
| 6624 | |||
| 6625 | ;;* UpperMemCheck - Called by 6300 PLUS to verify existence of | ||
| 6626 | ;; upper extended memory of 384K at FA0000h | ||
| 6627 | ;; | ||
| 6628 | ;; Returns carry set if no upper extended memory. | ||
| 6629 | ;; | ||
| 6630 | ;; This routine is called only by a 6300 PLUS, and | ||
| 6631 | ;; it reads the hardware switch DSW2 to do the job. | ||
| 6632 | ;; | ||
| 6633 | UpperMemCheck: | ||
| 6634 | push ax | ||
| 6635 | in al,66h | ||
| 6636 | and al,00001111b | ||
| 6637 | cmp al,00001011b | ||
| 6638 | pop ax | ||
| 6639 | jnz nomem | ||
| 6640 | clc | ||
| 6641 | ret | ||
| 6642 | nomem: | ||
| 6643 | stc | ||
| 6644 | ret | ||
| 6645 | |||
| 6646 | BREAK </A INIT Code> | ||
| 6647 | |||
| 6648 | ;** EMM device driver name | ||
| 6649 | ; | ||
| 6650 | ; The following datum defines the Above Board EMM 8 character | ||
| 6651 | ; device driver name that is looked for as part of TYPE 2 | ||
| 6652 | ; specific initialization. | ||
| 6653 | ; | ||
| 6654 | ; This datum is specific to TYPE 2 drivers | ||
| 6655 | ; | ||
| 6656 | |||
| 6657 | ABOVE_DEV_NAME DB "EMMXXXX0" | ||
| 6658 | |||
| 6659 | ;** ABOVE_INIT - Perform /A (TYPE 2) specific initialization | ||
| 6660 | ; | ||
| 6661 | ; This code performes the driver specific initialization for | ||
| 6662 | ; type 2 drivers. | ||
| 6663 | ; | ||
| 6664 | ; Swap ABOVE_BLKMOV code in for TYPE 1 code at BLKMOV | ||
| 6665 | ; Swap ABOVE_RESET code in for TYPE 1 code at RESET_SYSTEM | ||
| 6666 | ; Check to make sure EMM Above Board device driver is installed | ||
| 6667 | ; by looking for device name relative to INT 67H segment | ||
| 6668 | ; address. This is method 2 described on page 36 and 37 | ||
| 6669 | ; of the Expanded Memory Manager Programming Specification. | ||
| 6670 | ; | ||
| 6671 | ; WARNING! If run on a version of DOS where all INT vectors | ||
| 6672 | ; are managed by the kernel, or on a system where some | ||
| 6673 | ; foreign program (not EMM.SYS) is also using INT 67H, this | ||
| 6674 | ; method will fail to find the EMM device driver. | ||
| 6675 | ; The reason this method was used rather than the more portable | ||
| 6676 | ; method 1 described on pages 33 and 34 of the EMM Programming | ||
| 6677 | ; Specification is that the DOS Installable Device Driver | ||
| 6678 | ; document makes a statement about which DOS system calls | ||
| 6679 | ; may be made in a device initialization routine, and | ||
| 6680 | ; OPEN, IOCTL, and CLOSE are not included in the allowed | ||
| 6681 | ; set. Adherance to the Installable Device Driver document, | ||
| 6682 | ; therefore, excludes the use of method 1. | ||
| 6683 | ; | ||
| 6684 | ; Check the EMM device status | ||
| 6685 | ; Get the EMM map window address and set BASE_ADDR | ||
| 6686 | ; Get the available Above Board memory | ||
| 6687 | ; Adjust DEV_SIZE to be consistent with the available memory if needed, | ||
| 6688 | ; and also round DEV_SIZE up so that it is a multiple of the 16K | ||
| 6689 | ; granularity of the Above Board memory. | ||
| 6690 | ; Allocate DEV_SIZE worth of Above Board memory and set ABOVE_PID. | ||
| 6691 | ; After this point we can use CTRL_IO and/or BLKMOV to | ||
| 6692 | ; read/write the memory we have allocated. | ||
| 6693 | ; Install the INT 9 and INT 19 code by calling SET_RESET. | ||
| 6694 | ; Call DRIVEPARMS to set TERM_ADDR and other drive specific cache parms | ||
| 6695 | ; | ||
| 6696 | ; SEE ALSO | ||
| 6697 | ; INTEL Expanded Memory Manager Programming Specification | ||
| 6698 | ; | ||
| 6699 | ; ENTRY: | ||
| 6700 | ; Invokation line parameter values set. | ||
| 6701 | ; EXIT: | ||
| 6702 | ; ABOVE_BLKMOV code swapped in at BLKMOV | ||
| 6703 | ; ABOVE_RESET code swapped in at RESET_SYSTEM | ||
| 6704 | ; CARRY SET | ||
| 6705 | ; Error, message already printed. Driver not installed. | ||
| 6706 | ; No Above Board memory allocated. | ||
| 6707 | ; CARRY CLEAR | ||
| 6708 | ; BASE_ADDR set to segment address of Above Board map window | ||
| 6709 | ; ABOVE_PID contains PID of allocated above board memory | ||
| 6710 | ; DEV_SIZE set to TRUE size | ||
| 6711 | ; TERM_ADDR set | ||
| 6712 | ; | ||
| 6713 | ; USES: | ||
| 6714 | ; ALL but DS | ||
| 6715 | ; | ||
| 6716 | ; Code is specific to TYPE 2 driver | ||
| 6717 | ; | ||
| 6718 | |||
| 6719 | ABOVE_INIT: | ||
| 6720 | ASSUME DS:INT13CODE,ES:NOTHING,SS:NOTHING | ||
| 6721 | ; | ||
| 6722 | ; Swap above code into place | ||
| 6723 | ; | ||
| 6724 | PUSH CS | ||
| 6725 | POP ES | ||
| 6726 | MOV SI,OFFSET ABOVE_CODE | ||
| 6727 | MOV DI,OFFSET DRIVE_CODE | ||
| 6728 | MOV CX,OFFSET DRIVE_END - OFFSET DRIVE_CODE | ||
| 6729 | REP MOVSB | ||
| 6730 | MOV SI,OFFSET ABOVE_RESET | ||
| 6731 | MOV DI,OFFSET RESET_SYSTEM | ||
| 6732 | MOV CX,OFFSET RESET_INCLUDE - OFFSET RESET_SYSTEM | ||
| 6733 | REP MOVSB | ||
| 6734 | ; | ||
| 6735 | ; Check for presence of Above board memory manager | ||
| 6736 | ; | ||
| 6737 | MOV AX,(Get_Interrupt_Vector SHL 8) OR 67H | ||
| 6738 | INT 21H | ||
| 6739 | MOV DI,SDEVNAME | ||
| 6740 | MOV SI,OFFSET ABOVE_DEV_NAME | ||
| 6741 | MOV CX,8 | ||
| 6742 | REPE CMPSB | ||
| 6743 | JZ GOT_MANAGER | ||
| 6744 | MOV DX,OFFSET NO_ABOVE | ||
| 6745 | ABOVE_ERR: | ||
| 6746 | CALL PRINT | ||
| 6747 | STC | ||
| 6748 | RET | ||
| 6749 | |||
| 6750 | GOT_MANAGER: | ||
| 6751 | ; | ||
| 6752 | ; Check memory status | ||
| 6753 | ; | ||
| 6754 | MOV CX,8000H | ||
| 6755 | STLOOP: | ||
| 6756 | MOV AH,ABOVE_STATUS | ||
| 6757 | INT 67H | ||
| 6758 | CMP AH,ABOVE_SUCCESSFUL | ||
| 6759 | JZ MEM_OK | ||
| 6760 | CMP AH,ABOVE_ERROR_BUSY | ||
| 6761 | LOOPZ STLOOP | ||
| 6762 | ST_ERR: | ||
| 6763 | MOV DX,OFFSET BAD_ABOVE | ||
| 6764 | JMP ABOVE_ERR | ||
| 6765 | |||
| 6766 | MEM_OK: | ||
| 6767 | ; | ||
| 6768 | ; Get base address of map region and set BASE_ADDR | ||
| 6769 | ; | ||
| 6770 | MOV AH,ABOVE_GET_SEG | ||
| 6771 | INT 67H | ||
| 6772 | CMP AH,ABOVE_ERROR_BUSY | ||
| 6773 | JZ MEM_OK | ||
| 6774 | CMP AH,ABOVE_SUCCESSFUL | ||
| 6775 | JNZ ST_ERR | ||
| 6776 | MOV WORD PTR [BASE_ADDR],0 | ||
| 6777 | MOV WORD PTR [BASE_ADDR + 2],BX | ||
| 6778 | ; | ||
| 6779 | ; Allocate drive memory | ||
| 6780 | ; | ||
| 6781 | GET_AVAIL: | ||
| 6782 | MOV AH,ABOVE_GET_FREE | ||
| 6783 | INT 67H | ||
| 6784 | CMP AH,ABOVE_ERROR_BUSY | ||
| 6785 | JZ GET_AVAIL | ||
| 6786 | CMP AH,ABOVE_SUCCESSFUL | ||
| 6787 | JNZ ST_ERR | ||
| 6788 | MOV AX,DX ; AX is total 16K pages | ||
| 6789 | ; BX is un-allocated 16K pages | ||
| 6790 | MOV DX,OFFSET NO_MEM | ||
| 6791 | OR AX,AX | ||
| 6792 | JZ ABOVE_ERR | ||
| 6793 | MOV DX,OFFSET ERRMSG2 | ||
| 6794 | ; | ||
| 6795 | ; change in allocation strategy new default is all of available pages | ||
| 6796 | ; < 8192K. | ||
| 6797 | ; | ||
| 6798 | ; algorithm: if (free_pages < 8) then error(); | ||
| 6799 | ; else { | ||
| 6800 | ; if (free_pages > 200h) then free_pages = 200h; | ||
| 6801 | ; if (num_arg == 1) then dev_size = free_pages; | ||
| 6802 | ; else dev_size = min (dev_size,free_pages) | ||
| 6803 | |||
| 6804 | |||
| 6805 | |||
| 6806 | CMP BX,8 ; 128K = 16K * 8 = Min cache size | ||
| 6807 | JB ABOVE_ERR | ||
| 6808 | cmp bx,0200h ; 8192K = Max cache size | ||
| 6809 | jbe ab0$1 ; if less or equal fine | ||
| 6810 | mov bx,0200h ; else limit it to 8192K | ||
| 6811 | ab0$1: | ||
| 6812 | mov cx,4 ; to convert number of pages into no of k | ||
| 6813 | shl bx,cl | ||
| 6814 | cmp [num_arg],1 ; is numeric argument 1 ( means none ) | ||
| 6815 | jne ab0$2 ; cache size has been requested | ||
| 6816 | mov [dev_size],bx ; else use all of available cache | ||
| 6817 | jmp short ab001 ; | ||
| 6818 | ab0$2: | ||
| 6819 | cmp [dev_size],bx ; minimum of dev size and bx | ||
| 6820 | jb ab001 | ||
| 6821 | mov [dev_size],bx ; | ||
| 6822 | |||
| 6823 | |||
| 6824 | ab001: | ||
| 6825 | mov bx,[dev_size] | ||
| 6826 | mov [current_dev_size],bx ; Initialize current device size | ||
| 6827 | ; | ||
| 6828 | ; BX is K we want to allocate (limited by available K) | ||
| 6829 | ; BX is at least 16 | ||
| 6830 | ; | ||
| 6831 | MOV AX,BX | ||
| 6832 | MOV CX,4 ; Convert back to # of 16K pages | ||
| 6833 | SHR BX,CL | ||
| 6834 | TEST AX,0FH ; Even???? | ||
| 6835 | JZ OKAYU ; Yes | ||
| 6836 | INC BX ; Gotta round up | ||
| 6837 | PUSH BX | ||
| 6838 | MOV CX,4 | ||
| 6839 | SHL BX,CL | ||
| 6840 | MOV [DEV_SIZE],BX ; Correct dev size too by rounding it up to | ||
| 6841 | ; next multiple of 16K, no sense wasting | ||
| 6842 | ; part of a page. | ||
| 6843 | ;A | ||
| 6844 | mov [current_dev_size],bx ; Correct current device size also | ||
| 6845 | ;A | ||
| 6846 | POP BX | ||
| 6847 | OKAYU: | ||
| 6848 | MOV AH,ABOVE_ALLOC | ||
| 6849 | INT 67H | ||
| 6850 | CMP AH,ABOVE_ERROR_BUSY | ||
| 6851 | JZ OKAYU | ||
| 6852 | CMP AH,ABOVE_SUCCESSFUL | ||
| 6853 | JZ GOT_ID | ||
| 6854 | CMP AH,ABOVE_ERROR_MAP_CNTXT | ||
| 6855 | JZ ST_ERRJ | ||
| 6856 | CMP AH,ABOVE_ERROR_OUT_OF_PIDS | ||
| 6857 | JB ST_ERRJ | ||
| 6858 | MOV DX,OFFSET ERRMSG2 | ||
| 6859 | JMP ABOVE_ERR | ||
| 6860 | |||
| 6861 | ST_ERRJ: | ||
| 6862 | JMP ST_ERR | ||
| 6863 | |||
| 6864 | GOT_ID: | ||
| 6865 | MOV [ABOVE_PID],DX | ||
| 6866 | ; | ||
| 6867 | ; INSTALL ABOVE RESET handler | ||
| 6868 | ; | ||
| 6869 | CALL SET_RESET | ||
| 6870 | ; | ||
| 6871 | ; We are now in good shape. | ||
| 6872 | ; | ||
| 6873 | CALL DRIVEPARMS | ||
| 6874 | JNC RETYYY | ||
| 6875 | CALL DISK_ABORT | ||
| 6876 | STC | ||
| 6877 | RETYYY: | ||
| 6878 | RET | ||
| 6879 | |||
| 6880 | BREAK <Drive code for /A driver. Swapped in at BLKMOV> | ||
| 6881 | |||
| 6882 | ; | ||
| 6883 | ; This label defines the start of the code swapped in at DRIVE_CODE | ||
| 6884 | ; | ||
| 6885 | ABOVE_CODE LABEL WORD | ||
| 6886 | |||
| 6887 | ; | ||
| 6888 | ; WARNING DANGER!!!!!!! | ||
| 6889 | ; | ||
| 6890 | ; This code is tranfered over the /E driver code at DRIVE_CODE | ||
| 6891 | ; | ||
| 6892 | ; ALL jmps etc. must be IP relative. | ||
| 6893 | ; ALL data references must be to cells at the FINAL, TRUE location | ||
| 6894 | ; (no data cells may be named HERE, must be named up at BLKMOV). | ||
| 6895 | ; OFFSET of ABOVE_BLKMOV relative to ABOVE_CODE MUST be the same as | ||
| 6896 | ; the OFFSET of BLKMOV relative to DRIVE_CODE. | ||
| 6897 | ; SIZE of stuff between ABOVE_CODE and ABOVE_END MUST be less than | ||
| 6898 | ; or equal to size of stuff between DRIVE_CODE and DRIVE_END. | ||
| 6899 | |||
| 6900 | IF2 | ||
| 6901 | IF((OFFSET ABOVE_BLKMOV - OFFSET ABOVE_CODE) NE (OFFSET BLKMOV - OFFSET DRIVE_CODE)) | ||
| 6902 | %out ERROR BLKMOV, ABOVE_BLKMOV NOT ALIGNED | ||
| 6903 | ENDIF | ||
| 6904 | IF((OFFSET ABOVE_END - OFFSET ABOVE_CODE) GT (OFFSET DRIVE_END - OFFSET DRIVE_CODE)) | ||
| 6905 | %out ERROR ABOVE CODE TOO BIG | ||
| 6906 | ENDIF | ||
| 6907 | ENDIF | ||
| 6908 | |||
| 6909 | DD ? ; 24 bit address of start of this RAMDRV | ||
| 6910 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 6911 | ;** ABOVE_BLKMOV - Perform transfer for TYPE 2 driver | ||
| 6912 | ; | ||
| 6913 | ; This routine is the transfer routine for moving bytes | ||
| 6914 | ; to and from the Above Board memory containing the cache. | ||
| 6915 | ; | ||
| 6916 | ; The Above Board is implemented as 4 16K windows into the Above | ||
| 6917 | ; Board memory, giving a total window of 64K wich starts on some | ||
| 6918 | ; 16K boundary of the Above Board memory. Given that a DOS I/O | ||
| 6919 | ; request is up to 64K bytes starting on some sector boundary, | ||
| 6920 | ; the most general I/O picture is: | ||
| 6921 | ; | ||
| 6922 | ; |------------|------------|------------|------------|------------| | ||
| 6923 | ; | Above Brd | Above Brd | Above Brd | Above Brd | Above Brd | | ||
| 6924 | ; |Log page n |Log page n+1|Log page n+2|log page n+3|Log page n+4| | ||
| 6925 | ; |------------|------------|------------|------------|------------| | ||
| 6926 | ; |---|---| | | | ||
| 6927 | ; | | |---------------- 64K bytes of sectors -------------| | ||
| 6928 | ; Byte | | | | ||
| 6929 | ; offset|------------------|------------------------| | | ||
| 6930 | ; of first| Number of words in | | | ||
| 6931 | ; byte of | first part of I/O that |---|---| | ||
| 6932 | ; I/O in | can be performed once Number | ||
| 6933 | ; first | logical pages n - n+3 of words | ||
| 6934 | ; Log page| are mapped into physical in tail | ||
| 6935 | ; | pages 0 - 3 part of I/O | ||
| 6936 | ; Location of that have | ||
| 6937 | ; first byte to be done | ||
| 6938 | ; of sector M, once logical | ||
| 6939 | ; the start sector page n+4 is | ||
| 6940 | ; of the I/O mapped into | ||
| 6941 | ; physical page | ||
| 6942 | ; 0 | ||
| 6943 | ; | ||
| 6944 | ; One or both of "Byte offset of first byte of I/O in first page" and | ||
| 6945 | ; "Number of words in tail part of I/O" may be zero depending on the | ||
| 6946 | ; size of the I/O and its start offset in the first logical page it is | ||
| 6947 | ; possible to map. | ||
| 6948 | ; | ||
| 6949 | ; WARNING: IF A PRE-EMPTIVE MULTITASKING SYSTEM SCHEDULES A TASK WHICH | ||
| 6950 | ; IS USING THE ABOVE BOARD DURING THE TIME THIS DRIVER IS IN THE | ||
| 6951 | ; MIDDLE OF PERFORMING AN I/O, THE SYSTEM HAD BETTER MANAGE THE A | ||
| 6952 | ; BOARD MAPPING CONTEXT CORRECTLY OR ALL SORTS OF STRANGE UNPLEASANT | ||
| 6953 | ; THINGS WILL OCCUR. | ||
| 6954 | ; | ||
| 6955 | ; SEE ALSO | ||
| 6956 | ; INTEL Expanded Memory Manager Programming Specification | ||
| 6957 | ; | ||
| 6958 | ; ENTRY: | ||
| 6959 | ; ES:DI is packet transfer address. | ||
| 6960 | ; CX is number of words to transfer. | ||
| 6961 | ; DX:AX is 32 bit start byte offset (0 = start of cache) | ||
| 6962 | ; BH is 1 for WRITE, 0 for READ | ||
| 6963 | ; | ||
| 6964 | ; BASE_ADDR set to point to Above Board mapping window in main memory | ||
| 6965 | ; This "input" is not the responsibility of the caller. It | ||
| 6966 | ; is up to the initialization code to set it up when the | ||
| 6967 | ; device is installed | ||
| 6968 | ; | ||
| 6969 | ; EXIT: | ||
| 6970 | ; Carry Clear | ||
| 6971 | ; OK, operation performed successfully | ||
| 6972 | ; Carry Set | ||
| 6973 | ; Error during operation, AL is error number | ||
| 6974 | ; | ||
| 6975 | ; USES: | ||
| 6976 | ; ALL | ||
| 6977 | ; | ||
| 6978 | ; This routine is specific to TYPE 2 driver | ||
| 6979 | ; | ||
| 6980 | above_blkmov: | ||
| 6981 | assume ds:int13code,es:nothing,ss:nothing | ||
| 6982 | ; | ||
| 6983 | ; save mapping context and return with error if save fails | ||
| 6984 | ; | ||
| 6985 | save_mapping_context | ||
| 6986 | jnc ab_blk$1 | ||
| 6987 | ret | ||
| 6988 | ; | ||
| 6989 | ; find logical page number, offset of i/o in first page | ||
| 6990 | ; | ||
| 6991 | ab_blk$1: | ||
| 6992 | push cx | ||
| 6993 | mov cx,1024*16 ; 16k bytes / page | ||
| 6994 | div cx ; dx:ax / 16k --> log page numb in ax | ||
| 6995 | ; --> offset of i/o in dx | ||
| 6996 | mov si,dx ; transfer offset to si | ||
| 6997 | mov dx,ax ; store the page number in dx | ||
| 6998 | pop cx | ||
| 6999 | ; | ||
| 7000 | ; find case and dispatch accordingly | ||
| 7001 | ; | ||
| 7002 | ; case 0 : user buffer below page map, can use aaron's code | ||
| 7003 | ; case 1 : user buffer above page map, can use aaron's code | ||
| 7004 | ; case 2 : user buffer totally within page map, use pai's code | ||
| 7005 | ; case 3 : user buffer partly in page map partly below, error | ||
| 7006 | ; case 4 : user buffer partly in page map partly above, error | ||
| 7007 | ; | ||
| 7008 | push bx | ||
| 7009 | push cx | ||
| 7010 | ; | ||
| 7011 | ; if( final_user_off < pm_base_addr ) then case 0 | ||
| 7012 | ; | ||
| 7013 | mov ax,di ; get user buffer initial offset into ax | ||
| 7014 | shr ax,1 ; convert to word offset | ||
| 7015 | dec cx ; convert word count to 0 based number | ||
| 7016 | add ax,cx ; user buffer final word offset | ||
| 7017 | shr ax,1 ; convert to segment | ||
| 7018 | shr ax,1 ; | ||
| 7019 | shr ax,1 ; | ||
| 7020 | mov bx,es ; get segment of buffer | ||
| 7021 | add ax,bx ; now we have the segment of the user buffer | ||
| 7022 | ; with offset < 16 | ||
| 7023 | sub ax,word ptr [base_addr+2] ; compare against page map | ||
| 7024 | jc aar_cd ; if below page map then execute old code | ||
| 7025 | ; | ||
| 7026 | ; if( initial_user_off < pm_base_addr ) then error | ||
| 7027 | ; | ||
| 7028 | mov cx,4 | ||
| 7029 | mov bp,di ; get initial offset in bp | ||
| 7030 | shr bp,cl ; | ||
| 7031 | add bp,bx ; | ||
| 7032 | sub bp,word ptr [base_addr +2] | ||
| 7033 | jc ab_error ; | ||
| 7034 | ; | ||
| 7035 | ; if ( initial_user_off >= pm_end_addr ) then case1 | ||
| 7036 | ; | ||
| 7037 | cmp bp,4*1024 ; | ||
| 7038 | jae aar_cd ; | ||
| 7039 | ; | ||
| 7040 | ; if ( final_addr >= pm_end_addr ) then error | ||
| 7041 | ; | ||
| 7042 | cmp ax,4*1024 | ||
| 7043 | jae ab_error | ||
| 7044 | ; | ||
| 7045 | ; case 2 | ||
| 7046 | ; | ||
| 7047 | within_pm: jmp new_code ; user buffer in page map | ||
| 7048 | ; so we need to execute new code | ||
| 7049 | ab_error: | ||
| 7050 | add sp,4 | ||
| 7051 | mov al,0bbh ; general failure | ||
| 7052 | stc | ||
| 7053 | jmp short REST_CONT ; RESTORE CONTEXT!!! | ||
| 7054 | aar_cd: | ||
| 7055 | pop cx | ||
| 7056 | pop bx | ||
| 7057 | ; | ||
| 7058 | ; Referring back to the diagram given above the following routine is | ||
| 7059 | ; to take care of transfer of the most general case. | ||
| 7060 | ; What this routine does is break every I/O down into the above parts. | ||
| 7061 | ; The first or main part of the I/O is performed by mapping 1 to 4 | ||
| 7062 | ; sequential logical pages into the 4 physical pages and executing one | ||
| 7063 | ; REP MOVSW. If the tail word count is non-zero then the fith sequential | ||
| 7064 | ; logical page is mapped into physical page 0 and another REP MOVSW is | ||
| 7065 | ; executed. | ||
| 7066 | ; | ||
| 7067 | ; METHOD: | ||
| 7068 | ; Break I/O down as described above into main piece and tail piece | ||
| 7069 | ; Map the appropriate number of sequential pages (up to 4) | ||
| 7070 | ; into the page window at BASE_ADDR to set up the main piece | ||
| 7071 | ; of the I/O. | ||
| 7072 | ; Set appropriate seg and index registers and CX to perform the | ||
| 7073 | ; main piece of the I/O into the page window | ||
| 7074 | ; REP MOVSW | ||
| 7075 | ; IF there is a tail piece | ||
| 7076 | ; Map the next logical page into physical page 0 | ||
| 7077 | ; Reset the appropriate index register to point at phsical page 0 | ||
| 7078 | ; Move tail piece word count into CX | ||
| 7079 | ; REP MOVSW | ||
| 7080 | ; Restore Above Board page mapping context | ||
| 7081 | ; | ||
| 7082 | XOR BP,BP ; No tail page | ||
| 7083 | PUSH BX | ||
| 7084 | ; | ||
| 7085 | ; DX is first page #, SI is byte offset of start of I/O in first page | ||
| 7086 | ; | ||
| 7087 | MOV AX,DX | ||
| 7088 | MOV BX,SI | ||
| 7089 | SHR BX,1 ; # Words in first 16k page which are not part | ||
| 7090 | ; of I/O | ||
| 7091 | PUSH CX | ||
| 7092 | ADD BX,CX ; # of words we need to map to perform I/O | ||
| 7093 | MOV DX,BX | ||
| 7094 | AND DX,1FFFH ; DX is number of words to transfer last page | ||
| 7095 | ; remainder of div by words in 16K bytes | ||
| 7096 | MOV CL,13 ; Div by # words in 16K | ||
| 7097 | SHR BX,CL ; BX is number of pages to map (may need round up) | ||
| 7098 | OR DX,DX ; Remainder? | ||
| 7099 | JZ NO_REM | ||
| 7100 | INC BX ; Need one more page | ||
| 7101 | NO_REM: | ||
| 7102 | MOV CX,BX ; CX is total pages we need to map | ||
| 7103 | MOV BX,AX ; BX is first logical page | ||
| 7104 | CMP CX,4 ; We can map up to 4 pages | ||
| 7105 | JBE NO_TAIL | ||
| 7106 | MOV BP,DX ; Words to move in tail page saved in BP | ||
| 7107 | DEC CX ; Need second map for the 5th page | ||
| 7108 | POP AX | ||
| 7109 | SUB AX,DX ; Words to move in first 4 pages is input | ||
| 7110 | ; word count minus words in tail page | ||
| 7111 | PUSH AX ; Count for first mapping back on stack | ||
| 7112 | NO_TAIL: | ||
| 7113 | ; Map CX pages | ||
| 7114 | MOV DX,[ABOVE_PID] | ||
| 7115 | MOV AX,ABOVE_MAP SHL 8 ; Physical page 0 | ||
| 7116 | PUSH AX | ||
| 7117 | MAP_NEXT: | ||
| 7118 | POP AX ; Recover correct AX register | ||
| 7119 | PUSH AX | ||
| 7120 | PUSH BX | ||
| 7121 | PUSH DX | ||
| 7122 | INT 67H ; Damn call ABOVE_MAP zaps BX,DX,AX | ||
| 7123 | POP DX | ||
| 7124 | POP BX | ||
| 7125 | OR AH,AH | ||
| 7126 | JNZ MAP_ERR1 ; error | ||
| 7127 | IF2 | ||
| 7128 | IF (ABOVE_SUCCESSFUL) | ||
| 7129 | %out ASSUMPTION IN CODE THAT ABOVE_SUCCESSFUL = 0 IS INVALID | ||
| 7130 | ENDIF | ||
| 7131 | ENDIF | ||
| 7132 | NEXT_PAGE: | ||
| 7133 | INC BX ; Next logical page | ||
| 7134 | POP AX | ||
| 7135 | INC AL ; Next physical page | ||
| 7136 | PUSH AX | ||
| 7137 | LOOP MAP_NEXT | ||
| 7138 | POP AX ; Clean stack | ||
| 7139 | POP CX ; Word count for first page mapping | ||
| 7140 | POP AX ; Operation in AH | ||
| 7141 | ; | ||
| 7142 | ; BX has # of next logical page (Tail page if BP is non-zero) | ||
| 7143 | ; BP has # of words to move in tail page (0 if no tail) | ||
| 7144 | ; CX has # of words to move in current mapping | ||
| 7145 | ; SI is offset into current mapping of start of I/O | ||
| 7146 | ; AH indicates READ or WRITE | ||
| 7147 | ; | ||
| 7148 | PUSH AX ; Save op for possible second I/O | ||
| 7149 | OR AH,AH | ||
| 7150 | JZ READ_A | ||
| 7151 | ; | ||
| 7152 | ; WRITE | ||
| 7153 | ; | ||
| 7154 | PUSH ES | ||
| 7155 | PUSH DI | ||
| 7156 | MOV DI,SI ; Start page offset to DI | ||
| 7157 | POP SI ; DS:SI is transfer addr | ||
| 7158 | POP DS | ||
| 7159 | ASSUME DS:NOTHING | ||
| 7160 | MOV ES,WORD PTR [BASE_ADDR + 2] ; ES:DI -> start | ||
| 7161 | JMP SHORT FIRST_MOVE | ||
| 7162 | |||
| 7163 | READ_A: | ||
| 7164 | ASSUME DS:INT13CODE | ||
| 7165 | MOV DS,WORD PTR [BASE_ADDR + 2] ; DS:SI -> start | ||
| 7166 | ASSUME DS:NOTHING | ||
| 7167 | FIRST_MOVE: | ||
| 7168 | REP MOVSW | ||
| 7169 | OR BP,BP ; Tail? | ||
| 7170 | JNZ TAIL_IO ; Yup | ||
| 7171 | ALL_DONE: | ||
| 7172 | POP AX | ||
| 7173 | CLC | ||
| 7174 | REST_CONT: | ||
| 7175 | ; Restore page mapping context | ||
| 7176 | PUSH AX ; Save possible error code | ||
| 7177 | PUSHF ; And carry state | ||
| 7178 | REST_AGN: | ||
| 7179 | MOV DX,[ABOVE_PID] | ||
| 7180 | MOV AH,ABOVE_RESTORE_MAP_PID | ||
| 7181 | INT 67H | ||
| 7182 | OR AH,AH | ||
| 7183 | JZ ROK | ||
| 7184 | IF2 | ||
| 7185 | IF (ABOVE_SUCCESSFUL) | ||
| 7186 | %out ASSUMPTION IN CODE THAT ABOVE_SUCCESSFUL = 0 IS INVALID | ||
| 7187 | ENDIF | ||
| 7188 | ENDIF | ||
| 7189 | CMP AH,ABOVE_ERROR_BUSY | ||
| 7190 | JZ REST_AGN | ||
| 7191 | CMP AH,ABOVE_ERROR_NO_CNTXT | ||
| 7192 | JZ ROK ; Ignore the invalid PID error | ||
| 7193 | POP DX | ||
| 7194 | POP DX ; Clean stack | ||
| 7195 | MOV AL,0BBH ; General failure | ||
| 7196 | STC | ||
| 7197 | RET | ||
| 7198 | |||
| 7199 | ROK: | ||
| 7200 | POPF ; Recover carry state | ||
| 7201 | POP AX ; and possible error code | ||
| 7202 | RET | ||
| 7203 | |||
| 7204 | TAIL_IO: | ||
| 7205 | MOV DX,[ABOVE_PID] | ||
| 7206 | MAP_AGN: | ||
| 7207 | MOV AX,ABOVE_MAP SHL 8 ; map logical page BX to phys page 0 | ||
| 7208 | PUSH BX | ||
| 7209 | PUSH DX | ||
| 7210 | INT 67H ; Damn call ABOVE_MAP zaps BX,DX,AX | ||
| 7211 | POP DX | ||
| 7212 | POP BX | ||
| 7213 | OR AH,AH | ||
| 7214 | JNZ MAP_ERR2 ; Error | ||
| 7215 | IF2 | ||
| 7216 | IF (ABOVE_SUCCESSFUL) | ||
| 7217 | %out ASSUMPTION IN CODE THAT ABOVE_SUCCESSFUL = 0 IS INVALID | ||
| 7218 | ENDIF | ||
| 7219 | ENDIF | ||
| 7220 | SECOND_MOVE: | ||
| 7221 | POP AX ; Recover Op type | ||
| 7222 | PUSH AX | ||
| 7223 | OR AH,AH | ||
| 7224 | JZ READ_SEC | ||
| 7225 | ; | ||
| 7226 | ; WRITE | ||
| 7227 | ; | ||
| 7228 | XOR DI,DI ; ES:DI -> start of tail | ||
| 7229 | JMP SHORT SMOVE | ||
| 7230 | |||
| 7231 | READ_SEC: | ||
| 7232 | XOR SI,SI ; DS:SI -> start of tail | ||
| 7233 | SMOVE: | ||
| 7234 | MOV CX,BP | ||
| 7235 | REP MOVSW | ||
| 7236 | JMP ALL_DONE | ||
| 7237 | |||
| 7238 | MAP_ERR1: | ||
| 7239 | CMP AH,ABOVE_ERROR_BUSY ; Busy? | ||
| 7240 | JZ MAP_NEXT ; Yes, wait till not busy (INTs are ON) | ||
| 7241 | ADD SP,6 ; Clean stack | ||
| 7242 | JMP SHORT DNR_ERR | ||
| 7243 | |||
| 7244 | MAP_ERR2: | ||
| 7245 | CMP AH,ABOVE_ERROR_BUSY | ||
| 7246 | JZ MAP_AGN | ||
| 7247 | ADD SP,2 | ||
| 7248 | DNR_ERR: | ||
| 7249 | MOV AL,0AAH ; Drive not ready | ||
| 7250 | STC | ||
| 7251 | JMP REST_CONT | ||
| 7252 | ; | ||
| 7253 | ; | ||
| 7254 | ; this code has been written to handle te cases of overlapping usage | ||
| 7255 | ; of the above board page frame segment by the cache and user buffer | ||
| 7256 | ; assumption: in dos tracks cannot be more than 64 sectors long so | ||
| 7257 | ; in the worst case we shall have the user buffer occupying three | ||
| 7258 | ; pages is the page frame. we attempt to find the page that is | ||
| 7259 | ; available for the cache and use it repeatedly to access the cache | ||
| 7260 | ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| 7261 | ; the algorithm is: | ||
| 7262 | ; ****************************************************** | ||
| 7263 | ; [STEP1: determine the page we can use for the cache] | ||
| 7264 | ; | ||
| 7265 | ; if (initial_para_offset_user in page 1 or above ) then { | ||
| 7266 | ; physical_cache_page = 0; | ||
| 7267 | ; cache_segment = above board segment; | ||
| 7268 | ; } | ||
| 7269 | ; else { | ||
| 7270 | ; physical_cache_page = 3; | ||
| 7271 | ; cache_segment = above_board_segment + 3*1024; | ||
| 7272 | ; } | ||
| 7273 | ; | ||
| 7274 | ; ****************************************************** | ||
| 7275 | ; [STEP2: initial setup] | ||
| 7276 | ; | ||
| 7277 | ; count = user_count_requested; | ||
| 7278 | ; number_to_be_transferred = min ( count, (16K - si) >> 2 ); | ||
| 7279 | ; exchange source and destination if necessary; | ||
| 7280 | ; | ||
| 7281 | ; ******************************************************* | ||
| 7282 | ; [STEP3: set up transfer and do it] | ||
| 7283 | ; | ||
| 7284 | ; count = count - number_to_be_transferred; | ||
| 7285 | ; map_page cache_handle,physical_cache_page,logical_cache_page | ||
| 7286 | ; mov data | ||
| 7287 | ; | ||
| 7288 | ; ******************************************************* | ||
| 7289 | ; [STEP4: determine if another transfer needed and setup if so] | ||
| 7290 | ; | ||
| 7291 | ; if ( count == 0 ) then exit; | ||
| 7292 | ; if ( operation == read ) then source_offset = 0; | ||
| 7293 | ; else dest_offset = 0; | ||
| 7294 | ; number_to_be_transferred = min ( count, 8*1024 ); | ||
| 7295 | ; logical_page_number++ ; | ||
| 7296 | ; | ||
| 7297 | ; ******************************************************* | ||
| 7298 | ; [STEP5: go to do next block] | ||
| 7299 | ; | ||
| 7300 | ; goto [STEP3] | ||
| 7301 | ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| 7302 | ; | ||
| 7303 | new_code: | ||
| 7304 | assume ds:int13code,es:nothing,ss:nothing | ||
| 7305 | ; | ||
| 7306 | ; input parameters: | ||
| 7307 | ; | ||
| 7308 | ; bp : start para offset of user buffer in physical page frame | ||
| 7309 | ; ax : end para offset of user buffer in physical page frame | ||
| 7310 | ; di : transfer offset of user buffer | ||
| 7311 | ; es : transfer segment of user buffer | ||
| 7312 | ; dx : logical page number in cache | ||
| 7313 | ; si : offset from start in logical page number | ||
| 7314 | ; | ||
| 7315 | ; on stack { cx,bx } where cx = number of words, bx = read / write status | ||
| 7316 | ; | ||
| 7317 | ; [STEP1: finding physical cache page and page frame] | ||
| 7318 | ; | ||
| 7319 | ; | ||
| 7320 | ; assume is physical page 0 | ||
| 7321 | ; | ||
| 7322 | xor al,al ; use page 0 for cache | ||
| 7323 | mov bx,word ptr [base_addr+2] | ||
| 7324 | ; | ||
| 7325 | ; see if this assumption valid | ||
| 7326 | ; | ||
| 7327 | cmp bp,1024 ; is initial in page 1 or above | ||
| 7328 | jae ab$30 ; if so or assumption is valid | ||
| 7329 | ; | ||
| 7330 | ; else we have to correct our assumption | ||
| 7331 | ; | ||
| 7332 | mov al,3 ; use page 3 for cache | ||
| 7333 | add bx,3*1024 ; | ||
| 7334 | ; | ||
| 7335 | ; initialise page frame segment | ||
| 7336 | ; | ||
| 7337 | ab$30: | ||
| 7338 | mov ds,bx | ||
| 7339 | ; | ||
| 7340 | assume ds:nothing | ||
| 7341 | ; | ||
| 7342 | ; [STEP2: initialising transfer parameters] | ||
| 7343 | ; | ||
| 7344 | ; | ||
| 7345 | pop bp ; bp will have count of words left to be transferred | ||
| 7346 | pop bx ; read / write status | ||
| 7347 | push bx ; save it back again | ||
| 7348 | push dx ; save this too | ||
| 7349 | ; | ||
| 7350 | ; initially si offset into logical page, so we can only do 16*1024 - si | ||
| 7351 | ; byte transfer | ||
| 7352 | ; | ||
| 7353 | mov cx,16*1024 | ||
| 7354 | sub cx,si | ||
| 7355 | shr cx,1 ; convert to word count | ||
| 7356 | ; | ||
| 7357 | ; number to be transferred is the minimum of this and the user requested | ||
| 7358 | ; count | ||
| 7359 | ; | ||
| 7360 | cmp cx,bp | ||
| 7361 | jb ab$31 | ||
| 7362 | mov cx,bp | ||
| 7363 | ; | ||
| 7364 | ab$31: | ||
| 7365 | ; | ||
| 7366 | ; see if write, then we have to switch source with destination | ||
| 7367 | ; | ||
| 7368 | or bh,bh | ||
| 7369 | je ab$32 ; if read we don't have to do anything | ||
| 7370 | ; else we have to switch | ||
| 7371 | src_dest_switch | ||
| 7372 | ab$32: | ||
| 7373 | ; | ||
| 7374 | ; set direction flag so that we don't have to do it repeatedly | ||
| 7375 | ; | ||
| 7376 | cld | ||
| 7377 | ; | ||
| 7378 | ; [STEP3: set up transfer and do it] | ||
| 7379 | ; | ||
| 7380 | ab$33: | ||
| 7381 | ; | ||
| 7382 | ; update count of words still left to be transferred after this | ||
| 7383 | ; | ||
| 7384 | sub bp,cx | ||
| 7385 | ; | ||
| 7386 | ; map the logical page in cache to the physical page selected | ||
| 7387 | ; | ||
| 7388 | mov bx,dx ; get logical page into bx | ||
| 7389 | ; al already holds the physical page # | ||
| 7390 | map_page | ||
| 7391 | jnc ab$34 ; suceeded ? | ||
| 7392 | ; | ||
| 7393 | ; else report error | ||
| 7394 | ; | ||
| 7395 | add sp,4 | ||
| 7396 | stc | ||
| 7397 | jmp short restore_mp ; and go to restore page map | ||
| 7398 | ab$34: | ||
| 7399 | ; | ||
| 7400 | ; succeeded, do the transfer | ||
| 7401 | ; | ||
| 7402 | rep movsw | ||
| 7403 | ; | ||
| 7404 | ; | ||
| 7405 | ; [STEP4: check if transfer done, if not set up for next block] | ||
| 7406 | ; [STEP5: go back to STEP3] | ||
| 7407 | ; | ||
| 7408 | ; check if done | ||
| 7409 | ; | ||
| 7410 | or bp,bp ; count 0 | ||
| 7411 | je ab$40 ; yes, go to finish up | ||
| 7412 | ; | ||
| 7413 | ; recover original dx and bx, increment dx and then save both again | ||
| 7414 | ; | ||
| 7415 | pop dx | ||
| 7416 | pop bx | ||
| 7417 | inc dx | ||
| 7418 | push bx | ||
| 7419 | push dx | ||
| 7420 | ; | ||
| 7421 | ; words to be transferred minimum of count and 8*1024 words | ||
| 7422 | ; | ||
| 7423 | mov cx,8*1024 ; 8k words in a page | ||
| 7424 | cmp cx,bp ; | ||
| 7425 | jbe ab$35 ; if below or equal this is what we want | ||
| 7426 | ; | ||
| 7427 | mov cx,bp ; else we can transfer the whole count | ||
| 7428 | ab$35: | ||
| 7429 | ; | ||
| 7430 | ; see whether cache src or dest and accordingly reset either si or di | ||
| 7431 | ; | ||
| 7432 | or bh,bh ; read? | ||
| 7433 | jne ab$36 ; if write go to modify | ||
| 7434 | ; | ||
| 7435 | ; read, zero si and go back to step3 | ||
| 7436 | ; | ||
| 7437 | xor si,si | ||
| 7438 | jmp short ab$33 ; to step 3 | ||
| 7439 | ab$36: | ||
| 7440 | ; | ||
| 7441 | ; write, zero di and go back to step3 | ||
| 7442 | ; | ||
| 7443 | xor di,di | ||
| 7444 | jmp short ab$33 ; to step 3 | ||
| 7445 | ; | ||
| 7446 | ; finishing up we have to restore the page map | ||
| 7447 | ; | ||
| 7448 | ab$40: | ||
| 7449 | add sp,4 | ||
| 7450 | clc | ||
| 7451 | restore_mp: | ||
| 7452 | restore_mapping_context | ||
| 7453 | ret | ||
| 7454 | |||
| 7455 | DW ? ; SPACE for ABOVE_PID | ||
| 7456 | |||
| 7457 | ; | ||
| 7458 | ; This label defines the end of the code swapped in at DRIVE_CODE | ||
| 7459 | ; | ||
| 7460 | ABOVE_END LABEL WORD | ||
| 7461 | |||
| 7462 | BREAK <Drive code for /A driver. Swapped in at RESET_SYSTEM> | ||
| 7463 | |||
| 7464 | |||
| 7465 | ; | ||
| 7466 | ; WARNING DANGER!!!!!!! | ||
| 7467 | ; | ||
| 7468 | ; This code is tranfered over the /E driver code at RESET_SYSTEM | ||
| 7469 | ; | ||
| 7470 | ; ALL jmps etc. must be IP relative. | ||
| 7471 | ; ALL data references must be to cells at the FINAL, TRUE location | ||
| 7472 | ; (no data cells may be named HERE, must be named up at RESET_SYSTEM). | ||
| 7473 | ; SIZE of stuff between ABOVE_RESET and ABOVE_RESET_END MUST be less than | ||
| 7474 | ; or equal to size of stuff between RESET_SYSTEM and RESET_INCLUDE. | ||
| 7475 | ; | ||
| 7476 | ; NOTE: EACH ABOVE BOARD driver has an INT 19 and 9 handler. This is | ||
| 7477 | ; different from /E and RESMEM in which only the first | ||
| 7478 | ; driver has an INT 19 and 9 handler. | ||
| 7479 | ; | ||
| 7480 | |||
| 7481 | IF2 | ||
| 7482 | IF((OFFSET ABOVE_RESET_END - OFFSET ABOVE_RESET) GT (OFFSET RESET_INCLUDE - OFFSET RESET_SYSTEM)) | ||
| 7483 | %out ERROR ABOVE_RESET CODE TOO BIG | ||
| 7484 | ENDIF | ||
| 7485 | ENDIF | ||
| 7486 | |||
| 7487 | ;** ABOVE_RESET perform TYPE 2 (/A) driver specific reboot code | ||
| 7488 | ; | ||
| 7489 | ; This code issues an ABOVE_DEALLOC call for the memory | ||
| 7490 | ; associated with this particular TYPE 2 cache since the | ||
| 7491 | ; system is being re-booted and the driver is "gone". | ||
| 7492 | ; | ||
| 7493 | ; ENTRY | ||
| 7494 | ; NONE | ||
| 7495 | ; EXIT | ||
| 7496 | ; NONE | ||
| 7497 | ; USES | ||
| 7498 | ; NONE | ||
| 7499 | ; | ||
| 7500 | ; This code is specific to TYPE 2 drivers | ||
| 7501 | ; | ||
| 7502 | |||
| 7503 | ABOVE_RESET: | ||
| 7504 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 7505 | PUSH AX | ||
| 7506 | PUSH DX | ||
| 7507 | AGAIN_RESET: | ||
| 7508 | MOV DX,[ABOVE_PID] | ||
| 7509 | MOV AH,ABOVE_DEALLOC ; Close PID | ||
| 7510 | INT 67H | ||
| 7511 | CMP AH,ABOVE_ERROR_BUSY | ||
| 7512 | JZ AGAIN_RESET | ||
| 7513 | POP DX | ||
| 7514 | POP AX | ||
| 7515 | RET | ||
| 7516 | |||
| 7517 | ; | ||
| 7518 | ; This label defines the end of the code swapped in at RESET_SYSTEM | ||
| 7519 | ; | ||
| 7520 | ABOVE_RESET_END LABEL BYTE | ||
| 7521 | |||
| 7522 | BREAK <messages and common data> | ||
| 7523 | |||
| 7524 | ;** Message texts and common data | ||
| 7525 | ; | ||
| 7526 | ; Init data. This data is disposed of after initialization. | ||
| 7527 | ; it is mostly texts of all of the messages | ||
| 7528 | ; | ||
| 7529 | ; COMMON to TYPE 1 and 2 drivers | ||
| 7530 | ; | ||
| 7531 | ; THIS IS THE START OF DATA SUBJECT TO TRANSLATION | ||
| 7532 | |||
| 7533 | NO_ABOVE db "SMARTDrive : Expanded Memory Manager not present",13,10,"$" | ||
| 7534 | BAD_ABOVE db "SMARTDrive : Expanded Memory Status shows error",13,10,"$" | ||
| 7535 | BAD_AT db "SMARTDrive : Cannot run on this computer",13,10,"$" | ||
| 7536 | NO_MEM db "SMARTDrive : No extended memory available",13,10,"$" | ||
| 7537 | ERRMSG1 db "SMARTDrive : Invalid parameter",13,10,"$" | ||
| 7538 | ERRMSG2 db "SMARTDrive : Insufficient memory",13,10,"$" | ||
| 7539 | INIT_IO_ERR db "SMARTDrive : I/O error accessing cache memory",13,10,"$" | ||
| 7540 | NOHARD db "SMARTDrive : No hard drives on system",13,10,"$" | ||
| 7541 | BIGTRACK db "SMARTDrive : Too many bytes per track on hard drive",13,10,"$" | ||
| 7542 | BADVERMES db 13,10,"SMARTDrive : Incorrect DOS version",13,10,"$" | ||
| 7543 | |||
| 7544 | ; | ||
| 7545 | ; This is the Int13 header message. | ||
| 7546 | ; | ||
| 7547 | HEADERMES db 13,10,"Microsoft SMARTDrive Disk Cache v2.10",13,10,"$" | ||
| 7548 | |||
| 7549 | ; | ||
| 7550 | ; This is the status message used to display INT13 configuration | ||
| 7551 | ; it is: | ||
| 7552 | ; | ||
| 7553 | ; STATMES1<size in K><STATMES1A|STATMES1E>STATMES2<# tracks in cache>STATMES3 | ||
| 7554 | ; <sectors per track>STATMES4 | ||
| 7555 | ; | ||
| 7556 | ; It is up to translator to move the message text around the numbers | ||
| 7557 | ; so that the message is printed correctly when translated | ||
| 7558 | ; | ||
| 7559 | STATMES1 db " Cache size: $" | ||
| 7560 | STATMES1A db "K in Expanded Memory$" | ||
| 7561 | STATMES1E db "K in Extended Memory$" | ||
| 7562 | STATMES2 db 13,10," Room for $" | ||
| 7563 | STATMES3 db " tracks of $" | ||
| 7564 | STATMES4 db " sectors each",13,10,13,10,"$" | ||
| 7565 | ifdef OMTI | ||
| 7566 | omti_msg db " OMTI controller release",13,10,"$" | ||
| 7567 | endif | ||
| 7568 | |||
| 7569 | ;----------------------------------------------------------------------- | ||
| 7570 | ; | ||
| 7571 | ; END OF DATA SUBJECT TO TRANSLATION | ||
| 7572 | ; | ||
| 7573 | |||
| 7574 | IF DEBUG | ||
| 7575 | STATMES5 db "Device CS = $" | ||
| 7576 | STATMES6 db " decimal",13,10,"$" | ||
| 7577 | s5flagmsg db " = S5 flag",13,10,"$" | ||
| 7578 | U_msg db " = U Switch", 13,10,'$' | ||
| 7579 | ENDIF | ||
| 7580 | |||
| 7581 | db "This program is the property of Microsoft Corporation." | ||
| 7582 | |||
| 7583 | INT13_END LABEL BYTE | ||
| 7584 | |||
| 7585 | INT13CODE ENDS | ||
| 7586 | END | ||
| 7587 | \ No newline at end of file | ||
diff --git a/v4.0/src/DEV/SMARTDRV/SMARTDRV.LNK b/v4.0/src/DEV/SMARTDRV/SMARTDRV.LNK new file mode 100644 index 0000000..be9d1c2 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/SMARTDRV.LNK | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | int13 | ||
| 2 | int13.exe | ||
| 3 | int13.map -map; | ||
diff --git a/v4.0/src/DEV/SMARTDRV/SYSCALL.ASM b/v4.0/src/DEV/SMARTDRV/SYSCALL.ASM new file mode 100644 index 0000000..3f6d712 --- /dev/null +++ b/v4.0/src/DEV/SMARTDRV/SYSCALL.ASM | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | BREAK <system call definitions> | ||
| 2 | |||
| 3 | Abort EQU 0 ; 0 0 | ||
| 4 | Std_Con_Input EQU 1 ; 1 1 | ||
| 5 | Std_Con_Output EQU 2 ; 2 2 | ||
| 6 | Std_Aux_Input EQU 3 ; 3 3 | ||
| 7 | Std_Aux_Output EQU 4 ; 4 4 | ||
| 8 | Std_Printer_Output EQU 5 ; 5 5 | ||
| 9 | Raw_Con_IO EQU 6 ; 6 6 | ||
| 10 | Raw_Con_Input EQU 7 ; 7 7 | ||
| 11 | Std_Con_Input_No_Echo EQU 8 ; 8 8 | ||
| 12 | Std_Con_String_Output EQU 9 ; 9 9 | ||
| 13 | Std_Con_String_Input EQU 10 ; 10 A | ||
| 14 | Std_Con_Input_Status EQU 11 ; 11 B | ||
| 15 | Std_Con_Input_Flush EQU 12 ; 12 C | ||
| 16 | Disk_Reset EQU 13 ; 13 D | ||
| 17 | Set_Default_Drive EQU 14 ; 14 E | ||
| 18 | FCB_Open EQU 15 ; 15 F | ||
| 19 | FCB_Close EQU 16 ; 16 10 | ||
| 20 | Dir_Search_First EQU 17 ; 17 11 | ||
| 21 | Dir_Search_Next EQU 18 ; 18 12 | ||
| 22 | FCB_Delete EQU 19 ; 19 13 | ||
| 23 | FCB_Seq_Read EQU 20 ; 20 14 | ||
| 24 | FCB_Seq_Write EQU 21 ; 21 15 | ||
| 25 | FCB_Create EQU 22 ; 22 16 | ||
| 26 | FCB_Rename EQU 23 ; 23 17 | ||
| 27 | Get_Default_Drive EQU 25 ; 25 19 | ||
| 28 | Set_DMA EQU 26 ; 26 1A | ||
| 29 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 30 | ; C A V E A T P R O G R A M M E R ; | ||
| 31 | ; ; | ||
| 32 | Get_Default_DPB EQU 31 ; 31 1F | ||
| 33 | ; ; | ||
| 34 | ; C A V E A T P R O G R A M M E R ; | ||
| 35 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 36 | FCB_Random_Read EQU 33 ; 33 21 | ||
| 37 | FCB_Random_Write EQU 34 ; 34 22 | ||
| 38 | Get_FCB_File_Length EQU 35 ; 35 23 | ||
| 39 | Get_FCB_Position EQU 36 ; 36 24 | ||
| 40 | Set_Interrupt_Vector EQU 37 ; 37 25 | ||
| 41 | Create_Process_Data_Block EQU 38 ; 38 26 | ||
| 42 | FCB_Random_Read_Block EQU 39 ; 39 27 | ||
| 43 | FCB_Random_Write_Block EQU 40 ; 40 28 | ||
| 44 | Parse_File_Descriptor EQU 41 ; 41 29 | ||
| 45 | Get_Date EQU 42 ; 42 2A | ||
| 46 | Set_Date EQU 43 ; 43 2B | ||
| 47 | Get_Time EQU 44 ; 44 2C | ||
| 48 | Set_Time EQU 45 ; 45 2D | ||
| 49 | Set_Verify_On_Write EQU 46 ; 46 2E | ||
| 50 | ; Extended functionality group | ||
| 51 | Get_DMA EQU 47 ; 47 2F | ||
| 52 | Get_Version EQU 48 ; 48 30 | ||
| 53 | Keep_Process EQU 49 ; 49 31 | ||
| 54 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 55 | ; C A V E A T P R O G R A M M E R ; | ||
| 56 | ; ; | ||
| 57 | Get_DPB EQU 50 ; 50 32 | ||
| 58 | ; ; | ||
| 59 | ; C A V E A T P R O G R A M M E R ; | ||
| 60 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 61 | Set_CTRL_C_Trapping EQU 51 ; 51 33 | ||
| 62 | Get_InDOS_Flag EQU 52 ; 52 34 | ||
| 63 | Get_Interrupt_Vector EQU 53 ; 53 35 | ||
| 64 | Get_Drive_Freespace EQU 54 ; 54 36 | ||
| 65 | Char_Oper EQU 55 ; 55 37 | ||
| 66 | International EQU 56 ; 56 38 | ||
| 67 | ; Directory Group | ||
| 68 | MKDir EQU 57 ; 57 39 | ||
| 69 | RMDir EQU 58 ; 58 3A | ||
| 70 | CHDir EQU 59 ; 59 3B | ||
| 71 | ; File Group | ||
| 72 | Creat EQU 60 ; 60 3C | ||
| 73 | Open EQU 61 ; 61 3D | ||
| 74 | Close EQU 62 ; 62 3E | ||
| 75 | Read EQU 63 ; 63 3F | ||
| 76 | Write EQU 64 ; 64 40 | ||
| 77 | Unlink EQU 65 ; 65 41 | ||
| 78 | LSeek EQU 66 ; 66 42 | ||
| 79 | CHMod EQU 67 ; 67 43 | ||
| 80 | IOCtl EQU 68 ; 68 44 | ||
| 81 | XDup EQU 69 ; 69 45 | ||
| 82 | XDup2 EQU 70 ; 70 46 | ||
| 83 | Current_Dir EQU 71 ; 71 47 | ||
| 84 | ; Memory Group | ||
| 85 | Alloc EQU 72 ; 72 48 | ||
| 86 | Dealloc EQU 73 ; 73 49 | ||
| 87 | Setblock EQU 74 ; 74 4A | ||
| 88 | ; Process Group | ||
| 89 | Exec EQU 75 ; 75 4B | ||
| 90 | Exit EQU 76 ; 76 4C | ||
| 91 | Get_Return_Code EQU 77 ; 77 4D | ||
| 92 | Find_First EQU 78 ; 78 4E | ||
| 93 | ; Special Group | ||
| 94 | Find_Next EQU 79 ; 79 4F | ||
| 95 | ; SPECIAL SYSTEM GROUP | ||
| 96 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 97 | ; C A V E A T P R O G R A M M E R ; | ||
| 98 | ; ; | ||
| 99 | Set_Current_PDB EQU 80 ; 80 50 | ||
| 100 | Get_Current_PDB EQU 81 ; 81 51 | ||
| 101 | Get_In_Vars EQU 82 ; 82 52 | ||
| 102 | SetDPB EQU 83 ; 83 53 | ||
| 103 | ; ; | ||
| 104 | ; C A V E A T P R O G R A M M E R ; | ||
| 105 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 106 | Get_Verify_On_Write EQU 84 ; 84 54 | ||
| 107 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 108 | ; C A V E A T P R O G R A M M E R ; | ||
| 109 | ; ; | ||
| 110 | Dup_PDB EQU 85 ; 85 55 | ||
| 111 | ; ; | ||
| 112 | ; C A V E A T P R O G R A M M E R ; | ||
| 113 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 114 | Rename EQU 86 ; 86 56 | ||
| 115 | File_Times EQU 87 ; 87 57 | ||
| 116 | AllocOper EQU 88 ; 88 58 | ||
| 117 | ; Network extention system calls | ||
| 118 | GetExtendedError EQU 89 ; 89 59 | ||
| 119 | CreateTempFile EQU 90 ; 90 5A | ||
| 120 | CreateNewFile EQU 91 ; 91 5B | ||
| 121 | LockOper EQU 92 ; 92 5C Lock and Unlock | ||
| 122 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 123 | ; C A V E A T P R O G R A M M E R ; | ||
| 124 | ; ; | ||
| 125 | ServerCall EQU 93 ; 93 5D CommitAll, ServerDOSCall, | ||
| 126 | ; CloseByName, CloseUser, | ||
| 127 | ; CloseUserProcess, | ||
| 128 | ; GetOpenFileList | ||
| 129 | ; ; | ||
| 130 | ; C A V E A T P R O G R A M M E R ; | ||
| 131 | ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; | ||
| 132 | UserOper EQU 94 ; 94 5E Get and Set | ||
| 133 | AssignOper EQU 95 ; 95 5F On, Off, Get, Set, Cancel | ||
| 134 | xNameTrans EQU 96 ; 96 60 | ||
| 135 | PathParse EQU 97 ; 97 61 | ||
| 136 | GetCurrentPSP EQU 98 ; 98 62 | ||
| 137 | Hongeul EQU 99 ; 99 63 | ||
| 138 | |||
| 139 | Set_Oem_Handler EQU 248 ; 248 F8 | ||
| 140 | OEM_C1 EQU 249 ; 249 F9 | ||
| 141 | OEM_C2 EQU 250 ; 250 FA | ||
| 142 | OEM_C3 EQU 251 ; 251 FB | ||
| 143 | OEM_C4 EQU 252 ; 252 FC | ||
| 144 | OEM_C5 EQU 253 ; 253 FD | ||
| 145 | OEM_C6 EQU 254 ; 254 FE | ||
| 146 | OEM_C7 EQU 255 ; 255 FF | ||
| 147 | \ No newline at end of file | ||