diff options
Diffstat (limited to 'v4.0/src/DEV/VDISK/VDISKSYS.ASM')
| -rw-r--r-- | v4.0/src/DEV/VDISK/VDISKSYS.ASM | 3024 |
1 files changed, 3024 insertions, 0 deletions
diff --git a/v4.0/src/DEV/VDISK/VDISKSYS.ASM b/v4.0/src/DEV/VDISK/VDISKSYS.ASM new file mode 100644 index 0000000..544c610 --- /dev/null +++ b/v4.0/src/DEV/VDISK/VDISKSYS.ASM | |||
| @@ -0,0 +1,3024 @@ | |||
| 1 | PAGE ,132 | ||
| 2 | TITLE VDISK - Virtual Disk Device Driver, Version 4.00 | ||
| 3 | |||
| 4 | ;VDISK simulates a disk drive, using Random Access Memory as the storage medium. | ||
| 5 | |||
| 6 | ;(C) Copyright Microsoft Corporation, 1984 - 1988 | ||
| 7 | ;Licensed Material - Program Property of Microsoft Corp. | ||
| 8 | |||
| 9 | ;Add the following statement to CONFIG.SYS | ||
| 10 | ; DEVICE=[d:][path]VDISK.SYS bbb sss ddd [/E:m] | ||
| 11 | |||
| 12 | ; where: bbb is the desired buffer size (in kilobytes) | ||
| 13 | ; minimum 1KB, maximum is size of available memory, | ||
| 14 | ; default is 64KB. | ||
| 15 | |||
| 16 | ; VDISK will leave at least 64KB of available memory, | ||
| 17 | ; although subsequent device drivers (other than VDISK) | ||
| 18 | ; other programs that make themselves resident, and | ||
| 19 | ; COMMAND.COM will result in less than 64KB as shown | ||
| 20 | ; by CHKDSK. | ||
| 21 | |||
| 22 | ; Must be large enough for 1 boot sector + FAT sectors | ||
| 23 | ; + 1 directory sector + at least 1 data cluster, | ||
| 24 | ; or the device driver won't be installed. | ||
| 25 | |||
| 26 | ; sss is the desired sector size (in bytes) | ||
| 27 | ; 128, 256, or 512, default is 128. | ||
| 28 | ; Will be adjusted if number of FAT entries > 0FE0H | ||
| 29 | |||
| 30 | ; ddd is the desired number of directory entries | ||
| 31 | ; Minimum 2, maximum 512, default 64. | ||
| 32 | ; Will be rounded upward to sector size boundary. | ||
| 33 | |||
| 34 | ; /E may only be used if extended memory above 1 megabyte | ||
| 35 | ; is to be used. INT 15H functions 87H and 88H are used | ||
| 36 | ; to read and write this extended memory. | ||
| 37 | ; The m parameter in the /E option specifies the maximum | ||
| 38 | ; number of sectors that the VDISK will transfer at a time. | ||
| 39 | ; Optional values are 1,2,3,4,5,6,7 or 8 sectors, the default | ||
| 40 | ; is 8 sectors. | ||
| 41 | |||
| 42 | ; Brackets indicate optional operands. | ||
| 43 | |||
| 44 | |||
| 45 | ; Samples: | ||
| 46 | ; DEVICE=\path\VDISK.SYS 160 512 64 | ||
| 47 | ; results in a 160KB VDISK, with 512 byte sectors, 64 directory entries | ||
| 48 | |||
| 49 | ; DEVICE=VDISK.SYS Buffersize 60 Sectorsize 128 Directory entries 32 | ||
| 50 | ; (since only numbers are interpreted, you may comment the line with | ||
| 51 | ; non-numeric characters) | ||
| 52 | ; | ||
| 53 | ;========================================================================= | ||
| 54 | ; Change List | ||
| 55 | ; | ||
| 56 | ; AN000 - ver 4.0 specified changes | ||
| 57 | ; AN001 - DCR 377 Modify VDISK Extended Memory allocation technique | ||
| 58 | ; The allocation technique have been modified to | ||
| 59 | ; allocate EM from the top down. To notify other | ||
| 60 | ; users that EM has been used by VDISK, VDISK | ||
| 61 | ; hooks function 88h, INT 15h. | ||
| 62 | ; | ||
| 63 | ; AN002 - PTM3214 EMS VDISK needed to be modified for two errors. | ||
| 64 | ; AC002 The first related to VDISK returning the | ||
| 65 | ; "Insufficient Memory" message when in fact | ||
| 66 | ; there was enough EMS memory to support the | ||
| 67 | ; requested VDISK. | ||
| 68 | ; The second related to an EMS VDISK hanging when | ||
| 69 | ; a program was invoked from an EMS VDISK with a | ||
| 70 | ; non-standard sector size, i.e.; 128 bytes/sector, | ||
| 71 | ; etc. This error was caused by the incorrect | ||
| 72 | ; calculation of sectors per EMS page. | ||
| 73 | ; | ||
| 74 | ; AN003 - PTM3276 EMS VDISK causes a "Divide Overflow" message. | ||
| 75 | ; AC003 This is caused by a byte divide that should | ||
| 76 | ; be performed as a word divide. | ||
| 77 | ; | ||
| 78 | ; AN004 - PTM3301 EMS VDISK does not properly adjust the buffer | ||
| 79 | ; size when too much EMS memory is requested. | ||
| 80 | ; The code in UPDATE_AVAIL pertaining to EMS | ||
| 81 | ; space allocation has been modified. | ||
| 82 | ; | ||
| 83 | ; AN005 - DCR474 Convert VDISK to support /E for extended memory | ||
| 84 | ; and /X for expanded memory. | ||
| 85 | ; | ||
| 86 | ; AN006 - PTM4729 Enable VDISK for the INT 2F call to determine | ||
| 87 | ; the reserved EMS page for VDISK and FASTOPEN | ||
| 88 | ; | ||
| 89 | ;========================================================================= | ||
| 90 | |||
| 91 | ;Message text for VDISK is in module VDISKMSG. | ||
| 92 | .xlist | ||
| 93 | INCLUDE VDISKSYS.INC | ||
| 94 | INCLUDE SYSMSG.INC | ||
| 95 | MSG_UTILNAME<VDISK> | ||
| 96 | .list | ||
| 97 | SUBTTL Structure Definitions | ||
| 98 | PAGE | ||
| 99 | ;-----------------------------------------------------------------------; | ||
| 100 | ; Request Header (Common portion) ; | ||
| 101 | ;-----------------------------------------------------------------------; | ||
| 102 | RH EQU DS:[BX] ;addressability to Request Header structure | ||
| 103 | |||
| 104 | RHC STRUC ;fields common to all request types | ||
| 105 | DB ? ;length of Request Header (including data) | ||
| 106 | DB ? ;unit code (subunit) | ||
| 107 | RHC_CMD DB ? ;command code | ||
| 108 | RHC_STA DW ? ;status | ||
| 109 | DQ ? ;reserved for DOS | ||
| 110 | ;;;;; DW ? ;reserved for BIOS message flag ;an006; dms; | ||
| 111 | RHC ENDS ;end of common portion | ||
| 112 | |||
| 113 | CMD_INPUT EQU 4 ;RHC_CMD is INPUT request | ||
| 114 | |||
| 115 | ;status values for RHC_STA | ||
| 116 | |||
| 117 | STAT_DONE EQU 01H ;function complete status (high order byte) | ||
| 118 | STAT_CMDERR EQU 8003H ;invalid command code error | ||
| 119 | STAT_CRC EQU 8004H ;CRC error | ||
| 120 | STAT_SNF EQU 8008H ;sector not found error | ||
| 121 | STAT_BUSY EQU 0200H ;busy bit (9) for Removable Media call | ||
| 122 | ;-----------------------------------------------------------------------; | ||
| 123 | ; Request Header for INIT command ; | ||
| 124 | ;-----------------------------------------------------------------------; | ||
| 125 | RH0 STRUC | ||
| 126 | DB (TYPE RHC) DUP (?) ;common portion | ||
| 127 | RH0_NUN DB ? ;number of units | ||
| 128 | ;set to 1 if installation succeeds, | ||
| 129 | ;set to 0 to cause installation failure | ||
| 130 | RH0_ENDO DW ? ;offset of ending address | ||
| 131 | RH0_ENDS DW ? ;segment of ending address | ||
| 132 | RH0_BPBO DW ? ;offset of BPB array address | ||
| 133 | RH0_BPBS DW ? ;segment of BPB array address | ||
| 134 | RH0_DRIV DB ? ;drive code (DOS 3 only) | ||
| 135 | RH0_FLAG DW 0 ;initialized to no error ;an000; dms; | ||
| 136 | RH0 ENDS | ||
| 137 | |||
| 138 | RH0_BPBA EQU DWORD PTR RH0_BPBO ;offset/segment of BPB array address | ||
| 139 | ;Note: RH0_BPBA at entry to INIT points to all after DEVICE= on CONFIG.SYS stmt | ||
| 140 | |||
| 141 | ;-----------------------------------------------------------------------; | ||
| 142 | ; Request Header for MEDIA CHECK Command ; | ||
| 143 | ;-----------------------------------------------------------------------; | ||
| 144 | RH1 STRUC | ||
| 145 | DB (TYPE RHC) DUP (?) ;common portion | ||
| 146 | DB ? ;media descriptor | ||
| 147 | RH1_RET DB ? ;return information | ||
| 148 | RH1 ENDS | ||
| 149 | ;-----------------------------------------------------------------------; | ||
| 150 | ; Request Header for BUILD BPB Command ; | ||
| 151 | ;-----------------------------------------------------------------------; | ||
| 152 | RH2 STRUC | ||
| 153 | DB (TYPE RHC) DUP(?) ;common portion | ||
| 154 | DB ? ;media descriptor | ||
| 155 | DW ? ;offset of transfer address | ||
| 156 | DW ? ;segment of transfer address | ||
| 157 | RH2_BPBO DW ? ;offset of BPB table address | ||
| 158 | RH2_BPBS DW ? ;segment of BPB table address | ||
| 159 | RH2 ENDS | ||
| 160 | ;-----------------------------------------------------------------------; | ||
| 161 | ; Request Header for INPUT, OUTPUT, and OUTPUT with verify ; | ||
| 162 | ;-----------------------------------------------------------------------; | ||
| 163 | RH4 STRUC | ||
| 164 | DB (TYPE RHC) DUP (?) ;common portion | ||
| 165 | DB ? ;media descriptor | ||
| 166 | RH4_DTAO DW ? ;offset of transfer address | ||
| 167 | RH4_DTAS DW ? ;segment of transfer address | ||
| 168 | RH4_CNT DW ? ;sector count | ||
| 169 | RH4_SSN DW ? ;starting sector number | ||
| 170 | RH4 ENDS | ||
| 171 | |||
| 172 | RH4_DTAA EQU DWORD PTR RH4_DTAO ;offset/segment of transfer address | ||
| 173 | |||
| 174 | ;-----------------------------------------------------------------------; | ||
| 175 | ; Segment Descriptor (part of Global Descriptor Table) ; | ||
| 176 | ;-----------------------------------------------------------------------; | ||
| 177 | DESC STRUC ;data segment descriptor | ||
| 178 | DESC_LMT DW 0 ;segment limit (length) | ||
| 179 | DESC_BASEL DW 0 ;bits 15-0 of physical address | ||
| 180 | DESC_BASEH DB 0 ;bits 23-16 of physical address | ||
| 181 | DB 0 ;access rights byte | ||
| 182 | DW 0 ;reserved | ||
| 183 | DESC ENDS | ||
| 184 | |||
| 185 | SUBTTL Equates and Macro Definitions | ||
| 186 | PAGE | ||
| 187 | |||
| 188 | MEM_SIZE EQU 12H ;BIOS memory size determination INT | ||
| 189 | ;returns system size in KB in AX | ||
| 190 | |||
| 191 | EM_INT EQU 15H ;extended memory BIOS interrupt INT | ||
| 192 | EM_BLKMOVE EQU 87H ;block move function | ||
| 193 | EM_MEMSIZE EQU 8800H ;memory size determination in KB | ||
| 194 | |||
| 195 | DOS EQU 21H ;DOS request INT | ||
| 196 | DOS_PCHR EQU 02H ;print character function | ||
| 197 | DOS_PSTR EQU 09H ;print string function | ||
| 198 | DOS_VERS EQU 30H ;get DOS version | ||
| 199 | |||
| 200 | TAB EQU 09H ;ASCII tab | ||
| 201 | LF EQU 0AH ;ASCII line feed | ||
| 202 | CR EQU 0DH ;ASCII carriage return | ||
| 203 | |||
| 204 | PARA_SIZE EQU 16 ;number of bytes in one 8088 paragraph | ||
| 205 | DIR_ENTRY_SIZE EQU 32 ;number of bytes per directory entry | ||
| 206 | MAX_FATE EQU 0FE0H ;largest number of FAT entries allowed | ||
| 207 | |||
| 208 | ;default values used if parameters are omitted | ||
| 209 | |||
| 210 | DFLT_BSIZE EQU 64 ;default VDISK buffer size (KB) | ||
| 211 | DFLT_SSZ EQU 128 ;default sector size | ||
| 212 | DFLT_DIRN EQU 64 ;default number of directory entries | ||
| 213 | DFLT_ESS EQU 8 ;default maximum sectors to transfer | ||
| 214 | |||
| 215 | MIN_DIRN EQU 2 ;minimum number of directory entries | ||
| 216 | MAX_DIRN EQU 512 ;maximum number of directory entries | ||
| 217 | |||
| 218 | STACK_SIZE EQU 512 ;length of stack during initialization | ||
| 219 | |||
| 220 | SUBTTL Resident Data Area | ||
| 221 | PAGE | ||
| 222 | |||
| 223 | ;-----------------------------------------------------------------------; | ||
| 224 | ; Map INT 15H vector in low storage ; | ||
| 225 | ;-----------------------------------------------------------------------; | ||
| 226 | INT_VEC SEGMENT AT 00H | ||
| 227 | ORG 4*EM_INT | ||
| 228 | EM_VEC LABEL DWORD | ||
| 229 | EM_VECO DW ? ;offset | ||
| 230 | EM_VECS DW ? ;segment | ||
| 231 | INT_VEC ENDS | ||
| 232 | |||
| 233 | |||
| 234 | |||
| 235 | CSEG SEGMENT PARA PUBLIC 'CODE' | ||
| 236 | ASSUME CS:CSEG | ||
| 237 | ;-----------------------------------------------------------------------; | ||
| 238 | ; Resident data area. ; | ||
| 239 | ; ; | ||
| 240 | ; All variables and constants required after initialization ; | ||
| 241 | ; part one are defined here. ; | ||
| 242 | ;-----------------------------------------------------------------------; | ||
| 243 | |||
| 244 | START EQU $ ;begin resident VDISK data & code | ||
| 245 | |||
| 246 | ;DEVICE HEADER - must be at offset zero within device driver | ||
| 247 | DD -1 ;becomes pointer to next device header | ||
| 248 | DW 0800H ;attribute (IBM format block device) | ||
| 249 | ;supports OPEN/CLOSE/RM calls | ||
| 250 | DW OFFSET STRATEGY ;pointer to device "strategy" routine | ||
| 251 | DW OFFSET IRPT ;pointer to device "interrupt handler" | ||
| 252 | DB 1 ;number of block devices | ||
| 253 | DB 7 DUP (?) ;7 byte filler (remainder of 8-byte name) | ||
| 254 | ;END OF DEVICE HEADER | ||
| 255 | |||
| 256 | ;This volume label is placed into the directory of the new VDISK | ||
| 257 | ;This constant is also used to determine if a previous extended memory VDISK | ||
| 258 | ;has been installed. | ||
| 259 | |||
| 260 | VOL_LABEL DB 'VDISK V4.0' ;00-10 volume name (shows program level) | ||
| 261 | DB 28H ;11-11 attribute (volume label) | ||
| 262 | DT 0 ;12-21 reserved | ||
| 263 | DW 6000H ;22-23 time=12:00 noon | ||
| 264 | DW 0986H ;24-25 date=12/06/84 | ||
| 265 | VOL_LABEL_LEN EQU $-VOL_LABEL ;length of volume label | ||
| 266 | |||
| 267 | ;The following field, in the first extended memory VDISK device driver, | ||
| 268 | ;is the 24-bit address of the first free byte of extended memory. | ||
| 269 | ;This address is not in the common offset/segment format. | ||
| 270 | ;The initial value, 10 0000H, is 1 megabyte. | ||
| 271 | |||
| 272 | AVAIL_LO DW 0 ;address of first free byte of | ||
| 273 | AVAIL_HI DB 10H ;extended memory | ||
| 274 | |||
| 275 | INTV15 LABEL DWORD | ||
| 276 | INTV15O DW ? ;offset | ||
| 277 | INTV15S DW ? ;segment | ||
| 278 | |||
| 279 | |||
| 280 | PARAS_PER_SECTOR DW ? ;number of 16-byte paragraphs in one sector | ||
| 281 | |||
| 282 | START_BUFFER_PARA DW ? ;segment address of start of VDISK buffer | ||
| 283 | |||
| 284 | EM_New_Size dw ? ;an001; dms;new size for EM | ||
| 285 | EM_KSize dw ? ;an001; dms;size of EM currently. | ||
| 286 | |||
| 287 | EM_SW DB 0 ;NON-ZERO IF EXTENDED MEMORY | ||
| 288 | |||
| 289 | EM_STAT DW 0 ;AX from last unsuccessful extended memory I/O | ||
| 290 | |||
| 291 | START_EM_LO DW ? ;24-bit address of start of VDISK buffer | ||
| 292 | START_EM_HI DB ? ;(extended memory only) | ||
| 293 | |||
| 294 | WPARA_SIZE DW PARA_SIZE ;number of bytes in one paragraph | ||
| 295 | |||
| 296 | MAX_CNT DW ? ;(0FFFFH/BPB_SSZ) truncated, the maximum | ||
| 297 | ;number of sectors that can be transferred | ||
| 298 | ;without worrying about 64KB wrap | ||
| 299 | |||
| 300 | SECT_LEFT DW ? ;sectors left to transfer | ||
| 301 | |||
| 302 | IO_SRCA LABEL DWORD ;offset/segment of source | ||
| 303 | IO_SRCO DW ? ;offset | ||
| 304 | IO_SRCS DW ? ;segment | ||
| 305 | |||
| 306 | IO_TGTA LABEL DWORD ;offset/segment of target | ||
| 307 | IO_TGTO DW ? ;offset | ||
| 308 | IO_TGTS DW ? ;segment | ||
| 309 | |||
| 310 | ;-----------------------------------------------------------------------; | ||
| 311 | ; EMS Support ; | ||
| 312 | ;-----------------------------------------------------------------------; | ||
| 313 | |||
| 314 | EM_SW2 DB not EMS_Installed_Flag ;ac006;Default if EMS not installed | ||
| 315 | EMS_HANDLE DW ? ;AN000; EMS handle for reference | ||
| 316 | EMS_FRAME_ADDR DW ? ;AN000; EMS handle for reference | ||
| 317 | EMS_CURR_SECT DW ? ;an000; Current EMS sector being addressed | ||
| 318 | CURR_EMS_PAGE DW ? ;ac002; Current EMS page number | ||
| 319 | SECT_LEFT_IN_FRAME DW ? ;AN000; Sectors left to transfer in this frame | ||
| 320 | SECT_PER_PAGE DW ? ;AN000; Sectors per page | ||
| 321 | DOS_Page dw ? ;an006; EMS physical page for VDISK | ||
| 322 | |||
| 323 | EMS_SAVE_ARRAY DB 80h dup(0) ;an000; save current state of ems | ||
| 324 | EMS_SEG_ARRAY DD ? ;an000; save segment array | ||
| 325 | |||
| 326 | CURR_DTA_OFF DW ? ;AN000; DMS;CURRENT OFFSET OF DTA | ||
| 327 | |||
| 328 | PC_386 DB false ;AN000; DMS;386 machine flag | ||
| 329 | |||
| 330 | SUBLIST STRUC ;AN000;SUBLIST STRUCTURE | ||
| 331 | |||
| 332 | SL_SIZE DB ? ;AN000;SUBLIST SIZE | ||
| 333 | SL_RES DB ? ;AN000;RESERVED | ||
| 334 | SL_OFFSET DW ? ;AN000;PARM OFFSET | ||
| 335 | SL_SEGMENT DW ? ;AN000;PARM SEGMENT | ||
| 336 | SL_ID DB ? ;AN000;NUMBER OF PARM | ||
| 337 | SL_FLAG DB ? ;AN000;DISPLAY TYPE | ||
| 338 | SL_MAXW DB ? ;AN000;MAXIMUM FIELD WIDTH | ||
| 339 | SL_MINW DB ? ;AN000;MINIMUM FIELD WIDTH | ||
| 340 | SL_PAD DB ? ;AN000;PAD CHARACTER | ||
| 341 | |||
| 342 | SUBLIST ENDS ;AN000;END SUBLIST STRUCTURE | ||
| 343 | |||
| 344 | |||
| 345 | BIOS_SYSTEM_DESCRIPTOR struc ;AN000;SYSTEM TYPE STRUC | ||
| 346 | |||
| 347 | bios_SD_leng dw ? ;AN000;VECTOR LENGTH | ||
| 348 | bios_SD_modelbyte db ? ;AN000;SYSTEM MODEL TYPE | ||
| 349 | bios_SD_scnd_modelbyte db ? ;AN000; | ||
| 350 | db ? ;AN000; | ||
| 351 | bios_SD_featurebyte1 db ? ;AN000; | ||
| 352 | db 4 dup (?) ;AN000; | ||
| 353 | |||
| 354 | BIOS_SYSTEM_DESCRIPTOR ends ;AN000;END OF STRUC | ||
| 355 | |||
| 356 | ;-----------------------------------------------------------------------; | ||
| 357 | ; BIOS Parameter Block (BPB) ; | ||
| 358 | ;-----------------------------------------------------------------------; | ||
| 359 | ;This is where the characteristics of the virtual disk are established. | ||
| 360 | ;A copy of this block is moved into the boot record of the virtual disk. | ||
| 361 | ;DEBUG can be used to read sector zero of the virtual disk to examine the | ||
| 362 | ;boot record copy of this block. | ||
| 363 | |||
| 364 | BPB LABEL BYTE ;BIOS Parameter Block (BPB) | ||
| 365 | BPB_SSZ DW 0 ;number of bytes per disk sector | ||
| 366 | BPB_AUSZ DB 1 ;sectors per allocation unit | ||
| 367 | BPB_RES DW 1 ;number of reserved sectors (for boot record) | ||
| 368 | BPB_FATN DB 1 ;number of File Allocation Table (FAT) copies | ||
| 369 | BPB_DIRN DW 0 ;number of root directory entries | ||
| 370 | BPB_SECN DW 1 ;total number of sectors | ||
| 371 | ;computed from buffer size and sector size | ||
| 372 | ;(this includes reserved, FAT, directory, | ||
| 373 | ;and data sectors) | ||
| 374 | BPB_MCB DB 0FEH ;media descriptor byte | ||
| 375 | BPB_FATSZ DW 1 ;number of sectors occupied by a single FAT | ||
| 376 | ;computed from BPBSSZ and BPBSECN | ||
| 377 | BPB_LEN EQU $-BPB ;length of BIOS parameter block | ||
| 378 | |||
| 379 | BPB_PTR DW BPB ;BIOS Parameter Block pointer array (1 entry) | ||
| 380 | ;-----------------------------------------------------------------------; | ||
| 381 | ; Request Header (RH) address, saved here by "strategy" routine ; | ||
| 382 | ;-----------------------------------------------------------------------; | ||
| 383 | RH_PTRA LABEL DWORD | ||
| 384 | RH_PTRO DW ? ;offset | ||
| 385 | RH_PTRS DW ? ;segment | ||
| 386 | ;-----------------------------------------------------------------------; | ||
| 387 | ; Global Descriptor Table (GDT), used for extended memory moves ; | ||
| 388 | ;-----------------------------------------------------------------------; | ||
| 389 | ;Access Rights Byte (93H) is | ||
| 390 | ; P=1 (segment is mapped into physical memory) | ||
| 391 | ; E=0 (data segment descriptor) | ||
| 392 | ; D=0 (grow up segment, offsets must be <= limit) | ||
| 393 | ; W=1 (data segment may be written into) | ||
| 394 | ; DPL=0 (privilege level 0) | ||
| 395 | |||
| 396 | GDT LABEL BYTE ;begin global descriptor table | ||
| 397 | DESC <> ;dummy descriptor | ||
| 398 | DESC <> ;descriptor for GDT itself | ||
| 399 | SRC DESC <,,,93H,> ;source descriptor | ||
| 400 | TGT DESC <,,,93H,> ;target descriptor | ||
| 401 | DESC <> ;BIOS CS descriptor | ||
| 402 | DESC <> ;stack segment descriptor | ||
| 403 | |||
| 404 | SUBTTL INT 15H (size) interrupt handler | ||
| 405 | PAGE | ||
| 406 | ;-----------------------------------------------------------------------; | ||
| 407 | ; INT 15H Interrupt Handler routine ; | ||
| 408 | ;-----------------------------------------------------------------------; | ||
| 409 | |||
| 410 | ;========================================================================= | ||
| 411 | ; VDISK_INT15 : This routine traps the INT 15h requests to perform its | ||
| 412 | ; own unique services. This routine provides 1 INT 15h | ||
| 413 | ; service; function 8800h. | ||
| 414 | ; | ||
| 415 | ; Service - Function 8800h: Obtains the size of EM from the word | ||
| 416 | ; value EM_KSize | ||
| 417 | ; Call With: AX - 8800h | ||
| 418 | ; Returns : AX - Kbyte size of EM | ||
| 419 | ; | ||
| 420 | ;========================================================================= | ||
| 421 | VDISK_INT15 PROC ;an001; dms; | ||
| 422 | |||
| 423 | cmp ah,EM_Size_Get ;an001; dms;function 88h | ||
| 424 | ; $if e ;an001; dms;get size | ||
| 425 | JNE $$IF1 | ||
| 426 | mov ax,cs:EM_KSize ;an001; dms;return size | ||
| 427 | clc ;an001; dms;clear CY | ||
| 428 | ; $else ;an001; dms; | ||
| 429 | JMP SHORT $$EN1 | ||
| 430 | $$IF1: | ||
| 431 | jmp cs:INTV15 ;an001; dms;jump to org. vector | ||
| 432 | ; $endif ;an001; dms; | ||
| 433 | $$EN1: | ||
| 434 | |||
| 435 | iret ;an001; dms; | ||
| 436 | |||
| 437 | VDISK_INT15 ENDP ;an001; dms; | ||
| 438 | |||
| 439 | |||
| 440 | ASSUME DS:NOTHING | ||
| 441 | |||
| 442 | SUBTTL Device Strategy & interrupt entry points | ||
| 443 | PAGE | ||
| 444 | ;-----------------------------------------------------------------------; | ||
| 445 | ; Device "strategy" entry point ; | ||
| 446 | ; ; | ||
| 447 | ; Retain the Request Header address for use by Interrupt routine ; | ||
| 448 | ;-----------------------------------------------------------------------; | ||
| 449 | STRATEGY PROC FAR | ||
| 450 | MOV CS:RH_PTRO,BX ;offset | ||
| 451 | MOV CS:RH_PTRS,ES ;segment | ||
| 452 | RET | ||
| 453 | STRATEGY ENDP | ||
| 454 | ;-----------------------------------------------------------------------; | ||
| 455 | ; Table of command processing routine entry points ; | ||
| 456 | ;-----------------------------------------------------------------------; | ||
| 457 | CMD_TABLE LABEL WORD | ||
| 458 | DW OFFSET INIT_P1 ; 0 - Initialization | ||
| 459 | DW OFFSET MEDIA_CHECK ; 1 - Media check | ||
| 460 | DW OFFSET BLD_BPB ; 2 - Build BPB | ||
| 461 | DW OFFSET INPUT_IOCTL ; 3 - IOCTL input | ||
| 462 | DW OFFSET INPUT ; 4 - Input | ||
| 463 | DW OFFSET INPUT_NOWAIT ; 5 - Non destructive input no wait | ||
| 464 | DW OFFSET INPUT_STATUS ; 6 - Input status | ||
| 465 | DW OFFSET INPUT_FLUSH ; 7 - Input flush | ||
| 466 | DW OFFSET OUTPUT ; 8 - Output | ||
| 467 | DW OFFSET OUTPUT_VERIFY ; 9 - Output with verify | ||
| 468 | DW OFFSET OUTPUT_STATUS ;10 - Output status | ||
| 469 | DW OFFSET OUTPUT_FLUSH ;11 - Output flush | ||
| 470 | DW OFFSET OUTPUT_IOCTL ;12 - IOCTL output | ||
| 471 | DW OFFSET DEVICE_OPEN ;13 - Device OPEN | ||
| 472 | DW OFFSET DEVICE_CLOSE ;14 - Device CLOSE | ||
| 473 | MAX_CMD EQU ($-CMD_TABLE)/2 ;highest valid command follows | ||
| 474 | DW OFFSET REMOVABLE_MEDIA ;15 - Removable media | ||
| 475 | |||
| 476 | ;-----------------------------------------------------------------------; | ||
| 477 | ; Device "interrupt" entry point ; | ||
| 478 | ;-----------------------------------------------------------------------; | ||
| 479 | IRPT PROC FAR ;device interrupt entry point | ||
| 480 | PUSH DS ;save all registers modified | ||
| 481 | PUSH ES | ||
| 482 | PUSH AX | ||
| 483 | PUSH BX | ||
| 484 | PUSH CX | ||
| 485 | PUSH DX | ||
| 486 | PUSH DI | ||
| 487 | PUSH SI | ||
| 488 | ;BP isn't used, so it isn't saved | ||
| 489 | CLD ;all moves forward | ||
| 490 | |||
| 491 | LDS BX,CS:RH_PTRA ;get RH address passed to "strategy" into DS:BX | ||
| 492 | |||
| 493 | MOV AL,RH.RHC_CMD ;command code from Request Header | ||
| 494 | CBW ;zero AH (if AL > 7FH, next compare will | ||
| 495 | ;catch that error) | ||
| 496 | |||
| 497 | CMP AL,MAX_CMD ;if command code is too high | ||
| 498 | JA IRPT_CMD_HIGH ;jump to error routine | ||
| 499 | |||
| 500 | MOV DI,OFFSET IRPT_CMD_EXIT ;return addr from command processor | ||
| 501 | PUSH DI ;push return address onto stack | ||
| 502 | ;command routine issues "RET" | ||
| 503 | |||
| 504 | ADD AX,AX ;double command code for table offset | ||
| 505 | MOV DI,AX ;put into index register for JMP | ||
| 506 | |||
| 507 | XOR AX,AX ;initialize return to "no error" | ||
| 508 | |||
| 509 | ;At entry to command processing routine: | ||
| 510 | |||
| 511 | ; DS:BX = Request Header address | ||
| 512 | ; CS = VDISK code segment address | ||
| 513 | ; AX = 0 | ||
| 514 | |||
| 515 | ; top of stack is return address, IRPT_CMD_EXIT | ||
| 516 | |||
| 517 | JMP CS:CMD_TABLE[DI] ;call routine to handle the command | ||
| 518 | |||
| 519 | |||
| 520 | IRPT_CMD_ERROR: ;CALLed for unsupported character mode commands | ||
| 521 | |||
| 522 | INPUT_IOCTL: ;IOCTL input | ||
| 523 | INPUT_NOWAIT: ;Non-destructive input no wait | ||
| 524 | INPUT_STATUS: ;Input status | ||
| 525 | INPUT_FLUSH: ;Input flush | ||
| 526 | |||
| 527 | OUTPUT_IOCTL: ;IOCTL output | ||
| 528 | OUTPUT_STATUS: ;Output status | ||
| 529 | OUTPUT_FLUSH: ;Output flush | ||
| 530 | |||
| 531 | POP AX ;pop return address off stack | ||
| 532 | |||
| 533 | IRPT_CMD_HIGH: ;JMPed to if RHC_CMD > MAX_CMD | ||
| 534 | MOV AX,STAT_CMDERR ;"invalid command" and error | ||
| 535 | |||
| 536 | IRPT_CMD_EXIT: ;return from command routine | ||
| 537 | ;AX = value to OR into status word | ||
| 538 | LDS BX,CS:RH_PTRA ;restore DS:BX as Request Header pointer | ||
| 539 | OR AH,STAT_DONE ;add "done" bit to status word | ||
| 540 | MOV RH.RHC_STA,AX ;store status into request header | ||
| 541 | POP SI ;restore registers | ||
| 542 | POP DI | ||
| 543 | POP DX | ||
| 544 | POP CX | ||
| 545 | POP BX | ||
| 546 | POP AX | ||
| 547 | POP ES | ||
| 548 | POP DS | ||
| 549 | RET | ||
| 550 | IRPT ENDP | ||
| 551 | |||
| 552 | SUBTTL Command Processing routines | ||
| 553 | PAGE | ||
| 554 | ;-----------------------------------------------------------------------; | ||
| 555 | ; Command Code 1 - Media Check ; | ||
| 556 | ; At entry, DS:BX point to request header, AX = 0 ; | ||
| 557 | ;-----------------------------------------------------------------------; | ||
| 558 | MEDIA_CHECK PROC | ||
| 559 | MOV RH.RH1_RET,1 ;indicate media not changed | ||
| 560 | RET ;AX = zero, no error | ||
| 561 | MEDIA_CHECK ENDP | ||
| 562 | ;-----------------------------------------------------------------------; | ||
| 563 | ; Command Code 2 - Build BPB ; | ||
| 564 | ; At entry, DS:BX point to request header, AX = 0 ; | ||
| 565 | ;-----------------------------------------------------------------------; | ||
| 566 | BLD_BPB PROC | ||
| 567 | MOV RH.RH2_BPBO,OFFSET BPB ;return pointer to our BPB | ||
| 568 | MOV RH.RH2_BPBS,CS | ||
| 569 | RET ;AX = zero, no error | ||
| 570 | BLD_BPB ENDP | ||
| 571 | ;-----------------------------------------------------------------------; | ||
| 572 | ; Command Code 13 - Device Open ; | ||
| 573 | ; Command Code 14 - Device Close ; | ||
| 574 | ; Command Code 15 - Removable media ; | ||
| 575 | ; At entry, DS:BX point to request header, AX = 0 ; | ||
| 576 | ;-----------------------------------------------------------------------; | ||
| 577 | REMOVABLE_MEDIA PROC | ||
| 578 | MOV AX,STAT_BUSY ;set status bit 9 (busy) | ||
| 579 | ;indicating non-removable media | ||
| 580 | DEVICE_OPEN: ;NOP for device open | ||
| 581 | DEVICE_CLOSE: ;NOP for device close | ||
| 582 | RET | ||
| 583 | REMOVABLE_MEDIA ENDP ;fall thru to return | ||
| 584 | ;-----------------------------------------------------------------------; | ||
| 585 | ; Command Code 4 - Input ; | ||
| 586 | ; Command Code 8 - Output ; | ||
| 587 | ; Command Code 9 - Output with verify ; | ||
| 588 | ; At entry, DS:BX point to request header, AX = 0 ; | ||
| 589 | ;-----------------------------------------------------------------------; | ||
| 590 | INOUT PROC | ||
| 591 | INPUT: | ||
| 592 | OUTPUT: | ||
| 593 | OUTPUT_VERIFY: | ||
| 594 | ;;;;; PUSH DS ;ICE | ||
| 595 | ;;;;; push bx ;ICE | ||
| 596 | ;;;;; push ax ;ICE | ||
| 597 | |||
| 598 | ;;;;; mov bx,0140H ;ICE | ||
| 599 | ;;;;; xor ax,ax ;ICE | ||
| 600 | ;;;;; mov ds,ax ;ICE | ||
| 601 | ;;;;; mov ax,word ptr ds:[bx] ;ICE | ||
| 602 | ;;;;; mov word ptr ds:[bx],ax ;ICE | ||
| 603 | |||
| 604 | ;;;;; pop ax ;ICE | ||
| 605 | ;;;;; pop bx ;ICE | ||
| 606 | ;;;;; POP DS ;ICE | ||
| 607 | |||
| 608 | ;Make sure I/O is entirely within the VDISK sector boundaries | ||
| 609 | |||
| 610 | MOV CX,CS:BPB_SECN ;get total sector count | ||
| 611 | MOV AX,RH.RH4_SSN ;starting sector number | ||
| 612 | CMP AX,CX ;can't exceed total count | ||
| 613 | JA INOUT_E1 ;jump if start > total | ||
| 614 | |||
| 615 | ADD AX,RH.RH4_CNT ;start + sector count | ||
| 616 | CMP AX,CX ;can't exceed total count | ||
| 617 | JNA INOUT_A ;jump if start + count <= total | ||
| 618 | |||
| 619 | INOUT_E1: ;I/O not within VDISK sector boundaries | ||
| 620 | MOV RH.RH4_CNT,0 ;set sectors transferred to zero | ||
| 621 | MOV AX,STAT_SNF ;indicate 'Sector not found' error | ||
| 622 | RET ;return with error status in AX | ||
| 623 | |||
| 624 | INOUT_A: ;I/O within VDISK bounds | ||
| 625 | MOV AX,RH.RH4_CNT ;get sector count | ||
| 626 | MOV CS:SECT_LEFT,AX ;save as sectors left to process | ||
| 627 | |||
| 628 | MOV CS:SECT_LEFT_IN_FRAME,AX ;AN000; Save as sectors left to process | ||
| 629 | |||
| 630 | CMP CS:EM_SW,0 ;extended memory mode? | ||
| 631 | JNE INOUT_EM ;jump to extended memory I/O code | ||
| 632 | |||
| 633 | ;Compute offset and segment of VDISK buffer for starting segment in CX:SI | ||
| 634 | |||
| 635 | MOV AX,RH.RH4_SSN ;starting sector number | ||
| 636 | MUL CS:PARAS_PER_SECTOR ;* length of one sector in paragraphs | ||
| 637 | ADD AX,CS:START_BUFFER_PARA ;+ segment of VDISK buffer sector 0 | ||
| 638 | MOV CX,AX ;segment address to CX | ||
| 639 | XOR SI,SI ;offset is zero | ||
| 640 | |||
| 641 | ;Compute address of caller's Data Transfer Addr in DX:AX with smallest offset, | ||
| 642 | ;so that there is no possibility of overflowing a 64KB boundary moving MAX_CNT | ||
| 643 | ;sectors. | ||
| 644 | |||
| 645 | MOV AX,PARA_SIZE ;16 | ||
| 646 | MUL RH.RH4_DTAS ;* segment of caller's DTA in DX,AX | ||
| 647 | ADD AX,RH.RH4_DTAO ;+ offset of caller's DTA | ||
| 648 | ADC DL,0 ;carry in from addition | ||
| 649 | DIV CS:WPARA_SIZE ;AX is segment of caller's DTA | ||
| 650 | ;DX is smallest offset possible | ||
| 651 | ;AX:DX = DTA address | ||
| 652 | |||
| 653 | ;AX:DX is caller's DTA segment:offset, CX:SI is VDISK buffer segment:offset | ||
| 654 | |||
| 655 | ;If this is an OUTPUT request, exchange the source and target addresses | ||
| 656 | |||
| 657 | CMP RH.RHC_CMD,CMD_INPUT ;INPUT operation? | ||
| 658 | JE INOUT_B ;jump if INPUT operation | ||
| 659 | |||
| 660 | XCHG AX,CX ;swap source and target segment | ||
| 661 | XCHG DX,SI ;swap source and target offset | ||
| 662 | |||
| 663 | INOUT_B: ;CX:SI is source, AX:DX is target | ||
| 664 | MOV CS:IO_SRCS,CX ;save source segment | ||
| 665 | MOV CS:IO_SRCO,SI ;save source offset | ||
| 666 | MOV CS:IO_TGTS,AX ;save target segment | ||
| 667 | MOV CS:IO_TGTO,DX ;save target offset | ||
| 668 | |||
| 669 | JMP SHORT INOUT_E ;AX := SECT_LEFT, test for zero | ||
| 670 | INOUT_C: ;SECT_LEFT in AX, non-zero | ||
| 671 | |||
| 672 | ; Compute number of sectors to transfer in a single move, | ||
| 673 | ; AX = minimum of (SECT_LEFT, MAX_CNT) | ||
| 674 | |||
| 675 | ; MAX_CNT is the maximum number of sectors that can be moved without | ||
| 676 | ; spanning a 64KB boundary (0FFFFH / Sector size, remainder truncated) | ||
| 677 | |||
| 678 | MOV CX,CS:MAX_CNT ;MAX sectors with one move | ||
| 679 | CMP AX,CX ;if SECT_LEFT cannot span 64KB boundary | ||
| 680 | JBE INOUT_D ;then move SECT_LEFT sectors | ||
| 681 | |||
| 682 | MOV AX,CX ;else move MAX_CNT sectors | ||
| 683 | INOUT_D: | ||
| 684 | |||
| 685 | CALL INOUT_D_LOW_MEM ;AN000;LOW MEMORY TRANSFER | ||
| 686 | |||
| 687 | ;Determine if more sectors need to be transferred | ||
| 688 | |||
| 689 | INOUT_E: ;do while SECT_LEFT <> zero | ||
| 690 | MOV AX,CS:SECT_LEFT ;get sectors left to transfer | ||
| 691 | OR AX,AX ;set flags | ||
| 692 | JNZ INOUT_C ;go back to transfer some sectors | ||
| 693 | RET ;AX = zero, all sectors transferred | ||
| 694 | |||
| 695 | SUBTTL Extended Memory I/O routine | ||
| 696 | PAGE | ||
| 697 | ;-----------------------------------------------------------------------; | ||
| 698 | ; Extended Memory I/O routine ; | ||
| 699 | ;-----------------------------------------------------------------------; | ||
| 700 | INOUT_EM: ;Extended memory I/O routine | ||
| 701 | ;change to larger stack | ||
| 702 | MOV SI,SS ;save old SS in SI | ||
| 703 | MOV DX,SP ;save old SP in DX | ||
| 704 | CLI ;disable interrupts | ||
| 705 | MOV AX,CS | ||
| 706 | MOV SS,AX ;set SS = CS | ||
| 707 | MOV SP,OFFSET EM_STACK ;point to new stack | ||
| 708 | STI ;enable interrupts | ||
| 709 | PUSH SI ;save old SS at top of new stack | ||
| 710 | PUSH DX ;save old SP on new stack | ||
| 711 | |||
| 712 | MOV SI,RH.RH4_DTAO ;caller's DTA offset | ||
| 713 | |||
| 714 | |||
| 715 | CMP EM_SW,EM_Mem ;AC005; Is EM requested? | ||
| 716 | JE INOUT_EM_A ;AN000; | ||
| 717 | JMP INOUT_EMS ;AN000; Yes, compute page | ||
| 718 | |||
| 719 | INOUT_EM_A: ;AN000; No, compute 24-bit address | ||
| 720 | |||
| 721 | ;Compute 24-bit address of VDISK sector in CX (hi) and SI (low) | ||
| 722 | |||
| 723 | MOV AX,RH.RH4_SSN ;starting sector number | ||
| 724 | MUL CS:BPB_SSZ ;* sector size = offset within buffer | ||
| 725 | ADD AX,CS:START_EM_LO ;+ base address of this VDISK buffer | ||
| 726 | ADC DL,CS:START_EM_HI | ||
| 727 | MOV CX,DX ;save high byte | ||
| 728 | MOV SI,AX ;save low word | ||
| 729 | |||
| 730 | ;Compute 24-bit address of caller's DTA in DX (hi) and AX (low) | ||
| 731 | |||
| 732 | MOV AX,PARA_SIZE ;16 | ||
| 733 | MUL RH.RH4_DTAS ;* segment of caller's DTA | ||
| 734 | ADD AX,RH.RH4_DTAO ;+ offset of caller's DTA | ||
| 735 | ADC DL,0 ;carry in from addition | ||
| 736 | |||
| 737 | ;Caller's DTA address is in CX,SI, VDISK buffer address is in DX,AX. | ||
| 738 | |||
| 739 | ;If this is an OUTPUT request, exchange the source and target addresses | ||
| 740 | |||
| 741 | CMP RH.RHC_CMD,CMD_INPUT ;INPUT operation? | ||
| 742 | JE INOUT_EM_B ;jump if INPUT operation | ||
| 743 | |||
| 744 | XCHG DX,CX ;swap source and target high byte | ||
| 745 | XCHG AX,SI ;swap source and target low word | ||
| 746 | |||
| 747 | INOUT_EM_B: ;CX,SI is source, DX,AX is target | ||
| 748 | |||
| 749 | MOV SRC.DESC_BASEL,SI ;low 16 bits of source address | ||
| 750 | MOV SRC.DESC_BASEH,CL ;high 8 bits of source address | ||
| 751 | |||
| 752 | MOV TGT.DESC_BASEL,AX ;low 16 bits of target address | ||
| 753 | MOV TGT.DESC_BASEH,DL ;high 8 bits of target address | ||
| 754 | |||
| 755 | JMP SHORT INOUT_EM_E ;AX := SECT_LEFT, test for zero | ||
| 756 | INOUT_EM_C: ;SECT_LEFT in AX, non-zero | ||
| 757 | |||
| 758 | ; Compute number of sectors to transfer in a single move, | ||
| 759 | ; AX = minimum of (SECT_LEFT, MAX_CNT) | ||
| 760 | |||
| 761 | ; MAX_CNT is the maximum number of sectors that can be moved without | ||
| 762 | ; spanning a 64KB boundary (0FFFFH / Sector size, remainder truncated) | ||
| 763 | |||
| 764 | MOV CX,CS:MAX_CNT ;MAX sectors with one move | ||
| 765 | CMP AX,CX ;if SECT_LEFT cannot span 64KB boundary | ||
| 766 | JBE INOUT_EM_D ;then move SECT_LEFT sectors | ||
| 767 | |||
| 768 | MOV AX,CX ;else move MAX_CNT sectors | ||
| 769 | INOUT_EM_D: | ||
| 770 | SUB CS:SECT_LEFT,AX ;reduce number of sectors left to move | ||
| 771 | |||
| 772 | ;Move AX sectors from source to target | ||
| 773 | |||
| 774 | MUL CS:BPB_SSZ ;sectors * sector size = byte count | ||
| 775 | ;(cannot overflow into DX) | ||
| 776 | MOV TGT.DESC_LMT,AX ;store segment limit (byte count) | ||
| 777 | MOV SRC.DESC_LMT,AX | ||
| 778 | |||
| 779 | PUSH AX ;preserve byte count on stack | ||
| 780 | |||
| 781 | SHR AX,1 ;/2 = word count | ||
| 782 | MOV CX,AX ;word count to CX | ||
| 783 | |||
| 784 | PUSH CS | ||
| 785 | POP ES ;set ES = CS | ||
| 786 | MOV SI,OFFSET GDT ;ES:SI point to GDT | ||
| 787 | |||
| 788 | MOV AH,EM_BLKMOVE ;function is block move | ||
| 789 | INT EM_INT ;move an even number of words | ||
| 790 | |||
| 791 | POP CX ;get byte count back from stack | ||
| 792 | |||
| 793 | OR AH,AH ;get error code | ||
| 794 | |||
| 795 | JZ INOUT_UPDATE ; | ||
| 796 | JMP INOUT_EM_XE ;jump if I/O error encountered | ||
| 797 | |||
| 798 | INOUT_UPDATE: | ||
| 799 | |||
| 800 | ;Update source and target addresses | ||
| 801 | |||
| 802 | ADD SRC.DESC_BASEL,CX ;add bytes moved to source | ||
| 803 | ADC SRC.DESC_BASEH,0 ;pick up any carry | ||
| 804 | |||
| 805 | ADD TGT.DESC_BASEL,CX ;add bytes moved to target | ||
| 806 | ADC TGT.DESC_BASEH,0 ;pick up any carry | ||
| 807 | |||
| 808 | ;Determine if more sectors need to be transferred | ||
| 809 | |||
| 810 | INOUT_EM_E: ;do while SECT_LEFT <> zero | ||
| 811 | MOV AX,CS:SECT_LEFT ;get sectors left to transfer | ||
| 812 | OR AX,AX ;set flags | ||
| 813 | JNZ INOUT_EM_C ;go back to transfer some sectors | ||
| 814 | |||
| 815 | JMP INOUT_EM_X2 ;AN000; All done . . . exit | ||
| 816 | ;-----------------------------------------------------------------------; | ||
| 817 | ; EMS Support ;RPS; ; | ||
| 818 | ;-----------------------------------------------------------------------; | ||
| 819 | |||
| 820 | INOUT_EMS: ;AN000; | ||
| 821 | |||
| 822 | ; Save EMS state in case anyone is using it | ||
| 823 | PUSH AX ;AN000; DMS;SAVE IT | ||
| 824 | PUSH BX ;AN000; DMS;SAVE IT | ||
| 825 | PUSH DX ;AN000; DMS;SAVE IT | ||
| 826 | push di ;an000; dms;save it | ||
| 827 | push si ;an000; dms;save it | ||
| 828 | push ds ;an000; dms;save it | ||
| 829 | push es ;an000; dms;save it | ||
| 830 | mov ax,cs ;an000; dms;transfer cs to ds/es | ||
| 831 | mov ds,ax ;an000; dms; | ||
| 832 | mov es,ax ;an000; dms; | ||
| 833 | |||
| 834 | mov di,offset cs:EMS_SAVE_ARRAY ;an000; point to save area | ||
| 835 | mov si,offset cs:EMS_SEG_ARRAY ;an000; point to segment area | ||
| 836 | mov word ptr cs:EMS_SEG_ARRAY,0001h ;an000; 1 segment to save | ||
| 837 | mov ax,cs:EMS_Frame_Addr ;an000; get segment | ||
| 838 | mov word ptr cs:EMS_SEG_ARRAY+2,ax ;an000; segment | ||
| 839 | MOV AX,EMS_SAVE_STATE ;AN000; Function code to save active handle state | ||
| 840 | INT EMS_INT ;AN000; | ||
| 841 | |||
| 842 | pop es ;an000; dms;restore | ||
| 843 | pop ds ;an000; dms;restore | ||
| 844 | pop si ;an000; dms;restore | ||
| 845 | pop di ;an000; dms;restore | ||
| 846 | POP DX ;AN000; DMS;RESTORE | ||
| 847 | POP BX ;AN000; DMS;RESTORE | ||
| 848 | POP AX ;AN000; DMS;RESTORE | ||
| 849 | |||
| 850 | ; Compute offset and segment of VDISK frame for starting segment in CX:SI | ||
| 851 | ; and page containing VDISK starting sector | ||
| 852 | |||
| 853 | push ds ;an000; dms;save ds | ||
| 854 | push es ;an000; dms;save es | ||
| 855 | |||
| 856 | mov cs:curr_dta_off,0 ;an000; dms;current offset = 0 | ||
| 857 | mov ax,rh.rh4_ssn ;an000; dms;get 1st. sector | ||
| 858 | mov cs:ems_curr_sect,ax ;an000; dms;save it | ||
| 859 | call ems_page_off_calc ;an000; dms;calc page and off. | ||
| 860 | call ems_dta_calc ;an000; dms;calc DTA | ||
| 861 | call ems_src_tgt ;an000; dms;get src & tgt | ||
| 862 | |||
| 863 | ; $do ;an000; dms;while sectors left | ||
| 864 | $$DO4: | ||
| 865 | call map_frame ;an000; dms;map a page | ||
| 866 | call ems_trf ;an000; dms;transfer data | ||
| 867 | dec cs:sect_left ;an000; dms;sect_left - 1 | ||
| 868 | cmp cs:sect_left,0 ;an000; dms;continue? | ||
| 869 | ; $leave e ;an000; dms;no - exit | ||
| 870 | JE $$EN4 | ||
| 871 | ; yes - continue | ||
| 872 | mov ax,cs:ems_curr_sect ;an000; dms;get current sector | ||
| 873 | call ems_page_off_calc ;an000; dms;calc page and off. | ||
| 874 | call ems_dta_adj ;an000; dms;adjust DTA | ||
| 875 | call ems_src_tgt ;an000; dms;get src & tgt | ||
| 876 | ; $enddo ;an000; dms;end while | ||
| 877 | JMP SHORT $$DO4 | ||
| 878 | $$EN4: | ||
| 879 | |||
| 880 | pop es ;an000; dms;restore es | ||
| 881 | pop ds ;an000; dms;restore ds | ||
| 882 | |||
| 883 | ; Restore EMS state in case anyone was using it | ||
| 884 | ;AN000; No, | ||
| 885 | PUSH AX ;AN000; DMS;SAVE IT | ||
| 886 | PUSH BX ;AN000; DMS;SAVE IT | ||
| 887 | PUSH DX ;AN000; DMS;SAVE IT | ||
| 888 | PUSH SI ;AN000; DMS;SAVE IT | ||
| 889 | push ds ;an000; dms;save it | ||
| 890 | |||
| 891 | mov ax,cs ;an000; dms;get cs | ||
| 892 | mov ds,ax ;an000; dms;put in ds | ||
| 893 | MOV AX,EMS_RESTORE_STATE ;AN000; Function code to restore active handle state | ||
| 894 | MOV SI,OFFSET CS:EMS_SAVE_ARRAY ;AN000; POINT TO SAVE ARRAY | ||
| 895 | INT EMS_INT ;AN000; | ||
| 896 | |||
| 897 | pop ds ;an000; dms;restore | ||
| 898 | POP SI ;AN000; DMS;RESTORE | ||
| 899 | POP DX ;AN000; DMS;RESTORE | ||
| 900 | POP BX ;AN000; DMS;RESTORE | ||
| 901 | POP AX ;AN000; DMS;RESTORE | ||
| 902 | |||
| 903 | ;-----------------------------------------------------------------------; | ||
| 904 | |||
| 905 | INOUT_EM_X2: ;revert to original stack | ||
| 906 | POP DI ;get old SP | ||
| 907 | POP SI ;get old SS | ||
| 908 | CLI ;disable interrupts | ||
| 909 | MOV SS,SI ;restore old SS | ||
| 910 | MOV SP,DI ;restore old SP | ||
| 911 | STI ;enable interrupts | ||
| 912 | RET ;return to IRPT_EXIT | ||
| 913 | |||
| 914 | INOUT_EM_XE: ;some error with INT 15H | ||
| 915 | MOV CS:EM_STAT,AX ;save error status for debugging | ||
| 916 | MOV RH.RH4_CNT,0 ;indicate no sectors transferred | ||
| 917 | MOV AX,STAT_CRC ;indicate CRC error | ||
| 918 | JMP INOUT_EM_X2 ;fix stack and exit | ||
| 919 | INOUT ENDP | ||
| 920 | |||
| 921 | |||
| 922 | ;========================================================================= | ||
| 923 | ; EMS_PAGE_OFF_CALC : Calculates the current ems page to use and | ||
| 924 | ; the offset of the requested sector in that | ||
| 925 | ; page. | ||
| 926 | ; | ||
| 927 | ; Inputs: AX - Sector for input/output | ||
| 928 | ; SECT_PER_PAGE - # of sectors/ems page | ||
| 929 | ; BPB_SSZ - Size in bytes of a sector | ||
| 930 | ; EMS_FRAME_ADDR - Segment of ems page | ||
| 931 | ; | ||
| 932 | ; Outputs: CURR_EMS_PAGE - Currently active ems page | ||
| 933 | ; CX:SI - Segment:Offset of logical sector | ||
| 934 | ;========================================================================= | ||
| 935 | |||
| 936 | ems_page_off_calc proc near ;an000; dms;calc page/offset | ||
| 937 | |||
| 938 | xor dx,dx ;an002; dms;clear high word | ||
| 939 | div cs:sect_per_page ;an000; dms;determine page | ||
| 940 | mov cs:curr_ems_page,ax ;an002; dms;save page | ||
| 941 | mov ax,dx ;an002; dms;offset calc | ||
| 942 | mul cs:bpb_ssz ;an000; dms;calc offset | ||
| 943 | mov si,ax ;an000; dms;save sector offset | ||
| 944 | mov cx,cs:ems_frame_addr ;an000; dms;obtain sector seg | ||
| 945 | |||
| 946 | ret ;an000; dms; | ||
| 947 | |||
| 948 | ems_page_off_calc endp ;an000; dms; | ||
| 949 | |||
| 950 | |||
| 951 | ;========================================================================= | ||
| 952 | ; EMS_DTA_CALC : Calculate the DTA buffer to be used. | ||
| 953 | ; | ||
| 954 | ; Inputs: PARA_SIZE - 16 | ||
| 955 | ; RH4_DTAS - Segment of DTA from request packet | ||
| 956 | ; RH4_DTA0 - Offset of DTA from request packet | ||
| 957 | ; WPARA_SIZE- 16 | ||
| 958 | ; | ||
| 959 | ; Outputs: AX:DX - Segment:Offset of DTA buffer | ||
| 960 | ;========================================================================= | ||
| 961 | |||
| 962 | ems_dta_calc proc near ;an000; dms;calc DTA buffer | ||
| 963 | |||
| 964 | xor dx,dx ;an002; dms;clear high word | ||
| 965 | mov ax,para_size ;an000; dms;get para size | ||
| 966 | mul rh.rh4_dtas ;an000; dms;times DTA segment | ||
| 967 | add ax,rh.rh4_dtao ;an000; dms;+ DTA offset | ||
| 968 | adc dx,0 ;an002; dms;pick up carry | ||
| 969 | div cs:wpara_size ;an000; dms;/16 | ||
| 970 | |||
| 971 | ret ;an000; dms; | ||
| 972 | |||
| 973 | ems_dta_calc endp ;an000; dms; | ||
| 974 | |||
| 975 | |||
| 976 | ;========================================================================= | ||
| 977 | ; EMS_DTA_ADJ : Adjust DTA for the number of sectors having | ||
| 978 | ; been transferred. | ||
| 979 | ; | ||
| 980 | ; External Calls : EMS_DTA_CALC | ||
| 981 | ; | ||
| 982 | ; Inputs: CURR_DTA_OFF - Current offset value to be adjusted. | ||
| 983 | ; | ||
| 984 | ; Outputs: CURR_DTA_OFF - Adjusted offset value into DTA | ||
| 985 | ; DX - Adjusted offset value into DTA | ||
| 986 | ;========================================================================= | ||
| 987 | |||
| 988 | ems_dta_adj proc near ;an000; dms;adjust DTA | ||
| 989 | |||
| 990 | call ems_dta_calc ;an000; dms; | ||
| 991 | push ax ;an000; dms;save reg | ||
| 992 | mov ax,cs:curr_dta_off ;an000; dms;get current off. | ||
| 993 | add ax,cs:bpb_ssz ;an000; dms;adjust up | ||
| 994 | mov cs:curr_dta_off,ax ;an000; dms;save new off | ||
| 995 | add dx,ax ;an000; dms;set dx to new off | ||
| 996 | pop ax ;an000; dms;restore reg | ||
| 997 | ret ;an000; dms; | ||
| 998 | |||
| 999 | ems_dta_adj endp ;an000; dms; | ||
| 1000 | |||
| 1001 | ;========================================================================= | ||
| 1002 | ; EMS_SRC_TGT : Determine the source and target segments for | ||
| 1003 | ; data transfer. | ||
| 1004 | ; | ||
| 1005 | ; Inputs: RHC_CMD - Request packet command identifier | ||
| 1006 | ; AX:DX - DTA | ||
| 1007 | ; CX:SI - EMS page/sector | ||
| 1008 | ; | ||
| 1009 | ; Outputs: IO_SRCS - Segment of source of trf | ||
| 1010 | ; IO_SRCO - Offset of source of trf | ||
| 1011 | ; IO_TGTS - Segment of target for trf | ||
| 1012 | ; IO_TGTO - Offset of target for trf | ||
| 1013 | ;========================================================================= | ||
| 1014 | |||
| 1015 | ems_src_tgt proc near ;an000; dms;src/tgt calc | ||
| 1016 | |||
| 1017 | cmp rh.rhc_cmd,cmd_input ;an000; dms;input/output? | ||
| 1018 | ; $if ne ;an000; dms; | ||
| 1019 | JE $$IF7 | ||
| 1020 | xchg ax,cx ;an000; dms;swap src/tgt seg | ||
| 1021 | xchg dx,si ;an000; dms;swap src/tgt off | ||
| 1022 | ; $endif ;an000; dms; | ||
| 1023 | $$IF7: | ||
| 1024 | |||
| 1025 | mov cs:io_srcs,cx ;an000; dms;save src seg | ||
| 1026 | mov cs:io_srco,si ;an000; dms;save src off | ||
| 1027 | mov cs:io_tgts,ax ;an000; dms;save tgt seg | ||
| 1028 | mov cs:io_tgto,dx ;an000; dms;save tgt off | ||
| 1029 | ret ;an000; dms; | ||
| 1030 | |||
| 1031 | ems_src_tgt endp ;an000; dms; | ||
| 1032 | |||
| 1033 | |||
| 1034 | ;========================================================================= | ||
| 1035 | ; EMS_TRF : Perform the sector transfer of data. | ||
| 1036 | ; | ||
| 1037 | ; Inputs: BPB_SSZ - Sector size | ||
| 1038 | ; IO_SRCA - Source address | ||
| 1039 | ; IO_TGTA - Target address | ||
| 1040 | ; | ||
| 1041 | ; Outputs: Transferred data | ||
| 1042 | ; EMS_CURR_SECT - Incremented 1 | ||
| 1043 | ;========================================================================= | ||
| 1044 | |||
| 1045 | ems_trf proc near ;an000; dms;transfer data | ||
| 1046 | |||
| 1047 | mov ax,cs:bpb_ssz ;an000; dms;set to sector size | ||
| 1048 | shr ax,1 ;an000; dms;make words | ||
| 1049 | mov cx,ax ;an000; dms;set loop counter | ||
| 1050 | push ds ;an000; dms;save regs | ||
| 1051 | push es ;an000; dms; | ||
| 1052 | |||
| 1053 | lds si,cs:io_srca ;an000; dms;get src address | ||
| 1054 | les di,cs:io_tgta ;an000; dms;get tgt address | ||
| 1055 | |||
| 1056 | CMP CS:PC_386,TRUE ;AN000; DO WE HAVE A 386 MACHINE? | ||
| 1057 | ; $IF E ;AN000; YES | ||
| 1058 | JNE $$IF9 | ||
| 1059 | SHR CX,1 ;AN000; /2 = DW COUNT | ||
| 1060 | DB 66H ;AN000; SIMULATE A MOVSDW | ||
| 1061 | ; $ENDIF ;AN000; | ||
| 1062 | $$IF9: | ||
| 1063 | rep movsw ;an000; dms;perform transfer | ||
| 1064 | |||
| 1065 | pop es ;an000; dms;restore regs | ||
| 1066 | pop ds ;an000; dms; | ||
| 1067 | inc cs:ems_curr_sect ;an000; dms;increment sector | ||
| 1068 | |||
| 1069 | ret ;an000; dms; | ||
| 1070 | |||
| 1071 | ems_trf endp ;an000; dms; | ||
| 1072 | |||
| 1073 | |||
| 1074 | |||
| 1075 | MAP_FRAME PROC NEAR ;AN000; | ||
| 1076 | |||
| 1077 | PUSH BX ;AN000; DMS; | ||
| 1078 | mov ax,cs:DOS_Page ;an000; get physical page | ||
| 1079 | MOV AH,EMS_MAP_HANDLE ;AN000; EMS function to map page | ||
| 1080 | MOV BX,CS:CURR_EMS_PAGE ;AN000; Page number | ||
| 1081 | MOV DX,CS:EMS_HANDLE ;AN000; EMS handle | ||
| 1082 | INT EMS_INT ;AN000; | ||
| 1083 | POP BX ;AN000; DMS; | ||
| 1084 | RET ;AN000; | ||
| 1085 | |||
| 1086 | MAP_FRAME ENDP ;AN000; | ||
| 1087 | |||
| 1088 | |||
| 1089 | INOUT_D_LOW_MEM PROC NEAR ;AN000; LOW MEMORY TRANSFER | ||
| 1090 | |||
| 1091 | SUB CS:SECT_LEFT,AX ;reduce number of sectors left to move | ||
| 1092 | |||
| 1093 | ;Move AX sectors from source to target | ||
| 1094 | |||
| 1095 | MUL CS:BPB_SSZ ;sectors * sector size = byte count | ||
| 1096 | ;(cannot overflow into DX) | ||
| 1097 | SHR AX,1 ;/2 = word count | ||
| 1098 | MOV CX,AX ;word count to CX for \REP MOVSW | ||
| 1099 | |||
| 1100 | LDS SI,CS:IO_SRCA ;source segment/offset to DS:SI | ||
| 1101 | LES DI,CS:IO_TGTA ;target segment/offset to ES:DI | ||
| 1102 | |||
| 1103 | CMP CS:PC_386,TRUE ;AN000; DO WE HAVE A 386 MACHINE? | ||
| 1104 | ; $IF E ;AN000; YES | ||
| 1105 | JNE $$IF11 | ||
| 1106 | SHR CX,1 ;AN000; /2 = DW COUNT | ||
| 1107 | DB 66H ;AN000; SIMULATE A MOVSDW | ||
| 1108 | ; $ENDIF ;AN000; | ||
| 1109 | $$IF11: | ||
| 1110 | REP MOVSW ;AN000; PERFORM DOUBLE WORD MOVE | ||
| 1111 | |||
| 1112 | ;Update source and target paragraph addresses | ||
| 1113 | ;AX has number of words moved | ||
| 1114 | |||
| 1115 | SHR AX,1 ;words moved / 8 = paragraphs moved | ||
| 1116 | SHR AX,1 | ||
| 1117 | SHR AX,1 | ||
| 1118 | |||
| 1119 | ADD CS:IO_SRCS,AX ;add paragraphs moved to source segment | ||
| 1120 | ADD CS:IO_TGTS,AX ;add paragraphs moved to target segment | ||
| 1121 | |||
| 1122 | RET | ||
| 1123 | |||
| 1124 | INOUT_D_LOW_MEM ENDP | ||
| 1125 | |||
| 1126 | |||
| 1127 | |||
| 1128 | DW 40 DUP (?) ;stack for extended memory I/O | ||
| 1129 | EM_STACK LABEL WORD | ||
| 1130 | |||
| 1131 | SUBTTL Boot Record | ||
| 1132 | PAGE | ||
| 1133 | ;-----------------------------------------------------------------------; | ||
| 1134 | ; Adjust the assembly-time instruction counter to a paragraph ; | ||
| 1135 | ; boundary ; | ||
| 1136 | ;-----------------------------------------------------------------------; | ||
| 1137 | |||
| 1138 | IF ($-START) MOD 16 | ||
| 1139 | ORG ($-START) + 16 - (($-START) MOD 16) | ||
| 1140 | ENDIF | ||
| 1141 | |||
| 1142 | VDISK EQU $ ;start of virtual disk buffer | ||
| 1143 | VDISKP EQU ($-START) / PARA_SIZE ;length of program in paragraphs | ||
| 1144 | ;-----------------------------------------------------------------------; | ||
| 1145 | ; If this VDISK is in extended memory, this address is passed ; | ||
| 1146 | ; back to DOS as the end address that is to remain resident. ; | ||
| 1147 | ; ; | ||
| 1148 | ; It this VDISK is not in extended memory, the VDISK buffer ; | ||
| 1149 | ; begins at this address, and the address passed back to DOS ; | ||
| 1150 | ; as the end address that is to remain resident is this address ; | ||
| 1151 | ; plus the length of the VDISK buffer. ; | ||
| 1152 | ;-----------------------------------------------------------------------; | ||
| 1153 | |||
| 1154 | BOOT_RECORD LABEL BYTE ;Format of Boot Record documented in | ||
| 1155 | ;DOS Technical Reference Manual | ||
| 1156 | DB 0,0,0 ;3-byte jump to boot code (not bootable) | ||
| 1157 | DB 'VDISKx.x' ;8-byte vendor identification | ||
| 1158 | BOOT_BPB LABEL BYTE ;boot record copy of BIOS parameter block | ||
| 1159 | DW ? ;number of bytes per disk sector | ||
| 1160 | DB ? ;sectors per allocation unit | ||
| 1161 | DW ? ;number of reserved sectors (for boot record) | ||
| 1162 | DB ? ;number of File Allocation Table (FAT) copies | ||
| 1163 | DW ? ;number of root directory entries | ||
| 1164 | DW ? ;total number of sectors | ||
| 1165 | DB ? ;media descriptor byte | ||
| 1166 | DW ? ;number of sectors occupied by a single FAT | ||
| 1167 | ;end of boot record BIOS Parameter block | ||
| 1168 | |||
| 1169 | ;The following three words mean nothing to VDISK, they are placed here | ||
| 1170 | ;to conform to the DOS standard for boot records. | ||
| 1171 | DW 8 ;sectors per track | ||
| 1172 | DW 1 ;number of heads | ||
| 1173 | DW 0 ;number of hidden sectors | ||
| 1174 | ;The following word is the 16-bit kilobyte address of the first byte in | ||
| 1175 | ;extended memory that is not occupied by a VDISK buffer | ||
| 1176 | ;It is placed into this location so that other users of extended memory | ||
| 1177 | ;may find where all the VDISKs end. | ||
| 1178 | |||
| 1179 | ;This field may be accessed by moving the boot record of the First extended | ||
| 1180 | ;memory VDISK from absolute location 10 0000H. Before assuming that the | ||
| 1181 | ;value below is valid, the vendor ID (constant VDISK) should be verified | ||
| 1182 | ;to make sure that SOME VDISK has been installed. | ||
| 1183 | |||
| 1184 | ;For example, if two VDISKs are installed, one 320KB and one 64KB, the | ||
| 1185 | ;address calculations are as follows: | ||
| 1186 | |||
| 1187 | ;Extended memory start address = 100000H (1024KB) | ||
| 1188 | ;Start addr of 1st VDISK buffer = 100000H (1024KB) | ||
| 1189 | ;Length of 1st VDISK buffer = 050000H ( 320KB) | ||
| 1190 | ;End addr of 1st VDISK buffer = 14FFFFH | ||
| 1191 | ;Start addr of 2nd VDISK buffer = 150000H (1344KB) | ||
| 1192 | ;Length of 2nd VDISK buffer = 010000H ( 64KB) | ||
| 1193 | ;End addr of 2nd VDISK buffer = 15FFFFH | ||
| 1194 | ;First byte after all VDISKs = 160000H (1408KB) | ||
| 1195 | ;Divide by 1024 = 0580H (1408D) | ||
| 1196 | |||
| 1197 | ;-----------------------------------------------------------------------; | ||
| 1198 | ; Part 2 of Initialization (executed last) ; | ||
| 1199 | ;-----------------------------------------------------------------------; | ||
| 1200 | ;Initialization is divided into two parts. | ||
| 1201 | |||
| 1202 | ;INIT_P1 is overlaid by the virtual disk buffer | ||
| 1203 | |||
| 1204 | ;INIT_P1 is executed first, then jumps to INIT_P2. INIT_P2 returns to caller. | ||
| 1205 | |||
| 1206 | ;Exercise caution if extending the initialization part 2 code. | ||
| 1207 | ;It overlays the area immediately following the boot sector. | ||
| 1208 | ;If this section of code must be expanded, make sure it fits into the minimum | ||
| 1209 | ;sector size of 128 bytes. | ||
| 1210 | ;Label TEST_LENGTH must equate to a non-negative value (TEST_LENGTH >= 0). | ||
| 1211 | ;If this code it must be extended beyond the 128 byte length of the boot sector, | ||
| 1212 | ;move all of INIT_P2 before label VDISK. | ||
| 1213 | |||
| 1214 | ;Registers at entry to INIT_P2 (set up at end of INIT_P1): | ||
| 1215 | ; BL = media control byte from BPB (for FAT) | ||
| 1216 | ; CX = number of FAT copies | ||
| 1217 | ; DX = number of bytes in one FAT - 3 | ||
| 1218 | ; SI = OFFSET of Volume Label field | ||
| 1219 | ; ES:DI = VDISK buffer address of first FAT sector | ||
| 1220 | ; CS = DS = VDISK code segment | ||
| 1221 | |||
| 1222 | INIT_P2 PROC ;second part of initialization | ||
| 1223 | ASSUME DS:CSEG ;DS set in INIT_P1 | ||
| 1224 | |||
| 1225 | ;Initialize File Allocation Table(s) (FATs) | ||
| 1226 | |||
| 1227 | INIT_P2_FAT: ;set up one FAT, sector number in AX | ||
| 1228 | |||
| 1229 | PUSH CX ;save loop counter on stack | ||
| 1230 | MOV AL,BL ;media control byte | ||
| 1231 | STOSB ;store media control byte, increment DI | ||
| 1232 | MOV AX,0FFFFH ;bytes 2 and 3 of FAT are 0FFH | ||
| 1233 | STOSW | ||
| 1234 | |||
| 1235 | MOV CX,DX ;FAT size in bytes - 3 | ||
| 1236 | XOR AX,AX ;value to store in remainder of FAT | ||
| 1237 | REP STOSB ;clear remainder of FAT | ||
| 1238 | |||
| 1239 | POP CX ;get loop counter off stack | ||
| 1240 | LOOP INIT_P2_FAT ;loop for all copies of the FAT | ||
| 1241 | |||
| 1242 | ;Put the volume label in the first directory entry | ||
| 1243 | |||
| 1244 | MOV CX,VOL_LABEL_LEN ;length of volume directory entry | ||
| 1245 | REP MOVSB ;move volume id to directory | ||
| 1246 | |||
| 1247 | ;Zero the remainder of the directory | ||
| 1248 | |||
| 1249 | MOV AX,DIR_ENTRY_SIZE ;length of 1 directory entry | ||
| 1250 | MUL BPB_DIRN ;* number entries = bytes of directory | ||
| 1251 | SUB AX,VOL_LABEL_LEN ;less length of volume label | ||
| 1252 | MOV CX,AX ;length of rest of directory | ||
| 1253 | XOR AX,AX | ||
| 1254 | REP STOSB ;clear directory to nulls | ||
| 1255 | RET ;return with AX=0 | ||
| 1256 | INIT_P2 ENDP | ||
| 1257 | |||
| 1258 | PATCH_AREA DB 5 DUP ('PATCH AREA ') | ||
| 1259 | TEST_LENGTH EQU 128-($-VDISK) ;if negative, boot record has too much | ||
| 1260 | ;data area, move some fields below VDISK | ||
| 1261 | ;-----------------------------------------------------------------------; | ||
| 1262 | ; All fields that must remain resident after device driver ; | ||
| 1263 | ; initialization must be defined before this point. ; | ||
| 1264 | ;-----------------------------------------------------------------------; | ||
| 1265 | DB ' ' | ||
| 1266 | DB ' ' | ||
| 1267 | DB ' ' | ||
| 1268 | |||
| 1269 | MAXSEC_TRF DW 0 ;maximum number of sectors to transfer when | ||
| 1270 | ;in extended memory | ||
| 1271 | |||
| 1272 | BUFF_SIZE DW 0 ;desired VDISK buffer size in kilobytes | ||
| 1273 | |||
| 1274 | MIN_MEMORY_LEFT DW 100 ;minimum amount of system memory (kilobytes) | ||
| 1275 | ;that must remain after VDISK is installed | ||
| 1276 | |||
| 1277 | PARA_PER_KB DW 1024/PARA_SIZE ;paragraphs in one kilobyte | ||
| 1278 | C1024 DW 1024 ;bytes in one kilobyte | ||
| 1279 | DIRE_SIZE DW DIR_ENTRY_SIZE ;bytes in one directory entry | ||
| 1280 | DIR_SECTORS DW ? ;number of sectors of directory | ||
| 1281 | |||
| 1282 | ERR_FLAG DB 0 ;error indicators to condition messages | ||
| 1283 | ERR_BSIZE EQU 80H ;buffer size adjusted | ||
| 1284 | ERR_SSZ EQU 40H ;sector size adjusted | ||
| 1285 | ERR_DIRN EQU 20H ;number of directory entries adjusted | ||
| 1286 | ERR_PASS EQU 10H ;some adjustment made that requires | ||
| 1287 | ;recomputation of values previously computed | ||
| 1288 | ERR_SSZB EQU ERR_SSZ+ERR_PASS ;sector size altered this pass | ||
| 1289 | ERR_SYSSZ EQU 08H ;system storage too small for VDISK | ||
| 1290 | ERR_SWTCH EQU 04H ;invalid switch character | ||
| 1291 | ERR_EXTSW EQU 02H ;extender card switches don't match memory size | ||
| 1292 | ERR_ESIZE EQU 01H ;Transfer size adjusted | ||
| 1293 | |||
| 1294 | DOS_PG_SZ DB DOS_PAGE_SZ ;AN000; | ||
| 1295 | DOS_Page_Size_Word dw DOS_Page_Sz ;an000; | ||
| 1296 | |||
| 1297 | err_flag2 db 0 | ||
| 1298 | err_baddos equ 01h ; Invalid DOS Version | ||
| 1299 | |||
| 1300 | ;-----------------------------------------------------------------------; | ||
| 1301 | ; SUBLIST definitions and EQUATES for Message Retreiver ; | ||
| 1302 | ;-----------------------------------------------------------------------; | ||
| 1303 | ;AN000; Message Number | ||
| 1304 | INCORRECT_DOS EQU 1 ;AN000; | ||
| 1305 | SYS_TOO_SMALL EQU 2 ;AN000; | ||
| 1306 | VDISK_TITLE EQU 3 ;AN000; | ||
| 1307 | BUFFER_ADJUSTED EQU 4 ;AN000; | ||
| 1308 | SECTOR_ADJUSTED EQU 5 ;AN000; | ||
| 1309 | DIR_ADJUSTED EQU 6 ;AN000; | ||
| 1310 | INVALID_SW_CHAR EQU 7 ;AN000; | ||
| 1311 | TRANS_ADJUSTED EQU 8 ;AN000; | ||
| 1312 | BUF_SZ EQU 9 ;AN000; | ||
| 1313 | SEC_SZ EQU 10 ;AN000; | ||
| 1314 | DIR_ENTRIES EQU 11 ;AN000; | ||
| 1315 | TRANS_SZ EQU 12 ;AN000; | ||
| 1316 | VDISK_NOT_INST EQU 13 ;AN000; | ||
| 1317 | EXTEND_CARD_WRONG EQU 14 ;AN000; | ||
| 1318 | |||
| 1319 | NO_REPLACE EQU 0 ;AN000; CX = 0 -> No replacement | ||
| 1320 | ONE_REPLACE EQU 1 ;AN000; CX = 1 -> One replacement | ||
| 1321 | UNLIMITED_MAX EQU 0 ;AN000; MAX field - unlimited | ||
| 1322 | SMALLEST_MIN EQU 1 ;AN000; MIN field - 1 character long | ||
| 1323 | PAD_BLANK EQU 20H ;AN000; PAD character is a blank | ||
| 1324 | |||
| 1325 | |||
| 1326 | DRIVE_CODE DB ? ;AN000; | ||
| 1327 | DB ":",NULL ;AN000; ASCIIZ string for drive code | ||
| 1328 | |||
| 1329 | ; For the message: "VDISK Version 4.00 virtual disk %1",CR,LF | ||
| 1330 | |||
| 1331 | TITLE_SUBLIST LABEL BYTE | ||
| 1332 | |||
| 1333 | TT_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST) | ||
| 1334 | TT_RESV DB 0 ;AN000; RESERVED | ||
| 1335 | TT_VALUEO DW DRIVE_CODE ;AN000; Offset to ASCIIZ string | ||
| 1336 | TT_VALUES DW ? ;AN000; SEGMENT TO ASCIIZ STRING | ||
| 1337 | TT_ID DB 1 ;AN000; n of %n | ||
| 1338 | TT_FLAG DB Left_Align+Char_Field_ASCIIZ | ||
| 1339 | TT_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width | ||
| 1340 | TT_MINW DB SMALLEST_MIN ;AN000; Minimum field width | ||
| 1341 | TT_PAD DB PAD_BLANK ;AN000; Character for Pad field | ||
| 1342 | |||
| 1343 | ; For the message: "Buffer size: %1 KB",CR,LF | ||
| 1344 | |||
| 1345 | BUF_SZ_SUBLIST LABEL BYTE | ||
| 1346 | |||
| 1347 | B_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST) | ||
| 1348 | B_RESV DB 0 ;AN000; RESERVED | ||
| 1349 | B_VALUEO DW BUFF_SIZE ;AN000; Offset to binary number | ||
| 1350 | B_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER | ||
| 1351 | B_ID DB 1 ;AN000; n of %n | ||
| 1352 | B_FLAG DB Left_Align+Unsgn_Bin_Word | ||
| 1353 | B_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width | ||
| 1354 | B_MINW DB SMALLEST_MIN ;AN000; Minimum field width | ||
| 1355 | B_PAD DB PAD_BLANK ;AN000; Character for Pad field | ||
| 1356 | |||
| 1357 | ; For the message: "Sector size: %1",CR,LF | ||
| 1358 | |||
| 1359 | SEC_SZ_SUBLIST LABEL BYTE | ||
| 1360 | |||
| 1361 | S_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST) | ||
| 1362 | S_RESV DB 0 ;AN000; RESERVED | ||
| 1363 | S_VALUEO DW BPB_SSZ ;AN000; Offset to binary number | ||
| 1364 | S_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER | ||
| 1365 | S_ID DB 1 ;AN000; n of %n | ||
| 1366 | S_FLAG DB Left_Align+Unsgn_Bin_Word | ||
| 1367 | S_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width | ||
| 1368 | S_MINW DB SMALLEST_MIN ;AN000; Minimum field width | ||
| 1369 | S_PAD DB PAD_BLANK ;AN000; Character for Pad field | ||
| 1370 | |||
| 1371 | ; For the message: "Directory entries: %1",CR,LF | ||
| 1372 | |||
| 1373 | DIR_ENT_SUBLIST LABEL BYTE | ||
| 1374 | |||
| 1375 | D_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST) | ||
| 1376 | D_RESV DB 0 ;AN000; RESERVED | ||
| 1377 | D_VALUEO DW BPB_DIRN ;AN000; Offset to binary number | ||
| 1378 | D_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER | ||
| 1379 | D_ID DB 1 ;AN000; n of %n | ||
| 1380 | D_FLAG DB Left_Align+Unsgn_Bin_Word | ||
| 1381 | D_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width | ||
| 1382 | D_MINW DB SMALLEST_MIN ;AN000; Minimum field width | ||
| 1383 | D_PAD DB PAD_BLANK ;AN000; Character for Pad field | ||
| 1384 | |||
| 1385 | ; For the message: "Transfer size: %1",CR,LF | ||
| 1386 | |||
| 1387 | TRANS_SZ_SUBLIST LABEL BYTE | ||
| 1388 | |||
| 1389 | T_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST) | ||
| 1390 | T_RESV DB 0 ;AN000; RESERVED | ||
| 1391 | T_VALUEO DW MAXSEC_TRF ;AN000; Offset to binary number | ||
| 1392 | T_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER | ||
| 1393 | T_ID DB 1 ;AN000; n of %n | ||
| 1394 | T_FLAG DB Left_Align+Unsgn_Bin_Word | ||
| 1395 | T_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width | ||
| 1396 | T_MINW DB SMALLEST_MIN ;AN000; Minimum field width | ||
| 1397 | T_PAD DB PAD_BLANK ;AN000; Character for Pad field | ||
| 1398 | |||
| 1399 | ;-----------------------------------------------------------------------; | ||
| 1400 | ; EMS Support ; | ||
| 1401 | ;-----------------------------------------------------------------------; | ||
| 1402 | |||
| 1403 | FRAME_BUFFER DB 10 DUP(0) ;AN000; | ||
| 1404 | VDISK_Name db "VDISK " ;an000; dms; | ||
| 1405 | |||
| 1406 | four DB 4 | ||
| 1407 | |||
| 1408 | |||
| 1409 | SUBTTL Initialization, Part one | ||
| 1410 | PAGE | ||
| 1411 | ;-----------------------------------------------------------------------; | ||
| 1412 | ; Command Code 0 - Initialization ; | ||
| 1413 | ; At entry, DS:BX point to request header, AX = 0 ; | ||
| 1414 | ;-----------------------------------------------------------------------; | ||
| 1415 | ;Initialization is divided into two parts. | ||
| 1416 | ;This part, executed first, is later overlaid by the VDISK buffer. | ||
| 1417 | |||
| 1418 | INIT_P1 PROC ;first part of initialization | ||
| 1419 | |||
| 1420 | ;;;;; PUSH DS ;ICE | ||
| 1421 | ;;;;; push bx ;ICE | ||
| 1422 | ;;;;; push ax ;ICE | ||
| 1423 | |||
| 1424 | ;;;;; mov bx,0140H ;ICE | ||
| 1425 | ;;;;; xor ax,ax ;ICE | ||
| 1426 | ;;;;; mov ds,ax ;ICE | ||
| 1427 | ;;;;; mov ax,word ptr ds:[bx] ;ICE | ||
| 1428 | ;;;;; mov word ptr ds:[bx],ax ;ICE | ||
| 1429 | |||
| 1430 | ;;;;; pop ax ;ICE | ||
| 1431 | ;;;;; pop bx ;ICE | ||
| 1432 | ;;;;; POP DS ;ICE | ||
| 1433 | |||
| 1434 | MOV DX,SS ;save stack segment register | ||
| 1435 | MOV CX,SP ;save stack pointer register | ||
| 1436 | CLI ;inhibit interrupts while changing SS:SP | ||
| 1437 | MOV AX,CS ;move CS to SS through AX | ||
| 1438 | MOV SS,AX | ||
| 1439 | MOV SP,OFFSET MSGEND ;end of VDISKMSG | ||
| 1440 | ADD SP,STACK_SIZE ;+ length of our stack | ||
| 1441 | |||
| 1442 | STI ;allow interrupts | ||
| 1443 | |||
| 1444 | PUSH DX ;save old SS register on new stack | ||
| 1445 | PUSH CX ;SAVE OLD SP REGISTER ON NEW STACK | ||
| 1446 | |||
| 1447 | |||
| 1448 | |||
| 1449 | PUSH DS ;AN000;SAVE REGS | ||
| 1450 | PUSH ES ;AN000; | ||
| 1451 | |||
| 1452 | PUSH CS ;AN000;TRANSFER TO DS | ||
| 1453 | POP DS ;AN000; | ||
| 1454 | PUSH CS ;AN000; | ||
| 1455 | POP ES ;AN000; | ||
| 1456 | |||
| 1457 | ASSUME DS:CSEG,ES:CSEG ;AN000; | ||
| 1458 | |||
| 1459 | CALL SYSLOADMSG ;AN000; LOAD messages and do DOS version check | ||
| 1460 | JNC VDISK_CONTINUE_1 ;AN000; Did we load OK? | ||
| 1461 | or cs:err_flag2,err_baddos | ||
| 1462 | |||
| 1463 | push ds ;an006; dms;save ds | ||
| 1464 | push bx ;an006; dms;save bx | ||
| 1465 | lds bx,cs:RH_Ptra ;an006; dms;point to request header | ||
| 1466 | mov RH.RH0_Flag,-1 ;an006; dms;signal BIO and error occurred | ||
| 1467 | pop bx ;an006; dms;restore bx | ||
| 1468 | pop ds ;an006; dms;restore ds | ||
| 1469 | |||
| 1470 | MOV AX,VDISK_NOT_INST ;AN000;VDISK UNABLE TO BE INSTALLED | ||
| 1471 | MOV BX,NO_HANDLE ;AN000;NO DISPLAY HANDLE | ||
| 1472 | CALL SYSDISPMSG ;AN000;DISPLAY THE MESSAGE | ||
| 1473 | MOV AX,INCORRECT_DOS ;AN000;BAD DOS VERSION | ||
| 1474 | MOV BX,NO_HANDLE ;AN000;NO DISPLAY HANDLE | ||
| 1475 | CALL SYSDISPMSG ;AN000;DISPLAY THE MESSAGE | ||
| 1476 | |||
| 1477 | VDISK_CONTINUE_1: ;AN000; | ||
| 1478 | |||
| 1479 | POP ES ;AN000;RESTORE REGS | ||
| 1480 | POP DS ;AN000; | ||
| 1481 | ASSUME DS:NOTHING,ES:NOTHING ;AN000; | ||
| 1482 | |||
| 1483 | CALL PC_386_CHK ;AN000;SEE IF WE HAVE A 386 PC | ||
| 1484 | ; Yes, continue | ||
| 1485 | CALL GET_PARMS ;get parameters from CONFIG.SYS line | ||
| 1486 | |||
| 1487 | PUSH CS | ||
| 1488 | POP DS ;set DS = CS | ||
| 1489 | ASSUME DS:CSEG,ES:CSEG | ||
| 1490 | |||
| 1491 | CALL APPLY_DEFAULTS ;supply any values not specified | ||
| 1492 | CALL DETERMINE_START ;compute start address of VDISK buffer | ||
| 1493 | CALL VALIDATE ;validate parameters | ||
| 1494 | CALL COPY_BPB ;Copy BIOS Parameter Block to boot record | ||
| 1495 | |||
| 1496 | CALL VERIFY_EXTENDER ;Verify that extender card switches are right | ||
| 1497 | |||
| 1498 | TEST ERR_FLAG,ERR_EXTSW ;are switches wrong? | ||
| 1499 | JNZ INIT_P1_A ;if so, exit with messages | ||
| 1500 | |||
| 1501 | test cs:err_flag2,err_baddos | ||
| 1502 | jnz init_p1_a | ||
| 1503 | |||
| 1504 | CMP EM_SW,0 ;EXTENDED MEMORY REQUEST? | ||
| 1505 | JE INIT_P1_A ;jump if not | ||
| 1506 | |||
| 1507 | TEST ERR_FLAG,ERR_SYSSZ ;is system too small for VDISK? | ||
| 1508 | JNZ INIT_P1_A ;if so, don't do extended memory init | ||
| 1509 | |||
| 1510 | CALL UPDATE_AVAIL ;update AVAIL_HI and AVAIL_LO to reflect | ||
| 1511 | ;addition of extended memory VDISK | ||
| 1512 | CALL FORMAT_VDISK ;construct a boot record, FATs and | ||
| 1513 | ;directory in storage immediately | ||
| 1514 | ;following this device driver | ||
| 1515 | CALL MOVE_VDISK ;move formatted boot record, FATs, | ||
| 1516 | ;and directory to extended memory | ||
| 1517 | |||
| 1518 | INIT_P1_A: | ||
| 1519 | CALL FILL_RH ;fill in INIT request header | ||
| 1520 | CALL WRITE_MESSAGES ;display all messages | ||
| 1521 | POP CX ;get old SP from stack | ||
| 1522 | POP DX ;get old SS from stack | ||
| 1523 | CLI ;disable interrupts while changing SS:SP | ||
| 1524 | MOV SS,DX ;restore stack segment register | ||
| 1525 | MOV SP,CX ;restore stack pointer register | ||
| 1526 | STI ;enable interrupts | ||
| 1527 | ;-----------------------------------------------------------------------; | ||
| 1528 | ; INIT_P2 must be short enough to fit into the boot sector ; | ||
| 1529 | ; (minimum size of boot sector is 128 bytes), so we set up ; | ||
| 1530 | ; as many pointers as we can to help keep INIT_P2 short. ; | ||
| 1531 | ; ; | ||
| 1532 | ; ES:DI = storage address of first FAT sector ; | ||
| 1533 | ; BL = media control byte ; | ||
| 1534 | ; CX = number of FAT copies ; | ||
| 1535 | ; DX = number of bytes in one FAT, less 3 ; | ||
| 1536 | ; SI = offset of VOL label field ; | ||
| 1537 | ;-----------------------------------------------------------------------; | ||
| 1538 | MOV ES,START_BUFFER_PARA ;start paragraph of VDISK buffer | ||
| 1539 | |||
| 1540 | MOV AX,BPB_RES ;number of reserved sectors | ||
| 1541 | MUL BPB_SSZ ;* sector size | ||
| 1542 | MOV DI,AX ;ES:DI point to FAT start | ||
| 1543 | |||
| 1544 | MOV BL,BPB_MCB ;media control byte | ||
| 1545 | |||
| 1546 | MOV CL,BPB_FATN ;number of FAT copies | ||
| 1547 | XOR CH,CH | ||
| 1548 | |||
| 1549 | MOV AX,BPB_FATSZ ;FAT size in sectors | ||
| 1550 | MUL BPB_SSZ ;* sector size = total FAT bytes | ||
| 1551 | |||
| 1552 | SUB AX,3 ;-3 (FEFFFF stored by code) | ||
| 1553 | MOV DX,AX | ||
| 1554 | |||
| 1555 | MOV SI,OFFSET VOL_LABEL ;point to VOL label directory entry | ||
| 1556 | JMP INIT_P2 ;jump to second part of initialization | ||
| 1557 | ;this is redundant if the VDISK is in | ||
| 1558 | ;extended memory, but is executed anyway | ||
| 1559 | |||
| 1560 | |||
| 1561 | |||
| 1562 | SUBTTL PC_386_CHK | ||
| 1563 | PAGE | ||
| 1564 | ;========================================================================= | ||
| 1565 | ; PC_386_CHK : QUERIES THE BIOS TO DETERMINE WHAT TYPE OF | ||
| 1566 | ; MACHINE WE ARE ON. WE ARE LOOKING FOR A 386. | ||
| 1567 | ; THIS WILL BE USED TO DETERMINE IF A DW MOVE | ||
| 1568 | ; IS TO BE PERFORMED. | ||
| 1569 | ; | ||
| 1570 | ; INPUTS : NONE | ||
| 1571 | ; | ||
| 1572 | ; OUTPUTS : PC_386 - FLAG SIGNALS IF WE ARE ON A 386 MACHINE. | ||
| 1573 | ;========================================================================= | ||
| 1574 | |||
| 1575 | PC_386_CHK PROC NEAR ;AN000;DETERMINE MACHINE TYPE | ||
| 1576 | |||
| 1577 | PUSH AX ;AN000;SAVE AFFECTED REGS | ||
| 1578 | PUSH BX ;AN000; | ||
| 1579 | PUSH ES ;AN000; | ||
| 1580 | |||
| 1581 | MOV CS:PC_386,FALSE ;AN000;INITIALIZE TO FALSE | ||
| 1582 | |||
| 1583 | MOV AH,0C0H ;AN000;RETURN SYSTEM CONFIGURATION | ||
| 1584 | INT 15H ;AN000; | ||
| 1585 | |||
| 1586 | ; $IF NC ;AN000;IF A GOOD RETURN | ||
| 1587 | JC $$IF13 | ||
| 1588 | CMP AH,0 ;AN000;IS IT NEW FORMAT FOR CONFIG. | ||
| 1589 | ; $IF E ;AN000;YES | ||
| 1590 | JNE $$IF14 | ||
| 1591 | MOV AL,ES:[BX.BIOS_SD_MODELBYTE] ;AN000;CHECK MODEL | ||
| 1592 | CMP AL,0F8H ;AN000;IS IT A 386 MACHINE? | ||
| 1593 | ; $IF E ;AN000;YES | ||
| 1594 | JNE $$IF15 | ||
| 1595 | MOV CS:PC_386,TRUE ;AN000;SIGNAL A 386 | ||
| 1596 | ; $ENDIF ;AN000; | ||
| 1597 | $$IF15: | ||
| 1598 | ; $ENDIF ;AN000; | ||
| 1599 | $$IF14: | ||
| 1600 | ; $ENDIF ;AN000; | ||
| 1601 | $$IF13: | ||
| 1602 | |||
| 1603 | POP ES ;AN000;RESTORE REGS. | ||
| 1604 | POP BX ;AN000; | ||
| 1605 | POP AX ;AN000; | ||
| 1606 | |||
| 1607 | RET ;AN000; | ||
| 1608 | |||
| 1609 | PC_386_CHK ENDP ;AN000; | ||
| 1610 | |||
| 1611 | |||
| 1612 | SUBTTL GET_PARMS Parameter Line Scan | ||
| 1613 | PAGE | ||
| 1614 | ;-----------------------------------------------------------------------; | ||
| 1615 | ;GET_PARMS gets the parameters from the CONFIG.SYS statement ; | ||
| 1616 | ; ; | ||
| 1617 | ;Register usage: ; | ||
| 1618 | ; DS:SI indexes parameter string ; | ||
| 1619 | ; AL contains character from parameter string ; | ||
| 1620 | ; CX value from GET_NUMBER ; | ||
| 1621 | ;-----------------------------------------------------------------------; | ||
| 1622 | ASSUME DS:NOTHING ;DS:BX point to Request Header | ||
| 1623 | GET_PARMS PROC ;get parameters from CONFIG.SYS line | ||
| 1624 | PUSH DS ;save DS | ||
| 1625 | LDS SI,RH.RH0_BPBA ;DS:SI point to all after DEVICE= | ||
| 1626 | ;in CONFIG.SYS line | ||
| 1627 | XOR AL,AL ;not at end of line | ||
| 1628 | |||
| 1629 | ;Skip until first delimiter is found. There may be digits in the path string. | ||
| 1630 | |||
| 1631 | ;DS:SI points to \pathstring\VDISK.SYS nn nn nn | ||
| 1632 | ;The character following VDISK.SYS may have been changed to a null (00H). | ||
| 1633 | ;All letters have been changed to uppercase. | ||
| 1634 | |||
| 1635 | GET_PARMS_A: ;skip to DOS delimiter character | ||
| 1636 | CALL GET_PCHAR ;get parameter character into AL | ||
| 1637 | JZ Get_Parms_X_Exit ;get out if end of line encountered | ||
| 1638 | OR AL,AL ;test for null | ||
| 1639 | JZ GET_PARMS_C ; | ||
| 1640 | CMP AL,' ' | ||
| 1641 | JE GET_PARMS_C ; | ||
| 1642 | CMP AL,',' | ||
| 1643 | JE GET_PARMS_C ; | ||
| 1644 | CMP AL,';' | ||
| 1645 | JE GET_PARMS_C ; | ||
| 1646 | CMP AL,'+' | ||
| 1647 | JE GET_PARMS_C ; | ||
| 1648 | CMP AL,'=' | ||
| 1649 | JE GET_PARMS_C ; | ||
| 1650 | CMP AL,TAB | ||
| 1651 | JNE GET_PARMS_A ;skip until delimiter or CR | ||
| 1652 | |||
| 1653 | |||
| 1654 | |||
| 1655 | GET_PARMS_C: | ||
| 1656 | PUSH SI ;save to rescan | ||
| 1657 | MOV CS:EM_SW,0 ;INDICATE NO /E FOUND | ||
| 1658 | JMP GET_SLASH ;see if current character is an slash | ||
| 1659 | |||
| 1660 | GET_PARMS_D: ;scan for / | ||
| 1661 | CALL GET_PCHAR | ||
| 1662 | JZ GET_PARMS_B ;exit if end of line | ||
| 1663 | |||
| 1664 | GET_SLASH: ;check for slash | ||
| 1665 | CMP AL,'/' ;found slash? | ||
| 1666 | JNE GET_PARMS_D ;no, continue scan | ||
| 1667 | |||
| 1668 | CALL GET_PCHAR ;get char following slash | ||
| 1669 | CMP AL,'E' ;don't have to test for lower case E, | ||
| 1670 | ;letters have been changed to upper case | ||
| 1671 | JNE CHECK_FOR_X ;not 'E' ;AN005; | ||
| 1672 | CMP CS:EM_SW,'X' ;Was /X already defined? ;AN005; | ||
| 1673 | JE GET_PARMS_E ;indicate invalid switch ;AN005; | ||
| 1674 | MOV CS:EM_SW,AL ;indicate /E found ;AN005; | ||
| 1675 | JMP SHORT GOT_E_OR_X ;AN005; | ||
| 1676 | ;AN005; | ||
| 1677 | CHECK_FOR_X: ;AN005; | ||
| 1678 | CMP AL,'X' ;don't have to test for lower case X, ;AN005; | ||
| 1679 | ;letters have been changed to upper case ;AN005; | ||
| 1680 | JNE GET_PARMS_E ;not 'X' ;AN005; | ||
| 1681 | CMP CS:EM_SW,'E' ;Was /E already defined? ;AN005; | ||
| 1682 | JE GET_PARMS_E ;indicate invalid switch ;AN005; | ||
| 1683 | MOV CS:EM_SW,'X' ;indicate /X found ;AN005; | ||
| 1684 | ;AN005; | ||
| 1685 | GOT_E_OR_X: ;AN005; | ||
| 1686 | CALL GET_PCHAR ;get char following E or X ;AN005; | ||
| 1687 | CMP AL,':' ;is it a delimeter ? | ||
| 1688 | JNE GET_PARMS_D ;not a ':' | ||
| 1689 | |||
| 1690 | |||
| 1691 | CALL GET_MAXSIZE ;get maximum sector size | ||
| 1692 | |||
| 1693 | |||
| 1694 | JMP GET_PARMS_D ;continue forward scan | ||
| 1695 | |||
| 1696 | GET_PARMS_E: ;/ found, not 'E' | ||
| 1697 | OR CS:ERR_FLAG,ERR_SWTCH ;indicate invalid switch character | ||
| 1698 | JMP GET_PARMS_D ;continue scan | ||
| 1699 | |||
| 1700 | |||
| 1701 | |||
| 1702 | GET_PARMS_B: ;now pointing to first delimiter | ||
| 1703 | POP SI ;get pointer, used to rescan for /E | ||
| 1704 | XOR AL,AL ;not at EOL now | ||
| 1705 | CALL GET_PCHAR ;get first character | ||
| 1706 | CALL SKIP_TO_DIGIT ;skip to first digit | ||
| 1707 | |||
| 1708 | Get_Parms_X_Exit: | ||
| 1709 | |||
| 1710 | JZ GET_PARMS_X ;found EOL, no digits remain | ||
| 1711 | |||
| 1712 | CALL GET_NUMBER ;extract digits, convert to binary | ||
| 1713 | MOV CS:BUFF_SIZE,CX ;store buffer size | ||
| 1714 | |||
| 1715 | CALL SKIP_TO_DIGIT ;skip to next digit | ||
| 1716 | JZ GET_PARMS_X ;found EOL, no digits remain | ||
| 1717 | |||
| 1718 | CALL GET_NUMBER ;extract digits, convert to binary | ||
| 1719 | MOV CS:BPB_SSZ,CX ;store sector size | ||
| 1720 | |||
| 1721 | CALL SKIP_TO_DIGIT ;skip to next digit | ||
| 1722 | JZ GET_PARMS_X ;found EOL, no digits remain | ||
| 1723 | |||
| 1724 | CALL GET_NUMBER ;extract digits, convert to binary | ||
| 1725 | MOV CS:BPB_DIRN,CX ;store number of directory entries | ||
| 1726 | |||
| 1727 | |||
| 1728 | |||
| 1729 | GET_PARMS_X: ;premature end of line | ||
| 1730 | TEST cs:ERR_FLAG,ERR_SWTCH ;was an invalid switch character found? | ||
| 1731 | ; $if nz ;yes - set flag to regular VDISK ;an000; dms; | ||
| 1732 | JZ $$IF19 | ||
| 1733 | ; this is consistent with DOS 3.3 | ||
| 1734 | mov cs:EM_SW,0 ;set flag to regular VDISK ;an000; dms; | ||
| 1735 | ; $endif ; ;an000; dms; | ||
| 1736 | $$IF19: | ||
| 1737 | POP DS ;restore DS | ||
| 1738 | RET | ||
| 1739 | |||
| 1740 | |||
| 1741 | GET_MAXSIZE PROC ;get maximum sector size | ||
| 1742 | |||
| 1743 | CALL GET_PCHAR ;get next character | ||
| 1744 | CALL CHECK_NUM ;is it a number ? | ||
| 1745 | JZ GET_NEXTNUM ;yes, go get next number | ||
| 1746 | OR CS:ERR_FLAG,ERR_ESIZE ;indicate invalid sector size | ||
| 1747 | RET ; | ||
| 1748 | GET_NEXTNUM: ;get next number | ||
| 1749 | CALL GET_NUMBER ;extract digits and convert to binary | ||
| 1750 | MOV CS:MAXSEC_TRF,CX ;save maximum sector size to transfer | ||
| 1751 | RET | ||
| 1752 | GET_MAXSIZE ENDP | ||
| 1753 | |||
| 1754 | |||
| 1755 | |||
| 1756 | GET_PCHAR PROC ;internal proc to get next character into AL | ||
| 1757 | CMP AL,CR ;carriage return already encountered? | ||
| 1758 | JE GET_PCHAR_X ;don't read past end of line | ||
| 1759 | CMP AL,LF ;line feed already encountered? | ||
| 1760 | JE GET_PCHAR_X ;don't read past end of line | ||
| 1761 | LODSB ;get char from DS:SI, increment SI | ||
| 1762 | CMP AL,CR ;is the char a carriage return? | ||
| 1763 | JE GET_PCHAR_X ;yes, set Z flag at end of line | ||
| 1764 | CMP AL,LF ;no, is it a line feed? | ||
| 1765 | GET_PCHAR_X: ;attempted read past end of line | ||
| 1766 | RET | ||
| 1767 | GET_PCHAR ENDP ;returns char in AL | ||
| 1768 | |||
| 1769 | |||
| 1770 | CHECK_NUM PROC ;check AL for ASCII digit | ||
| 1771 | CMP AL,'0' ;< '0'? | ||
| 1772 | JB CHECK_NUM_X ;exit if it is | ||
| 1773 | |||
| 1774 | CMP AL,'9' ;> '9'? | ||
| 1775 | JA CHECK_NUM_X ;exit if it is | ||
| 1776 | |||
| 1777 | CMP AL,AL ;set Z flag to indicate numeric | ||
| 1778 | CHECK_NUM_X: | ||
| 1779 | RET ;Z set if numeric, NZ if not numeric | ||
| 1780 | CHECK_NUM ENDP | ||
| 1781 | |||
| 1782 | |||
| 1783 | SKIP_TO_DIGIT PROC ;skip to first numeric character | ||
| 1784 | CALL CHECK_NUM ;is current char a digit? | ||
| 1785 | JZ SKIP_TO_DIGIT_X ;if so, skip is complete | ||
| 1786 | |||
| 1787 | CALL GET_PCHAR ;get next character from line | ||
| 1788 | JNZ SKIP_TO_DIGIT ;loop until first digit or CR or LF | ||
| 1789 | RET ;character is CR or LF | ||
| 1790 | |||
| 1791 | SKIP_TO_DIGIT_X: | ||
| 1792 | CMP AL,0 ;digit found, force NZ | ||
| 1793 | RET | ||
| 1794 | SKIP_TO_DIGIT ENDP | ||
| 1795 | |||
| 1796 | C10 DW 10 | ||
| 1797 | GN_ERR DB ? ;zero if no overflow in accumulation | ||
| 1798 | |||
| 1799 | GET_NUMBER PROC ;convert string of digits to binary value | ||
| 1800 | XOR CX,CX ;accumulate number in CX | ||
| 1801 | MOV CS:GN_ERR,CL ;no overflow yet | ||
| 1802 | GET_NUMBER_A: ;accumulate next digit | ||
| 1803 | SUB AL,'0' ;convert ASCII to binary | ||
| 1804 | CBW ;clear AH | ||
| 1805 | XCHG AX,CX ;previous accumulation in AX, new digit in CL | ||
| 1806 | MUL CS:C10 ;DX:AX := AX*10 | ||
| 1807 | OR CS:GN_ERR,DL ;set GN_ERR <> 0 if overflow | ||
| 1808 | ADD AX,CX ;add new digit from | ||
| 1809 | XCHG AX,CX ;number now in CX | ||
| 1810 | DEC SI ;back up to prior entry | ||
| 1811 | MOV AL,' ' ;blank out prior entry | ||
| 1812 | MOV [SI],AL ; | ||
| 1813 | INC SI ;set to current entry | ||
| 1814 | CALL GET_PCHAR ;get next character | ||
| 1815 | CALL CHECK_NUM ;see if it was numeric | ||
| 1816 | JZ GET_NUMBER_A ;continue accumulating | ||
| 1817 | CMP CS:GN_ERR,0 ;did we overflow? | ||
| 1818 | JE GET_NUMBER_B ;if not, we're done | ||
| 1819 | XOR CX,CX ;return zero (always invalid) if overflow | ||
| 1820 | GET_NUMBER_B: | ||
| 1821 | RET ;number in CX, next char in AL | ||
| 1822 | GET_NUMBER ENDP | ||
| 1823 | |||
| 1824 | GET_PARMS ENDP | ||
| 1825 | |||
| 1826 | SUBTTL APPLY_DEFAULTS | ||
| 1827 | PAGE | ||
| 1828 | ;-----------------------------------------------------------------------; | ||
| 1829 | ; APPLY_DEFAULTS supplies any parameter values that the user ; | ||
| 1830 | ; failed to specify ; | ||
| 1831 | ;-----------------------------------------------------------------------; | ||
| 1832 | ASSUME DS:CSEG | ||
| 1833 | APPLY_DEFAULTS PROC | ||
| 1834 | XOR AX,AX | ||
| 1835 | CMP BUFF_SIZE,AX ;is buffer size zero? | ||
| 1836 | JNE APPLY_DEFAULTS_A ;no, user specified something | ||
| 1837 | |||
| 1838 | MOV BUFF_SIZE,DFLT_BSIZE ;supply default buffer size | ||
| 1839 | OR ERR_FLAG,ERR_BSIZE ;indicate buffersize adjusted | ||
| 1840 | |||
| 1841 | APPLY_DEFAULTS_A: | ||
| 1842 | CMP BPB_SSZ,AX ;is sector size zero? | ||
| 1843 | JNE APPLY_DEFAULTS_B ;no, user specified something | ||
| 1844 | |||
| 1845 | MOV BPB_SSZ,DFLT_SSZ ;supply default sector size | ||
| 1846 | OR ERR_FLAG,ERR_SSZ ;indicate sector size adjusted | ||
| 1847 | |||
| 1848 | APPLY_DEFAULTS_B: | ||
| 1849 | CMP BPB_DIRN,AX ;are directory entries zero? | ||
| 1850 | JNE APPLY_DEFAULTS_C ;no, user specified something | ||
| 1851 | |||
| 1852 | MOV BPB_DIRN,DFLT_DIRN ;supply default directory entries | ||
| 1853 | OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted | ||
| 1854 | |||
| 1855 | APPLY_DEFAULTS_C: ; | ||
| 1856 | CMP EM_SW,0 ;EXTENDED MEMORY | ||
| 1857 | JE APPLY_DEFAULTS_D ;no, jump around | ||
| 1858 | CMP MAXSEC_TRF,AX ;is maximum sectors zero? | ||
| 1859 | JNE APPLY_DEFAULTS_D ;no, user specified something | ||
| 1860 | |||
| 1861 | MOV MAXSEC_TRF,DFLT_ESS ;supply default maximum number of | ||
| 1862 | ;sector to transfer | ||
| 1863 | OR ERR_FLAG,ERR_ESIZE ;indicate transfer size adjusted | ||
| 1864 | APPLY_DEFAULTS_D: | ||
| 1865 | RET | ||
| 1866 | APPLY_DEFAULTS ENDP | ||
| 1867 | |||
| 1868 | SUBTTL DETERMINE_START address of VDISK buffer | ||
| 1869 | PAGE | ||
| 1870 | ;-----------------------------------------------------------------------; | ||
| 1871 | ; DETERMINE_START figures out the starting address of the VDISK ; | ||
| 1872 | ; buffer ; | ||
| 1873 | ;-----------------------------------------------------------------------; | ||
| 1874 | ASSUME DS:CSEG | ||
| 1875 | DETERMINE_START PROC | ||
| 1876 | |||
| 1877 | ;If extended memory is NOT being used, the VDISK buffer immediately | ||
| 1878 | ;follows the resident code. | ||
| 1879 | |||
| 1880 | ;If extended memory IS being used, START_BUFFER_PARA becomes the | ||
| 1881 | ;end of device driver address passed back to DOS. | ||
| 1882 | |||
| 1883 | MOV AX,CS ;start para of VDISK code | ||
| 1884 | ADD AX,VDISKP ;+ length of resident code | ||
| 1885 | MOV START_BUFFER_PARA,AX ;save as buffer start para | ||
| 1886 | |||
| 1887 | CMP EM_SW,0 ;IS EXTENDED MEMORY REQUESTED? | ||
| 1888 | JE DETERMINE_START_X ;if not, we're done here | ||
| 1889 | |||
| 1890 | ;-----------------------------------------------------------------------;AN000; | ||
| 1891 | ;If EMS is not installed, the calculation to determine the starting address | ||
| 1892 | ;of the VDISK will remain the same. | ||
| 1893 | |||
| 1894 | ;If EMS is installed we really don't need this calculation, the EMM will | ||
| 1895 | ;manage the expanded memory insuring mutiple VDISKs may reside concurrently. | ||
| 1896 | ;-----------------------------------------------------------------------;AN000; | ||
| 1897 | |||
| 1898 | cmp EM_SW,EMS_Mem ;EMS requested? ;an005; dms; | ||
| 1899 | je Determine_Start_X ;yes - leave routine ;an005; dms; | ||
| 1900 | ;no - continue routine | ||
| 1901 | |||
| 1902 | clc ;an001; dms;clear carry for INT | ||
| 1903 | MOV AX,EM_MEMSIZE ;an001; dms; get EM memory size | ||
| 1904 | INT EM_INT ;an001; dms; INT 15h | ||
| 1905 | JC Determine_Start_X ;an001; dms; no extended memory installed | ||
| 1906 | or ax,ax ;an001; dms;see if memory returned | ||
| 1907 | jz Determine_Start_X ;an001; dms;signal no memory | ||
| 1908 | |||
| 1909 | xor dx,dx ;an001; dms;clear dx | ||
| 1910 | sub ax,cs:Buff_Size ;an001; dms;get starting KB location | ||
| 1911 | jc Determine_Start_X ;an001; dms;buffer too large | ||
| 1912 | |||
| 1913 | mov cs:EM_New_Size,ax ;an001; dms;save new size of EM for later use | ||
| 1914 | mul C1024 ;an001; dms;get total byte count | ||
| 1915 | add ax,cs:Avail_Lo ;an001; dms;add in low word of EM start | ||
| 1916 | adc dl,cs:Avail_Hi ;an001; dms;add in high word of EM start | ||
| 1917 | |||
| 1918 | mov cs:Avail_Lo,ax ;an001; dms;save new low beginning word | ||
| 1919 | mov cs:Avail_Hi,dl ;an001; dms;save new high beginning word | ||
| 1920 | |||
| 1921 | mov cs:Start_EM_Lo,ax ;an001; dms;load in new beginning word | ||
| 1922 | mov cs:Start_EM_Hi,dl ;an001; dms;load in new beginning byte | ||
| 1923 | |||
| 1924 | DETERMINE_START_X: | ||
| 1925 | |||
| 1926 | RET | ||
| 1927 | DETERMINE_START ENDP | ||
| 1928 | |||
| 1929 | SUBTTL VALIDATE parameters | ||
| 1930 | PAGE | ||
| 1931 | ;-----------------------------------------------------------------------; | ||
| 1932 | ; VALIDATE adjusts parameters as necessary ; | ||
| 1933 | ;-----------------------------------------------------------------------; | ||
| 1934 | VAL_SSZ_TBL LABEL WORD ;table of valid sector sizes | ||
| 1935 | VAL_SSZ_S DW 128 ;smallest valid sector size | ||
| 1936 | DW 256 | ||
| 1937 | VAL_SSZ_L DW 512 ;largest valid sector size | ||
| 1938 | VAL_SSZ_N EQU ($-VAL_SSZ_TBL)/2 ;number of table entries | ||
| 1939 | |||
| 1940 | ASSUME DS:CSEG | ||
| 1941 | VALIDATE PROC ;validate parameters | ||
| 1942 | ;;ice PUSH DS ;ICE | ||
| 1943 | ;;ice push bx ;ICE | ||
| 1944 | ;;ice push ax ;ICE | ||
| 1945 | |||
| 1946 | ;;ice mov bx,0140H ;ICE | ||
| 1947 | ;;ice xor ax,ax ;ICE | ||
| 1948 | ;;ice mov ds,ax ;ICE | ||
| 1949 | ;;ice mov ax,word ptr ds:[bx] ;ICE | ||
| 1950 | ;;ice mov word ptr ds:[bx],ax ;ICE | ||
| 1951 | |||
| 1952 | ;;ice pop ax ;ICE | ||
| 1953 | ;;ice pop bx ;ICE | ||
| 1954 | ;;ice POP DS ;ICE | ||
| 1955 | MOV BPB_AUSZ,1 ;initial allocation unit is 1 sector | ||
| 1956 | |||
| 1957 | CALL VAL_BSIZE ;validate buffer size | ||
| 1958 | |||
| 1959 | CALL VAL_SSZ ;validate (adjust if necessary) BPB_SSZ | ||
| 1960 | |||
| 1961 | VALIDATE_A: | ||
| 1962 | AND ERR_FLAG,255-ERR_PASS ;indicate nothing changed this pass | ||
| 1963 | |||
| 1964 | MOV AX,BPB_SSZ ;sector size | ||
| 1965 | CWD ;clear DX for division | ||
| 1966 | DIV WPARA_SIZE ;sector size/para size | ||
| 1967 | MOV PARAS_PER_SECTOR,AX ;number of paragraphs/sector | ||
| 1968 | |||
| 1969 | mov ax,EMS_Page_Size ;an002; dms;EMS page size | ||
| 1970 | xor dx,dx ;an002; dms;clear high word | ||
| 1971 | div BPB_SSZ ;an002; dms;get sectors/page | ||
| 1972 | mov Sect_Per_Page,ax ;an002; dms;save sectors/page | ||
| 1973 | |||
| 1974 | ;;;;; MOV AX,BPB_SSZ ;AN000; Sector size | ||
| 1975 | ;;;;; xor dx,dx ;an001; clear high word | ||
| 1976 | ;;;;; DIV DOS_Page_Size_Word ;an001; Sector size/page size | ||
| 1977 | ;;;;; MOV SECT_PER_PAGE,AX ;an001; Number of sectors/page | ||
| 1978 | |||
| 1979 | MOV AX,BUFF_SIZE ;requested buffersize in KB | ||
| 1980 | MUL C1024 ;DX:AX = buffer size in bytes | ||
| 1981 | DIV BPB_SSZ ;/sector size = # sectors | ||
| 1982 | MOV BPB_SECN,AX ;store number of sectors | ||
| 1983 | |||
| 1984 | CALL VAL_DIRN ;validate number of directory entries | ||
| 1985 | |||
| 1986 | TEST ERR_FLAG,ERR_PASS ;may have reset sector size | ||
| 1987 | JNZ VALIDATE_A ;recompute directory & FAT sizes | ||
| 1988 | |||
| 1989 | CALL VAL_FAT ;compute FAT entries, validity test | ||
| 1990 | |||
| 1991 | TEST ERR_FLAG,ERR_PASS ;if cluster size altered this pass | ||
| 1992 | JNZ VALIDATE_A ;recompute directory & FAT sizes | ||
| 1993 | |||
| 1994 | ;Make certain buffer size is large enough to contain: | ||
| 1995 | ; boot sector(s) | ||
| 1996 | ; FAT sector(s) | ||
| 1997 | ; directory sector(s) | ||
| 1998 | ; at least 1 data cluster | ||
| 1999 | |||
| 2000 | MOV AL,BPB_FATN ;number of FAT copies | ||
| 2001 | CBW ;clear AH | ||
| 2002 | MUL BPB_FATSZ ;* sectors for 1 FAT = FAT sectors | ||
| 2003 | ADD AX,BPB_RES ;+ reserved sectors | ||
| 2004 | ADD AX,DIR_SECTORS ;+ directory sectors | ||
| 2005 | MOV CL,BPB_AUSZ ;get sectors/cluster | ||
| 2006 | XOR CH,CH ;CX = sectors in one cluster | ||
| 2007 | ADD AX,CX ;+ one data cluster | ||
| 2008 | CMP BPB_SECN,AX ;compare with sectors available | ||
| 2009 | JAE VALIDATE_X ;jump if enough sectors | ||
| 2010 | |||
| 2011 | CMP DIR_SECTORS,1 ;down to 1 directory sector? | ||
| 2012 | JBE VALIDATE_C ;can't let it go below 1 | ||
| 2013 | |||
| 2014 | MOV AX,BPB_SSZ ;sector size | ||
| 2015 | CWD ;clear DX for division | ||
| 2016 | DIV DIRE_SIZE ;sectorsize/dir entry size = entries/sector | ||
| 2017 | SUB BPB_DIRN,AX ;reduce directory entries by 1 sector | ||
| 2018 | |||
| 2019 | OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted | ||
| 2020 | JMP VALIDATE_A ;retry with new directory entries number | ||
| 2021 | |||
| 2022 | VALIDATE_C: ;not enough space for any VDISK | ||
| 2023 | OR ERR_FLAG,ERR_SYSSZ | ||
| 2024 | VALIDATE_X: | ||
| 2025 | RET | ||
| 2026 | |||
| 2027 | SUBTTL VAL_BSIZE Validate buffer size | ||
| 2028 | PAGE | ||
| 2029 | ;-----------------------------------------------------------------------; | ||
| 2030 | ; VAL_BSIZE adjusts the buffer size as necessary ; | ||
| 2031 | ;-----------------------------------------------------------------------; | ||
| 2032 | VAL_BSIZE PROC | ||
| 2033 | CALL GET_MSIZE ;determine memory available to VDISK | ||
| 2034 | ;returns available KB in AX | ||
| 2035 | OR AX,AX ;is any memory available at all? | ||
| 2036 | JNZ VAL_BSIZE_B ;yes, continue | ||
| 2037 | |||
| 2038 | OR ERR_FLAG,ERR_SYSSZ ;indicate system too small for VDISK | ||
| 2039 | MOV BUFF_SIZE,1 ;set up minimal values to continue init | ||
| 2040 | MOV AX,VAL_SSZ_S ;smallest possible sector size | ||
| 2041 | MOV BPB_SSZ,AX | ||
| 2042 | MOV BPB_DIRN,4 ;4 directory entries | ||
| 2043 | RET | ||
| 2044 | |||
| 2045 | VAL_BSIZE_B: ;some memory is available | ||
| 2046 | CMP AX,BUFF_SIZE ;is available memory >= requested? | ||
| 2047 | JAE VAL_BSIZE_C ;if so, we're done | ||
| 2048 | |||
| 2049 | MOV BUFF_SIZE,AX ;give all available memory | ||
| 2050 | mov cs:EM_New_Size,0 ;an001; dms;save new size of EM for later use | ||
| 2051 | mov ax,cs:Avail_Lo ;an001; dms;get low word of EM start | ||
| 2052 | mov dl,cs:Avail_Hi ;an001; dms;get high byte of EM start | ||
| 2053 | |||
| 2054 | mov cs:Start_EM_Lo,ax ;an001; dms;load in new beginning word | ||
| 2055 | mov cs:Start_EM_Hi,dl ;an001; dms;load in new beginning byte | ||
| 2056 | OR ERR_FLAG,ERR_BSIZE ;indicate buffersize adjusted | ||
| 2057 | VAL_BSIZE_C: | ||
| 2058 | |||
| 2059 | |||
| 2060 | RET | ||
| 2061 | |||
| 2062 | |||
| 2063 | GET_MSIZE PROC ;determine memory available to VDISK | ||
| 2064 | ;returns KB available in AX | ||
| 2065 | CMP EM_SW,0 ;EXTENDED MEMORY? | ||
| 2066 | JE GET_MSIZE_2 ;use non-extended memory routine | ||
| 2067 | |||
| 2068 | cmp EM_SW,EM_Mem ;Extended memory requested? ;an005; dms; | ||
| 2069 | je Use_Extended_Support ;yes ;an005; dms; | ||
| 2070 | ;no - check for EMS availability | ||
| 2071 | |||
| 2072 | |||
| 2073 | CALL EMS_CHECK ;AN000; Check if EMS is installed | ||
| 2074 | JC GET_MSIZE_Z ;AN000; Yes, it is installed but in error | ||
| 2075 | ; then notify caller by setting AX to zero | ||
| 2076 | CMP AH,NOT EMS_INSTALLED_FLAG ;AN000; | ||
| 2077 | JE Get_Msize_Z ;ac005; flag an error occurred | ||
| 2078 | MOV EM_SW2,AH ;AN000; Set EMS flag | ||
| 2079 | CALL EMS_GET_PAGES ;AN000; Get count of total number of pages | ||
| 2080 | xor dx,dx ;an002; clear high word | ||
| 2081 | MUL DOS_Page_Size_Word ;ac002; Number of pages * KB per page | ||
| 2082 | RET ;AN000; Return with AX = number of whole free kilobytes | ||
| 2083 | ; | ||
| 2084 | USE_EXTENDED_SUPPORT: ;AN000; No, EMS is not installed | ||
| 2085 | |||
| 2086 | MOV AX,EM_MEMSIZE ;function code to AH | ||
| 2087 | INT EM_INT ;get extended memory size in AX | ||
| 2088 | JC GET_MSIZE_Z ;if error, no extended memory installed | ||
| 2089 | or ax,ax ;an000; dms;see if memory returned | ||
| 2090 | jz GET_MSIZE_Z ;an000; dms;signal no memory | ||
| 2091 | |||
| 2092 | RET | ||
| 2093 | |||
| 2094 | GET_MSIZE_2: ;non-extended memory size determination | ||
| 2095 | |||
| 2096 | ;Compute AX = total system size, - (VDISK end address + 64KB) | ||
| 2097 | |||
| 2098 | MOV AX,START_BUFFER_PARA ;paragraph end of VDISK code | ||
| 2099 | XOR DX,DX ;clear for division | ||
| 2100 | DIV PARA_PER_KB ;KB address of load point | ||
| 2101 | ADD DX,0FFFFH ;round upward to KB boundary | ||
| 2102 | ADC AX,MIN_MEMORY_LEFT ;pick up CY and the 64KB we should leave | ||
| 2103 | PUSH AX ;save across interrupt | ||
| 2104 | INT MEM_SIZE ;get total system size | ||
| 2105 | POP DX ;amount of total that we can't use | ||
| 2106 | SUB AX,DX ;available space to VDISK | ||
| 2107 | JNC GET_MSIZE_X ;exit if positive | ||
| 2108 | |||
| 2109 | GET_MSIZE_Z: | ||
| 2110 | XOR AX,AX ;indicate no memory available | ||
| 2111 | GET_MSIZE_X: ;exit from memory size determination | ||
| 2112 | RET | ||
| 2113 | GET_MSIZE ENDP | ||
| 2114 | |||
| 2115 | VAL_BSIZE ENDP | ||
| 2116 | |||
| 2117 | |||
| 2118 | |||
| 2119 | EMS_CHECK PROC NEAR ;AN000; | ||
| 2120 | |||
| 2121 | CALL EMS_CHECK1 ;AN000; SEE IF EMS INSTALLED | ||
| 2122 | JNC EMS_INSTALLED ;AN000; No, | ||
| 2123 | MOV AH,NOT EMS_INSTALLED_FLAG ;AN000; Flag EMS not installed | ||
| 2124 | CLC ;AN000; Make sure carry is Clear | ||
| 2125 | JMP SHORT EMS_CHECK_EXIT ;AN000; Leave check routine | ||
| 2126 | |||
| 2127 | EMS_INSTALLED: ;AN000; Yes, | ||
| 2128 | |||
| 2129 | push es ;an000; save es - call destroys it | ||
| 2130 | push di ;an006; save di | ||
| 2131 | |||
| 2132 | mov ah,EMS_2F_Handler ;an006;see if our 2Fh is there | ||
| 2133 | xor al,al ;an006; | ||
| 2134 | int 2Fh ;an006; | ||
| 2135 | cmp al,0ffh ;an006;2Fh handler there? | ||
| 2136 | ; $if e ;an006;yes | ||
| 2137 | JNE $$IF21 | ||
| 2138 | mov ah,EMS_2F_Handler ;an006;get EMS page for VDISK | ||
| 2139 | mov al,0FFh ;an006; | ||
| 2140 | mov di,0FEh ;an006; | ||
| 2141 | int 2Fh ;ac006; | ||
| 2142 | |||
| 2143 | or ah,ah ;an006;page available? | ||
| 2144 | ; $if z ;an006;yes | ||
| 2145 | JNZ $$IF22 | ||
| 2146 | mov cs:EMS_Frame_Addr,es ;an006;save segment value | ||
| 2147 | mov cs:DOS_Page,di ;an006;save physical page # | ||
| 2148 | clc ;an006;flag memory available | ||
| 2149 | mov ah,EMS_INSTALLED_FLAG ;an000;signal EMS here | ||
| 2150 | ; $else ;an006;no memory avail. | ||
| 2151 | JMP SHORT $$EN22 | ||
| 2152 | $$IF22: | ||
| 2153 | mov ah,not EMS_INSTALLED_FLAG ;an000;signal no EMS | ||
| 2154 | stc ;an006;flag it | ||
| 2155 | ; $endif ;an006; | ||
| 2156 | $$EN22: | ||
| 2157 | ; $else | ||
| 2158 | JMP SHORT $$EN21 | ||
| 2159 | $$IF21: | ||
| 2160 | mov ah,not EMS_INSTALLED_FLAG ;AN000;signal no EMS | ||
| 2161 | stc ;an006;signal not there | ||
| 2162 | ; $endif | ||
| 2163 | $$EN21: | ||
| 2164 | |||
| 2165 | pop di ;an006;restore di | ||
| 2166 | pop es ;an000;restore es | ||
| 2167 | |||
| 2168 | EMS_Check_Exit: | ||
| 2169 | |||
| 2170 | RET ;AN000; Return | ||
| 2171 | |||
| 2172 | EMS_CHECK ENDP ;AN000; | ||
| 2173 | |||
| 2174 | |||
| 2175 | |||
| 2176 | ;========================================================================= | ||
| 2177 | ; EMS_CHECK1 : THIS MODULE DETERMINES WHETHER OR NOT EMS IS | ||
| 2178 | ; INSTALLED FOR THIS SESSION. | ||
| 2179 | ; | ||
| 2180 | ; INPUTS : NONE | ||
| 2181 | ; | ||
| 2182 | ; OUTPUTS : ES:BX - FRAME ARRAY | ||
| 2183 | ; CY - EMS NOT AVAILABLE | ||
| 2184 | ; NC - EMS AVAILABLE | ||
| 2185 | ;========================================================================= | ||
| 2186 | |||
| 2187 | EMS_CHECK1 PROC NEAR ;AN000;EMS INSTALL CHECK | ||
| 2188 | |||
| 2189 | push ds ;an000;save ds - we stomp it | ||
| 2190 | mov ax,00h ;an000;set ax to 0 | ||
| 2191 | mov ds,ax ;an000;set ds to 0 | ||
| 2192 | cmp ds:word ptr[067h*4+0],0 ;an000;see if int 67h is there | ||
| 2193 | pop ds ;an000;restore ds | ||
| 2194 | ; $IF NE ;AN000;EMS VECTOR CONTAINS DATA | ||
| 2195 | JE $$IF27 | ||
| 2196 | MOV AH,EMS_STATUS ;AN000;see if EMS installed | ||
| 2197 | XOR AL,AL ;AN000;CLEAR AL | ||
| 2198 | INT EMS_INT ;AN000; | ||
| 2199 | OR AH,AH ;AN000;EMS INSTALLED? | ||
| 2200 | ; $IF Z ;AN000;YES | ||
| 2201 | JNZ $$IF28 | ||
| 2202 | MOV AH,EMS_VERSION ;AN000;GET VERSION NUMBER | ||
| 2203 | XOR AL,AL ;AN000;CLEAR AL | ||
| 2204 | INT EMS_INT ;AN000; | ||
| 2205 | CMP AL,EMS_VERSION_LEVEL ;AN000;CORRECT VERSION? | ||
| 2206 | ; $IF AE ;AN000;YES | ||
| 2207 | JNAE $$IF29 | ||
| 2208 | CLC ;AN000;FLAG IT AS GOOD EMS | ||
| 2209 | ; $ELSE ;AN000; | ||
| 2210 | JMP SHORT $$EN29 | ||
| 2211 | $$IF29: | ||
| 2212 | STC ;AN000;BAD EMS | ||
| 2213 | ; $ENDIF ;AN000; | ||
| 2214 | $$EN29: | ||
| 2215 | ; $ELSE ;AN000; | ||
| 2216 | JMP SHORT $$EN28 | ||
| 2217 | $$IF28: | ||
| 2218 | STC ;AN000;EMS NOT INSTALLED | ||
| 2219 | ; $ENDIF ;AN000; | ||
| 2220 | $$EN28: | ||
| 2221 | ; $ELSE ;AN000; | ||
| 2222 | JMP SHORT $$EN27 | ||
| 2223 | $$IF27: | ||
| 2224 | STC ;AN000;EMS VECTOR NOT THERE | ||
| 2225 | ; $ENDIF ;AN000; | ||
| 2226 | $$EN27: | ||
| 2227 | |||
| 2228 | RET ;AN000;RETURN TO CALLER | ||
| 2229 | |||
| 2230 | EMS_CHECK1 ENDP ;AN000; | ||
| 2231 | |||
| 2232 | |||
| 2233 | EMS_GET_PAGES PROC NEAR ;AN000; | ||
| 2234 | |||
| 2235 | MOV AH,EMS_GET_NUM_PAGES ;AN000; Query EMS for page count | ||
| 2236 | INT EMS_INT ;AN000; | ||
| 2237 | OR AH,AH ;AN000; Has EMS returned page count? | ||
| 2238 | JNZ EMS_GET_ERROR ;AN000; Yes, | ||
| 2239 | MOV AX,BX ;AN000; Get number of pages | ||
| 2240 | RET ;AN000; | ||
| 2241 | |||
| 2242 | EMS_GET_ERROR: ;AN000; | ||
| 2243 | STC ;AN000; | ||
| 2244 | RET ;AN000; | ||
| 2245 | |||
| 2246 | EMS_GET_PAGES ENDP | ||
| 2247 | |||
| 2248 | SUBTTL VAL_SSZ Validate Sector Size | ||
| 2249 | PAGE | ||
| 2250 | ;-----------------------------------------------------------------------; | ||
| 2251 | ; VAL_SSZ validates sector size, adjusting if necessary ; | ||
| 2252 | ;-----------------------------------------------------------------------; | ||
| 2253 | VAL_SSZ PROC ;validate sector size | ||
| 2254 | CMP CS:EM_SW,0 ;EXTENDED MEMORY? | ||
| 2255 | JE VAL_SSZ_ST ;no,go check sector size | ||
| 2256 | MOV BX,MAXSEC_TRF ;move number of sectors to transfer | ||
| 2257 | CMP BX,1 ;> or equal to 1 ? | ||
| 2258 | JB DFLT_TRF ;set default if it is | ||
| 2259 | CMP BX,8 ;> than 8 ? | ||
| 2260 | JA DFLT_TRF ;set default if it is | ||
| 2261 | JMP VAL_SSZ_ST ;continue processing | ||
| 2262 | |||
| 2263 | DFLT_TRF: ;set default | ||
| 2264 | MOV MAXSEC_TRF,DFLT_ESS ; | ||
| 2265 | MOV BX,MAXSEC_TRF ; | ||
| 2266 | OR CS:ERR_FLAG,ERR_ESIZE ;indicate transfer size adjusted | ||
| 2267 | |||
| 2268 | VAL_SSZ_ST: ;validate sector size | ||
| 2269 | MOV MAX_CNT,BX ;initialize maximum number of sectors | ||
| 2270 | ;to transfer for extended memory case | ||
| 2271 | MOV BX,BPB_SSZ ;requested sector size | ||
| 2272 | MOV CX,VAL_SSZ_N ;number of table entries | ||
| 2273 | MOV SI,OFFSET VAL_SSZ_TBL ;DS:SI point to table start | ||
| 2274 | VAL_SSZ_A: | ||
| 2275 | LODSW ;get table entry, step table pointer | ||
| 2276 | CMP AX,BX ;is value in table? | ||
| 2277 | JE VAL_SSZ_X ;exit if value found | ||
| 2278 | LOOP VAL_SSZ_A ;loop until table end | ||
| 2279 | |||
| 2280 | MOV BX,DFLT_SSZ ;get default sector size | ||
| 2281 | MOV BPB_SSZ,BX ;set sector size to default value | ||
| 2282 | OR ERR_FLAG,ERR_SSZ ;indicate sector size adjusted | ||
| 2283 | VAL_SSZ_X: | ||
| 2284 | |||
| 2285 | ;Compute the maximum number of sectors that can be moved in 64KB (less one) | ||
| 2286 | ;Restricting moves to this amount avoids 64KB boundary problems. | ||
| 2287 | |||
| 2288 | CMP CS:EM_SW,0 ;EXTENDED MEMORY? | ||
| 2289 | JNE SIZE_DONE ;yes, we are done | ||
| 2290 | XOR DX,DX | ||
| 2291 | MOV AX,0FFFFH ;64KB - 1 | ||
| 2292 | DIV BX ;/sector size | ||
| 2293 | MOV MAX_CNT,AX ;max sectors in one move | ||
| 2294 | SIZE_DONE: | ||
| 2295 | RET | ||
| 2296 | VAL_SSZ ENDP | ||
| 2297 | |||
| 2298 | SUBTTL VAL_DIRN Validate number of directory entries | ||
| 2299 | PAGE | ||
| 2300 | ;-----------------------------------------------------------------------; | ||
| 2301 | ; VAL_DIRN validates and adjusts the number of directory entries. ; | ||
| 2302 | ; ; | ||
| 2303 | ; Minimum is MIN_DIRN, maximum is MAX_DIRN. If outside these ; | ||
| 2304 | ; limits, DFLT_DIRN is used. ; | ||
| 2305 | ; ; | ||
| 2306 | ; The number of directory entries is rounded upward to fill ; | ||
| 2307 | ; a sector ; | ||
| 2308 | ;-----------------------------------------------------------------------; | ||
| 2309 | VAL_DIRN PROC | ||
| 2310 | MOV AX,BPB_DIRN ;requested directory entries | ||
| 2311 | CMP AX,MIN_DIRN ;if less than minimum | ||
| 2312 | JB VAL_DIRN_A ;use default instead | ||
| 2313 | |||
| 2314 | CMP AX,MAX_DIRN ;if <= maximum | ||
| 2315 | JBE VAL_DIRN_B ;accept value as provided | ||
| 2316 | |||
| 2317 | VAL_DIRN_A: | ||
| 2318 | MOV AX,DFLT_DIRN ;use default directory entries | ||
| 2319 | OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted | ||
| 2320 | VAL_DIRN_B: ;AX is number of directory entries | ||
| 2321 | MUL DIRE_SIZE ;* 32 = bytes of directory requested | ||
| 2322 | DIV BPB_SSZ ;/ sector size = # of directory sectors | ||
| 2323 | OR DX,DX ;test remainder for zero | ||
| 2324 | JZ VAL_DIRN_C ;jump if exact fit | ||
| 2325 | |||
| 2326 | INC AX ;increment directory sectors | ||
| 2327 | OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted | ||
| 2328 | VAL_DIRN_C: ;make sure enough sectors available | ||
| 2329 | MOV DX,BPB_SECN ;total sectors on media | ||
| 2330 | SUB DX,BPB_RES ;less reserved sectors | ||
| 2331 | SUB DX,2 ;less minimum FAT and 1 data sector | ||
| 2332 | CMP AX,DX ;if directory sectors <= available | ||
| 2333 | JLE VAL_DIRN_D ;use requested amount | ||
| 2334 | |||
| 2335 | MOV AX,1 ;use only one directory sector | ||
| 2336 | OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted | ||
| 2337 | VAL_DIRN_D: | ||
| 2338 | MOV DIR_SECTORS,AX ;save number of directory sectors | ||
| 2339 | MUL BPB_SSZ ;dir sectors * sector size = dir bytes | ||
| 2340 | DIV DIRE_SIZE ;dir bytes / entry size = entries | ||
| 2341 | MOV BPB_DIRN,AX ;store adjusted directory entries | ||
| 2342 | RET | ||
| 2343 | VAL_DIRN ENDP | ||
| 2344 | |||
| 2345 | SUBTTL VAL_FAT Validate File Allocation Table (FAT) | ||
| 2346 | PAGE | ||
| 2347 | ;-----------------------------------------------------------------------; | ||
| 2348 | ;VAL_FAT computes: ; | ||
| 2349 | ;BPB_FATSZ, the number of sectors required per FAT copy ; | ||
| 2350 | ; ; | ||
| 2351 | ;Each FAT entry is 12 bits long, for a maximum of 4095 FAT entries. ; | ||
| 2352 | ;(A few FAT entries are reserved, so the highest number of FAT entries ; | ||
| 2353 | ;we permit is 0FE0H.) With large buffer sizes and small sector sizes, ; | ||
| 2354 | ;we have more allocation units to describe than a 12-bit entry will ; | ||
| 2355 | ;describe. If the number of FAT entries is too large, the sector size ; | ||
| 2356 | ;is increased (up to a maximum of 512 bytes), and then the allocation ; | ||
| 2357 | ;unit (cluster) size is doubled, until we have few enough allocation ; | ||
| 2358 | ;units to be properly described in 12 bits. ; | ||
| 2359 | ; ; | ||
| 2360 | ;This computation is slightly conservative in that the FAT entries ; | ||
| 2361 | ;necessary to describe the FAT sectors are included in the computation. ; | ||
| 2362 | ;-----------------------------------------------------------------------; | ||
| 2363 | VAL_FAT PROC | ||
| 2364 | MOV AX,BPB_SECN ;total number of sectors | ||
| 2365 | SUB AX,BPB_RES ;don't count boot sector(s) | ||
| 2366 | SUB AX,DIR_SECTORS ;don't count directory sectors | ||
| 2367 | |||
| 2368 | CMP AX,0000h ;an000; dms; fix ptm 112; any left? | ||
| 2369 | JA VAL_FAT_A ;an000; dms; fix ptm 112; yes | ||
| 2370 | |||
| 2371 | ;;;;; JG VAL_FAT_A ;jump if some remaining | ||
| 2372 | MOV BPB_SSZ,DFLT_SSZ ;force default sector size | ||
| 2373 | OR ERR_FLAG,ERR_SSZ+ERR_PASS ;indicate sector size adjusted | ||
| 2374 | JMP SHORT VAL_FAT_X ;recompute all values | ||
| 2375 | VAL_FAT_A: | ||
| 2376 | XOR DX,DX ;clear DX for division | ||
| 2377 | MOV CL,BPB_AUSZ ;CX = sectors/cluster | ||
| 2378 | XOR CH,CH | ||
| 2379 | DIV CX ;whole number of clusters in AX | ||
| 2380 | ADD DX,0FFFFH ;set carry if remainder | ||
| 2381 | ADC AX,0 ;increment AX if remainder | ||
| 2382 | CMP AX,MAX_FATE ;number of FAT entries too large? | ||
| 2383 | JBE VAL_FAT_C ;no, continue | ||
| 2384 | |||
| 2385 | MOV AX,BPB_SSZ ;pick up current sector size | ||
| 2386 | CMP AX,VAL_SSZ_L ;already at largest permitted? | ||
| 2387 | JE VAL_FAT_B ;yes, can't make it any larger | ||
| 2388 | |||
| 2389 | SHL BPB_SSZ,1 ;double sector size | ||
| 2390 | OR ERR_FLAG,ERR_SSZB ;indicate sector size adjusted | ||
| 2391 | JMP SHORT VAL_FAT_X ;recompute all sizes with new BPBSSZ | ||
| 2392 | |||
| 2393 | VAL_FAT_B: ;sector size is at maximum | ||
| 2394 | SHL BPB_AUSZ,1 ;double allocation unit size | ||
| 2395 | OR ERR_FLAG,ERR_PASS ;indicate another pass required | ||
| 2396 | JMP SHORT VAL_FAT_X ;recompute values | ||
| 2397 | |||
| 2398 | VAL_FAT_C: ;FAT size = 1.5 * number of clusters | ||
| 2399 | MOV CX,AX ;number of clusters | ||
| 2400 | SHL AX,1 ;* 2 | ||
| 2401 | ADD AX,CX ;* 3 | ||
| 2402 | SHR AX,1 ;* 1.5 | ||
| 2403 | ADC AX,3 ;add 3 bytes for first 2 FAT entries | ||
| 2404 | ;(media descriptor and FFFFH), and CY | ||
| 2405 | XOR DX,DX ;clear DX for division | ||
| 2406 | DIV BPB_SSZ ;FAT size/sector size | ||
| 2407 | ADD DX,0FFFFH ;set carry if remainder | ||
| 2408 | ADC AX,0 ;round upward | ||
| 2409 | MOV BPB_FATSZ,AX ;number of sectors for 1 FAT copy | ||
| 2410 | VAL_FAT_X: | ||
| 2411 | RET | ||
| 2412 | VAL_FAT ENDP | ||
| 2413 | |||
| 2414 | |||
| 2415 | VALIDATE ENDP | ||
| 2416 | |||
| 2417 | SUBTTL COPY_BPB Copy BPB to Boot Record | ||
| 2418 | PAGE | ||
| 2419 | ;-----------------------------------------------------------------------; | ||
| 2420 | ; COPY_BPB copies the BIOS Parameter Block (BPB) ; | ||
| 2421 | ; to the VDISK Boot Record ; | ||
| 2422 | ;-----------------------------------------------------------------------; | ||
| 2423 | ASSUME DS:CSEG | ||
| 2424 | COPY_BPB PROC ;Copy BBP to Boot Record | ||
| 2425 | PUSH DS | ||
| 2426 | POP ES ;set ES = DS | ||
| 2427 | |||
| 2428 | MOV CX,BPB_LEN ;length of BPB | ||
| 2429 | MOV SI,OFFSET BPB ;source offset | ||
| 2430 | MOV DI,OFFSET BOOT_BPB ;target offset | ||
| 2431 | REP MOVSB ;copy BPB to boot record | ||
| 2432 | RET | ||
| 2433 | COPY_BPB ENDP | ||
| 2434 | |||
| 2435 | SUBTTL VERIFY_EXTENDER | ||
| 2436 | PAGE | ||
| 2437 | ;-----------------------------------------------------------------------; | ||
| 2438 | ; VERIFY_EXTENDER makes sure that if an Expansion Unit is ; | ||
| 2439 | ; installed, the memory size switches on the Extender Card ; | ||
| 2440 | ; are correctly set. ; | ||
| 2441 | ;-----------------------------------------------------------------------; | ||
| 2442 | |||
| 2443 | |||
| 2444 | ASSUME DS:CSEG | ||
| 2445 | EXT_P210 EQU 0210H ;write to latch expansion bus data | ||
| 2446 | ;read to verify expansion bus data | ||
| 2447 | EXT_P213 EQU 0213H ;Expansion Unit status | ||
| 2448 | |||
| 2449 | VERIFY_EXTENDER PROC | ||
| 2450 | |||
| 2451 | NOP | ||
| 2452 | |||
| 2453 | MOV DX,EXT_P210 ;Expansion bus data port address | ||
| 2454 | |||
| 2455 | MOV AX,5555H ;set data pattern | ||
| 2456 | OUT DX,AL ;write 55H to control port | ||
| 2457 | PUSH DX | ||
| 2458 | POP DX | ||
| 2459 | |||
| 2460 | JMP SHORT $+2 ;Let the I/O circuits catch up | ||
| 2461 | IN AL,020h ;Clear the CMOS bus drivers! | ||
| 2462 | |||
| 2463 | IN AL,DX ;recover data | ||
| 2464 | CMP AH,AL ;did we recover the same data? | ||
| 2465 | JNE VERIFY_EXTENDER_X ;if not, no extender card | ||
| 2466 | |||
| 2467 | NOT AX ;set AX = 0AAAAH | ||
| 2468 | OUT DX,AL ;write 0AAH to control port | ||
| 2469 | PUSH DX ;load data line | ||
| 2470 | POP DX ;load data line | ||
| 2471 | |||
| 2472 | JMP SHORT $+2 ;Let the I/O circuits catch up | ||
| 2473 | IN AL,020h ;Clear the CMOS bus drivers! | ||
| 2474 | |||
| 2475 | IN AL,DX ;recover data | ||
| 2476 | CMP AH,AL ;did we recover the same data? | ||
| 2477 | JNE VERIFY_EXTENDER_X ;if not, no extender card | ||
| 2478 | |||
| 2479 | ;Expansion Unit is present. | ||
| 2480 | |||
| 2481 | ;Determine what the switch settings should be on the Extender Card | ||
| 2482 | |||
| 2483 | INT MEM_SIZE ;get system memory size in KB in AX | ||
| 2484 | ADD AX,63D ;memory size + 63K | ||
| 2485 | MOV CL,6 ;2^6 = 64 | ||
| 2486 | SHR AX,CL ;divide by 64 | ||
| 2487 | ;AX is highest segment address | ||
| 2488 | MOV AH,AL ;save number of segments | ||
| 2489 | |||
| 2490 | ;Read Expander card switch settings | ||
| 2491 | |||
| 2492 | MOV DX,EXT_P213 ;expansion unit status | ||
| 2493 | IN AL,DX ;read status | ||
| 2494 | ;bits 7-4 (hi nibble) are switches | ||
| 2495 | MOV CL,4 ;shift count | ||
| 2496 | SHR AL,CL ;shift switches to bits 3-0 of AL | ||
| 2497 | |||
| 2498 | CMP AH,AL ;do switches match memory size? | ||
| 2499 | JE VERIFY_EXTENDER_X ;yes, exit normally | ||
| 2500 | |||
| 2501 | OR ERR_FLAG,ERR_EXTSW ;indicate switch settings are wrong | ||
| 2502 | |||
| 2503 | VERIFY_EXTENDER_X: | ||
| 2504 | RET | ||
| 2505 | VERIFY_EXTENDER ENDP | ||
| 2506 | |||
| 2507 | SUBTTL UPDATE_AVAIL | ||
| 2508 | PAGE | ||
| 2509 | ;-----------------------------------------------------------------------; | ||
| 2510 | ; UPDATE_AVAIL updates the address of the first byte in extended ; | ||
| 2511 | ; memory not used by any VDISK buffer ; | ||
| 2512 | ;-----------------------------------------------------------------------; | ||
| 2513 | ;If EMS is installed, we must allocate memory here and obtain the ; | ||
| 2514 | ;handle which we will use throughout our existance. AVAIL_LO and _HI ; | ||
| 2515 | ;really mean nothing to us. ; | ||
| 2516 | ;-----------------------------------------------------------------------; | ||
| 2517 | |||
| 2518 | UPDATE_AVAIL PROC | ||
| 2519 | MOV AX,BUFF_SIZE ;number of KB of VDISK buffer | ||
| 2520 | |||
| 2521 | CMP EM_SW2,EMS_INSTALLED_FLAG ;AN000; Is EMS installed? | ||
| 2522 | JNE USE_INT15_LOGIC ;ac006; Yes, | ||
| 2523 | xor dx,dx ;an003; clear high word | ||
| 2524 | div DOS_Page_Size_Word ;ac003; Calculate number of pages needed | ||
| 2525 | or dx,dx ;an004; remainder? | ||
| 2526 | ; $if nz ;an004; yes | ||
| 2527 | JZ $$IF36 | ||
| 2528 | inc ax ;an004; need 1 extra page | ||
| 2529 | ; $endif ;an004; | ||
| 2530 | $$IF36: | ||
| 2531 | MOV BX,AX ;AN000; Prepare for EMS call | ||
| 2532 | |||
| 2533 | MOV AH,EMS_ALLOC_PAGES ;AN000; Allocate requested pages | ||
| 2534 | INT EMS_INT ;AN000; | ||
| 2535 | OR AH,AH ;AN000; Was there an error allocating? | ||
| 2536 | JNZ ALLOC_ERROR ;AN000; No, | ||
| 2537 | MOV EMS_HANDLE,DX ;AN000; Save EMS handle for this VDISK | ||
| 2538 | call EMS_Build_Handle_Name ;an000; dms; | ||
| 2539 | |||
| 2540 | RET ;AN000; | ||
| 2541 | ;AN000; | ||
| 2542 | ALLOC_ERROR: ;AN000; | ||
| 2543 | MOV ERR_FLAG,EMS_ALLOC_ERROR ;AN000; ?????? *RPS | ||
| 2544 | RET ;AN000; | ||
| 2545 | ;AN000; | ||
| 2546 | USE_INT15_LOGIC: ;AN000; | ||
| 2547 | |||
| 2548 | call Modify_CMOS_EM ;an001; dms;adjust EM for new size | ||
| 2549 | |||
| 2550 | RET | ||
| 2551 | UPDATE_AVAIL ENDP | ||
| 2552 | |||
| 2553 | |||
| 2554 | ;========================================================================= | ||
| 2555 | ; Modify_CMOS_EM : This routine modifies the size of extended | ||
| 2556 | ; memory. By modifying the size of extended | ||
| 2557 | ; memory other users will not have the potential | ||
| 2558 | ; to overlay a VDISK residing in EM. | ||
| 2559 | ; | ||
| 2560 | ; Inputs : EM_New_Size - The new size that EM will be after | ||
| 2561 | ; creation of this VDISK. | ||
| 2562 | ; Outputs : Modified data in CMOS for EM. Bytes 17h & 18h at | ||
| 2563 | ; port 71h. | ||
| 2564 | ;========================================================================= | ||
| 2565 | |||
| 2566 | Modify_CMOS_EM Proc Near ;an001; dms; | ||
| 2567 | |||
| 2568 | push ax ;an001; dms;save ax | ||
| 2569 | call Steal_Int15 ;an001; dms;get INT 15h vector | ||
| 2570 | |||
| 2571 | mov ax,word ptr cs:EM_New_Size ;an001; dms;transfer new size | ||
| 2572 | mov word ptr cs:EM_KSize,ax ;an001; dms;set EM size to new size | ||
| 2573 | pop ax ;an001; dms;restore ax | ||
| 2574 | |||
| 2575 | ret ;an001; dms; | ||
| 2576 | |||
| 2577 | Modify_CMOS_EM endp ;an001; dms; | ||
| 2578 | |||
| 2579 | ;========================================================================= | ||
| 2580 | ; EMS_Build_Handle_Name - This routine will build an EMS handle's | ||
| 2581 | ; name as follows: | ||
| 2582 | ; VDISK D: | ||
| 2583 | ; | ||
| 2584 | ; Inputs : DX - Handle to have associated name | ||
| 2585 | ; | ||
| 2586 | ; Outputs : Handle name | ||
| 2587 | ;========================================================================= | ||
| 2588 | |||
| 2589 | EMS_Build_Handle_Name proc near ;an000; dms; | ||
| 2590 | |||
| 2591 | push si ;an000; dms;save si | ||
| 2592 | push cx ;an000; dms;save cx | ||
| 2593 | |||
| 2594 | push ds ;an000; dms;save ds | ||
| 2595 | push bx ;an000; dms;save bx | ||
| 2596 | lds bx,RH_Ptra ;an000; dms;point to request header | ||
| 2597 | mov ch,RH.RH0_Driv ;an000; dms;get drive number | ||
| 2598 | add ch,'A' ;an000; dms;convert to drive letter | ||
| 2599 | pop bx ;an000; dms;restore bx | ||
| 2600 | pop ds ;an000; dms;restore ds | ||
| 2601 | |||
| 2602 | mov si,offset VDISK_Name ;an000; dms;point to "VDISK " literal | ||
| 2603 | mov byte ptr [si+6],ch ;an000; dms;put drive letter in string | ||
| 2604 | mov byte ptr [si+7],":" ;an000; dms;colon terminate it | ||
| 2605 | |||
| 2606 | mov ax,EMS_Set_Handle_Name ;an000; dms;set the handle's name | ||
| 2607 | int EMS_INT ;an000; dms; | ||
| 2608 | |||
| 2609 | pop cx ;an000; dms;restore cx | ||
| 2610 | pop si ;an000; dms;restore si | ||
| 2611 | |||
| 2612 | ret ;an000; dms; | ||
| 2613 | |||
| 2614 | EMS_Build_Handle_Name endp ;an000; dms; | ||
| 2615 | |||
| 2616 | SUBTTL FORMAT_VDISK | ||
| 2617 | PAGE | ||
| 2618 | ;-----------------------------------------------------------------------; | ||
| 2619 | ; This Request Header is used by MOVE_VDISK to move the ; | ||
| 2620 | ; first few sectors of the virtual disk (boot, FAT, and ; | ||
| 2621 | ; Directory) into extended memory. ; | ||
| 2622 | ;-----------------------------------------------------------------------; | ||
| 2623 | |||
| 2624 | MOVE_RH DB MOVE_RH_L ;length of request header | ||
| 2625 | DB 0 ;sub unit | ||
| 2626 | DB 8 ;output operation | ||
| 2627 | DW 0 ;status | ||
| 2628 | DQ ? ;reserved for DOS | ||
| 2629 | DB ? ;media descriptor byte | ||
| 2630 | MOVE_RHO DW ? ;offset of data transfer address | ||
| 2631 | MOVE_RHS DW ? ;segment of data transfer address | ||
| 2632 | MOVE_RHCNT DW ? ;count of sectors to transfer | ||
| 2633 | DW 0 ;starting sector number | ||
| 2634 | MOVE_RH_L EQU $-MOVE_RH ;length of request header | ||
| 2635 | |||
| 2636 | ;-----------------------------------------------------------------------; | ||
| 2637 | ; FORMAT_VDISK formats the boot sector, FAT, and directory of an ; | ||
| 2638 | ; extended memory VDISK in storage immediately following ; | ||
| 2639 | ; VDISK code, in preparation for moving to extended memory. ; | ||
| 2640 | ;-----------------------------------------------------------------------; | ||
| 2641 | FORMAT_VDISK PROC ;format boot record, FATs and directory | ||
| 2642 | |||
| 2643 | MOV AX,CS ;compute 20-bit address | ||
| 2644 | MUL WPARA_SIZE ;16 * segment | ||
| 2645 | ADD AX,OFFSET MSGEND ;+ offset | ||
| 2646 | ADC DL,0 ;pick up carry | ||
| 2647 | ADD AX,STACK_SIZE ;plus stack size | ||
| 2648 | ADC DL,0 ;pick up carry | ||
| 2649 | |||
| 2650 | DIV WPARA_SIZE ;split into segment(AX)&offset(DX) | ||
| 2651 | MOV MOVE_RHS,AX ;save in Request Header for move | ||
| 2652 | MOV MOVE_RHO,DX | ||
| 2653 | |||
| 2654 | MOV DI,DX ;offset to DI | ||
| 2655 | MOV ES,AX ;segment to ES | ||
| 2656 | |||
| 2657 | ;copy the boot record | ||
| 2658 | |||
| 2659 | MOV SI,OFFSET BOOT_RECORD ;point to source field | ||
| 2660 | MOV AX,BPB_RES ;number of reserved sectors | ||
| 2661 | MUL BPB_SSZ ;* sector size = length of boot records | ||
| 2662 | MOV CX,AX ;length to CX for move | ||
| 2663 | REP MOVSB ;move boot record(s) | ||
| 2664 | |||
| 2665 | ;format the FAT(s) | ||
| 2666 | |||
| 2667 | MOV CL,BPB_FATN ;number of FATs | ||
| 2668 | XOR CH,CH | ||
| 2669 | FORMAT_VDISK_A: ;set up one FAT | ||
| 2670 | PUSH CX ;save loop counter on stack | ||
| 2671 | MOV AL,BPB_MCB ;media control byte | ||
| 2672 | STOSB ;store media control byte, increment DI | ||
| 2673 | MOV AX,0FFFFH ;bytes 2 and 3 of FAT are 0FFH | ||
| 2674 | STOSW | ||
| 2675 | MOV AX,BPB_FATSZ ;number of sectors per FAT | ||
| 2676 | MUL BPB_SSZ ;* sector size = length of FAT in bytes | ||
| 2677 | SUB AX,3 ;less the 3 bytes we've stored | ||
| 2678 | MOV CX,AX ;count to CX | ||
| 2679 | XOR AX,AX | ||
| 2680 | REP STOSB ;clear remainder of FAT | ||
| 2681 | POP CX ;get loop counter off stack | ||
| 2682 | LOOP FORMAT_VDISK_A ;loop for all copies of the FAT | ||
| 2683 | |||
| 2684 | ;Format the directory | ||
| 2685 | |||
| 2686 | MOV SI,OFFSET VOL_LABEL ;point to volume label | ||
| 2687 | MOV CX,VOL_LABEL_LEN ;length of volume directory entry | ||
| 2688 | REP MOVSB ;move volume id to directory | ||
| 2689 | MOV AX,DIR_ENTRY_SIZE ;length of 1 directory entry | ||
| 2690 | MUL BPB_DIRN ;* number entries = bytes of directory | ||
| 2691 | SUB AX,VOL_LABEL_LEN ;less length of volume label | ||
| 2692 | MOV CX,AX ;CX = length of rest of directory | ||
| 2693 | XOR AX,AX | ||
| 2694 | REP STOSB ;clear directory to nulls | ||
| 2695 | RET | ||
| 2696 | FORMAT_VDISK ENDP | ||
| 2697 | |||
| 2698 | SUBTTL STEAL_INT15 | ||
| 2699 | PAGE | ||
| 2700 | ;-----------------------------------------------------------------------; | ||
| 2701 | ; STEAL_INT15 changes the INT 15H vector to point to this VDISK ; | ||
| 2702 | ; so that subsequent calls to INT15H may determine the actual ; | ||
| 2703 | ; size of EM after VDISK's allocation of it. ; | ||
| 2704 | ;-----------------------------------------------------------------------; | ||
| 2705 | STEAL_INT15 PROC | ||
| 2706 | PUSH DS | ||
| 2707 | XOR AX,AX | ||
| 2708 | MOV DS,AX ;set DS = 0 | ||
| 2709 | ASSUME DS:INT_VEC | ||
| 2710 | CLI ;disable interrupts | ||
| 2711 | LES DI,DS:EM_VEC ;get original vector's content | ||
| 2712 | MOV CS:INTV15O,DI ;save original vector | ||
| 2713 | MOV CS:INTV15S,ES | ||
| 2714 | MOV DS:EM_VECO,OFFSET VDISK_INT15 ;offset of new INT routine | ||
| 2715 | MOV DS:EM_VECS,CS ;segment of new INT routine | ||
| 2716 | STI ;enable interrupts again | ||
| 2717 | POP DS ;restore DS | ||
| 2718 | RET | ||
| 2719 | STEAL_INT15 ENDP | ||
| 2720 | |||
| 2721 | |||
| 2722 | |||
| 2723 | SUBTTL MOVE_VDISK | ||
| 2724 | PAGE | ||
| 2725 | ;-----------------------------------------------------------------------; | ||
| 2726 | ; MOVE_VDISK moves the formatted boot sector, FAT, and directory ; | ||
| 2727 | ; into extended memory. ; | ||
| 2728 | ;-----------------------------------------------------------------------; | ||
| 2729 | |||
| 2730 | MOVE_VDISK PROC | ||
| 2731 | MOV AL,cs:BPB_FATN ;number of FAT copies | ||
| 2732 | CBW ;clear AH | ||
| 2733 | MUL cs:BPB_FATSZ ;number of FAT sectors | ||
| 2734 | ADD AX,cs:BPB_RES ;+ reserved sectors | ||
| 2735 | ADD AX,cs:DIR_SECTORS ;+ directory sectors | ||
| 2736 | MOV cs:MOVE_RHCNT,AX ;store as I/O length | ||
| 2737 | |||
| 2738 | MOV BX,OFFSET MOVE_RH ;DS:BX point to request header | ||
| 2739 | PUSH DS ;make sure DS gets preserved | ||
| 2740 | CALL INOUT ;move to extended memory | ||
| 2741 | POP DS | ||
| 2742 | RET | ||
| 2743 | MOVE_VDISK ENDP | ||
| 2744 | |||
| 2745 | SUBTTL FILL_RH Fill in Request Header | ||
| 2746 | PAGE | ||
| 2747 | ;-----------------------------------------------------------------------; | ||
| 2748 | ; FILL_RH fills in the Request Header returned to DOS ; | ||
| 2749 | ;-----------------------------------------------------------------------; | ||
| 2750 | ASSUME DS:CSEG | ||
| 2751 | FILL_RH PROC ;fill in INIT Request Header fields | ||
| 2752 | MOV CX,START_BUFFER_PARA ;segment end of VDISK resident code | ||
| 2753 | MOV AX,PARAS_PER_SECTOR ;paragraphs per sector | ||
| 2754 | MUL BPB_SECN ;* number of sectors | ||
| 2755 | ADD AX,CX ;+ starting segment | ||
| 2756 | MOV DX,AX ;DX is segment of end VDISK buffer | ||
| 2757 | CMP EM_SW,0 ;AC000; DMS; IF EM NOT REQUESTED | ||
| 2758 | ; $IF NE ;AN000; DMS; EM REQUESTED | ||
| 2759 | JE $$IF38 | ||
| 2760 | MOV DX,CX ;AN000; DMS;END OF CODE SEGMENT ADDR | ||
| 2761 | ; $ENDIF ;AN000; DMS; | ||
| 2762 | $$IF38: | ||
| 2763 | |||
| 2764 | FILL_RH_A: ;DX is proper ending segment address | ||
| 2765 | MOV AL,1 ;number of units | ||
| 2766 | test CS:err_flag2,err_baddos | ||
| 2767 | jnz dont_install | ||
| 2768 | |||
| 2769 | TEST ERR_FLAG,ERR_SYSSZ+ERR_EXTSW ;if bypassing install | ||
| 2770 | JZ FILL_RH_B ;jump if installing driver | ||
| 2771 | |||
| 2772 | dont_install: | ||
| 2773 | MOV DX,CS ;segment of end address | ||
| 2774 | XOR AL,AL ;number of units is zero | ||
| 2775 | FILL_RH_B: | ||
| 2776 | PUSH DS ;preserve DS | ||
| 2777 | LDS BX,RH_PTRA ;get Request Header addr in DS:BX | ||
| 2778 | MOV RH.RH0_NUN,AL ;store number of units (0 or 1) | ||
| 2779 | MOV RH.RH0_ENDO,0 ;end offset is always zero | ||
| 2780 | MOV RH.RH0_ENDS,DX ;end of VDISK or end of buffer | ||
| 2781 | MOV RH.RH0_BPBO,OFFSET BPB_PTR | ||
| 2782 | MOV RH.RH0_BPBS,CS ;BPB array address | ||
| 2783 | POP DS ;restore DS | ||
| 2784 | RET | ||
| 2785 | FILL_RH ENDP | ||
| 2786 | |||
| 2787 | SUBTTL WRITE_MESSAGES and associated routines | ||
| 2788 | PAGE | ||
| 2789 | ;-----------------------------------------------------------------------; | ||
| 2790 | ; WRITE_MESSAGE writes a series of messages to the standard ; | ||
| 2791 | ; output device showing the VDISK parameter values actually used. ; | ||
| 2792 | ;-----------------------------------------------------------------------; | ||
| 2793 | |||
| 2794 | ASSUME DS:CSEG | ||
| 2795 | WRITE_MESSAGES PROC ;display all messages | ||
| 2796 | |||
| 2797 | |||
| 2798 | test cs:err_flag2,err_baddos ;AN000; | ||
| 2799 | JZ DISPLAY_ALL_MESSAGES ;AN000; | ||
| 2800 | RET | ||
| 2801 | |||
| 2802 | DISPLAY_ALL_MESSAGES: ;AN000; No, then display messages | ||
| 2803 | |||
| 2804 | PUSH DS ;preserve DS | ||
| 2805 | LDS BX,RH_PTRA ;get Request Header Address | ||
| 2806 | MOV CL,RH.RH0_DRIV ;get drive code | ||
| 2807 | ADD CL,'A' ;convert to drive letter | ||
| 2808 | POP DS ;restore DS | ||
| 2809 | |||
| 2810 | MOV AX,VDISK_TITLE ;AN000; 'VDISK Version 3.3 virtual disk $' | ||
| 2811 | LEA SI,TITLE_SUBLIST ;AN000; Specify SUBLIST to use for replacement | ||
| 2812 | MOV DRIVE_CODE,CL ;AN000; Save drive code | ||
| 2813 | MOV CX,ONE_REPLACE ;AN000; Notify SYSDISPMSG of 1 replacement | ||
| 2814 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2815 | JNC WRITE_MESSAGES_A ;AN000; Was there an error? | ||
| 2816 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2817 | |||
| 2818 | ;If any of the user specified values has been adjusted, issue an | ||
| 2819 | ;appropriate message | ||
| 2820 | |||
| 2821 | WRITE_MESSAGES_A: ;AN000; NO, | ||
| 2822 | TEST ERR_FLAG,ERR_BSIZE ;was buffersize adjusted? | ||
| 2823 | JZ WRITE_MESSAGES_B ;if not, skip message | ||
| 2824 | |||
| 2825 | MOV AX,BUFFER_ADJUSTED ;AN000; "Buffer size adjusted",CR,LF | ||
| 2826 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2827 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2828 | |||
| 2829 | WRITE_MESSAGES_B: ;AN000; NO, | ||
| 2830 | TEST ERR_FLAG,ERR_SSZ ;was sector size adjusted? | ||
| 2831 | JZ WRITE_MESSAGES_C ;if not, skip message | ||
| 2832 | |||
| 2833 | MOV AX,SECTOR_ADJUSTED ;AN000; "Sector size adjusted",CR,LF | ||
| 2834 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2835 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2836 | JNC WRITE_MESSAGES_C ;AN000; Was there an error? | ||
| 2837 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2838 | |||
| 2839 | WRITE_MESSAGES_C: | ||
| 2840 | TEST ERR_FLAG,ERR_DIRN ;were directory entries adjusted? | ||
| 2841 | JZ WRITE_MESSAGES_D0 ;if not, skip message | ||
| 2842 | |||
| 2843 | MOV AX,DIR_ADJUSTED ;AN000; "Directory entries adjusted",CR,LF | ||
| 2844 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2845 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2846 | JNC WRITE_MESSAGES_D0 ;AN000; Was there an error? | ||
| 2847 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2848 | |||
| 2849 | WRITE_MESSAGES_D0: | ||
| 2850 | TEST ERR_FLAG,ERR_ESIZE ;was transfer size adjusted? | ||
| 2851 | JZ WRITE_MESSAGES_D ;if not, skip message | ||
| 2852 | |||
| 2853 | MOV AX,TRANS_ADJUSTED ;AN000; "Transfer size adjusted",CR,LF | ||
| 2854 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2855 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2856 | JNC WRITE_MESSAGES_D ;AN000; Was there an error? | ||
| 2857 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2858 | |||
| 2859 | WRITE_MESSAGES_D: | ||
| 2860 | TEST ERR_FLAG,ERR_SWTCH ;was an invalid switch character found? | ||
| 2861 | JZ WRITE_MESSAGES_E ;if not, skip message | ||
| 2862 | |||
| 2863 | MOV AX,INVALID_SW_CHAR ;AN000; "Invalid switch character",CR,LF | ||
| 2864 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2865 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2866 | JNC WRITE_MESSAGES_E ;AN000; Was there an error? | ||
| 2867 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2868 | |||
| 2869 | WRITE_MESSAGES_E: | ||
| 2870 | TEST ERR_FLAG,ERR_SYSSZ ;is system size too small to install? | ||
| 2871 | JZ WRITE_MESSAGES_F ;if not, bypass error message | ||
| 2872 | |||
| 2873 | MOV AX,VDISK_NOT_INST ;AN000; "VDISK not installed - " | ||
| 2874 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2875 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2876 | MOV AX,SYS_TOO_SMALL ;AN000; "Insufficient memory",CR,LF | ||
| 2877 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2878 | JNC WRITE_MESSAGES_RET ;AN000; Was there an error? | ||
| 2879 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2880 | WRITE_MESSAGES_RET: | ||
| 2881 | RET ;skip messages showing adjusted sizes | ||
| 2882 | |||
| 2883 | WRITE_MESSAGES_F: | ||
| 2884 | TEST ERR_FLAG,ERR_EXTSW ;extender card switches wrong? | ||
| 2885 | JZ WRITE_MESSAGES_G ;if not, bypass error message | ||
| 2886 | |||
| 2887 | MOV AX,VDISK_NOT_INST ;AN000; "VDISK not installed - " | ||
| 2888 | MOV CX,NO_REPLACE ;AN000; Notify SYSDISPMSG of no replacement | ||
| 2889 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2890 | MOV AX,EXTEND_CARD_WRONG ;AN000; "Extender Card switches",CR,LF,"do not match system memory size",CR,LF,CR,LF | ||
| 2891 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2892 | JNC WRITE_MESSAGES_RET ;AN000; Was there an error? | ||
| 2893 | JMP SYSDISP_ERROR ;AN000; YES, display the extended error | ||
| 2894 | |||
| 2895 | WRITE_MESSAGES_G: ;display adjusted size messages | ||
| 2896 | MOV AX,BUF_SZ ;AN000; "Buffer size: %1 KB",CR,LF | ||
| 2897 | LEA SI,BUF_SZ_SUBLIST ;AN000; Specify SUBLIST to use for replacement | ||
| 2898 | MOV CX,ONE_REPLACE ;AN000; Notify SYSDISPMSG of 1 replacement | ||
| 2899 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2900 | JC SYSDISP_ERROR ;AN000; | ||
| 2901 | |||
| 2902 | MOV AX,SEC_SZ ;AN000; "Sector size: %1",CR,LF | ||
| 2903 | LEA SI,SEC_SZ_SUBLIST ;AN000; Specify SUBLIST to use for replacement | ||
| 2904 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2905 | JC SYSDISP_ERROR ;AN000; | ||
| 2906 | |||
| 2907 | MOV AX,DIR_ENTRIES ;AN000; "Directory entries: %1",CR,LF | ||
| 2908 | LEA SI,DIR_ENT_SUBLIST ;AN000; Specify SUBLIST to use for replacement | ||
| 2909 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2910 | JC SYSDISP_ERROR ;AN000; | ||
| 2911 | |||
| 2912 | CMP CS:EM_SW,0 ;extended memory ? | ||
| 2913 | JE END_LINE ; | ||
| 2914 | MOV AX,TRANS_SZ ;AN000; "Transfer size: %1",CR,LF,CR,LF | ||
| 2915 | LEA SI,TRANS_SZ_SUBLIST ;AN000; Specify SUBLIST to use for replacement | ||
| 2916 | CALL DISPLAY_MESSAGE ;AN000; Display the message | ||
| 2917 | JC SYSDISP_ERROR ;AN000; | ||
| 2918 | |||
| 2919 | |||
| 2920 | END_LINE: | ||
| 2921 | RET ;return to INIT_P1 | ||
| 2922 | |||
| 2923 | SYSDISP_ERROR: | ||
| 2924 | |||
| 2925 | push ds ;an006; dms;save ds | ||
| 2926 | push bx ;an006; dms;save bx | ||
| 2927 | lds bx,cs:RH_Ptra ;an006; dms;point to request header | ||
| 2928 | mov RH.RH0_Flag,-1 ;an006; dms;signal BIO and error occurred | ||
| 2929 | pop bx ;an006; dms;restore bx | ||
| 2930 | pop ds ;an006; dms;restore ds | ||
| 2931 | |||
| 2932 | ;AN000; Set error conditions | ||
| 2933 | MOV BX,NO_HANDLE ;AN000; Write to NO_HANDLE | ||
| 2934 | MOV CX,NO_REPLACE ;AN000; | ||
| 2935 | MOV DH,EXT_ERR_CLASS ;AN000; | ||
| 2936 | MOV DL,NO_INPUT ;AN000; | ||
| 2937 | |||
| 2938 | PUSH DS ;AN000;SET UP ADDRESSIBILITY TO MSG | ||
| 2939 | PUSH ES ;AN000; | ||
| 2940 | |||
| 2941 | PUSH CS ;AN000;TRANSFER CS | ||
| 2942 | POP DS ;AN000; TO DS | ||
| 2943 | PUSH CX ;AN000;TRANSFER CS | ||
| 2944 | POP ES ;AN000; TO ES | ||
| 2945 | |||
| 2946 | ASSUME DS:CSEG,ES:CSEG ;AN000; | ||
| 2947 | CALL GET_PARM_SEGMENT ;AN000;OBTAIN PARM SEGMENT | ||
| 2948 | |||
| 2949 | CALL SYSDISPMSG ;AN000; | ||
| 2950 | |||
| 2951 | POP ES ;AN000;RESTORE REG | ||
| 2952 | POP DS ;AN000;RESTORE REG | ||
| 2953 | ASSUME DS:NOTHING,ES:NOTHING ;AN000; | ||
| 2954 | |||
| 2955 | RET ;AN000; | ||
| 2956 | |||
| 2957 | WRITE_MESSAGES ENDP | ||
| 2958 | |||
| 2959 | |||
| 2960 | DISPLAY_MESSAGE PROC NEAR | ||
| 2961 | ;AN000; Set default values | ||
| 2962 | MOV BX,NO_HANDLE ;AN000; Output handle is NO_HANDLE | ||
| 2963 | MOV DH,UTILITY_MSG_CLASS ;AN000; Utility class message | ||
| 2964 | MOV DL,NO_INPUT ;AN000; No input is requested | ||
| 2965 | PUSH DS ;AN000;SET UP ADDRESSIBILITY TO MSG | ||
| 2966 | PUSH ES ;AN000; | ||
| 2967 | |||
| 2968 | PUSH CS ;AN000;TRANSFER CS | ||
| 2969 | POP DS ;AN000; TO DS | ||
| 2970 | PUSH CS ;AN000;TRANSFER CS | ||
| 2971 | POP ES ;AN000; TO ES | ||
| 2972 | |||
| 2973 | ASSUME DS:CSEG,ES:CSEG ;AN000; | ||
| 2974 | CALL GET_PARM_SEGMENT ;AN000;OBTAIN PARM SEGMENT | ||
| 2975 | |||
| 2976 | CALL SYSDISPMSG ;AN000; | ||
| 2977 | |||
| 2978 | POP ES ;AN000;RESTORE REG | ||
| 2979 | POP DS ;AN000;RESTORE REG | ||
| 2980 | ASSUME DS:NOTHING,ES:NOTHING ;AN000; | ||
| 2981 | |||
| 2982 | RET ;AN000; | ||
| 2983 | |||
| 2984 | DISPLAY_MESSAGE ENDP | ||
| 2985 | |||
| 2986 | GET_PARM_SEGMENT PROC ;AN000;OBTAIN PARM SEGMENT | ||
| 2987 | |||
| 2988 | PUSH CX ;AN000;SAVE CX - WE STOMP IT | ||
| 2989 | PUSH SI ;AN000;SAVE SI - WE STOMP IT | ||
| 2990 | |||
| 2991 | CMP CX,00H ;AN000;SEE IF REPLACEMENT IS REQUIRED | ||
| 2992 | JE GPS_END ;AN000;END IF ZERO | ||
| 2993 | |||
| 2994 | GPS_CONTINUE: ;AN000;LOOP CONTINUE | ||
| 2995 | |||
| 2996 | MOV [SI].SL_SEGMENT,DS ;AN000;SET UP SEGMENT | ||
| 2997 | ADD SI,11 ;AN000;INCREASE SI BY TABLE SZ | ||
| 2998 | |||
| 2999 | LOOP GPS_CONTINUE ;AN000;CONTINUE LOOP IF CX NOT ZERO | ||
| 3000 | |||
| 3001 | GPS_END: ;AN000;EXIT POINT | ||
| 3002 | |||
| 3003 | POP SI ;AN000;RESTORE SI | ||
| 3004 | POP CX ;AN000;RESTORE CX | ||
| 3005 | |||
| 3006 | RET ;AN000;RETURN TO CALLER | ||
| 3007 | |||
| 3008 | GET_PARM_SEGMENT ENDP ;AN000; | ||
| 3009 | |||
| 3010 | |||
| 3011 | |||
| 3012 | |||
| 3013 | INIT_P1 ENDP ;end of INIT part one | ||
| 3014 | .xlist | ||
| 3015 | MSG_SERVICES <MSGDATA> ;AN000: | ||
| 3016 | MSG_SERVICES <LOADmsg> ;AN000; | ||
| 3017 | MSG_SERVICES <DISPLAYmsg,CHARmsg,NUMmsg> ;AN000; | ||
| 3018 | MSG_SERVICES <VDISK.CL1,VDISK.CL2,VDISK.CLA> ;AN000; | ||
| 3019 | .list | ||
| 3020 | MSGEND LABEL BYTE ;AN000; | ||
| 3021 | |||
| 3022 | CSEG ENDS | ||
| 3023 | END | ||
| 3024 | \ No newline at end of file | ||