summaryrefslogtreecommitdiff
path: root/v4.0/src/DEV/VDISK/VDISKSYS.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/DEV/VDISK/VDISKSYS.ASM')
-rw-r--r--v4.0/src/DEV/VDISK/VDISKSYS.ASM3024
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;-----------------------------------------------------------------------;
102RH EQU DS:[BX] ;addressability to Request Header structure
103
104RHC STRUC ;fields common to all request types
105 DB ? ;length of Request Header (including data)
106 DB ? ;unit code (subunit)
107RHC_CMD DB ? ;command code
108RHC_STA DW ? ;status
109 DQ ? ;reserved for DOS
110;;;;; DW ? ;reserved for BIOS message flag ;an006; dms;
111RHC ENDS ;end of common portion
112
113CMD_INPUT EQU 4 ;RHC_CMD is INPUT request
114
115;status values for RHC_STA
116
117STAT_DONE EQU 01H ;function complete status (high order byte)
118STAT_CMDERR EQU 8003H ;invalid command code error
119STAT_CRC EQU 8004H ;CRC error
120STAT_SNF EQU 8008H ;sector not found error
121STAT_BUSY EQU 0200H ;busy bit (9) for Removable Media call
122;-----------------------------------------------------------------------;
123; Request Header for INIT command ;
124;-----------------------------------------------------------------------;
125RH0 STRUC
126 DB (TYPE RHC) DUP (?) ;common portion
127RH0_NUN DB ? ;number of units
128 ;set to 1 if installation succeeds,
129 ;set to 0 to cause installation failure
130RH0_ENDO DW ? ;offset of ending address
131RH0_ENDS DW ? ;segment of ending address
132RH0_BPBO DW ? ;offset of BPB array address
133RH0_BPBS DW ? ;segment of BPB array address
134RH0_DRIV DB ? ;drive code (DOS 3 only)
135RH0_FLAG DW 0 ;initialized to no error ;an000; dms;
136RH0 ENDS
137
138RH0_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;-----------------------------------------------------------------------;
144RH1 STRUC
145 DB (TYPE RHC) DUP (?) ;common portion
146 DB ? ;media descriptor
147RH1_RET DB ? ;return information
148RH1 ENDS
149;-----------------------------------------------------------------------;
150; Request Header for BUILD BPB Command ;
151;-----------------------------------------------------------------------;
152RH2 STRUC
153 DB (TYPE RHC) DUP(?) ;common portion
154 DB ? ;media descriptor
155 DW ? ;offset of transfer address
156 DW ? ;segment of transfer address
157RH2_BPBO DW ? ;offset of BPB table address
158RH2_BPBS DW ? ;segment of BPB table address
159RH2 ENDS
160;-----------------------------------------------------------------------;
161; Request Header for INPUT, OUTPUT, and OUTPUT with verify ;
162;-----------------------------------------------------------------------;
163RH4 STRUC
164 DB (TYPE RHC) DUP (?) ;common portion
165 DB ? ;media descriptor
166RH4_DTAO DW ? ;offset of transfer address
167RH4_DTAS DW ? ;segment of transfer address
168RH4_CNT DW ? ;sector count
169RH4_SSN DW ? ;starting sector number
170RH4 ENDS
171
172RH4_DTAA EQU DWORD PTR RH4_DTAO ;offset/segment of transfer address
173
174;-----------------------------------------------------------------------;
175; Segment Descriptor (part of Global Descriptor Table) ;
176;-----------------------------------------------------------------------;
177DESC STRUC ;data segment descriptor
178DESC_LMT DW 0 ;segment limit (length)
179DESC_BASEL DW 0 ;bits 15-0 of physical address
180DESC_BASEH DB 0 ;bits 23-16 of physical address
181 DB 0 ;access rights byte
182 DW 0 ;reserved
183DESC ENDS
184
185 SUBTTL Equates and Macro Definitions
186 PAGE
187
188MEM_SIZE EQU 12H ;BIOS memory size determination INT
189 ;returns system size in KB in AX
190
191EM_INT EQU 15H ;extended memory BIOS interrupt INT
192EM_BLKMOVE EQU 87H ;block move function
193EM_MEMSIZE EQU 8800H ;memory size determination in KB
194
195DOS EQU 21H ;DOS request INT
196DOS_PCHR EQU 02H ;print character function
197DOS_PSTR EQU 09H ;print string function
198DOS_VERS EQU 30H ;get DOS version
199
200TAB EQU 09H ;ASCII tab
201LF EQU 0AH ;ASCII line feed
202CR EQU 0DH ;ASCII carriage return
203
204PARA_SIZE EQU 16 ;number of bytes in one 8088 paragraph
205DIR_ENTRY_SIZE EQU 32 ;number of bytes per directory entry
206MAX_FATE EQU 0FE0H ;largest number of FAT entries allowed
207
208;default values used if parameters are omitted
209
210DFLT_BSIZE EQU 64 ;default VDISK buffer size (KB)
211DFLT_SSZ EQU 128 ;default sector size
212DFLT_DIRN EQU 64 ;default number of directory entries
213DFLT_ESS EQU 8 ;default maximum sectors to transfer
214
215MIN_DIRN EQU 2 ;minimum number of directory entries
216MAX_DIRN EQU 512 ;maximum number of directory entries
217
218STACK_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;-----------------------------------------------------------------------;
226INT_VEC SEGMENT AT 00H
227 ORG 4*EM_INT
228EM_VEC LABEL DWORD
229EM_VECO DW ? ;offset
230EM_VECS DW ? ;segment
231INT_VEC ENDS
232
233
234
235CSEG 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
244START 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
260VOL_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
265VOL_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
272AVAIL_LO DW 0 ;address of first free byte of
273AVAIL_HI DB 10H ;extended memory
274
275INTV15 LABEL DWORD
276INTV15O DW ? ;offset
277INTV15S DW ? ;segment
278
279
280PARAS_PER_SECTOR DW ? ;number of 16-byte paragraphs in one sector
281
282START_BUFFER_PARA DW ? ;segment address of start of VDISK buffer
283
284EM_New_Size dw ? ;an001; dms;new size for EM
285EM_KSize dw ? ;an001; dms;size of EM currently.
286
287EM_SW DB 0 ;NON-ZERO IF EXTENDED MEMORY
288
289EM_STAT DW 0 ;AX from last unsuccessful extended memory I/O
290
291START_EM_LO DW ? ;24-bit address of start of VDISK buffer
292START_EM_HI DB ? ;(extended memory only)
293
294WPARA_SIZE DW PARA_SIZE ;number of bytes in one paragraph
295
296MAX_CNT DW ? ;(0FFFFH/BPB_SSZ) truncated, the maximum
297 ;number of sectors that can be transferred
298 ;without worrying about 64KB wrap
299
300SECT_LEFT DW ? ;sectors left to transfer
301
302IO_SRCA LABEL DWORD ;offset/segment of source
303IO_SRCO DW ? ;offset
304IO_SRCS DW ? ;segment
305
306IO_TGTA LABEL DWORD ;offset/segment of target
307IO_TGTO DW ? ;offset
308IO_TGTS DW ? ;segment
309
310;-----------------------------------------------------------------------;
311; EMS Support ;
312;-----------------------------------------------------------------------;
313
314EM_SW2 DB not EMS_Installed_Flag ;ac006;Default if EMS not installed
315EMS_HANDLE DW ? ;AN000; EMS handle for reference
316EMS_FRAME_ADDR DW ? ;AN000; EMS handle for reference
317EMS_CURR_SECT DW ? ;an000; Current EMS sector being addressed
318CURR_EMS_PAGE DW ? ;ac002; Current EMS page number
319SECT_LEFT_IN_FRAME DW ? ;AN000; Sectors left to transfer in this frame
320SECT_PER_PAGE DW ? ;AN000; Sectors per page
321DOS_Page dw ? ;an006; EMS physical page for VDISK
322
323EMS_SAVE_ARRAY DB 80h dup(0) ;an000; save current state of ems
324EMS_SEG_ARRAY DD ? ;an000; save segment array
325
326CURR_DTA_OFF DW ? ;AN000; DMS;CURRENT OFFSET OF DTA
327
328PC_386 DB false ;AN000; DMS;386 machine flag
329
330SUBLIST STRUC ;AN000;SUBLIST STRUCTURE
331
332SL_SIZE DB ? ;AN000;SUBLIST SIZE
333SL_RES DB ? ;AN000;RESERVED
334SL_OFFSET DW ? ;AN000;PARM OFFSET
335SL_SEGMENT DW ? ;AN000;PARM SEGMENT
336SL_ID DB ? ;AN000;NUMBER OF PARM
337SL_FLAG DB ? ;AN000;DISPLAY TYPE
338SL_MAXW DB ? ;AN000;MAXIMUM FIELD WIDTH
339SL_MINW DB ? ;AN000;MINIMUM FIELD WIDTH
340SL_PAD DB ? ;AN000;PAD CHARACTER
341
342SUBLIST ENDS ;AN000;END SUBLIST STRUCTURE
343
344
345BIOS_SYSTEM_DESCRIPTOR struc ;AN000;SYSTEM TYPE STRUC
346
347bios_SD_leng dw ? ;AN000;VECTOR LENGTH
348bios_SD_modelbyte db ? ;AN000;SYSTEM MODEL TYPE
349bios_SD_scnd_modelbyte db ? ;AN000;
350 db ? ;AN000;
351bios_SD_featurebyte1 db ? ;AN000;
352 db 4 dup (?) ;AN000;
353
354BIOS_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
364BPB LABEL BYTE ;BIOS Parameter Block (BPB)
365BPB_SSZ DW 0 ;number of bytes per disk sector
366BPB_AUSZ DB 1 ;sectors per allocation unit
367BPB_RES DW 1 ;number of reserved sectors (for boot record)
368BPB_FATN DB 1 ;number of File Allocation Table (FAT) copies
369BPB_DIRN DW 0 ;number of root directory entries
370BPB_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)
374BPB_MCB DB 0FEH ;media descriptor byte
375BPB_FATSZ DW 1 ;number of sectors occupied by a single FAT
376 ;computed from BPBSSZ and BPBSECN
377BPB_LEN EQU $-BPB ;length of BIOS parameter block
378
379BPB_PTR DW BPB ;BIOS Parameter Block pointer array (1 entry)
380;-----------------------------------------------------------------------;
381; Request Header (RH) address, saved here by "strategy" routine ;
382;-----------------------------------------------------------------------;
383RH_PTRA LABEL DWORD
384RH_PTRO DW ? ;offset
385RH_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
396GDT LABEL BYTE ;begin global descriptor table
397 DESC <> ;dummy descriptor
398 DESC <> ;descriptor for GDT itself
399SRC DESC <,,,93H,> ;source descriptor
400TGT 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;=========================================================================
421VDISK_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
437VDISK_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;-----------------------------------------------------------------------;
449STRATEGY PROC FAR
450 MOV CS:RH_PTRO,BX ;offset
451 MOV CS:RH_PTRS,ES ;segment
452 RET
453STRATEGY ENDP
454;-----------------------------------------------------------------------;
455; Table of command processing routine entry points ;
456;-----------------------------------------------------------------------;
457CMD_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
473MAX_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;-----------------------------------------------------------------------;
479IRPT 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
520IRPT_CMD_ERROR: ;CALLed for unsupported character mode commands
521
522INPUT_IOCTL: ;IOCTL input
523INPUT_NOWAIT: ;Non-destructive input no wait
524INPUT_STATUS: ;Input status
525INPUT_FLUSH: ;Input flush
526
527OUTPUT_IOCTL: ;IOCTL output
528OUTPUT_STATUS: ;Output status
529OUTPUT_FLUSH: ;Output flush
530
531 POP AX ;pop return address off stack
532
533IRPT_CMD_HIGH: ;JMPed to if RHC_CMD > MAX_CMD
534 MOV AX,STAT_CMDERR ;"invalid command" and error
535
536IRPT_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
550IRPT 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;-----------------------------------------------------------------------;
558MEDIA_CHECK PROC
559 MOV RH.RH1_RET,1 ;indicate media not changed
560 RET ;AX = zero, no error
561MEDIA_CHECK ENDP
562;-----------------------------------------------------------------------;
563; Command Code 2 - Build BPB ;
564; At entry, DS:BX point to request header, AX = 0 ;
565;-----------------------------------------------------------------------;
566BLD_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
570BLD_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;-----------------------------------------------------------------------;
577REMOVABLE_MEDIA PROC
578 MOV AX,STAT_BUSY ;set status bit 9 (busy)
579 ;indicating non-removable media
580DEVICE_OPEN: ;NOP for device open
581DEVICE_CLOSE: ;NOP for device close
582 RET
583REMOVABLE_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;-----------------------------------------------------------------------;
590INOUT PROC
591INPUT:
592OUTPUT:
593OUTPUT_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
619INOUT_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
624INOUT_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
663INOUT_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
670INOUT_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
683INOUT_D:
684
685 CALL INOUT_D_LOW_MEM ;AN000;LOW MEMORY TRANSFER
686
687;Determine if more sectors need to be transferred
688
689INOUT_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;-----------------------------------------------------------------------;
700INOUT_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
719INOUT_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
747INOUT_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
756INOUT_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
769INOUT_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
798INOUT_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
810INOUT_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
820INOUT_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
905INOUT_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
914INOUT_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
919INOUT 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
936ems_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
948ems_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
962ems_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
973ems_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
988ems_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
999ems_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
1015ems_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
1031ems_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
1045ems_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
1071ems_trf endp ;an000; dms;
1072
1073
1074
1075MAP_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
1086MAP_FRAME ENDP ;AN000;
1087
1088
1089INOUT_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
1124INOUT_D_LOW_MEM ENDP
1125
1126
1127
1128 DW 40 DUP (?) ;stack for extended memory I/O
1129EM_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
1142VDISK EQU $ ;start of virtual disk buffer
1143VDISKP 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
1154BOOT_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
1158BOOT_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
1222INIT_P2 PROC ;second part of initialization
1223 ASSUME DS:CSEG ;DS set in INIT_P1
1224
1225;Initialize File Allocation Table(s) (FATs)
1226
1227INIT_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
1256INIT_P2 ENDP
1257
1258PATCH_AREA DB 5 DUP ('PATCH AREA ')
1259TEST_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
1269MAXSEC_TRF DW 0 ;maximum number of sectors to transfer when
1270 ;in extended memory
1271
1272BUFF_SIZE DW 0 ;desired VDISK buffer size in kilobytes
1273
1274MIN_MEMORY_LEFT DW 100 ;minimum amount of system memory (kilobytes)
1275 ;that must remain after VDISK is installed
1276
1277PARA_PER_KB DW 1024/PARA_SIZE ;paragraphs in one kilobyte
1278C1024 DW 1024 ;bytes in one kilobyte
1279DIRE_SIZE DW DIR_ENTRY_SIZE ;bytes in one directory entry
1280DIR_SECTORS DW ? ;number of sectors of directory
1281
1282ERR_FLAG DB 0 ;error indicators to condition messages
1283ERR_BSIZE EQU 80H ;buffer size adjusted
1284ERR_SSZ EQU 40H ;sector size adjusted
1285ERR_DIRN EQU 20H ;number of directory entries adjusted
1286ERR_PASS EQU 10H ;some adjustment made that requires
1287 ;recomputation of values previously computed
1288ERR_SSZB EQU ERR_SSZ+ERR_PASS ;sector size altered this pass
1289ERR_SYSSZ EQU 08H ;system storage too small for VDISK
1290ERR_SWTCH EQU 04H ;invalid switch character
1291ERR_EXTSW EQU 02H ;extender card switches don't match memory size
1292ERR_ESIZE EQU 01H ;Transfer size adjusted
1293
1294DOS_PG_SZ DB DOS_PAGE_SZ ;AN000;
1295DOS_Page_Size_Word dw DOS_Page_Sz ;an000;
1296
1297err_flag2 db 0
1298err_baddos equ 01h ; Invalid DOS Version
1299
1300;-----------------------------------------------------------------------;
1301; SUBLIST definitions and EQUATES for Message Retreiver ;
1302;-----------------------------------------------------------------------;
1303 ;AN000; Message Number
1304INCORRECT_DOS EQU 1 ;AN000;
1305SYS_TOO_SMALL EQU 2 ;AN000;
1306VDISK_TITLE EQU 3 ;AN000;
1307BUFFER_ADJUSTED EQU 4 ;AN000;
1308SECTOR_ADJUSTED EQU 5 ;AN000;
1309DIR_ADJUSTED EQU 6 ;AN000;
1310INVALID_SW_CHAR EQU 7 ;AN000;
1311TRANS_ADJUSTED EQU 8 ;AN000;
1312BUF_SZ EQU 9 ;AN000;
1313SEC_SZ EQU 10 ;AN000;
1314DIR_ENTRIES EQU 11 ;AN000;
1315TRANS_SZ EQU 12 ;AN000;
1316VDISK_NOT_INST EQU 13 ;AN000;
1317EXTEND_CARD_WRONG EQU 14 ;AN000;
1318
1319NO_REPLACE EQU 0 ;AN000; CX = 0 -> No replacement
1320ONE_REPLACE EQU 1 ;AN000; CX = 1 -> One replacement
1321UNLIMITED_MAX EQU 0 ;AN000; MAX field - unlimited
1322SMALLEST_MIN EQU 1 ;AN000; MIN field - 1 character long
1323PAD_BLANK EQU 20H ;AN000; PAD character is a blank
1324
1325
1326DRIVE_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
1331TITLE_SUBLIST LABEL BYTE
1332
1333TT_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST)
1334TT_RESV DB 0 ;AN000; RESERVED
1335TT_VALUEO DW DRIVE_CODE ;AN000; Offset to ASCIIZ string
1336TT_VALUES DW ? ;AN000; SEGMENT TO ASCIIZ STRING
1337TT_ID DB 1 ;AN000; n of %n
1338TT_FLAG DB Left_Align+Char_Field_ASCIIZ
1339TT_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width
1340TT_MINW DB SMALLEST_MIN ;AN000; Minimum field width
1341TT_PAD DB PAD_BLANK ;AN000; Character for Pad field
1342
1343; For the message: "Buffer size: %1 KB",CR,LF
1344
1345BUF_SZ_SUBLIST LABEL BYTE
1346
1347B_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST)
1348B_RESV DB 0 ;AN000; RESERVED
1349B_VALUEO DW BUFF_SIZE ;AN000; Offset to binary number
1350B_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER
1351B_ID DB 1 ;AN000; n of %n
1352B_FLAG DB Left_Align+Unsgn_Bin_Word
1353B_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width
1354B_MINW DB SMALLEST_MIN ;AN000; Minimum field width
1355B_PAD DB PAD_BLANK ;AN000; Character for Pad field
1356
1357; For the message: "Sector size: %1",CR,LF
1358
1359SEC_SZ_SUBLIST LABEL BYTE
1360
1361S_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST)
1362S_RESV DB 0 ;AN000; RESERVED
1363S_VALUEO DW BPB_SSZ ;AN000; Offset to binary number
1364S_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER
1365S_ID DB 1 ;AN000; n of %n
1366S_FLAG DB Left_Align+Unsgn_Bin_Word
1367S_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width
1368S_MINW DB SMALLEST_MIN ;AN000; Minimum field width
1369S_PAD DB PAD_BLANK ;AN000; Character for Pad field
1370
1371; For the message: "Directory entries: %1",CR,LF
1372
1373DIR_ENT_SUBLIST LABEL BYTE
1374
1375D_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST)
1376D_RESV DB 0 ;AN000; RESERVED
1377D_VALUEO DW BPB_DIRN ;AN000; Offset to binary number
1378D_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER
1379D_ID DB 1 ;AN000; n of %n
1380D_FLAG DB Left_Align+Unsgn_Bin_Word
1381D_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width
1382D_MINW DB SMALLEST_MIN ;AN000; Minimum field width
1383D_PAD DB PAD_BLANK ;AN000; Character for Pad field
1384
1385; For the message: "Transfer size: %1",CR,LF
1386
1387TRANS_SZ_SUBLIST LABEL BYTE
1388
1389T_SIZE DB 11 ;AN000; SUBLIST size (PTR to next SUBLIST)
1390T_RESV DB 0 ;AN000; RESERVED
1391T_VALUEO DW MAXSEC_TRF ;AN000; Offset to binary number
1392T_VALUES DW ? ;AN000; SEGMENT TO BINARY NUMBER
1393T_ID DB 1 ;AN000; n of %n
1394T_FLAG DB Left_Align+Unsgn_Bin_Word
1395T_MAXW DB UNLIMITED_MAX ;AN000; Maximum field width
1396T_MINW DB SMALLEST_MIN ;AN000; Minimum field width
1397T_PAD DB PAD_BLANK ;AN000; Character for Pad field
1398
1399;-----------------------------------------------------------------------;
1400; EMS Support ;
1401;-----------------------------------------------------------------------;
1402
1403FRAME_BUFFER DB 10 DUP(0) ;AN000;
1404VDISK_Name db "VDISK " ;an000; dms;
1405
1406four 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
1418INIT_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
1477VDISK_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
1518INIT_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
1575PC_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
1609PC_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
1623GET_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
1635GET_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
1655GET_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
1660GET_PARMS_D: ;scan for /
1661 CALL GET_PCHAR
1662 JZ GET_PARMS_B ;exit if end of line
1663
1664GET_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;
1677CHECK_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;
1685GOT_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
1696GET_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
1702GET_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
1708Get_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
1729GET_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
1741GET_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 ;
1748GET_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
1752GET_MAXSIZE ENDP
1753
1754
1755
1756GET_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?
1765GET_PCHAR_X: ;attempted read past end of line
1766 RET
1767GET_PCHAR ENDP ;returns char in AL
1768
1769
1770CHECK_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
1778CHECK_NUM_X:
1779 RET ;Z set if numeric, NZ if not numeric
1780CHECK_NUM ENDP
1781
1782
1783SKIP_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
1791SKIP_TO_DIGIT_X:
1792 CMP AL,0 ;digit found, force NZ
1793 RET
1794SKIP_TO_DIGIT ENDP
1795
1796C10 DW 10
1797GN_ERR DB ? ;zero if no overflow in accumulation
1798
1799GET_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
1802GET_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
1820GET_NUMBER_B:
1821 RET ;number in CX, next char in AL
1822GET_NUMBER ENDP
1823
1824GET_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
1833APPLY_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
1841APPLY_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
1848APPLY_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
1855APPLY_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
1864APPLY_DEFAULTS_D:
1865 RET
1866APPLY_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
1875DETERMINE_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
1924DETERMINE_START_X:
1925
1926 RET
1927DETERMINE_START ENDP
1928
1929 SUBTTL VALIDATE parameters
1930 PAGE
1931;-----------------------------------------------------------------------;
1932; VALIDATE adjusts parameters as necessary ;
1933;-----------------------------------------------------------------------;
1934VAL_SSZ_TBL LABEL WORD ;table of valid sector sizes
1935VAL_SSZ_S DW 128 ;smallest valid sector size
1936 DW 256
1937VAL_SSZ_L DW 512 ;largest valid sector size
1938VAL_SSZ_N EQU ($-VAL_SSZ_TBL)/2 ;number of table entries
1939
1940 ASSUME DS:CSEG
1941VALIDATE 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
1961VALIDATE_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
2022VALIDATE_C: ;not enough space for any VDISK
2023 OR ERR_FLAG,ERR_SYSSZ
2024VALIDATE_X:
2025 RET
2026
2027 SUBTTL VAL_BSIZE Validate buffer size
2028 PAGE
2029;-----------------------------------------------------------------------;
2030; VAL_BSIZE adjusts the buffer size as necessary ;
2031;-----------------------------------------------------------------------;
2032VAL_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
2045VAL_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
2057VAL_BSIZE_C:
2058
2059
2060 RET
2061
2062
2063GET_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 ;
2084USE_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
2094GET_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
2109GET_MSIZE_Z:
2110 XOR AX,AX ;indicate no memory available
2111GET_MSIZE_X: ;exit from memory size determination
2112 RET
2113GET_MSIZE ENDP
2114
2115VAL_BSIZE ENDP
2116
2117
2118
2119EMS_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
2127EMS_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
2168EMS_Check_Exit:
2169
2170 RET ;AN000; Return
2171
2172EMS_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
2187EMS_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
2230EMS_CHECK1 ENDP ;AN000;
2231
2232
2233EMS_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
2242EMS_GET_ERROR: ;AN000;
2243 STC ;AN000;
2244 RET ;AN000;
2245
2246EMS_GET_PAGES ENDP
2247
2248 SUBTTL VAL_SSZ Validate Sector Size
2249 PAGE
2250;-----------------------------------------------------------------------;
2251; VAL_SSZ validates sector size, adjusting if necessary ;
2252;-----------------------------------------------------------------------;
2253VAL_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
2263DFLT_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
2268VAL_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
2274VAL_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
2283VAL_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
2294SIZE_DONE:
2295 RET
2296VAL_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;-----------------------------------------------------------------------;
2309VAL_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
2317VAL_DIRN_A:
2318 MOV AX,DFLT_DIRN ;use default directory entries
2319 OR ERR_FLAG,ERR_DIRN ;indicate directory entries adjusted
2320VAL_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
2328VAL_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
2337VAL_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
2343VAL_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;-----------------------------------------------------------------------;
2363VAL_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
2375VAL_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
2393VAL_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
2398VAL_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
2410VAL_FAT_X:
2411 RET
2412VAL_FAT ENDP
2413
2414
2415VALIDATE 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
2424COPY_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
2433COPY_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
2445EXT_P210 EQU 0210H ;write to latch expansion bus data
2446 ;read to verify expansion bus data
2447EXT_P213 EQU 0213H ;Expansion Unit status
2448
2449VERIFY_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
2503VERIFY_EXTENDER_X:
2504 RET
2505VERIFY_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
2518UPDATE_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;
2542ALLOC_ERROR: ;AN000;
2543 MOV ERR_FLAG,EMS_ALLOC_ERROR ;AN000; ?????? *RPS
2544 RET ;AN000;
2545 ;AN000;
2546USE_INT15_LOGIC: ;AN000;
2547
2548 call Modify_CMOS_EM ;an001; dms;adjust EM for new size
2549
2550 RET
2551UPDATE_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
2566Modify_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
2577Modify_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
2589EMS_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
2614EMS_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
2624MOVE_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
2630MOVE_RHO DW ? ;offset of data transfer address
2631MOVE_RHS DW ? ;segment of data transfer address
2632MOVE_RHCNT DW ? ;count of sectors to transfer
2633 DW 0 ;starting sector number
2634MOVE_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;-----------------------------------------------------------------------;
2641FORMAT_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
2669FORMAT_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
2696FORMAT_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;-----------------------------------------------------------------------;
2705STEAL_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
2719STEAL_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
2730MOVE_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
2743MOVE_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
2751FILL_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
2764FILL_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
2772dont_install:
2773 MOV DX,CS ;segment of end address
2774 XOR AL,AL ;number of units is zero
2775FILL_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
2785FILL_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
2795WRITE_MESSAGES PROC ;display all messages
2796
2797
2798 test cs:err_flag2,err_baddos ;AN000;
2799 JZ DISPLAY_ALL_MESSAGES ;AN000;
2800 RET
2801
2802DISPLAY_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
2821WRITE_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
2829WRITE_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
2839WRITE_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
2849WRITE_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
2859WRITE_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
2869WRITE_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
2880WRITE_MESSAGES_RET:
2881 RET ;skip messages showing adjusted sizes
2882
2883WRITE_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
2895WRITE_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
2920END_LINE:
2921 RET ;return to INIT_P1
2922
2923SYSDISP_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
2957WRITE_MESSAGES ENDP
2958
2959
2960DISPLAY_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
2984DISPLAY_MESSAGE ENDP
2985
2986GET_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
3008GET_PARM_SEGMENT ENDP ;AN000;
3009
3010
3011
3012
3013INIT_P1 ENDP ;end of INIT part one
3014.xlist
3015MSG_SERVICES <MSGDATA> ;AN000:
3016MSG_SERVICES <LOADmsg> ;AN000;
3017MSG_SERVICES <DISPLAYmsg,CHARmsg,NUMmsg> ;AN000;
3018MSG_SERVICES <VDISK.CL1,VDISK.CL2,VDISK.CLA> ;AN000;
3019.list
3020MSGEND LABEL BYTE ;AN000;
3021
3022CSEG ENDS
3023 END
3024 \ No newline at end of file