diff options
Diffstat (limited to 'v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM')
| -rw-r--r-- | v4.0/src/DEV/SMARTDRV/SMARTDRV.ASM | 7587 |
1 files changed, 7587 insertions, 0 deletions
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 | ||