From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/BIOS/BIOSTRUC.INC | 103 ++ v4.0/src/BIOS/CLOCKSUB.INC | 78 + v4.0/src/BIOS/CMOSEQU.INC | 50 + v4.0/src/BIOS/DEFEMS.INC | 33 + v4.0/src/BIOS/DEVMARK.INC | 23 + v4.0/src/BIOS/JUMPMAC.INC | 31 + v4.0/src/BIOS/LOCSCR | 1 + v4.0/src/BIOS/MAKEFILE | 167 +++ v4.0/src/BIOS/MS96TPI.INC | 536 +++++++ v4.0/src/BIOS/MSAUX.ASM | 281 ++++ v4.0/src/BIOS/MSBDATA.INC | 722 ++++++++++ v4.0/src/BIOS/MSBIO.LNK | 14 + v4.0/src/BIOS/MSBIO.SKL | 139 ++ v4.0/src/BIOS/MSBIO1.ASM | 645 +++++++++ v4.0/src/BIOS/MSBIO2.ASM | 572 ++++++++ v4.0/src/BIOS/MSCLOCK.ASM | 296 ++++ v4.0/src/BIOS/MSCON.ASM | 328 +++++ v4.0/src/BIOS/MSDISK.ASM | 2443 +++++++++++++++++++++++++++++++ v4.0/src/BIOS/MSDSKPR.INC | 22 + v4.0/src/BIOS/MSEQU.INC | 76 + v4.0/src/BIOS/MSEXTRN.INC | 97 ++ v4.0/src/BIOS/MSGROUP.INC | 46 + v4.0/src/BIOS/MSHARD.ASM | 427 ++++++ v4.0/src/BIOS/MSINIT.ASM | 2819 ++++++++++++++++++++++++++++++++++++ v4.0/src/BIOS/MSIOCTL.INC | 1362 ++++++++++++++++++ v4.0/src/BIOS/MSLOAD.ASM | 1090 ++++++++++++++ v4.0/src/BIOS/MSLOAD.INC | 7 + v4.0/src/BIOS/MSLPT.ASM | 270 ++++ v4.0/src/BIOS/MSMACRO.INC | 192 +++ v4.0/src/BIOS/MSSTACK.INC | 306 ++++ v4.0/src/BIOS/MSVOLID.INC | 297 ++++ v4.0/src/BIOS/PSOPTION.INC | 63 + v4.0/src/BIOS/PUSHPOP.INC | 20 + v4.0/src/BIOS/READCLOC.INC | 165 +++ v4.0/src/BIOS/STKINIT.INC | 271 ++++ v4.0/src/BIOS/SYSCONF.ASM | 3392 ++++++++++++++++++++++++++++++++++++++++++++ v4.0/src/BIOS/SYSIMES.ASM | 38 + v4.0/src/BIOS/SYSINIT1.ASM | 2668 ++++++++++++++++++++++++++++++++++ v4.0/src/BIOS/SYSINIT2.ASM | 1624 +++++++++++++++++++++ 39 files changed, 21714 insertions(+) create mode 100644 v4.0/src/BIOS/BIOSTRUC.INC create mode 100644 v4.0/src/BIOS/CLOCKSUB.INC create mode 100644 v4.0/src/BIOS/CMOSEQU.INC create mode 100644 v4.0/src/BIOS/DEFEMS.INC create mode 100644 v4.0/src/BIOS/DEVMARK.INC create mode 100644 v4.0/src/BIOS/JUMPMAC.INC create mode 100644 v4.0/src/BIOS/LOCSCR create mode 100644 v4.0/src/BIOS/MAKEFILE create mode 100644 v4.0/src/BIOS/MS96TPI.INC create mode 100644 v4.0/src/BIOS/MSAUX.ASM create mode 100644 v4.0/src/BIOS/MSBDATA.INC create mode 100644 v4.0/src/BIOS/MSBIO.LNK create mode 100644 v4.0/src/BIOS/MSBIO.SKL create mode 100644 v4.0/src/BIOS/MSBIO1.ASM create mode 100644 v4.0/src/BIOS/MSBIO2.ASM create mode 100644 v4.0/src/BIOS/MSCLOCK.ASM create mode 100644 v4.0/src/BIOS/MSCON.ASM create mode 100644 v4.0/src/BIOS/MSDISK.ASM create mode 100644 v4.0/src/BIOS/MSDSKPR.INC create mode 100644 v4.0/src/BIOS/MSEQU.INC create mode 100644 v4.0/src/BIOS/MSEXTRN.INC create mode 100644 v4.0/src/BIOS/MSGROUP.INC create mode 100644 v4.0/src/BIOS/MSHARD.ASM create mode 100644 v4.0/src/BIOS/MSINIT.ASM create mode 100644 v4.0/src/BIOS/MSIOCTL.INC create mode 100644 v4.0/src/BIOS/MSLOAD.ASM create mode 100644 v4.0/src/BIOS/MSLOAD.INC create mode 100644 v4.0/src/BIOS/MSLPT.ASM create mode 100644 v4.0/src/BIOS/MSMACRO.INC create mode 100644 v4.0/src/BIOS/MSSTACK.INC create mode 100644 v4.0/src/BIOS/MSVOLID.INC create mode 100644 v4.0/src/BIOS/PSOPTION.INC create mode 100644 v4.0/src/BIOS/PUSHPOP.INC create mode 100644 v4.0/src/BIOS/READCLOC.INC create mode 100644 v4.0/src/BIOS/STKINIT.INC create mode 100644 v4.0/src/BIOS/SYSCONF.ASM create mode 100644 v4.0/src/BIOS/SYSIMES.ASM create mode 100644 v4.0/src/BIOS/SYSINIT1.ASM create mode 100644 v4.0/src/BIOS/SYSINIT2.ASM (limited to 'v4.0/src/BIOS') diff --git a/v4.0/src/BIOS/BIOSTRUC.INC b/v4.0/src/BIOS/BIOSTRUC.INC new file mode 100644 index 0000000..f131e11 --- /dev/null +++ b/v4.0/src/BIOS/BIOSTRUC.INC @@ -0,0 +1,103 @@ +%OUT BIOSTRUC.INC... +; SCCSID = @(#)BIOSTRUC.INC 1.0 86/09/30 +; ROM BIOS CALL PACKET STRUCTURES + +;******************************* +;System Service call ( Int 15h ) +;******************************* +;Function AH = 0C0h, Return system configuration +;For PC and PCJR on return: +; (AH) = 80h +; (CY) = 1 +;For PCXT, PC PORTABLE and PCAT on return: +; (AH) = 86h +; (CY) = 1 +;For all others: +; (AH) = 0 +; (CY) = 0 +; (ES:BX) = pointer to system descriptor vector in ROS +; System descriptor : +; DW xxxx length of descriptor in bytes, +; minimum length = 8 +; DB xx model byte +; 0FFh = PC +; 0FEh = PC/XT, Portable +; 0FDh = PC/JR +; 0FCh = PC/AT, 6Mhz PC/AT, +; 6Mhz PC/AT running coprocessor(?), +; PS/2 Model 50, 50 z +; 0FAh = PS/2 Model 25, 30 +; 0F9h = PC Convertible +; 0F8h = PS/2 Model 80 +; 0F7h = Nova +; 0E0 thru 0EFh = reserved +; +; DB xx secondary model byte +; 000h = PC1 +; 000h = PC/XT, Portable +; 000h = PC/JR +; 000h = PC/AT +; 001h = 6Mhz PC/AT +; 003h = 6Mhz PC/AT running coprocessor(?) +; 004h = PS/2 Model 50, 50z +; 001h = PS/2 Model 25 +; 000h = PC Convertible +; 000h = PS/2 Model 80 +; 000h = Nova +; +; DB xx bios revision level +; 00 for first release, subsequent release +; of code with same model byte and +; secondary model byte require revison level +; to increase by one. +; +; DB xx feature information byte 1 +; X0000000 = 1, bios use DMA channel 3 +; = 0, DMA channel 3 not used +; +; 0X000000 = 1, 2nd Interrupt chip present +; = 0, 2nd Interrupt chip not present +; +; 00X00000 = 1, Real Time Clock present +; = 0, Real Time Clock not present +; +; 000X0000 = 1, Keyboard escape sequence(INT15h) +; called in keyboard interrupt +; (Int 09h). +; = 0, Keyboard escape sequence not +; called. +; 0000XXXX reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; +; DB xx feature information byte 2 - reserved +; + +BIOS_SYSTEM_DESCRIPTOR struc +bios_SD_leng dw ? +bios_SD_modelbyte db ? +bios_SD_scnd_modelbyte db ? + db ? +bios_SD_featurebyte1 db ? + db 4 dup (?) +BIOS_SYSTEM_DESCRIPTOR ends + +;FeatureByte1 bit map equates +DMAchannel3 equ 10000000b +ScndIntController equ 01000000b +RealTimeClock equ 00100000b +KeyEscapeSeq equ 00010000b +; +;Model Byte +MDL_PC1 EQU 0FFH +MDL_XT EQU 0FEH +MDL_JR EQU 0FDH +MDL_AT EQU 0FCH +MDL_CONVERT EQU 0F9H + +mdl_ps2_30 equ 0fah +mdl_ps2_80 equ 0f8h diff --git a/v4.0/src/BIOS/CLOCKSUB.INC b/v4.0/src/BIOS/CLOCKSUB.INC new file mode 100644 index 0000000..65b6698 --- /dev/null +++ b/v4.0/src/BIOS/CLOCKSUB.INC @@ -0,0 +1,78 @@ +; +; date_verify loosely checks bcd date values to be in range in bin_date_time +; +date_verify: ; +assume ds:code,es:nothing + cmp byte ptr bin_date_time+0,20h ; century check + ja date_error ; jmp error + jz century_20 ; jmp in 20th century + cmp byte ptr bin_date_time+0,19h ; century check + jb date_error ; jmp error + cmp byte ptr bin_date_time+1,80h ; year check + jb date_error ; jmp error +century_20: ; + cmp byte ptr bin_date_time+1,99h ; year check + ja date_error ; jmp error + cmp byte ptr bin_date_time+2,12h ; month check + ja date_error ; jmp error + cmp byte ptr bin_date_time+2,00h ; month check + jbe date_error ; jmp error + cmp byte ptr bin_date_time+3,31h ; day check + ja date_error ; jmp error + cmp byte ptr bin_date_time+3,00h ; day check + jbe date_error ; jmp error + clc ; set success flag + ret ; +date_error: ; + stc ; set error flag + ret ; + +; +; time_verify very loosely checks bcd date values to be in range in bin_date_time +; +time_verify: +assume ds:code,es:nothing + cmp byte ptr bin_date_time+0,24H + ja time_error + cmp byte ptr bin_date_time+1,59H + ja time_error + cmp byte ptr bin_date_time+2,59H + ja time_error + clc + ret +time_error: + stc + ret + +; +; bcd_verify checks values in bin_date_time to be valid +; bcd numerals. carry set if any nibble out of range +; +bcd_verify: ; +assume ds:code,es:nothing + mov cx,4 ; 4 bytes to check + mov bx,offset bin_date_time ; +bv_loop: ; + mov al,[bx] ; get a bcd number (0..99) + mov ah,al ; + and ax,0f00fh ; 10's place in high ah, 1's in al + cmp al,10 ; is 1's place in range? + ja bv_error ; jmp out of range + shr ah,1 ; swap nibbles + shr ah,1 ; ... + shr ah,1 ; ... + shr ah,1 ; ... + and ah,0fh ; get rid of any erroneous bits + cmp ah,10 ; is 10's place in range + ja bv_error ; jmp out of range + inc bx ; next byte + dec cx ; + jnz bv_loop ; + clc ; set success flag + ret ; +bv_error: ; + stc ; set error flag + ret ; +; +; Dos 3.30 - The real time clock structures were moved to msbio2.asm +; diff --git a/v4.0/src/BIOS/CMOSEQU.INC b/v4.0/src/BIOS/CMOSEQU.INC new file mode 100644 index 0000000..b52b259 --- /dev/null +++ b/v4.0/src/BIOS/CMOSEQU.INC @@ -0,0 +1,50 @@ + ;;Rev 3.30 Modification +;Equates for CMOS. + +;---------------------------------------- +; CMOS EQUATES FOR THIS SYSTEM : +;------------------------------------------------------------------------------- +CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT +CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT +NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - + ; HIGH BIT OF CMOS LOCATION ADDRESS + +;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- +CMOS_SECONDS EQU 000H ; SECONDS +CMOS_SEC_ALARM EQU 001H ; SECONDS ALARM ## NOTE: ALL LOCATIONS +CMOS_MINUTES EQU 002H ; MINUTES | IN THE CMOS AREA +CMOS_MIN_ALARM EQU 003H ; MINUTES ALARM | ARE IBM USE ONLY +CMOS_HOURS EQU 004H ; HOURS | AND SUBJECT TO +CMOS_HR_ALARM EQU 005H ; HOURS ALARM | CHANGE. ONLY THE +CMOS_DAY_WEEK EQU 006H ; DAY OF THE WEEK | POST & BIOS CODE +CMOS_DAY_MONTH EQU 007H ; DAY OF THE MONTH | SHOULD DIRECTLY +CMOS_MONTH EQU 008H ; MONTH | ACCESS LOCATIONS +CMOS_YEAR EQU 009H ; YEAR (TWO DIGITS) | IN CMOS STORAGE. +CMOS_REG_A EQU 00AH ; STATUS REGISTER A '----------------- +CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM +CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS +CMOS_REG_D EQU 00DH ; STATUS REGISTER D BATTERY +CMOS_DIAG EQU 00EH ; POST DIAGNOSTIC STATUS RESULTS BYTE +CMOS_SHUT_DOWN EQU 00FH ; SHUTDOWN STATUS COMMAND BYTE +CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; +; EQU 011H ; - RESERVED ;C +CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H +; EQU 013H ; - RESERVED ;E +CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C +CMOS_B_M_S_LO EQU 015H ; BASE MEMORY SIZE - LOW BYTE (X1024) ;K +CMOS_B_M_S_HI EQU 016H ; BASE MEMORY SIZE - HIGH BYTE ;S +CMOS_E_M_S_LO EQU 017H ; EXPANSION MEMORY SIZE - LOW BYTE ;U +CMOS_E_M_S_HI EQU 018H ; EXPANSION MEMORY SIZE - HIGH BYTE ;M +CMOS_DISK_1 EQU 019H ; FIXED DISK TYPE - DRIVE C EXTENSION ;E +CMOS_DISK_2 EQU 01AH ; FIXED DISK TYPE - DRIVE D EXTENSION ;D +; EQU 01BH ; - 1BH THROUGH 2DH - RESERVED ; +CMOS_CKSUM_HI EQU 02EH ; CMOS CHECKSUM - HIGH BYTE ;* +CMOS_CKSUM_LO EQU 02FH ; CMOS CHECKSUM - LOW BYTE ;* +CMOS_U_M_S_LO EQU 030H ; USABLE MEMORY ABOVE 1 MEG - LOW BYTE +CMOS_U_M_S_HI EQU 031H ; USABLE MEMORY ABOVE 1 MEG - HIGH BYTE +CMOS_CENTURY EQU 032H ; DATE CENTURY BYTE (BCD) +CMOS_INFO128 EQU 033H ; 128KB INFORMATION STATUS FLAG BYTE +; EQU 034H ; - 34H THROUGH 3FH - RESERVED +; + ;;End of Modification + \ No newline at end of file diff --git a/v4.0/src/BIOS/DEFEMS.INC b/v4.0/src/BIOS/DEFEMS.INC new file mode 100644 index 0000000..a1786d0 --- /dev/null +++ b/v4.0/src/BIOS/DEFEMS.INC @@ -0,0 +1,33 @@ +;J.K. This is a temporary version of EMS function definitions needed for +;IBMBIO SYSINIT. + +EMS_INT equ 67h ;interrupt vector designated for EMS. + +EMS_STATUS equ 40h ;status of memery manager +EQ_PAGES equ 42h ;get number of unallocated & total pages +E_GET_HANDLE equ 43h ;allocate pages +EMAP_L_TO_P equ 44h ;Map logical to physical page +EMAP_STATE equ 4Fh ;Mapping status + GET_MAP_STATE equ 00h + GET_MAP_SIZE equ 02h + SET_MAP_STATE equ 01h +EDE_ALLOCATE equ 45h ;deallocate pages +EMS_VERSION equ 46h ;Get EMM version number +GET_PAGE_FRAME equ 58h ;Get page frame address + GET_PAGEFRAME_TAB equ 00H + GET_NUM_PAGEFRAME equ 01H +EMS_HANDLE_NAME equ 53h + SET_HANDLE_NAME equ 01h + +IBM_PAGE_ID equ 255 ;Physical page id that will be used by + ;IBMBIO and IBMDOS for buffer manipulation. + +;MAX_NUM_PAGEFRAME equ 12 ;maximum number of page frames IBMBIO can + ;handle + +MAX_NUM_PAGEFRAME equ 64 ;maximum number of page frames MSBIO can + ;handle + +EMSVERSION equ 40h ;4.0 + + \ No newline at end of file diff --git a/v4.0/src/BIOS/DEVMARK.INC b/v4.0/src/BIOS/DEVMARK.INC new file mode 100644 index 0000000..1b919f7 --- /dev/null +++ b/v4.0/src/BIOS/DEVMARK.INC @@ -0,0 +1,23 @@ +;Structure, Equtes for DEVMARK for MEM command. + +DEVMARK struc +DEVMARK_ID db 0 +DEVMARK_SEG dw 0 +DEVMARK_SIZE dw 0 +DEVMARK_DUM db 3 dup (?) +DEVMARK_FILENAME db 8 dup (' ') +DEVMARK ends + +DEVMARK_STK equ 'S' +DEVMARK_DEVICE equ 'D' +DEVMARK_IFS equ 'I' +DEVMARK_BUF equ 'B' +DEVMARK_CDS equ 'L' ;lastdrive +DEVMARK_FILES equ 'F' +DEVMARK_FCBS equ 'X' +DEVMARK_INST equ 'T' ;used for SYSINIT BASE for INSTALL= command. +DEVMARK_EMS_STUB equ 'E' + +SETBRKDONE equ 00000001b +FOR_DEVMARK equ 00000010b +NOT_FOR_DEVMARK equ 11111101b diff --git a/v4.0/src/BIOS/JUMPMAC.INC b/v4.0/src/BIOS/JUMPMAC.INC new file mode 100644 index 0000000..e631e2e --- /dev/null +++ b/v4.0/src/BIOS/JUMPMAC.INC @@ -0,0 +1,31 @@ + ;;Rev 3.30 Modification +; +; given a label either 2 byte jump to another label _J +; if it is near enough or 3 byte jump to +; + +jump macro lbl + local a +.xcref + + ifndef lbl&_j ;; is this the first invocation +a: + JMP lbl + ELSE + IF (lbl&_J GE $) OR ($-lbl&_J GT 126) +a: + JMP lbl ;; is the jump too far away? + ELSE +a: + JMP lbl&_J ;; do the short one... + ENDIF + ENDIF +lbl&_j = a +.cref + endm +.xcref jump +;REDEFINE THE ABOVE MACRO TO ALWAYS TRY A 3 BYTE NEAR JUMP +JUMP MACRO LBL + JMP LBL + ENDM ;;End of Modification + \ No newline at end of file diff --git a/v4.0/src/BIOS/LOCSCR b/v4.0/src/BIOS/LOCSCR new file mode 100644 index 0000000..2bbd69c --- /dev/null +++ b/v4.0/src/BIOS/LOCSCR @@ -0,0 +1 @@ +70 diff --git a/v4.0/src/BIOS/MAKEFILE b/v4.0/src/BIOS/MAKEFILE new file mode 100644 index 0000000..66a281f --- /dev/null +++ b/v4.0/src/BIOS/MAKEFILE @@ -0,0 +1,167 @@ +#************************** makefile for bios *************************** + +dest =io +msg =..\messages +dos =..\dos +inc =..\inc +hinc =..\h + +# +####################### dependencies begin here. ######################### +# + +all: $(dest).sys + +msbio.cl1: msbio.skl \ + $(msg)\$(COUNTRY).msg + +msload.obj: msload.asm \ + makefile \ + msbio.cl1 \ + $(inc)\bootform.inc \ + $(inc)\versiona.inc \ + msload.inc + +msload.com: msload.obj + link msload.obj,msload,,; + exe2bin msload.exe msload.com + +msbio1.obj: msbio1.asm \ + makefile \ + msbdata.inc \ + msgroup.inc \ + jumpmac.inc \ + pushpop.inc \ + $(inc)\devsym.inc \ + msdskpr.inc \ + msmacro.inc + +mscon.obj: mscon.asm \ + makefile \ + msgroup.inc \ + jumpmac.inc \ + msmacro.inc + +msaux.obj: msaux.asm \ + makefile \ + msgroup.inc \ + jumpmac.inc \ + msmacro.inc + +mslpt.obj: mslpt.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + msmacro.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc $(inc)\bpb.inc + +msclock.obj: msclock.asm \ + makefile \ + msgroup.inc \ + msmacro.inc + +msdisk.obj: msdisk.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + pushpop.inc \ + msmacro.inc \ + $(inc)\devsym.inc \ + msdskpr.inc \ + msioctl.inc $(inc)\ioctl.inc $(inc)\bpb.inc + +msinit.obj: msinit.asm \ + makefile \ + msgroup.inc \ + msdskpr.inc \ + msequ.inc $(inc)\msbds.inc \ + $(inc)\cputype.inc \ + msmacro.inc \ + readcloc.inc \ + clocksub.inc \ + msextrn.inc + + +sysinit1.obj: sysinit1.asm \ + makefile \ + msstack.inc \ + msbio.cl4 \ + msbio.cl5 \ + stkinit.inc \ + devmark.inc \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\cputype.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + + +sysconf.obj: sysconf.asm \ + makefile \ + psoption.inc \ + devmark.inc \ + $(inc)\psdata.inc \ + $(inc)\parse.asm \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + +sysinit2.obj: sysinit2.asm \ + makefile \ + devmark.inc \ + $(inc)\copyrigh.inc \ + $(inc)\smifssym.inc \ + $(inc)\devsym.inc \ + $(inc)\ioctl.inc \ + $(inc)\smdossym.inc $(inc)\dosmac.inc $(inc)\bpb.inc $(inc)\buffer.inc \ + $(inc)\sysvar.inc $(inc)\vector.inc $(inc)\dirent.inc \ + $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\pdb.inc $(inc)\exe.inc $(inc)\sf.inc $(inc)\arena.inc \ + $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\syscall.inc + +sysimes.obj: sysimes.asm \ + makefile \ + msmacro.inc \ + msbio.cl3 \ + msequ.inc $(inc)\msbds.inc + +msbio2.obj: msbio2.asm \ + makefile \ + msgroup.inc \ + msequ.inc \ + $(inc)\msbds.inc \ + $(inc)\devsym.inc \ + pushpop.inc \ + msmacro.inc \ + msbio.cl2 \ + ms96tpi.inc msvolid.inc + +mshard.obj: mshard.asm $(inc)\postequ.inc $(inc)\dseg.inc + +$(dest).sys: msbio.cl1 msbio1.obj mscon.obj msaux.obj \ + mslpt.obj msclock.obj msdisk.obj msbio2.obj \ + msinit.obj mshard.obj sysinit1.obj sysconf.obj \ + sysinit2.obj sysimes.obj \ + msload.com \ + makefile + link @msbio.lnk + exe2bin msbio.exe msbio.bin + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS LOGICAL DRIVE + CALL SETDRIVE ;GET BDS FOR DRIVE + INC WORD PTR DS:[DI].OPCNT + JMP EXIT ;ARR 2.41 + +DSK$CLOSE: ;ARR 2.41 + PUBLIC DSK$CLOSE + + MESSAGE FTESTDISK,<"DISK CLOSE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS LOGICAL DRIVE + CALL SETDRIVE ;GET BDS FOR DRIVE + CMP WORD PTR DS:[DI].OPCNT,0 + JZ EXITJX ; WATCH OUT FOR WRAP ARR 2.41 + DEC WORD PTR DS:[DI].OPCNT +EXITJX: + JMP EXIT + +; INPUT : DS:DI POINTS TO CURRENT BDS FOR DRIVE. +; RETURN : ZERO SET IF NO OPEN FILES +; ZERO RESET IF OPEN FILES +CHKOPCNT: + MESSAGE FTEST96,<"CHECK OPEN COUNT "> + MNUM FTEST96,AX + MESSAGE FTEST96, + CMP WORD PTR DS:[DI].OPCNT,0 + RET + +; +; AT MEDIA CHECK TIME, WE NEED TO REALLY GET DOWN AND CHECK WHAT THE CHANGE IS. +; THIS IS GUARANTEED TO BE EXPENSIVE. +; + PUBLIC MEDIACHECK +MEDIACHECK: + CALL CHECKSINGLE ; MAKE SURE CORRECT DISK IS IN PLACE + XOR SI,SI + CALL HASCHANGE + JZ MEDIARET + CALL CHECKROMCHANGE + JNZ MEDIADOVOLID + PUSH AX + PUSH DX +;SB33001**************************************************************** + mov DL, DS:[DI.drivenum] ;SB ; set logical drive number ;3.30* + mov AH, 16h ;SB ; get changeline status ;3.30* + int 13h ;SB ; call rom diskette routine ;3.30* +;SB33001**************************************************************** + POP DX + POP AX + JC MEDIADOVOLID + MOV SI,1 ; SIGNAL NO CHANGE +; THERE ARE SOME DRIVES WITH CHANGELINE THAT "LOSE" THE CHANGELINE INDICATION +; IF A DIFFERENT DRIVE IS ACCESSED AFTER THE CURRENT ONE. IN ORDER TO AVOID +; MISSING A MEDIA CHANGE, WE RETURN AN "I DON'T KNOW" TO DOS IF THE CHANGELINE +; IS NOT ACTIVE AND WE ARE ACCESSING A DIFFERENT DRIVE FROM THE LAST ONE. +; IF WE ARE ACCESSING THE SAME DRIVE, THEN WE CAN SAFELY RELY ON THE CHANGELINE +; STATUS. + PUBLIC LOSECHNG +LOSECHNG: + MOV BL,CS:[TIM_DRV] ; GET LAST DRIVE ACCESSED + CMP BYTE PTR [DI].DRIVENUM,BL + JZ MEDIARET +; DO THE 2 SECOND TWIDDLE. IF TIME >= 2 SECONDS, DO A VOLID CHECK. +; OTHERWISE RETURN "I DON'T KNOW" (STRICTLY SPEAKING, WE SHOULD RETURN A +; "NOT CHANGED" HERE SINCE THE 2 SECOND TEST SAID NO CHANGE.) - RS. + SAVEREG + CALL CHECK_TIME_OF_ACCESS + RESTOREREG + OR SI,SI + JZ MEDIADOVOLID ; CHECK_TIME SAYS ">= 2 SECS PASSED" + XOR SI,SI ; RETURN "I DON'T KNOW" + PUBLIC MEDIARET +MEDIARET: + RET +; +; SOMEHOW THE MEDIA WAS CHANGED. LOOK AT VID TO SEE. WE DO NOT LOOK AT FAT +; BECAUSE THIS MAY BE DIFFERENT SINCE WE ONLY SET MEDBYT WHEN DOING A READ +; OR WRITE. +; +MEDIADOVOLID: + CALL GETBP ; BUILD A NEW BPB IN CURRENT BDS + JC MEDIARET + CALL CHECK_VID + JNC MEDIARET + CALL MAPERROR ; FIX UP AL FOR RETURN TO DOS + RET +; +; SIMPLE, QUICK CHECK OF LATCHED CHANGE. IF NO INDICATION, THEN RETURN +; OTHERWISE DO EXPENSIVE CHECK. IF THE EXPENSIVE TEST FAILS, POP OFF THE +; RETURN AND SET AL = 15 (FOR INVALID MEDIA CHANGE) WHICH WILL BE RETURNED TO +; DOS. +;J.K. 9/16/86 For DOS 3.3, this will work only for the drive that has +;J.K. 9/16/86 changeline. + PUBLIC CHECKLATCHIO +CHECKLATCHIO: +; IF RETURNING FAKE BPB THEN ASSUME THE DISK HAS NOT CHANGED +; TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB +; JNZ CHECKRET +;J.K. 9/16/86 +; call HasChange ;change line supported? +; jz CheckRet ;No. Just return + CALL CHKOPCNT + JNZ CHECKROM +CHECKRET: + RET +; +; CHECK FOR PAST ROM INDICATIONS. IF NO ROM CHANGE INDICATED, THEN RETURN OK. +; + PUBLIC CHECKROM +CHECKROM: + CALL CHECKROMCHANGE + JZ CHECKRET ; NO CHANGE +; +; WE NOW SEE THAT A CHANGE LINE HAS BEEN SEEN IN THE PAST. LET'S DO THE +; EXPENSIVE VERIFICATION. +; + MESSAGE FTEST96,<"CHECKROMCHANGE SAYS YES...",CR,LF> + CALL GETBP ; BUILD BPB IN CURRENT BDS + JC RET_NO_ERROR_MAP ; GETBP HAS ALREADY CALLED MAPERROR + CALL CHECK_VID + JC CHECKLATCHRET ; DISK ERROR TRYING TO READ IN. + OR SI,SI ; IS CHANGED FOR SURE? + JNS CHECKRET + CALL RETURNVID +CHECKLATCHRET: + CALL MAPERROR ; FIX UP AL FOR RETURN TO DOS +RET_NO_ERROR_MAP: + STC + POP SI ; POP OFF RETURN ADDRESS + RET + +; +; CHECK THE FAT AND THE VID. RETURN IN DI -1 OR 0. RETURN WITH CARRY SET +; ONLY IF THERE WAS A DISK ERROR. RETURN THAT ERROR CODE IN AX. +; + PUBLIC CHECKFATVID +CHECKFATVID: + MESSAGE FTEST96,<"CHECK FAT",CR,LF> + CALL FAT_CHECK + OR SI,SI + JS CHANGED_DRV +; +; THE FAT WAS THE SAME. HOW ABOUT THE VOLUME ID? +; +CHECK_VID: +;J.K. Now with the extended BOOT record, the logic should be enhanced. +;If it is the extended BOOT record, then we check the volume serial +;number instead of volume id. If it is different, then set SI to -1. +;If it is same, then SI= 1 (No change). +;If it is not the extended BOOT record, then just follows the old +;logic. DOS 4.00 will check if the # of FAT in the boot record BPB +;is not 0. If it is 0 then it must be Non_FAT based system and +;should have already covered by extended boot structure checking. +;So, we will return "I don't know" by setting SI to 0. +;This routine assume the newest valid boot record is in CS:[DISKSECTOR]. +;(This will be gauranteed by a successful GETBP call right before this +;routine.) + MESSAGE FTEST96,<"CHECK VID",CR,LF> +;SB34MS96TPI001********************************************************* +;SB check the EXT_Boot_Sig variable for the Extended boot signature +;SB if it is set then go to do the extended ID check otherwise continue +;SB with code below +;SB 2 LOCS + + cmp cs:[Ext_Boot_Sig],Ext_Boot_Signature + jz Do_Ext_Check_Id +;SB34MS96TPI001********************************************************* + call HasChange ;AN000; + jz CheckRet ;AN000; + + xor si,si ;AN000; assume I don't know. + cmp byte ptr cs:[SECPERCLUSINSECTOR]+3,0 ;AN000; Don't read vol id from + je CHECKFATRET ;AN000; the directory if not FAT system + CALL READ_VOLUME_ID + JC CHECKFATRET + CALL CHECK_VOLUME_ID + OR SI,SI + JNZ CHANGED_DRV + MESSAGE FTEST96,<"VID NOT CHANGED",CR,LF> + +VID_NO_Changed: + CALL RESETCHANGED + clc ;AN000; +CHECKFATRET: + RET +CHANGED_DRV: + MOV CS:[TIM_DRV],-1 ; ENSURE THAT WE ASK ROM FOR MEDIA + RET ; CHECK NEXT TIME ROUND + ; + ; extended ID check + ; +Do_Ext_Check_ID: ;AN000; + push ax ;AN000; +;SB34MS96TPI002************************************************************** +;SB The code to check extended ID is basically a check to see if the +;Sb volume serial number is still the same. The volume serial number +;SB previously read is in cs:[Boot_Serial_H] and cs:[Boot_Serial_L] +;SB high and low words respectively. DS:DI points to the BDS of the +;SB drive under consideration. The BDS has fields containing the +;SB high and low words of the volume serial number of the media in the +;SB drive. Compare these fields to the fields mentioned above. If these +;SB fields do not match the media has changed and so we should jump +;SB to the code starting at Ext_Changed else return "I don't know" status +;SB in the register used for the changeline status and continue executing +;SB the code given below. For temporary storage use the register which +;SB has been saved and restored around this block. +;SB 7 LOCS +;SB BDS fields in inc\msbds.inc + + mov ax,cs:[Boot_Serial_L] + cmp ax,word ptr ds:[di+VOL_SERIAL] + jnz Ext_Changed + mov ax,cs:[Boot_Serial_H] + cmp ax,word ptr ds:[di+VOL_SERIAL+2] + jnz Ext_Changed + xor si,si ; don't know + +;SB34MS96TPI002************************************************************** + pop ax ;AN000; +; jmp CheckFatRet ;AN000; + jmp VID_NO_Changed ;AN001;Reset the flag +Ext_Changed: ;AN000; Serial number is different! + pop ax ;AN000; + mov si, -1 ;AN000; disk changed! + clc ;AN000; clear carry. Only SI is meaningful here. + jmp Changed_Drv ;AN000; + +; +; AT I/O TIME, WE DETECTED THE ERROR. NOW WE NEED TO DETERMINE WHETHER THE +; MEDIA WAS TRULY CHANGED OR NOT. WE RETURN NORMALLY IF MEDIA CHANGE UNKNOWN. +; AND WE POP OFF THE CALL AND JMP TO HARDERR IF WE SEE AN ERROR. +; + PUBLIC CHECKIO +CHECKIO: + CMP AH,06 + JNZ CHECKFATRET + CALL CHKOPCNT + JZ CHECKFATRET ; NO OPEN FILES +; IF RETURNING FAKE BPB THEN IGNORE DISK CHANGES +; TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB +; JNZ IGNORECHANGE + CALL GETBP ; BUILD UP A NEW BPB IN CURRENT BDS + JC NO_ERROR_MAP ; GETBP HAS ALREADY CALLED MAPERROR + CALL CHECKFATVID + JC CHECKIORET ; DISK ERROR TRYING TO READ IN. + OR SI,SI ; IS CHANGED FOR SURE? + JS CHECKIOERR ; YES CHANGED +IGNORECHANGE: + INC BP ; ALLOW A RETRY + RET +CHECKIOERR: + CALL RETURNVID +CHECKIORET: +; POP SI ; POP OFF RETURN + STC ; MAKE SURE CARRY GETS PASSED THROUGH + JMP HARDERR + +NO_ERROR_MAP: + JMP HARDERR2 +; +; RETURN VID SETS UP THE VID FOR A RETURN TO DOS. +; + PUBLIC RETURNVID +RETURNVID: + MESSAGE FTEST96,<"RETURN VID",CR,LF> + PUSH DS ; SAVE POINTER TO CURRENT BDS + PUSH DI + PUSH CX + CALL INIT_VID_LOOP ; SETS ES:DI -> VID + LDS BX,CS:[PTRSAV] + MOV [BX.EXTRA],DI + MOV [BX.EXTRA+2],ES + POP CX + POP DI ; RESTORE CURRENT BDS + POP DS + MOV AH,6 ; INVALID MEDIA CHANGE + STC + RET + +; +; MUNGE THE TIME OF LAST SUCCESSFUL ACCESS FOR TWEEKED DRIVES +; +; DON'T NEED ANY MORE +; TWEEKCHECK: +; PUSH AX +; MOV AX,WORD PTR DS:[DI].FLAGS +; TEST AL,FCHANGED_BY_FORMAT +; JZ TWEEKDONE +; MOV CS:[TIM_DRV],-1 +; TWEEKDONE: +; POP AX +; RET + +; +; DRIVE IS THE LOGICAL DRIVE TO USE +; +; FORMAT_MEDIA_CHECK: ;ARR 2.42 +; PUSH AX +; MOV AX,WORD PTR DS:[DI].FLAGS +; TEST AL,FCHANGED_BY_FORMAT +; JZ RETF1 ; MEDIA NOT CHANGED VIA FORMAT +; AND AL,NOT FCHANGED_BY_FORMAT +; MOV WORD PTR [DI].FLAGS,AX ; RESET CHANGED_BY_FORMAT BIT +; MOV SI,-1 ; MEDIA CHANGED VIA FORMAT +; RETF1: +; POP AX +; RET + +; +; MOVES THE POINTER TO THE VOLID FOR THE DRIVE INTO THE ORIGINAL REQUEST PACKET +; ON ENTRY, DS:BX POINTS TO THE ORIGINAL PACKET. +; NO ATTEMPT IS MADE TO PRESERVE REGISTERS. +; +MEDIA_SET_VID: ; ARR 2.42 + PUBLIC MEDIA_SET_VID + + CALL INIT_VID_LOOP ; SETS ES:DI -> VID + LDS BX,CS:[PTRSAV] ; GET POINTER TO PACKET + MOV WORD PTR [BX.TRANS+1],DI + MOV WORD PTR [BX.TRANS+3],ES + RET + + +; +; HIDENSITY - EXAMINE A DRIVE/MEDIA DESCRIPTOR TO SET THE MEDIA TYPE. IF +; THE MEDIA DESCRIPTOR IS NOT F9 (NOT 96TPI OR 3 1/2), WE RETURN AND LET THE +; CALLER DO THE REST. OTHERWISE, WE POP OFF THE RETURN AND JUMP TO THE TAIL +; OF GETBP. FOR 3.5" MEDIA, WE JUST RETURN. +; +; INPUTS: DS:DI POINT TO CORRECT BDS FOR THIS DRIVE +; AH HAS MEDIA BYTE +; +; OUTPUTS: CARRY CLEAR +; NO REGISTERS MODIFIED +; CARRY SET +; AL = SECTORS/FAT +; BH = NUMBER OF ROOT DIRECTORY ENTRIES +; BL = SECTORS PER TRACK +; CX = NUMBER OF SECTORS +; DH = SECTORS PER ALLOCATION UNIT +; DL = NUMBER OF HEADS +; +HIDENSITY: + PUBLIC HIDENSITY +; +; CHECK FOR CORRECT DRIVE +; + TEST WORD PTR DS:[DI].FLAGS,FCHANGELINE ; IS IT SPECIAL? + JZ DOFLOPPY ; NO, DO NORMAL FLOPPY TEST +; +; WE HAVE A MEDIA BYTE THAT IS PRETTY COMPLEX. EXAMINE DRIVE INFORMATION +; TABLE TO SEE WHAT KIND IT IS. +; + CMP BYTE PTR DS:[DI].FORMFACTOR,FFSMALL; IS IT SINGLE-MEDIA? + JZ DOFLOPPY ; YES, USE FATID... +; +; 96 TPI DRIVE +; + CMP AH,0F9H + JNZ DOFLOPPY + MOV AL,7 ; SEVEN SECTORS / FAT + MOV BX,224*256+0FH ; 224 ROOT DIR ENTRIES & 0F SECTOR MAX + MOV CX,80*15*2 ; 80 TRACKS, 15 SECTORS/TRACK, 2 SIDES + MOV DX,01*256+2 ; SECTORS/ALLOCATION UNIT & HEAD MAX +POPR: + ADD SP,2 ; POP OFF RETURN ADDRESS + JMP HAS1 ; RETURN TO TAIL OF GETBP + +DOFLOPPY: + RET + + PATHSTART 001,TPI96 + +; +; CERTAIN BOGUS PROGRAMS AVOID DOS ALTOGETHER AND USE INT 13 DIRECTLY. THESE +; PROGRAMS EVEN RETRY OPERATIONS AND, THUS, WILL IGNORE THE DISK CHANGE LOGIC. +; +; WE HOOK INT 13 AND NOTE ALL ERRORS. +; + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUBLIC REAL13 +REAL13 DD ? +OLDINT DD ? +DMY DW ? + + PATHEND 001,TPI96 + + PUBLIC INT13 +INT13 PROC FAR + POP WORD PTR OLDINT + POP WORD PTR OLDINT+2 + POP DMY + MESSAGE FTEST13,<"*"> + PUSHF + CALL REAL13 ; SIMULATE ANOTHER INT 13 + JC ERR13 ; DID AN ERROR OCCUR? + JMP OLDINT ; NO, RETURN AND POP OFF FLAGS +ERR13: + MESSAGE FTEST13,<"INT 13 ERROR "> + MNUM FTEST13,AX + MESSAGE FTEST13, + PUSHF ; SAVE STATE + CMP AH,06H ; DID I SEE A CHANGE EVENT? + JZ GOTERR ; YES +B: POPF ; NO, SOME OTHER ERROR, IGNORE IT + JMP OLDINT ; RETURN AND POP OFF FLAGS +GOTERR: OR DL,DL ; IS THIS FOR THE HARD DISK? + JS B ; YES, IGNORE + MOV WORD PTR CS:[FLAGBITS],FCHANGED + CALL SET_CHANGED_DL + JMP B +INT13 ENDP + +; +; SET_CHANGED_DL - SETS FLAG BITS ACCORDING TO BITS SET IN [FLAGBITS]. +; ESSENTIALLY USED TO INDICATE CHANGELINE, OR FORMAT. +; +; INPUTS: DL CONTAINS PHYSICAL DRIVE NUMBER +; [FLAGBITS] CONTAINS BITS TO SET IN THE FLAG FIELD IN THE BDSS +; OUTPUTS: NONE +; REGISTERS MODIFIED: FLAGS +; +SET_CHANGED_DL: + PUBLIC SET_CHANGED_DL + + MESSAGE FTEST96,<"SET CHANGED",CR,LF> + PUSH BX + PUSH DX + MOV BL,DL +ALL_SET: + MOV DX,CS:[FLAGBITS] ; GET BITS TO SET IN FLAG FIELD + XOR BH,BH +; +; IN THE VIRTUAL DRIVE SYSTEM WE *MUST* FLAG THE OTHER DRIVES AS BEING CHANGED +; +; ASSUME FIRST BDS IS IN THIS SEGMENT + PUSH AX + PUSH DS ; SAVE CURRENT BDS + PUSH DI + LDS DI,DWORD PTR CS:[START_BDS] +SCAN_BDS: + CMP DI,-1 + JZ SKIPSET + CMP BYTE PTR [DI].DRIVENUM,BL + JNZ GET_NEXT_BDS +; +; SOMEONE MAY COMPLAIN, BUT THIS *ALWAYS* MUST BE DONE WHEN A DISK CHANGE IS +; NOTED. THERE ARE *NO* OTHER COMPROMISING CIRCUMSTANCES. +; +SETCHANGED: + OR WORD PTR DS:[DI].FLAGS,DX ; SIGNAL CHANGE ON OTHER DRIVE +GET_NEXT_BDS: + MOV AX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,AX + JMP SHORT SCAN_BDS +SKIPSET: + POP DI ; RESTORE CURRENT BDS + POP DS + POP AX + POP DX + POP BX + RET + +; +; CHECKROMCHANGE - SEE IF EXTERNAL PROGRAM HAS DIDDLED ROM CHANGE LINE. +; +; INPUTS: DS:DI POINTS TO CURRENT BDS. +; OUTPUTS: ZERO SET - NO CHANGE +; ZERO RESET - CHANGE +; REGISTERS MODIFIED: NONE + +CHECKROMCHANGE: + MESSAGE FTEST13,<"CHECKROM "> + MNUM FTEST13 + MESSAGE FTEST13, + TEST WORD PTR [DI].FLAGS,FCHANGED + RET + +; +; RESETCHANGED - RESTORE VALUE OF CHANGE LINE +; +; INPUTS: DS:DI POINTS TO CURRENT BDS +; OUTPUTS: NONE +; REGISTERS MODIFIED: NONE + + public ResetChanged +RESETCHANGED: + MESSAGE FTEST13,<"RESETCHANGED "> + MNUM FTEST13 + MESSAGE FTEST13, + AND WORD PTR DS:[DI].FLAGS,NOT FCHANGED + RET + +; +; HASCHANGE - SEE IF DRIVE CAN SUPPLY CHANGE LINE +; +; INPUTS: DS:DI POINTS TO CURRENT BDS +; OUTPUTS: ZERO SET - NO CHANGE LINE AVAILABLE +; ZERO RESET - CHANGE LINE AVAILABLE +; REGISTERS MODIFIED: NONE + + PUBLIC HASCHANGE +HASCHANGE: + MESSAGE FTEST13,<"HASCHANGE "> + MNUM FTEST13 + MESSAGE FTEST13, + TEST WORD PTR [DI].FLAGS,FCHANGELINE + RET + + ASSUME DS:CODE + + INCLUDE MSVOLID.INC + + PUBLIC END96TPI +END96TPI LABEL BYTE diff --git a/v4.0/src/BIOS/MSAUX.ASM b/v4.0/src/BIOS/MSAUX.ASM new file mode 100644 index 0000000..4d5a95e --- /dev/null +++ b/v4.0/src/BIOS/MSAUX.ASM @@ -0,0 +1,281 @@ + TITLE MSAUX - DOS 3.3 +;---------------------------------------------------------------- +; : +; A U X - AUXILARY DEVICE DRIVER : +; : +; : +; This file contains the Auxilary Device Driver. The : +; auxilary driver handles calls to and from the RS-232 port. : +; Three devices uses this code: AUX, COM1, and COM2. AUX and : +; COM1 talk to the zero RS-232 card and COM2 talks to the : +; 'one' RS-232 card. The beginning of the interrupt entry : +; point for these devices sets the variable AUXNUM in the : +; msbio.asm module. If the value is 0 the routines in this : +; file will talk to the the 'zero' card. If the value in : +; AUXNUM is 1 the routines will talk to the 'one' card. : +; The procedure GETDX is called to put the value 0 or 1 in : +; the DX register depending on the value in AUXBUF. : +; : +; The routines in this files are: : +; : +; routine function : +; ------- -------- : +; AUX$READ Read characters from the : +; specified device. : +; AUX$RDND Non-desrucrtive read with : +; no waiting. : +; AUX$FLSH Flush specified device input : +; buffer. : +; AUX$WRIT Write characters to the : +; specified device. : +; AUX$WRST Get status of specified : +; device : +; : +; These routines are not called directly. Call are made via : +; the strategy and interrupt entry point (see Device Header). : +; : +; Data structure: : +; The Aux Device has a two byte buffer called AUXBUF. The : +; first byte is for the zero card, the second byte is for the : +; one card. A zero value in the byte indicates the buffer is : +; empty. The routines use GETBX to get the address of the : +; buffer. : +; : +;---------------------------------------------------------------- + +;;Ver 3.30 modification --------------------------- + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE JUMPMAC.INC + INCLUDE MSMACRO.INC + + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN GETDX:NEAR ;MSBIO1 + EXTRN RDEXIT:NEAR ;MSCON + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + ;DATA + EXTRN AUXBUF:BYTE ;MSDATA + +; VALUES IN AH, REQUESTING FUNCTION OF INT 14H IN ROM BIOS +AUXFUNC_SEND EQU 1 ;TRANSMIT +AUXFUNC_RECEIVE EQU 2 ;READ +AUXFUNC_STATUS EQU 3 ;REQUEST STATUS + +; ERROR FLAGS, REPORTED BY INT 14H + +; THESE FLAGS REPORTED IN AH: +FLAG_DATA_READY EQU 01H ;DATA READY +FLAG_OVERRUN EQU 02H ;OVERRUN ERROR +FLAG_PARITY EQU 04H ;PARITY ERROR +FLAG_FRAME EQU 08H ;FRAMING ERROR +FLAG_BREAK EQU 10H ;BREAK DETECT +FLAG_TRANHOL_EMP EQU 20H ;TRANSMIT HOLDING REGISTER EMPTY +FLAG_TRANSHF_EMP EQU 40H ;TRANSMIT SHIFT REGISTER EMPTY +FLAG_TIMEOUT EQU 80H ;TIMEOUT + +; THESE FLAGS REPORTED IN AL: +FLAG_DELTA_CTS EQU 01H ;DELTA CLEAR TO SEND +FLAG_DELTA_DSR EQU 02H ;DELTA DATA SET READY +FLAG_TRAIL_RING EQU 04H ;TRAILING EDGE RING INDICATOR +FLAG_DELTA_SIG EQU 08H ;DELTA RECEIVE LINE SIGNAL DETECT +FLAG_CTS EQU 10H ;CLEAR TO SEND +FLAG_DSR EQU 20H ;DATA SET READY +FLAG_RING EQU 40H ;RING INDICATOR +FLAG_REC_SIG EQU 80H ;RECEIVE LINE SIGNAL DETECT +;;End of modification ------------------ + + +;---------------------------------------------------------------- +; : +; Read zero or more characters from Auxilary Device : +; : +; input:es:[di] points to area to receive aux data : +; cx has number of bytes to be read : +; "auxnum" first byte has number of aux device (rel 0): +; : +;---------------------------------------------------------------- + PUBLIC AUX$READ +AUX$READ PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + jcxz EXVEC2 ; if no characters, get out + call GETBX ; put address of AUXBUF in BX + xor AX,AX ; clear AX register + xchg AL,[BX] ; Get character , if any, from + ; buffer and clear buffer + or AL,AL ; if AL is nonzero there was a + ; character in the buffer + jnz AUX2 ; if so skip AUXIN call +AUX1: ; + call AUXIN ; get character from port +AUX2: ; + stosb ; store character + loop AUX1 ; if more character, go around again +EXVEC2: ; + Jump EXIT ; all done, successful exit +AUX$READ ENDP + +; +; AUXIN: make a call on ROM BIOS to read character from +; the auxilary device, then do some error checking. +; If an error occurs then AUXIN jumps to ERR$CNT and +; does NOT return to where it was called from. +; + +AUXIN PROC NEAR + + mov ah,AUXFUNC_RECEIVE + call AUXOP + ;check for Frame, Parity, or Overrun errors + ;WARNING: these error bits are unpredictable + ; if timeout (bit 7) is set + test ah,FLAG_FRAME or FLAG_PARITY or FLAG_OVERRUN + jz AROK ;No error if all bits are clear + + ;Error getting character + add sp,+2 ;Remove rtn address (near call) + xor al,al + or al,FLAG_REC_SIG or FLAG_DSR or FLAG_CTS + + JUMP ERR$CNT +AROK: + RET ;CHAR JUST READ IS IN AL, STATUS IS IN AH +AUXIN ENDP + +;---------------------------------------------------------------- +; : +; Aux non-destructive read with no waiting : +; : +; input: es:[di] points to area to receive aux data : +; : +;---------------------------------------------------------------- +; + PUBLIC AUX$RDND +AUX$RDND PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call GETBX ; have BX point to AUXBUF + mov AL,[BX] ; copy contents of buffer to AL + or AL,AL ; if AL is non-zero (char in buffer) + jnz AUXRDX ; then return character + call AUXSTAT ; if not, get status of AUX device + TEST AH,FLAG_DATA_READY ;TEST DATA READY + jz AUXBUS ; then device is busy (not ready) + + TEST AL,FLAG_DSR ;TEST DATA SET READY + jz AUXBUS ; then device is busy (not ready) + call AUXIN ; else aux is ready, get character + call GETBX ; have bx point to AUXBUF + mov [BX],AL ; save character in buffer +AUXRDX: ; + Jump RDEXIT ; return character + +AUXBUS: ; + Jump BUS$EXIT ; jump to device busy exit +AUX$RDND ENDP + +;---------------------------------------------------------------- +; : +; Aux Output Status : +; : +;---------------------------------------------------------------- + PUBLIC AUX$WRST +AUX$WRST PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call AUXSTAT ; get status of AUX in AX + ; now test to see if device is busy + ; if this bit is not set, +;;Ver 3.30 modification ----------------------- + TEST AL,FLAG_DSR ;TEST DATA SET READY + jz AUXBUS ; then device is busy (not ready) + TEST AH,FLAG_TRANHOL_EMP ;TEST TRANSMIT HOLD REG EMPTY +;;End of modification ------------------------- + jz AUXBUS ; then device is busy (not ready) + Jump Exit + +AUX$WRST ENDP + +; +; AUXSTAT makes a call on the ROM-BIOS to determine the status +; of the auxilary device +; Outputs: +; AX is filled with status of port. +; DX is changes to specify which card - either 0, 1 (, 2, 3) ;ba +; NO other registers are modified +; + +AUXSTAT proc near + mov ah,AUXFUNC_STATUS + call AUXOP + ret +AUXSTAT endp + +AUXOP PROC NEAR + ;AH=FUNCTION CODE + ;0=INIT, 1=SEND, 2=RECEIVE, 3=STATUS + call GETDX ; have DX point to proper card + int 14h ; call rom-bios for status + ret +AUXOP ENDP + +;---------------------------------------------------------------- +; : +; Flush AUX Input buffer - set contents of AUXBUF to zero : +; : +;---------------------------------------------------------------- + PUBLIC AUX$FLSH +AUX$FLSH PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + call GETBX ; get BX to point to AUXBUF + mov BYTE PTR [BX],0 ; zero out buffer + Jump Exit ; all done, successful return +AUX$FLSH ENDP + + + +;---------------------------------------------------------------- +; : +; Write to Auxilary Device : +; : +;---------------------------------------------------------------- + PUBLIC AUX$WRIT +AUX$WRIT PROC NEAR + ASSUME DS:CODE ; SET BY AUX DEVICE DRIVER ENTRY ROUTINE + jcxz EXVEC2 ; if CX is zero, no characters + ; to be written, jump to exit +AUX$LOOP: + mov AL,ES:[DI] ; get character to be written + inc DI ; move DI pointer to next character +;;Ver 3.30 modification --------------------------- + MOV AH,AUXFUNC_SEND ;VALUE=1, INDICATES A WRITE + CALL AUXOP ;SEND CHARACTER OVER AUX PORT + + TEST AH,FLAG_TIMEOUT ;CHECK FOR ERROR +;;End of modification --------------------------- + jz AWOK ; then no error + mov AL,10 ; else indicate write fault + Jump ERR$CNT ; call error routines + + ; if CX is non-zero, still more +AWOK: + loop AUX$LOOP ; more characrter to print + Jump Exit ; all done, successful return +AUX$WRIT ENDP + + +; +; GETBX puts the address of AUXBUF (the Auxilary Device buffer) +; in BX. After calling GETBX, a routine can get to AUXBUF +; with [BX]. +; +; NOTE: The getdx routine is in msbio1 and looks like: +; mov dx,word ptr cs:[auxnum] +; +GETBX PROC NEAR + call GETDX + mov BX,DX + add BX,OFFSET AUXBUF + ret +GETBX ENDP + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSBDATA.INC b/v4.0/src/BIOS/MSBDATA.INC new file mode 100644 index 0000000..d0be320 --- /dev/null +++ b/v4.0/src/BIOS/MSBDATA.INC @@ -0,0 +1,722 @@ +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 3.4 - J.K. +;AC000 - Changed for DOS Version 3.4 - J.K. +;ANxxx - PTR, DCRs +;============================================================================== +;AN001 - d9 Double word MOV instruction for 80386 based machine. 7/1/87 J.K. +;AN002 - d25 Change DASD ERP to that recommended by Storage Systems. 7/29/87 J.K. +;AN003; d304 Boot record structure change for OS2 11/9/87 J.K. +;============================================================================== + EXTRN INIT:NEAR + + PUBLIC START$ +START$: + JMP INIT ;START$ PATCH BY INIT TO POINT TO + ;HDRIVE BPB +; PUBLIC FORMAT_PATCH +;FORMAT_PATCH: ;ARR 2.42 +; JMP FMTSET ;MJB001 DISPATCH FOR CALL FROM FORMAT UTILITY + + + PATHSTART 001,BIO + +; DB 20 DUP (0) ;IBM WANTS SOME ZEROED AREA (DELETED) + + +;HEADER DB "Ver 2.45" +;-------------------------------------------------------------- +; +; COMMAND JUMP TABLES +; +; BEWARE - THESE TABLES OVERLAP SOMEWHAT! -C.P. +; + ODD +DSKTBL LABEL BYTE + DB 24 ; THIS IS THE SIZE OF THE TABLE YUK!!!! + DW DSK$INIT + DW MEDIA$CHK + DW GET$BPB + DW CMDERR ;RS + DW DSK$READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW DSK$WRIT + DW DSK$WRITV + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW CMDERR ;RS + + PUBLIC TABLE_PATCH +TABLE_PATCH LABEL WORD ;ARR 2.42 + DW DSK$OPEN ;ARR 2.41 + DW DSK$CLOSE ;ARR 2.41 + DW DSK$REM ;ARR 2.41 + DW EXIT + DW EXIT + DW EXIT + DW GENERIC$IOCTL ; KGS 3.20 + DW EXIT + DW EXIT + DW EXIT + DW IOCTL$GETOWN ; RS 3.20 + DW IOCTL$SETOWN ; RE 3.20 + + ODD +CONTBL LABEL BYTE + DB 10 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW CON$READ + DW CON$RDND + DW EXIT + DW CON$FLSH + DW CON$WRIT + DW CON$WRIT + DW EXIT ;ARR 2.41 + +; DW CMDERR ;J.K. 4/29/86 for CON$GENIOCTL support +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CMDERR ;J.K. 4/29/86 +; DW CON$GENIOCTL ;J.K. 4/29/86 + + ODD +AUXTBL LABEL BYTE + DB 10 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW AUX$READ + DW AUX$RDND + DW EXIT + DW AUX$FLSH + DW AUX$WRIT + DW AUX$WRIT + DW AUX$WRST + + ODD +TIMTBL LABEL BYTE + DB 9 + DW EXIT + DW EXIT + DW EXIT + DW CMDERR + DW TIM$READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW TIM$WRIT + DW TIM$WRIT + + ODD +PRNTBL LABEL BYTE + DB 24 + DW EXIT ;INIT + DW EXIT + DW EXIT + DW CMDERR + DW EXIT$ZER ;INDICATE ZERO CHARS READ + DW BUS$EXIT + DW EXIT + DW EXIT + DW PRN$WRIT + DW PRN$WRIT + DW PRN$STAT + DW EXIT + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW EXIT ;ARR 2.41 + DW PRN$TILBUSY + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW PRN$GENIOCTL ;RS 3.20 + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW EXIT ;RS 3.20 + DW CMDERR ;RS 3.20 + DW CMDERR ;RS 3.20 + + EVENB + PUBLIC OLD13 ;(MOVED HERE FROM IBMBIO2) +OLD13 label DWORD + db '5986' ;J.K. 11/7/86 Secrete Code for DOS 3.30 IBMBIO. + PUBLIC ORIG13 +ORIG13 label DWORD + db '21',0,0 ;J.K. 11/8/86 This is my employee serial # !!! + + EVENB + PUBLIC PTRSAV +PTRSAV DD 0 + PUBLIC AUXBUF +AUXBUF DB 0,0,0,0 ;SET OF 1 BYTE BUFFERS FOR COM 1,2,3, AND 4 + + EVENB + PUBLIC PREVOPER,NUMBER_OF_SEC +PREVOPER DW ? ; HOLDS INT 13 REQUEST (I.E. REGISTER AX). +NUMBER_OF_SEC DB ? ; HOLDS NUMBER OF SECTORS TO READ ON AN ECC ERROR + + IF ($-CODE) GT 100H + %OUT VDISK BUFFER NOT CORRECTLY LOCATED + ELSE + ORG 100H + ENDIF + PUBLIC VDISK_AREA +VDISK_AREA DB 108 DUP(0) ;FOR USE BY VDISK + + EVENB +; WARNING!!! THESE ARE ADDRESSED TOGETHER IN GETDX +AUXNUM DB 0 ;WHICH AUX DEVICE WAS REQUESTED + DB 0 + + EVENB + PUBLIC CONHEADER +CONHEADER LABEL WORD ;HEADER FOR DEVICE "CON" + DD AUXDEV2 + DW 1000000000010011B ;CON IN AND CON OUT + SPECIAL + DW STRATEGY + DW CON$IN + DB 'CON ' + + EVENB + PUBLIC AUXDEV2 +AUXDEV2 LABEL WORD ;HEADER FOR DEVICE "AUX" + DD PRNDEV2 + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'AUX ' + + EVENB + PUBLIC PRNDEV2 +PRNDEV2 LABEL WORD ;HEADER FOR DEVICE "PRN" + DD TIMDEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN0$IN + DB 'PRN ' + + EVENB + PUBLIC TIMDEV +TIMDEV LABEL WORD + DD DSKDEV + DW 1000000000001000B + DW STRATEGY + DW TIM$IN + DB 'CLOCK$ ' + + EVENB + PUBLIC DSKDEV +DSKDEV LABEL WORD + DD COM1DEV + DW 0000100001000010B ;J.K.I1. 32 bit sector calculation + DW STRATEGY + DW DSK$IN +DRVMAX DB 4 + PUBLIC DRVMAX + + PUBLIC STEP_DRV +STEP_DRV DB -2 ; ARR 2.20 LAST DRIVE ACCESSED + + PUBLIC PHYS_DRV +PHYS_DRV DB 0 ; USED BY SETDRIVE FOR GETTING BDS FOR + ; LOGICAL DRIVE, OR PHYSICAL DRIVE. + PUBLIC FHAVE96 +FHAVE96 DB 0 ; FLAG TO INDICATE PRESENCE OF + ; 96TPI SUPPORT + PUBLIC SINGLE +SINGLE DB 0 ; USED TO DETECT SINGLE DRIVE SYSTEMS + + PUBLIC FHAVEK09 +FHAVEK09 DB 0 ;INDICATES IF THIS IS A K09 OR NOT + ; USED BY CONSOLE DRIVER. + PUBLIC NEW_ROM +NEW_ROM DB 0 ;SET TO 1 IF WE HAVE A ROM THAT CAN + ; HANDLE STRANGE MEDIA LAYOUTS. + + PUBLIC FSETOWNER +FSETOWNER DB ? ;=1 IF WE ARE SETTING THE OWNER OF A + ;DRIVE. (EXAMINED BY CHECKSINGLE). + public Secrete_Code +Secrete_Code dw 'jk' ;J.K. 11/7/86 Secrete code for DOS 3.30 IBMBIO. + + EVENB + PUBLIC COM1DEV +COM1DEV LABEL WORD + DD LPT1DEV + DW 1000000000000000B + DW STRATEGY + DW AUX0$IN + DB 'COM1 ' + + EVENB + PUBLIC LPT1DEV +LPT1DEV LABEL WORD + DD LPT2DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN1$IN + DB 'LPT1 ' + + EVENB + PUBLIC LPT2DEV +LPT2DEV LABEL WORD + DD LPT3DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN2$IN + DB 'LPT2 ' + + EVENB + PUBLIC LPT3DEV +LPT3DEV LABEL WORD + DD COM2DEV + DW CHARDEV + OUTTILBUSY + DEV320 + DW STRATEGY + DW PRN3$IN + DB 'LPT3 ' + + EVENB + PUBLIC COM2DEV +COM2DEV LABEL WORD + DD COM3DEV + DW 1000000000000000B + DW STRATEGY + DW AUX1$IN + DB 'COM2 ' + + EVENB + PUBLIC COM3DEV +COM3DEV LABEL WORD ;EDK + DD COM4DEV + DW 1000000000000000B + DW STRATEGY + DW AUX2$IN + DB 'COM3 ' + + EVENB + PUBLIC COM4DEV +COM4DEV LABEL WORD ;EDK + DW -1,CODE + DW 1000000000000000B + DW STRATEGY + DW AUX3$IN + DB 'COM4 ' + +; HARD-WIRE THE LINK TO THE NEXT INT2F HANDLER. + EVENB + PUBLIC NEXT2F_13 +NEXT2F_13 LABEL WORD + EXTRN INT2F_DISK:FAR ;IBMBIO2 + DD INT2F_DISK + + EVENB + PUBLIC START_BDS +START_BDS LABEL WORD + DD BDS1 ;START OF BDS LINKED LIST. + PUBLIC ACCESSCOUNT +ACCESSCOUNT DB 0 ; NUMBER OF TIMES MEDIA CHECK CALLED + PUBLIC TIM_DRV +TIM_DRV DB -1 ; TIME WHEN LAST DISK I/O PERFORMED + PUBLIC FLAGBITS +FLAGBITS DW 0 ; BITS TO SET IN FLAG FIELD WHEN DOING + ; A SET_CHANGED_DL + PUBLIC MEDBYT +MEDBYT DB ? + + EVENB + PUBLIC WRTVERIFY +WRTVERIFY LABEL WORD + PUBLIC RFLAG +RFLAG DB ROMREAD ;2 FOR READ, 3 FOR WRITE +VERIFY DB 0 ;1 IF VERIFY AFTER WRITE + PUBLIC SECCNT +SECCNT DW 0 + PUBLIC HARDNUM +HARDNUM DB 99 ;LOGICAL DRIVE NUMBER OF FIRST HARDFILE + PUBLIC MOTORSTARTUP,SETTLECURRENT,SETTLESLOW +MOTORSTARTUP DB ? ; VALUE FROM TABLE +SETTLECURRENT DB ? ; VALUE FROM TABLE +SETTLESLOW DB ? ; SLOW SETTLE VALUE + +NEXTSPEED DB ? ; VALUE OF SPEED TO BE USED + public save_head_sttl +Save_head_sttl db ? ;used by READ_SECTOR routine + + PUBLIC EOT +EOT DB 9 + + EVENB + PUBLIC DPT +DPT DD ? + +;KEEP THE NEXT TWO ITEMS CONTIGUOUS - SEE IOCTL_BLOCK FOR REASON + PUBLIC CURSEC,CURHD,CURTRK,SPSAV +CURSEC DB 0 ;CURRENT SECTOR +CURHD DB 0 ;CURRENT HEAD +CURTRK DW 0 ;CURRENT TRACK +SPSAV DW 0 ;SAVE THE STACK POINTER + +; THE FOLLOWING ARE USED FOR IOCTL FUNCTION CALLS + PUBLIC FORMT_EOT,HDNUM,TRKNUM,GAP_PATCH +FORMT_EOT DB 8 ; EOT USED FOR FORMAT +HDNUM DB 0 ; HEAD NUMBER +TRKNUM DW 0 ; TRACK BEING MANIPULATED +GAP_PATCH DB 50H ; FORMAT GAP PATCHED INTO DPT + +;DISK ERRORS RETURNED FROM THE IBM ROM + PUBLIC ERRIN +ERRIN LABEL BYTE + db 0cch ;AN002; Write Fault error + DB 80H ;NO RESPONSE + DB 40H ;SEEK FAILURE + DB 10H ;BAD CRC + DB 8 ;DMA OVERRUN + DB 6 ; MEDIA CHANGE + DB 4 ;SECTOR NOT FOUND + DB 3 ;WRITE ATTEMPT TO WRITE-PROTECT DISK + PUBLIC LSTERR +LSTERR DB 0 ;ALL OTHER ERRORS + +;RETURNED ERROR CODES CORRESPONDING TO ABOVE + PUBLIC ERROUT +ERROUT LABEL BYTE + db 10 ;AN002; Write Fault error + DB 2 ;NO RESPONSE + DB 6 ;SEEK FAILURE + DB 4 ;BAD CRC + DB 4 ;DMA OVERRUN + DB 15 ; INVALID MEDIA CHANGE + DB 8 ;SECTOR NOT FOUND + DB 0 ;WRITE ATTEMPT ON WRITE-PROTECT DISK + DB 12 ;GENERAL ERROR + PUBLIC NUMERR +NUMERR = ERROUT-ERRIN + +;------------------------------------------------------------- + +; READ IN BOOT SECTOR HERE, READ DONE IN READBOOT. +; ALSO READ SECTOR FOR DMA CHECK FOR HARD DISK. + +;J.K. The buffer for a disk sector is going to be at a double word boundary +; for 80386 machine. + + IF ($-CODE) Mod 4 ;AN001; + Org ($-CODE)+4-(($-CODE) Mod 4) ;AN001; + ENDIF ;AN001; + + PUBLIC DISKSECTOR +DiskSector DB 11 DUP(?) ; TAKE CARE OF 3 JUMP BYTES PLUS OEM NAME. + PUBLIC BPB_IN_SECTOR +Bpb_In_Sector DW ? + PUBLIC SECPERCLUSINSECTOR +SecPerClusInSector DB ? + DW ? + public NumberOfFats +NumberOfFats DB ? + DW ? + DW ? + PUBLIC MEDIABYTE +MediaByte DB ? + DW ? + DW ? + DW ? + DW ? + DW ? ;AN000; Extended Hidden sector (high) + DW ? ;AN000; Extended Total sector (low) + DW ? ;AN000; Extended Total sector (high) + db ? ;AN003; PHYDRV in boot record. + db ? ;AN003; CURRENT HEAD in boot record. + public Ext_Boot_Sig +Ext_Boot_Sig DB ? ;AN000; Extended Boot record sig. (=90h) + public Boot_Serial_L +Boot_Serial_L DW ? ;AN000; Boot volume serial number (Low) + public Boot_Serial_H +Boot_Serial_H DW ? ;AN000; Boot volume serial number (High) + public Boot_Volume_Label +Boot_Volume_Label DB 11 dup (' ') ;AN000; Volume label + public Boot_System_ID +Boot_System_ID DB 8 dup (' ') ;AN000; File system Id. + DB 512-($-DISKSECTOR) DUP (?) + +;********************************************************************* +; "BDS" CONTAINS INFORMATION FOR EACH DRIVE IN THE SYSTEM. +; VARIOUS VALUES ARE PATCHED WHENEVER ACTIONS ARE PERFORMED. +; SECTORS/ALLOC. UNIT IN BPB INITIALLY SET TO -1 TO SIGNIFY THAT +; THE BPB HAS NOT BEEN FILLED. LINK ALSO SET TO -1 TO SIGNIFY END +; OF LIST. # OF CYLINDERS IN MAXPARMS INITIALIZED TO -1 TO INDICATE +; THAT THE PARAMETERS HAVE NOT BEEN SET. +; + EVENB +BDS1 LABEL WORD + DD BDS2 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE1 +FDRIVE1 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT1 DW 0 ;OPEN REF. COUNT + + DB 3 ;FORM FACTOR +FLAGS1 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB1 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK1 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO1 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI1 DW -1 +VOLID1 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER1 dd 0 ;Current volume serial number from Boot record +SYSID1 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS2 LABEL WORD + DD BDS3 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE2 +FDRIVE2 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT2 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS2 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB2 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK2 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO2 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI2 DW -1 +VOLID2 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER2 dd 0 ;Current volume serial number from Boot record +SYSID2 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS3 LABEL WORD + DD BDS4 ;LINK TO NEXT STRUCTURE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE3 +FDRIVE3 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT3 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS3 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB3 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK3 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO3 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI3 DW -1 +VOLID3 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER3 dd 0 ;Current volume serial number from Boot record +SYSID3 db "FAT12 ",0 ;Current file system id from Boot record + + EVENB +BDS4 LABEL WORD + DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 0 ;INT 13 DRIVE NUMBER + DB 0 ;LOGICAL DRIVE LETTER + PUBLIC FDRIVE4 +FDRIVE4 DW 512 ;PHYSICAL SECTOR SIZE IN BYTES + DB -1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 64 ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 00000000B ;MEDIA DESCRIPTOR, INITIALLY 00H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 1 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT (low word) + dw 0 ;J.K. Hidden sector (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 0 ; TRUE => LARGE FATS +OPCNT4 DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGS4 DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +; RECOMMENDED BPB FOR DRIVE. +RECBPB4 DW 512 ;BYTES PER SECTOR + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. ALLOCATION TABLES + DW 0E0H ;NUMBER DIRECTORY ENTRIES + DW 9*40 ;NUMBER SECTORS (AT 512 BYTES EA.) + DB 0F0H ;MEDIA DESCRIPTOR, INITIALLY F0H. + DW 2 ;NUMBER OF FAT SECTORS + DW 9 ;SECTOR LIMIT + DW 2 ;HEAD LIMIT + DW 0 ;HIDDEN SECTOR COUNT(low) + dw 0 ;J.K. Hidden sector count (high) + dw 0 ;J.K. Number sectors (low) + dw 0 ;J.K. Number sectors (high) + DB 6 DUP (?) +TRACK4 DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LO4 DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HI4 DW -1 +VOLID4 DB "NO NAME ",0 ;VOLUME ID FOR THIS DISK +VOLSER4 dd 0 ;Current volume serial number from Boot record +SYSID4 db "FAT12 ",0 ;Current file system id from Boot record + +BPBTYPE STRUC +SPF DB ? +SPT DB ? +CDIRE DB ? +CSEC DW ? +SPA DB ? +CHEAD DB ? +BPBTYPE ENDS + PUBLIC SM92 +SM92 BPBTYPE <3,9,70H,2*9*80,2,2> + +;----------------------------------------------- +; +; C O N - CONSOLE DEVICE DRIVER +; + PUBLIC ALTAH +ALTAH DB 0 ;SPECIAL KEY HANDLING + public KEYRD_Func +KEYRD_Func DB 0 ;AN000; Default is conventional keyboard read + public KEYSTS_Func +KEYSTS_Func DB 1 ;AN000; Defualt if conventional keyboard status check. + +; PUBLIC SAV_SC_INFO ;J.K. 4/29/86 FOR CON$GENIOCTL +; PUBLIC SAV_SC_MODE +; PUBLIC SAV_SC_COLORS +; PUBLIC SAV_SC_WIDTH +; PUBLIC SAV_SC_LENGTH +;SAV_SC_INFO LABEL BYTE +;SAV_SC_MODE DB 0 +;SAV_SC_COLORS DW 0 +;SAV_SC_WIDTH DW 0 +;SAV_SC_LENGTH DW 0 ;J.K. 4/29/86 FOR CON$GENIOCTL + +;------------------------------------------------------------- +; +; P R N - PRINTER DEVICE +; + PUBLIC PRINTDEV +PRINTDEV DB 0 ; INDEX INTO ABOVE ARRAY + +; THE FOLLOWING VARIABLE CAN BE MODIFIED VIA IOCTL SUB-FUNCTION 16. IN THIS +; WAY, THE WAIT CAN BE SET TO SUIT THE SPEED OF THE PARTICULAR PRINTER BEING +; USED. ONE FOR EACH PRINTER DEVICE. + + EVENB + PUBLIC WAIT_COUNT +WAIT_COUNT DW 4 DUP (50H) ; ARRAY OF RETRY COUNTS FOR PRINTER + + EVENB + PUBLIC DAYCNT +DAYCNT DW 0 + + + IF iTEST ;Testing Mode for IBMBIO. + PUBLIC NUMBUF +NUMBUF DB 5 DUP (?) + PUBLIC DIGITS +DIGITS DB "0123456789ABCDEF" + PUBLIC FTESTBITS +;FTESTBITS DW FTESTDISK+FTESTINIT +FTESTBITS DW fTestDISK +;ftestbits dw ftestclock + ENDIF + + PATHEND 001,BIO + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSBIO.LNK b/v4.0/src/BIOS/MSBIO.LNK new file mode 100644 index 0000000..d1a15bd --- /dev/null +++ b/v4.0/src/BIOS/MSBIO.LNK @@ -0,0 +1,14 @@ +msbio1+ +msCON+ +msAUX+ +msLPT+ +msCLOCK+ +msDISK+ +msBIO2+ +mshard+ +msinit+ +sysinit1+ +sysconf+ +sysinit2+ +sysimes,msbio,msBIO/M; + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSBIO.SKL b/v4.0/src/BIOS/MSBIO.SKL new file mode 100644 index 0000000..9c890df --- /dev/null +++ b/v4.0/src/BIOS/MSBIO.SKL @@ -0,0 +1,139 @@ +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.0 - J.K. +;AC000 - Changed for DOS Version 4.0 - J.K. +;AN00x - PTM number for DOS Version 4.0 - J.K. +;============================================================================== +;============================================================================== +;AN001 D246, P976 Show "Bad command or parameters - ..." msg 9/22/87 J.K. +;AN002 D274 Take "file" out from "Incorrect order..." msg 10/07/87 J.K. +;AN003 D486 Share installation for large media 02/24/88 J.K. +;============================================================================== +;=================== +:class 1 +;=================== +; MESSAGES FOR THE IBM BOOT SECTOR. NUL Terminated. +; This is used by IBMBOOT and IBMLOAD program and it stays in IBMBOOT directory. + +;For IBMLOAD program +;SYSMSG DB 13,10,"Non-System disk or disk error",13,10 +; DB "Replace and strike any key when ready",13,10,0 +:use 001 BOOT SYSMSG + +;=================== +:class 2 +;=================== +; SCCSID = @(#)biomes.asm 1.2 85/07/25 +; SINGLE DRIVE MESSAGE FOR IBMBIO.COM. NUL TERMINATED. +;IFNDEF PATHSTART +;PATHSTART MACRO INDEX,ABBR +; IFDEF PATHGEN +; PUBLIC ABBR&INDEX&S,ABBR&INDEX&E +; ABBR&INDEX&S LABEL BYTE +; ENDIF +; ENDM +;ENDIF +; +;IFNDEF PATHEND +;PATHEND MACRO INDEX,ABBR +; IFDEF PATHGEN +; ABBR&INDEX&E LABEL BYTE +; ENDIF +; ENDM +;ENDIF +; PATHSTART 001,BIOMS + + +:def 20 SNGMSG DB 13,10,"Insert diskette for drive " +:def 21 DRVLET DB "A: and strike",13,10,"any key when ready",13,10,10,0 + +; PATHEND 001,BIOMS + +;================== +:class 3 +;================== + +; PRINTED when there is a bad command in CONFIG.SYS. '$' TERMINATED, note +; that this message includes crlfm! +;PATHSTART 001,SYSMES + +:def 03 BADOPM DB 13,10,"Unrecognized command in CONFIG.SYS" + +;BADSIZ_POST LABEL BYTE +;BADLD_POST LABEL BYTE + +:def 04 CRLFM DB 13,10,'$' + +:def 22 BadParm db 13,10,"Bad command or parameters - $" ;AN001; + +;PRINTED when installed device specifies too large a sector size.'$' terminated. +; FORM: device name +:def 05 BADSIZ_PRE DB 13,10,"Sector size too large in file $" + +;PRINTED when installed device cannot be found. '$' terminated. +; FORM: device name +:def 06 BADLD_PRE DB 13,10,"Bad or missing $" + +;PRINTED when command interpreter is not found. NUL terminated. +; FORM: +:def 07 BADCOM DB "Command Interpreter",0 + +;PRINTED when country code, code page combination was not found in country.sys file. '$' terminated. +; FORM: +:def 08 BADCOUNTRY DB 13,10,"Invalid country code or code page",13,10,"$" + +;PRINTED when code page id is missing or wrong syntax. - J.K. +; FORM: +:def 09 BADCOUNTRYCOM DB 13,10,"Error in COUNTRY command",13,10,"$" + +;PRINTED when the memory left is not sufficient to handle COUTRY.SYS file +; FORM: +:def 10 INSUFMEMORY DB 13,10, "Insufficient memory for COUNTRY.SYS file",13,10,"$" + +; PRINTED when there is insufficient memory. '$' TERMINATED, note +; that this message includes crlfm! +:def 11 BADMEM DB 13,10,"Configuration too large for memory",13,10,"$" + +; PRINTED when the attempt is made to install a block device which would +; have a drive letter > 'Z' +:def 12 BADBLOCK DB 13,10,"Too many Block Devices",13,10,"$" + +; PRINTED when the attempt is made to install a stack with invalid +; combinations of # of stacks, stack size. - J.K. 5/23/86 +:def 13 BADSTACK DB 13,10,"Invalid STACK parameters",13,10,"$" + +;AN000; - PRINTED when encountering a command that is not "install=" after +; we had a "Install=" command. - J.K.I1. +; Translation::: Please leave the last blank space at the end of the line +; as it is. +:def 14 BADORDER DB 13,10,"Incorrect order in CONFIG.SYS line ","$" + +;AN000; - PRINTED when the command failed. +; Translation::: Please leave the last blank space at the end of the line +; as it is. +:def 15 ERRORCMD DB "Error in CONFIG.SYS line ","$" + +;AN003; - PRINTED when SHARE.EXE is not loaded and has a large media > 32 MB. +:def 23 SHAREWARNMSG db "WARNING! SHARE should be loaded for large media",13,10,"$" + +;================== +:class 4 +;================== +;IBMBIO SYSINIT +;Message for SYSINIT_BASE program. +:def 16 Mem_alloc_err db 13,10,"Memory allocation error","$" + + +;================== +:class 5 +;================== +; %OUT STKMES.INC... +; SCCSID = @(#)stkmes.inc 1.0 86/10/21 + +; PUBLIC FATAL_MSG +:def 17 FATAL_MSG DB 0DH,0AH,7,0DH,0AH + DB "Internal stack overflow",0DH,0AH + DB "System halted",0DH,0AH,"$" +; +:END + diff --git a/v4.0/src/BIOS/MSBIO1.ASM b/v4.0/src/BIOS/MSBIO1.ASM new file mode 100644 index 0000000..36dac91 --- /dev/null +++ b/v4.0/src/BIOS/MSBIO1.ASM @@ -0,0 +1,645 @@ + + PAGE ,132 ; + TITLE MSBIO1.asm - BIOS +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +COMMENT * +THE LINK STEP IS PERFORMED BY USING THE FOLLOWING "NEW.ARF" FILE: +msbio1+ +msSTACK+ +MsCON+ +msAUX+ +msLPT+ +msCLOCK+ +msdISK+ +msBIO2+ +C:\BIO2\OLDOBJ\disk+ +C:\BIO2\OLDOBJ\msinit+ +C:\BIO2\OLDOBJ\sysinit1+ +C:\BIO2\OLDOBJ\sysinit2+ +C:\BIO2\OLDOBJ\sysimes,msbio,/M; + +THE FOLLOWING IS A BATCH FILE THAT CAN BE USED TO CREATE THE IBMBIO.COM +WHERE "LOCSCR" IS A FILE THAT JUST HAS THE NUMBER, 70: + +link @NEW.ARF +exe2bin ibmbio ibmbio.com buffer to dump in Hex. +; CX -> # of bytes (Length of the buffer) +; +DUMPBYTES proc near + pushf + push ax +dumploops: + lodsb + mov ah, al + shr ah, 1 + shr ah, 1 + shr ah, 1 + shr ah, 1 + call hex_to_ascii + push ax + mov al, ah + call outchar + pop ax + call outchar + mov al, ' ' + call outchar + loop dumploops + + mov al, 0dh + call outchar + mov al, 0ah + call outchar + + pop ax + popf + ret +DUMPBYTES endp + + PUBLIC Hex_to_ascii +Hex_to_ascii proc near ;J.K. - 4/9/86 + and ax, 0f0fh + add ah, 30h + cmp ah, 3ah + jb hta_$1 + add ah, 7 +hta_$1: + add al, 30h + cmp al, 3ah + jb hta_$2 + add al, 7 +hta_$2: + ret +Hex_to_ascii endp + + PUBLIC outchar +Outchar proc near + PUSH AX + PUSH SI + PUSH DI + PUSH BP + PUSH BX +;SB33002******************************************************* + MOV AH, 0Eh ;SET COMMAND TO WRITE A CHAR ;SB;3.30* + MOV BX, 7 ;SET FOREGROUND COLOR ;SB;3.30* + INT 10h ;CALL ROM-BIOS ;SB;3.30* +;SB33002******************************************************* + POP BX + POP BP + POP DI + POP SI + POP AX + RET +Outchar endp + + ENDIF + INCLUDE MSMACRO.INC + +;--------------------------------------------------- +; +; DEVICE ENTRY POINT +; +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER +EXTRA = 22 ;USUALLY A POINTER TO VOL ID FOR ERROR 15 +START_L = 26 ;AN000; Extended start sector (Low) +START_H = 28 ;AN000; Extended start sector (High) + + PUBLIC STRATEGY +STRATEGY PROC FAR + MOV WORD PTR CS:[PTRSAV],BX + MOV WORD PTR CS:[PTRSAV+2],ES + RET +STRATEGY ENDP + + PUBLIC CON$IN +CON$IN PROC FAR + PUSH SI + MOV SI,OFFSET CONTBL + JMP SHORT ENTRY +CON$IN ENDP + + PUBLIC AUX0$IN +AUX0$IN PROC FAR + PUSH SI + PUSH AX + XOR AL,AL + JMP SHORT AUXENT +AUX0$IN ENDP + + PUBLIC AUX1$IN +AUX1$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,1 + JMP short AUXENT ;J.K. 4/15/86 +AUX1$IN ENDP + +;SB33102**************************************************************** +;SB Add code to handle two more COM Ports +;boban + + PUBLIC AUX2$IN +AUX2$IN proc far + push si + push ax + mov al,2 + jmp short AUXENT +AUX2$IN endp + + PUBLIC AUX3$IN +AUX3$IN proc far + push si + push ax + mov al,3 + jmp short AUXENT + +;SB33102**************************************************************** + +AUXENT: + MOV SI,OFFSET AUXTBL + JMP SHORT ENTRY1 +AUX3$IN ENDP + +PRN0$IN PROC FAR + PUBLIC PRN0$IN + + PUSH SI + PUSH AX + XOR AX,AX + JMP SHORT PRNENT +PRN0$IN ENDP + + PUBLIC PRN1$IN +PRN1$IN PROC FAR + PUSH SI + PUSH AX + XOR AL,AL + MOV AH,1 + JMP SHORT PRNENT +PRN1$IN ENDP + + PUBLIC PRN2$IN +PRN2$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,1 + MOV AH,2 + JMP SHORT PRNENT +PRN2$IN ENDP + + PUBLIC PRN3$IN +PRN3$IN PROC FAR + PUSH SI + PUSH AX + MOV AL,2 + MOV AH,3 +PRNENT: + MOV SI,OFFSET PRNTBL + MOV CS:[PRINTDEV],AH ;SAVE INDEX INTO ARRAY OF RETRY COUNTS + JMP SHORT ENTRY1 +PRN3$IN ENDP + + PUBLIC TIM$IN +TIM$IN PROC FAR + PUSH SI + MOV SI,OFFSET TIMTBL + JMP SHORT ENTRY +TIM$IN ENDP + + PUBLIC DSK$IN +DSK$IN PROC FAR + PUSH SI + MOV SI,OFFSET DSKTBL + +ENTRY: + PUSH AX +ENTRY1: + PUSH CX + PUSH DX + PUSH DI + PUSH BP + PUSH DS + PUSH ES + PUSH BX + + MOV CS:[AUXNUM],AL ;SAVE CHOICE OF AUX/PRN DEVICE + + LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET + ASSUME DS:NOTHING + + MOV AL,BYTE PTR DS:[BX].UNIT ;AL = UNIT CODE + MOV AH,BYTE PTR DS:[BX].MEDIA ;AH = MEDIA DESCRIP + MOV CX,WORD PTR DS:[BX].COUNT ;CX = COUNT + MOV DX,WORD PTR DS:[BX].START ;DX = START SECTOR + +;SB34MSB100********************************************************************* +;SB +;SB The disk device driver can now handle 32 bit start sector number. +;SB So we should check to see if a 32 bit sector number has been specified +;SB and if so get it. Whether a 32 bit sector has been specified or not +;SB the disk driver expects a 32 bit sector number with the high word +;SB in cs:Start_Sec_H and the low word in dx. +;SB +;SB Algorithm: +;SB 1. Check to see if the request is for the disk driver by +;SB checking to see if SI points to DSKTBL. +;SB +;SB 2. If request not for the disk nothing special needs to be done. +;SB +;SB 3. If request for the disk then check to see if a 32 bit +;SB sector number has been specified by seeing whether the +;SB the conventional sector number specified is -1. If so +;SB we need to pick the 32 bit sector number from the new +;SB fields in the request packet. See the request header +;SB struc for the fields you need. If the conventional +;SB sector field is not -1 then a 16 bit sector number +;SB has been specified and we just need to initalise the +;SB high word in cs:Start_Sec_H to 0 +;SB +;SB NOTE: START_L and START_H are the offsets withing the IO_REQUEST packet +;SB which contain the low and hi words of the 32 bit start sector if +;SB it has been used. +;SB +;SB NOTE:Remember not to destroy the registers which have been set up before + + CMP SI,OFFSET DSKTBL + JNZ DSK_REQ_CONT ; Not Disk Req + CMP DX,-1 + JNZ DSK_REQ_16 + MOV DX,DS:[BX].START_H ; 32 bits DSK REQ + MOV CS:START_SEC_H,DX ; CS:Start_sec_H = Packet.Start_H + MOV DX,DS:[BX].START_L ; DX = Packet.Start_L + JMP SHORT DSK_REQ_CONT +DSK_REQ_16: + MOV CS:START_SEC_H,0 +DSK_REQ_CONT: + +;SB34MSB100********************************************************************* + + XCHG DI,AX + MOV AL,BYTE PTR DS:[BX].CMD + CMP AL,CS:[SI] ;ARR 2.41 + JA CMDERR + + CBW ; NOTE THAT AL <= 15 MEANS OK + SHL AX,1 + + ADD SI,AX + XCHG AX,DI + + LES DI,DWORD PTR DS:[BX].TRANS + + PUSH CS + POP DS + + ASSUME DS:CODE + + CLD + JMP WORD PTR [SI+1] ;GO DO COMMAND +DSK$IN ENDP + PAGE +;===================================================== +;= +;= SUBROUTINES SHARED BY MULTIPLE DEVICES +;= +;===================================================== +;---------------------------------------------------------- +; +; EXIT - ALL ROUTINES RETURN THROUGH THIS PATH +; + PUBLIC BUS$EXIT +BUS$EXIT PROC FAR + ASSUME DS:NOTHING + MOV AH,00000011B + JMP SHORT ERR1 + + PUBLIC CMDERR +CMDERR: + MOV AL,3 ;UNKNOWN COMMAND ERROR + + PUBLIC ERR$CNT +ERR$CNT: + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + + PUBLIC ERR$EXIT +ERR$EXIT: + MOV AH,10000001B ;MARK ERROR RETURN + JMP SHORT ERR1 +BUS$EXIT ENDP + +EXITP PROC FAR + ASSUME DS:CODE ; WE ARE NOT SURE THIS IS CORRECT 3/18/86 +EXIT$ZER: + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + XOR AX,AX + MOV WORD PTR [BX].COUNT,AX ;INDICATE NO CHARS READ + + PUBLIC EXIT +EXIT: + ASSUME DS:NOTHING + MOV AH,00000001B +ERR1: + ASSUME DS:NOTHING + LDS BX,CS:[PTRSAV] + MOV WORD PTR [BX].STATUS,AX ;MARK OPERATION COMPLETE + + POP BX + POP ES + POP DS + POP BP + POP DI + POP DX + POP CX + POP AX + POP SI + RET ;RESTORE REGS AND RETURN +EXITP ENDP + +;------------------------------------------------------------- +; +; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE +; +; CALLED VIA INT 29H +; + PUBLIC CHROUT +CHROUT = 29H + + PUBLIC OUTCHR +OUTCHR PROC FAR + PUSH AX + PUSH SI + PUSH DI + PUSH BP +;SB33002a******************************************************* + push bx ; ;SB ;3.30 + mov AH, 0Eh ; set command to write a character;SB;3.30 + mov BX, 7 ; set foreground color ;SB ;3.30 + int 10h ; call rom-bios ;SB ;3.30 + pop bx ; ;SB ;3.30 +;SB33002a******************************************************* + POP BP + POP DI + POP SI + POP AX + IRET +OUTCHR ENDP +;---------------------------------------------- +; +; SET DX TO AUXNUM +; + PUBLIC GETDX +GETDX PROC NEAR + MOV DX,WORD PTR CS:[AUXNUM] + RET +GETDX ENDP + PAGE +;************************************************** ARR 2.15 + +;----------------------------------------------- +; +; TIMER INTERRUPT HANDLER +; +;TIMER_LOW DW 0 +;TIMER_HIGH DW 0 +; +;TIMER: +; STI +; PUSH AX +; PUSH CX +; PUSH DX +; PUSH DS +; PUSH CS +; POP DS +; XOR AX,AX +; INT 1AH ; GET ROM TIME AND ZAP ROLL OVER +; MOV [TIMER_HIGH],CX +; MOV [TIMER_LOW],DX +; OR AL,AL +; JZ T5 +; INC WORD PTR [DAYCNT] ; ONE DAY GONE BY +;T5: +; POP DS +; POP DX +; POP CX +; POP AX +; IRET +;************************************************** ARR 2.15 +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSBIO2.ASM b/v4.0/src/BIOS/MSBIO2.ASM new file mode 100644 index 0000000..50b25bc --- /dev/null +++ b/v4.0/src/BIOS/MSBIO2.ASM @@ -0,0 +1,572 @@ + PAGE ,132 ; + TITLE MSBIO2 - BIOS + + %OUT ...MSBIO2.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; - P1820 New Message SKL file 10/20/87 J.K. +;AN002; - P5045 New INT 2fh for Get BDS table vector for EMS 06/06/88 J.K. +;============================================================================== + +ROMSEGMENT EQU 0F000H +MODELBYTE EQU DS:BYTE PTR [0FFFEH] +MODELPCJR EQU 0FDH + + itest=0 + + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE DEVSYM.INC + INCLUDE PUSHPOP.INC + INCLUDE MSMACRO.INC + + ASSUME DS:NOTHING,ES:NOTHING + + EXTRN DSK$IN:NEAR + EXTRN SETPTRSAV:NEAR + EXTRN OUTCHR:NEAR + EXTRN SETDRIVE:NEAR + EXTRN FLUSH:NEAR + EXTRN HARDERR:NEAR + EXTRN HARDERR2:NEAR + EXTRN MAPERROR:NEAR + EXTRN GETBP:NEAR + EXTRN CHECKSINGLE:NEAR + EXTRN CHECK_TIME_OF_ACCESS:NEAR + EXTRN EXIT:NEAR + EXTRN HAS1:NEAR + EXTRN READ_SECTOR:NEAR + EXTRN INT_2F_13:FAR + + EXTRN OLD13:DWORD + +;DATA + EXTRN PTRSAV:DWORD ;IBMBIO1 + EXTRN START_BDS:WORD + EXTRN FDRIVE1:WORD + EXTRN FDRIVE2:WORD + EXTRN FDRIVE3:WORD + EXTRN FDRIVE4:WORD + EXTRN FLAGBITS:WORD + EXTRN TIM_DRV:BYTE + EXTRN MEDBYT:BYTE + EXTRN DRVMAX:BYTE + extrn Ext_Boot_Sig:byte ;AN000; ibmbdata + extrn SecPerClusInSector:byte ;AN000; ibmbdata + extrn Boot_Serial_L:word ;AN000; ibmbdata + extrn Boot_Serial_H:word ;AN000; ibmbdata + + PATHSTART 005,DISK + EVENB + public Model_Byte +MODEL_BYTE DB 0FFH ; MODEL BYTE. SET UP AT INIT TIME. + ; FF - PC1 + ; FE - XT (64/256K PLANAR) + ; FD - PC-JR + ; FC - PC/AT + public Secondary_Model_Byte +Secondary_Model_Byte db 0 + + PUBLIC ORIG19 +ORIG19 DD ? + + PUBLIC INT19SEM +INT19SEM DB 0 ; INDICATE THAT ALL INT 19 + ; INITIALIZATION IS COMPLETE + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + public Int19OLD&AA +Int19OLD&AA dd -1 ;Orignal hardware int. vectors for INT 19h. + ENDM + + EVENB + PUBLIC DSKDRVS +DSKDRVS DW FDRIVE1 + DW FDRIVE2 + DW FDRIVE3 + DW FDRIVE4 + PUBLIC HDSKTAB +HDSKTAB DW HDRIVE + DW DRIVEX +;* Next area is reseved for mini disk BPB pointers *** J.K. 4/7/86 +;* Don't change this position. Should be addressible from DskDrvs *** J.K. 4/7/86 +MINI_DISK_BPB_PTRS DB 40 dup (?) ;J.K. 4/7/86 - memory reserved for Mini disk. + + EVENB + PUBLIC INT_2F_NEXT +INT_2F_NEXT DD ? + +RET_ADDR DD ? + + PATHEND 005,DISK +; = = = = = = = = = = = = = = = = = = = = + +; INT19 +; +; WE "HOOK" THE INT 19 VECTOR, BECAUSE CONTRARY TO IBM DOCUMENTATION, +; IT DOES NOT "BOOTSTRAP" THE MACHINE. IT LEAVES MEMORY ALMOST UNTOUCHED. +; SINCE THE BIOS_INIT CODE ASSUMES THAT CERTAIN INTERRUPT VECTORS POINT TO +; THE ROM_BIOS WE MUST "UNHOOK" THEM BEFORE ISSUING THE ACTUAL INT_19. +; CURRENTLY THE ONLY VECTORS THAT NEED TO BE UNHOOKED ARE INT_19, INT_13, +; AND THE HARDWARE INTERRUPTS. +; + PUBLIC INT19 +INT19 PROC FAR + XOR AX,AX + MOV DS,AX + assume ds:nothing + assume es:nothing + + LES DI,OLD13 + MOV DS:[13H*4],DI + MOV DS:[13H*4+2],ES + + CMP BYTE PTR INT19SEM, 0 + JNZ INT19VECS + JMP DOINT19 + +; ON THE PCJR, DON'T REPLACE ANY VECTORS +; MODEL BYTE DEFINITIONS FROM IBMSTACK.ASM + MOV AX,ROMSEGMENT + MOV DS,AX + MOV AL,MODELPCJR + + CMP AL,MODELBYTE + JNE INT19VECS + JMP DOINT19 + +;Stacks code has changed these hardware interrupt vectors +;STKINIT in SYSINIT1 will initialzie Int19hOLDxx values. +INT19VECS: + XOR AX,AX + MOV DS,AX + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + + LES DI,Int19OLD&AA +;SB33103****************************************************************** + + mov ax,es ; + cmp ax,-1 ;OPT 0ffffh is unlikely segment + je skip_int&AA ;OPT no need to check selector too + cmp di,-1 ;OPT 0ffffh is unlikely offset + je skip_int&AA + +;SB33103****************************************************************** + MOV DS:[AA&H*4],DI + MOV DS:[AA&H*4+2],ES +skip_int&AA: + ENDM + +DOINT19: + LES DI,ORIG19 + MOV DS:[19H*4],DI + MOV DS:[19H*4+2],ES + + INT 19H +INT19 ENDP + + ASSUME DS:CODE + PUBLIC DSK$INIT +DSK$INIT PROC NEAR + PUSH CS + POP DS + MOV AH,BYTE PTR DRVMAX + MOV DI,OFFSET DSKDRVS + JMP SETPTRSAV +DSK$INIT ENDP + +; +; INT 2F HANDLER FOR EXTERNAL BLOCK DRIVERS TO COMMUNICATE WITH THE INTERNAL +; BLOCK DRIVER IN IBMDISK. THE MULTIPLEX NUMBER CHOSEN IS 8. THE HANDLER +; SETS UP THE POINTER TO THE REQUEST PACKET IN [PTRSAV] AND THEN JUMPS TO +; DSK$IN, THE ENTRY POINT FOR ALL DISK REQUESTS. +; ON EXIT FROM THIS DRIVER (AT EXIT), WE WILL RETURN TO THE EXTERNAL DRIVER +; THAT ISSUED THIS INT 2F, AND CAN THEN REMOVE THE FLAGS FROM THE STACK. +; THIS SCHEME ALLOWS US TO HAVE A SMALL EXTERNAL DEVICE DRIVER, AND MAKES +; THE MAINTAINANCE OF THE VARIOUS DRIVERS (DRIVER AND IBMBIO) MUCH EASIER, +; SINCE WE ONLY NEED TO MAKE CHANGES IN ONE PLACE (MOST OF THE TIME). +; +; 06/03/88 J.K. When AL=3, return DS:DI -> Start of BDS table. +; (EMS device driver hooks INT 13h to handle 16KB DMA overrun +; problem. BDS table is going to be used to get head/sector +; informations without calling Generic IOCTL Get Device Parm call.) +; +; AL CONTAINS THE INT2F FUNCTION: +; 0 - CHECK FOR INSTALLED HANDLER - RESERVED +; 1 - INSTALL THE BDS INTO THE LINKED LIST +; 2 - DOS REQUEST +; 3 - Get BDS vector ;06/03/88 J.K. +; Return BDS table starting pointer in DS:DI + +MYNUM EQU 8 + + PUBLIC INT2F_DISK +INT2F_DISK PROC FAR + CMP AH,MYNUM + JE MINE + JMP CS:[INT_2F_NEXT] ; CHAIN TO NEXT INT 2F HANDLER +MINE: + CMP AL,0F8H ; IRET ON RESERVED FUNCTIONS + JB DO_FUNC + IRET +DO_FUNC: + OR AL,AL ; A GET INSTALLED STATE REQUEST? + JNE DISP_FUNC + MOV AL,0FFH + IRET +DISP_FUNC: + MESSAGE FTESTINIT,<"INT2F_DISK",CR,LF> + CMP AL,1 ; REQUEST FOR INSTALLING BDS? + JNE DO_DOS_REQ + CALL INSTALL_BDS + IRET + +DO_DOS_REQ: +; SET UP POINTER TO REQUEST PACKET + cmp al, 3 ;AN002; Get BDS vector? + je DO_Get_BDS_Vector ;AN002; + MOV WORD PTR CS:[PTRSAV],BX ;othrwise DOS function. + MOV WORD PTR CS:[PTRSAV+2],ES + JMP DSK$IN + +DO_Get_BDS_Vector: ;AN002; AL=3 + push cs ;AN002; + pop ds ;AN002; + mov di, Start_BDS ;AN002; + IRET ;AN002; + +INT2F_DISK ENDP + +; +; INSTALL_BDS INSTALLS A BDS A LOCATION DS:DI INTO THE CURRENT LINKED LIST OF +; BDS MAINTAINED BY THIS DEVICE DRIVER. IT PLACES THE BDS AT THE END OF THE +; LIST. + PUBLIC INSTALL_BDS +INSTALL_BDS PROC NEAR + MESSAGE FTESTINIT,<"INSTALL BDS",CR,LF> +; DS:DI POINT TO BDS TO BE INSTALLED + LES SI,DWORD PTR CS:[START_BDS] ; START AT BEGINNING OF LIST + PUSH ES ; SAVE POINTER TO CURRENT BDS + PUSH SI +; ES:SI NOW POINT TO BDS IN LINKED LIST +LOOP_NEXT_BDS: + CMP SI,-1 ; GOT TO END OF LINKED LIST? + JZ INSTALL_RET +; IF WE HAVE SEVERAL LOGICAL DRIVES USING THE SAME PHYSICAL DRIVE, WE MUST +; SET THE I_AM_MULT FLAG IN EACH OF THE APPROPRIATE BDSS. + MOV AL,BYTE PTR DS:[DI].DRIVENUM + CMP BYTE PTR ES:[SI].DRIVENUM,AL + JNZ NEXT_BDS + MESSAGE FTESTINIT,<"LOGICAL DRIVES",CR,LF> + XOR BX,BX + MOV BL,FI_AM_MULT + OR WORD PTR DS:[DI].FLAGS,BX ; SET FLAGS IN BOTH BDSS CONCERNED + OR WORD PTR ES:[SI].FLAGS,BX + MOV BL,FI_OWN_PHYSICAL + XOR BX,-1 + AND WORD PTR DS:[DI].FLAGS,BX ; RESET THAT FLAG FOR 'NEW' BDS +; WE MUST ALSO SET THE FCHANGELINE BIT CORRECTLY. + MOV BX,WORD PTR ES:[SI].FLAGS ; DETERMINE IF CHANGELINE AVAILABLE + AND BL,FCHANGELINE + XOR BH,BH + OR WORD PTR DS:[DI].FLAGS,BX + +NEXT_BDS: +; BEFORE MOVING TO NEXT BDS, PRESERVE POINTER TO CURRENT ONE. THIS IS NEEDED AT +; THE END WHEN THE NEW BDS IS LINKED INTO THE LIST. + POP BX ; DISCARD PREVIOUS POINTER TO BDS + POP BX + PUSH ES + PUSH SI + MOV BX,WORD PTR ES:[SI].LINK + 2 + MOV SI,WORD PTR ES:[SI].LINK + MOV ES,BX + JMP SHORT LOOP_NEXT_BDS + +INSTALL_RET: + POP SI ; RETRIEVE POINTER TO LAST BDS + POP ES ; IN LINKED LIST. + MOV AX,DS + MOV WORD PTR ES:[SI].LINK+2,AX ; INSTALL BDS + MOV WORD PTR ES:[SI].LINK,DI + MOV WORD PTR DS:[DI].LINK,-1 ; SET NEXT POINTER TO NULL + RET +INSTALL_BDS ENDP + +; +; RE_INIT INSTALLS THE INT 2F VECTOR THAT WILL HANDLE COMMUNICATION BETWEEN +; EXTERNAL BLOCK DRIVERS AND THE INTERNAL DRIVER. IT ALSO INSTALLS THE +; RESET_INT_13 INTERFACE. IT IS CALLED BY SYSYINIT +; + PUBLIC RE_INIT +RE_INIT PROC FAR + MESSAGE FTESTINIT,<"REINIT",CR,LF> + PUSH AX + PUSH DS + PUSH DI + XOR DI,DI + MOV DS,DI + MOV DI,2FH*4 ; POINT IT TO INT 2F VECTOR + MOV AX,WORD PTR DS:[DI] + MOV WORD PTR CS:[INT_2F_NEXT],AX + MOV AX,WORD PTR DS:[DI+2] ; PRESERVE OLD INT 2F VECTOR + MOV WORD PTR CS:[INT_2F_NEXT+2],AX + +; INSTALL THE RESET_INT_13 +; INTERFACE + +; +; THE FOLLOWING TWO LINES ARE NOT NEEDED ANYMORE BECAUSE THE LINK HAS BEEN +; HARD-WIRED INTO THE CODE AT NEXT2F_13. - RAJEN. +;------------------------------------------------------------------------------ +; MOV WORD PTR CS:[NEXT2F_13],OFFSET INT2F_DISK ; PRESERVE INT2F_DISK POINTER +; MOV WORD PTR CS:[NEXT2F_13+2],CS +;------------------------------------------------------------------------------ + + CLI + MOV WORD PTR DS:[DI],OFFSET INT_2F_13 ; INSTALL NEW VECTORS + MOV WORD PTR DS:[DI+2],CS + STI + POP DI + POP DS + POP AX + + RET + +RE_INIT ENDP + +;------------------------------------------------- +; +; ASK TO SWAP THE DISK IN DRIVE A: +; + PUBLIC SWPDSK +SWPDSK PROC NEAR + MOV AL,BYTE PTR DS:[DI].DRIVELET ; GET THE DRIVE LETTER +;USING A DIFFERENT DRIVE IN A ONE DRIVE SYSTEM SO REQUEST THE USER CHANGE DISKS + ADD AL,"A" + MOV CS:DRVLET,AL + PUSH DS ; PRESERVE SEGMENT REGISTER + PUSH CS + POP DS + MOV SI,OFFSET SNGMSG ; DS:SI -> MESSAGE + PUSH BX + CALL WRMSG ;PRINT DISK CHANGE MESSAGE + CALL FLUSH +;SB33003*************************************************************** + xor AH, AH ; set command to read character;SB + int 16h ; call rom-bios ;SB +;SB33003*************************************************************** + POP BX + POP DS ; RESTORE SEGMENT REGISTER +WRMRET: + RET +SWPDSK ENDP + +;---------------------------------------------- +; +; WRITE OUT MESSAGE POINTED TO BY [SI] +; + PUBLIC WRMSG +WRMSG PROC NEAR + LODSB ;GET THE NEXT CHARACTER OF THE MESSAGE + OR AL,AL ;SEE IF END OF MESSAGE + JZ WRMRET +; INT CHROUT + PUSHF + PUSH CS + CALL OUTCHR + JMP SHORT WRMSG +WRMSG ENDP + +; INCLUDE BIOMES.INC + include MSBIO.CL2 + +; +; END OF SUPPORT FOR MULTIPLE FLOPPIES WITH NO LOGICAL DRIVES +; THIS IS NOT 'SPECIAL' ANY MORE BECAUSE WE NOW HAVE THE CAPABILITY OF +; DEFINING LOGICAL DRIVES IN CONFIG.SYS. WE THEREFORE KEEP THE CODE FOR +; SWAPPING RESIDENT ALL THE TIME. +; + +;J.K. 10/1/86 ******************************************************* +;Variables for Dynamic Relocatable modules +;These should be stay resident. + + public INT6C_RET_ADDR +INT6C_RET_ADDR DD ? ; return address from INT 6C for P12 machine + + PATHSTART 001,CLK +; +; DATA STRUCTURES FOR REAL-TIME DATE AND TIME +; + public BIN_DATE_TIME + public MONTH_TABLE + public DAYCNT2 + public FEB29 +BIN_DATE_TIME: + DB 0 ; CENTURY (19 OR 20) OR HOURS (0-23) + DB 0 ; YEAR IN CENTURY (0...99) OR MINUTES (0-59) + DB 0 ; MONTH IN YEAR (1...12) OR SECONDS (0-59) + DB 0 ; DAY IN MONTH (1...31) +MONTH_TABLE: ; + DW 0 ;MJB002 JANUARY + DW 31 ;MJB002 FEBRUARY + DW 59 ;MJB002 + DW 90 ;MJB002 + DW 120 ;MJB002 + DW 151 ;MJB002 + DW 181 ;MJB002 + DW 212 ;MJB002 + DW 243 ;MJB002 + DW 273 ;MJB002 + DW 304 ;MJB002 + DW 334 ;MJB002 DECEMBER +DAYCNT2 DW 0000 ;MJB002 TEMP FOR COUNT OF DAYS SINCE 1-1-80 +FEB29 DB 0 ;MJB002 FEBRUARY 29 IN A LEAP YEAR FLAG + PATHEND 001,CLK + +;******************************************************************** +; + + PUBLIC ENDFLOPPY +ENDFLOPPY LABEL BYTE +; +; END OF CODE FOR VIRTUAL FLOPPY DRIVES +; + PUBLIC ENDSWAP +ENDSWAP LABEL BYTE + + PATHSTART 004,BIO + + PUBLIC HNUM +HNUM DB 0 ;NUMBER OF HARDFILES + PUBLIC HARDDRV +HARDDRV DB 80H ;PHYSICAL DRIVE NUMBER OF FIRST HARDFILE +;********************************************************************** +; "HDRIVE" IS A HARD DISK WITH 512 BYTE SECTORS +;********************************************************************* + EVENB + PUBLIC BDSH +BDSH DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 80 ;INT 13 DRIVE NUMBER + DB "C" ;LOGICAL DRIVE LETTER + PUBLIC HDRIVE +HDRIVE: + DW 512 + DB 1 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. OF ALLOCATION TABLES + DW 16 ;NUMBER OF DIRECTORY ENTRIES + DW 0000 ;NUMBER OF SECTORS (AT 512 BYTES EACH) + DB 11111000B ;MEDIA DESCRIPTOR + DW 1 ;NUMBER OF FAT SECTORS + DW 00 ;SECTOR LIMIT + DW 00 ;HEAD LIMIT + DW 00 ;HIDDEN SECTOR COUNT(low) + dw 00 ;AN000; Hidden Sector (high) + dw 00 ;AN000; Number of Sectors (low) + dw 00 ;AN000; Number of Sectors (high) + DB 0 ; TRUE => BIGFAT +OPCNTH DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGSH DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +RECBPBH DB 31 DUP (?) ; RECOMMENDED BPB FOR DRIVE +TRACKH DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LOH DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HIH DW -1 +VOLIDH DB "NO NAME ",0 ;AN000; VOLUME ID FOR THIS DISK +VolSerH dd 0 ;AN000; Current volume serial number from Boot record +SysIDH db "FAT12 " ,0 ;AN000; Current file system id from Boot record + +; +; END OF SINGLE HARD DISK SECTION +; + PUBLIC ENDONEHARD +ENDONEHARD LABEL BYTE +;********************************************************************** +; "DRIVEX " IS AN EXTRA TYPE OF DRIVE USUALLY RESERVED FOR AN +; ADDITIONAL HARD FILE +;********************************************************************* + EVENB + PUBLIC BDSX +BDSX DW -1 ;LINK TO NEXT STRUCTURE + DW CODE + DB 81 ;INT 13 DRIVE NUMBER + DB "D" ;LOGICAL DRIVE LETTER + PUBLIC DRIVEX +DRIVEX: + DW 512 + DB 00 ;SECTORS/ALLOCATION UNIT + DW 1 ;RESERVED SECTORS FOR DOS + DB 2 ;NO. OF ALLOCATION TABLES + DW 0000 ;NUMBER OF DIRECTORY ENTRIES + DW 0000 ;NUMBER OF SECTORS (AT 512 BYTES EACH) + DB 11111000B ;MEDIA DESCRIPTOR + DW 0000 ;NUMBER OF FAT SECTORS + DW 00 ;SECTOR LIMIT + DW 00 ;HEAD LIMIT + DW 00 ;HIDDEN SECTOR COUNT (low) + dw 00 ;AN000; Hidden Sector (high) + dw 00 ;AN000; Number of Sectors (low) + dw 00 ;AN000; Number of Sectors (high) + DB 0 ; TRUE => BIGFAT +OPCNTD DW 0 ;OPEN REF. COUNT + DB 3 ;FORM FACTOR +FLAGSD DW 0020H ;VARIOUS FLAGS +; DB 9 DUP (0) ;RESERVED FOR FUTURE USE + DW 40 ; NUMBER OF CYLINDERS +RECBPBD DB 31 DUP (?) ; RECOMMENDED BPB FOR DRIVE +TRACKD DB -1 ;LAST TRACK ACCESSED ON THIS DRIVE +TIM_LOD DW -1 ;KEEP THESE TWO CONTIGUOUS (?) +TIM_HID DW -1 +VOLIDD DB "NO NAME ",0 ;AN000; VOLUME ID FOR THIS DISK +VolSerD dd 0 ;AN000; Current volume serial number from Boot record +SysIDD db "FAT12 " ,0 ;AN000; Current file system id from Boot record + +; +; END OF SECTION FOR TWO HARD DISKS + PUBLIC ENDTWOHARD +ENDTWOHARD LABEL BYTE + + PATHEND 004,BIO + + PUBLIC TWOHARD +TWOHARD LABEL BYTE + PAGE + INCLUDE MS96TPI.INC + +;********************************************************************* +;Memory allocation for BDSM table. - J.K. 2/21/86 +;********************************************************************* + PUBLIC BDSMs +BDSMs BDSM_type Max_mini_dsk_num dup (<>) ;currently max. 23 + +;** End_of_BDSM defined in IBMINIT.ASM will be used to set the appropriate +;** ending address of BDSM table. + +; +;;3.3 BUG FIX -SP ------------------------------ +;;Migrated into 4.00 -MRW +;Paragraph buffer between the BDSMs and MSHARD +; +;The relocation code for MSHARD needs this. this cannot be used for +;anything. nothing can come before this or after this.....IMPORTANT!!!! +;don't get too smart and using this buffer for anything!!!!!! +; + db 16 dup(0) +; +;end of bug fix buffer +;; +;;3.3 BUG FIX -SP------------------------------ + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSCLOCK.ASM b/v4.0/src/BIOS/MSCLOCK.ASM new file mode 100644 index 0000000..5d66d03 --- /dev/null +++ b/v4.0/src/BIOS/MSCLOCK.ASM @@ -0,0 +1,296 @@ + TITLE MSCLOCK - DOS 3.3 +;---------------------------------------------------------------- +; : +; CLOCK DEVICE DRIVER : +; : +; : +; This file contains the Clock Device Driver. : +; : +; The routines in this files are: : +; : +; routine function : +; ------- -------- : +; TIM$WRIT Set the current time : +; TIM$READ Read the current time : +; Time_To_Ticks Convert time to corresponding : +; number of clock ticks : +; : +; The clock ticks at the rate of: : +; : +; 1193180/65536 ticks/second (about 18.2 ticks per second): +; See each routine for information on the use. : +; : +;---------------------------------------------------------------- + + + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSMACRO.INC + + EXTRN EXIT:NEAR +; +; DAYCNT is the number of days since 1-1-80. +; Each time the clock is read it is necessary to check if another day has +; passed. The ROM only returns the day rollover once so if it is missed +; the time will be off by a day. +; + EXTRN DAYCNT:WORD ;MSDATA + +;;Rev 3.30 Modification ------------------------------------------------ +; variables for real time clock setting + public HaveCMOSClock +HaveCMOSClock db 0 ;set by MSINIT. + public base_century +base_century db 19 + public base_year +base_year db 80 + public month_tab +month_tab db 31,28,31,30,31,30,31,31,30,31,30,31 + +; The following are indirect intra-segment call addresses. The +;procedures are defined in MSINIT for relocation. MSINIT will set these +;address when the relocation is done. + public BinToBCD +BinToBCD dw 0 ;should point to Bin_To_BCD proc in MSINIT + public DaycntToDay +DaycntToDay dw 0 ;should point to Daycnt_to_day in MSINIT + +;******************************************************************** +; Indirect call address of TIME_TO_TICKS procedure. +;This will be used by the relocatable portable suspend/resume code. + + public TimeToTicks +TimeToTicks dw Time_To_Ticks + +;;End of Modification ------------------------------------------------ + +;-------------------------------------------------------------------- +; +; Settime sets the current time +; +; On entry ES:[DI] has the current time: +; +; number of days since 1-1-80 (WORD) +; minutes (0-59) (BYTE) +; hours (0-23) (BYTE) +; hundredths of seconds (0-99) (BYTE) +; seconds (0-59) (BYTE) +; +; Each number has been checked for the correct range. +; + PUBLIC TIM$WRIT +TIM$WRIT PROC NEAR + ASSUME DS:CODE + mov AX,WORD PTR ES:[DI] + push AX ;DAYCNT. We need to set this at the very + ; end to avoid tick windows. +;;Rev 3.30 Modification + cmp HaveCMOSClock, 0 + je No_CMOS_1 + mov al,es:[di+3] ;get binary hours + call BinToBCD ;convert to BCD + mov ch,al ;CH = BCD hours + mov al,es:[di+2] ;get binary minutes + call BinToBCD ;convert to BCD + mov cl,al ;CL = BCD minutes + mov al,es:[di+5] ;get binary seconds + call BinToBCD ;convert to BCD + mov dh,al ;DH = BCD seconds + mov dl,0 ;DL = 0 (ST) or 1 (DST) + cli ;turn off timer + mov ah,03h ;set RTC time + int 1Ah ;call rom bios clock routine + sti + +;;End of Modification +No_CMOS_1: + mov CX,WORD PTR ES:[DI+2] + mov DX,WORD PTR ES:[DI+4] +;;Rev 3.30 Modification + call time_to_ticks ; convert time to ticks + ;CX:DX now has time in ticks + cli ; Turn off timer + mov AH, 1 ; command is set time in clock + int 1Ah ; call rom-bios clock routines + pop [DAYCNT] + sti +;CMOS clock ------------------------------------- + cmp HaveCMOSClock, 0 + je No_CMOS_2 + call DaycntToDay ; convert to BCD format + cli ; Turn off timer + mov AH,05h ; set RTC date + int 1Ah ; call rom-bios clock routines + sti +;------------------------------------------------ + +No_CMOS_2: + jmp EXIT +TIM$WRIT ENDP +;;End of Modification + + + +; +; convert time to ticks +; input : time in CX and DX +; ticks returned in CX:DX +; +public time_to_ticks +TIME_TO_TICKS PROC NEAR + + ; first convert from Hour,min,sec,hund. to + ; total number of 100th of seconds + mov AL,60 + mul CH ;Hours to minutes + mov CH,0 + add AX,CX ;Total minutes + mov CX,6000 ;60*100 + mov BX,DX ;Get out of the way of the multiply + mul CX ;Convert to 1/100 sec + mov CX,AX + mov AL,100 + mul BH ;Convert seconds to 1/100 sec + add CX,AX ;Combine seconds with hours and min. + adc DX,0 ;Ripple carry + mov BH,0 + add CX,BX ;Combine 1/100 sec + adc DX,0 + +;;Rev 3.30 Modification +;DX:CX IS TIME IN 1/100 SEC + XCHG AX,DX + XCHG AX,CX ;NOW TIME IS IN CX:AX + MOV BX,59659 + MUL BX ;MULTIPLY LOW HALF + XCHG DX,CX + XCHG AX,DX ;CX->AX, AX->DX, DX->CX + MUL BX ;MULTIPLY HIGH HALF + ADD AX,CX ;COMBINE OVERLAPPING PRODUCTS + ADC DX,0 + XCHG AX,DX ;AX:DX=TIME*59659 + MOV BX,5 + DIV BL ;DIVIDE HIGH HALF BY 5 + MOV CL,AL + MOV CH,0 + MOV AL,AH ;REMAINDER OF DIVIDE-BY-5 + CBW + XCHG AX,DX ;USE IT TO EXTEND LOW HALF + DIV BX ;DIVDE LOW HALF BY 5 + MOV DX,AX + ; CX:DX is now number of ticks in time + ret +TIME_TO_TICKS ENDP +;;End of Modification + + +; +; Gettime reads date and time +; and returns the following information: +; +; ES:[DI] =count of days since 1-1-80 +; ES:[DI+2]=hours +; ES:[DI+3]=minutes +; ES:[DI+4]=seconds +; ES:[DI+5]=hundredths of seconds +; + PUBLIC TIM$READ +TIM$READ PROC NEAR + ; read the clock + xor AH, AH ; set command to read clock + int 1Ah ; call rom-bios to get time + + or al,al ; check for a new day + jz noroll1 ; if al=0 then don't reset day count + INC [DAYCNT] ; CATCH ROLLOVE +noroll1: + MOV SI,[DAYCNT] + +; +; we now need to convert the time in tick to the time in 100th of +; seconds. The relation between tick and seconds is: +; +; 65536 seconds +; ---------------- +; 1,193,180 tick +; +; To get to 100th of second we need to multiply by 100. The equation is: +; +; Ticks from clock * 65536 * 100 +; --------------------------------- = time in 100th of seconds +; 1,193,180 +; +; Fortunately this fromula simplifies to: +; +; Ticks from clock * 5 * 65,536 +; --------------------------------- = time in 100th of seconds +; 59,659 +; +; The calculation is done by first multipling tick by 5. Next we divide by +; 59,659. In this division we multiply by 65,536 by shifting the dividend +; my 16 bits to the left. +; +; start with ticks in CX:DX +; multiply by 5 + MOV AX,CX + MOV BX,DX + SHL DX,1 + RCL CX,1 ;TIMES 2 + SHL DX,1 + RCL CX,1 ;TIMES 4 + ADD DX,BX + ADC AX,CX ;TIMES 5 + XCHG AX,DX + + +; now have ticks * 5 in DX:AX +; we now need to multiply by 65,536 and divide by 59659 d. + + mov CX,59659 ; get divisor + div CX + ; DX now has remainder + ; AX has high word of final quotient + mov BX,AX ; put high work if safe place + xor AX,AX ; this is the multiply by 65536 + div CX ; BX:AX now has time in 100th of seconds + +; +;Rounding based on the remainder may be added here +;The result in BX:AX is time in 1/100 second. + mov DX,BX + mov CX,200 ;Extract 1/100's +;Division by 200 is necessary to ensure no overflow--max result +;is number of seconds in a day/2 = 43200. + div CX + cmp DL,100 ;Remainder over 100? + jb NOADJ + sub DL,100 ;Keep 1/100's less than 100 +NOADJ: + cmc ;If we subtracted 100, carry is now set + mov BL,DL ;Save 1/100's +;To compensate for dividing by 200 instead of 100, we now multiply +;by two, shifting a one in if the remainder had exceeded 100. + rcl AX,1 + mov DL,0 + rcl DX,1 + mov CX,60 ;Divide out seconds + div CX + mov BH,DL ;Save the seconds + div CL ;Break into hours and minutes + xchg AL,AH + +;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) + + push AX + MOV AX,SI ; DAYCNT + stosw + pop AX + stosw + mov AX,BX + stosw + jmp EXIT + +TIM$READ ENDP +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSCON.ASM b/v4.0/src/BIOS/MSCON.ASM new file mode 100644 index 0000000..68fcfff --- /dev/null +++ b/v4.0/src/BIOS/MSCON.ASM @@ -0,0 +1,328 @@ + PAGE ,132 ; + TITLE MSCON - BIOS + %OUT ...MSCON.ASM +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== + + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE JUMPMAC.INC + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + +;*** DOS 3.3 will not support more than 25 rows +; INCLUDE DEVSYM.INC ;J.K. 4/29/86 for CON$GENIOCTL support +; INCLUDE IOCTL.INC ;J.K. 4/29/86 for CON$GENIOCTL support + + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + +; EXTRN CMDERR:NEAR ;MSBIO1 J.K. 4/29/86 + +;DATA + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN FHAVEK09:BYTE ;MSDISK + EXTRN ALTAH:BYTE ;MSBDATA + EXTRN KEYRD_Func:Byte ;MSBDATA + EXTRN KEYSTS_Func:Byte ;MSBDATA + +; EXTRN SAV_SC_INFO:BYTE ;MSBDATA J.K. 4/29/86 +; EXTRN SAV_SC_MODE:BYTE ;MSBDATA J.K. 4/29/86 +;------------------------------------------------------ +; +; CONSOLE READ ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$READ +CON$READ PROC NEAR + JCXZ CON$EXIT +CON$LOOP: + CALL CHRIN ;GET CHAR IN AL + STOSB ;STORE CHAR AT ES:DI + LOOP CON$LOOP +CON$EXIT: + JUMP EXIT +CON$READ ENDP +;--------------------------------------------------------- +; +; INPUT SINGLE CHAR INTO AL +; +;J.K.5/12/87 We are going to issue extended keyboard function, if supported. +;The returning value of the extended key stroke of the extended key board +;function uses 0E0h in AL instead of 00 as in the conventional key board +;function. This creates a conflict when the user entered real Greek Alpha +;charater (= 0E0h) to distinguish the extended key stroke and the Greek Alpha. +;This case will be handled in the following manner; +; AH = 16h +; INT 16h +; If AL == 0, then extended code (in AH) +; else If AL == 0E0h, then +; IF AH <> 0, then extended code (in AH) +; else Greek_Alpha character. +;Also, for compatibility reason, if an extended code is detected, then we +;are going to change the value in AL from 0E0h to 00h. + + +CHRIN PROC NEAR +;AN000; +; XOR AX,AX + mov ah,KEYRD_Func ;AN000; Set by MSINIT. 0 or 10h + xor al,al ;AN000; + XCHG AL,ALTAH ;GET CHARACTER & ZERO ALTAH + + OR AL,AL + JNZ KEYRET +;SB34CON000************************************************************** +;SB Keyboard I/O interrupt +;SB AH already contains the keyboard read function number +;SB 1 LOC + + int 16h +;SB34CON000************************************************************** +ALT10: + OR AX,AX ;CHECK FOR NON-KEY AFTER BREAK + JZ CHRIN + CMP AX,7200H ;CHECK FOR CTRL-PRTSC + JNZ ALT_Ext_Chk ;AN000; + MOV AL,16 + jmp KeyRet ;AN000; +ALT_Ext_Chk: +;SB34CON001************************************************************** +;SB IF operation was extended function (i.e. KEYRD_Func != 0) THEN +;SB IF character read was 0E0h THEN +;SB IF extended byte was zero (i.e. AH == 0) THEN +;SB goto keyret +;SB ELSE +;SB set AL to zero +;SB goto ALT_SAVE +;SB ENDIF +;SB ENDIF +;SB ENDIF +;SB 9 LOCS + + cmp BYTE PTR KEYRD_Func,0 + jz NOT_EXT + cmp al,0E0h + jnz NOT_EXT + or ah,ah + jz KEYRET + xor al,al + jmp short ALT_SAVE +NOT_EXT: + +;SB34CON001************************************************************** + OR AL,AL ;SPECIAL CASE? + JNZ KEYRET +ALT_SAVE: + MOV ALTAH,AH ;STORE SPECIAL KEY +KEYRET: + RET +CHRIN ENDP + +;-------------------------------------------------------------- +; +; KEYBOARD NON DESTRUCTIVE READ, NO WAIT +; +; PC-CONVERTIBLE-TYPE MACHINE: IF BIT 10 IS SET BY THE DOS IN THE STATUS WORD +; OF THE REQUEST PACKET, AND THERE IS NO CHARACTER IN THE INPUT BUFFER, THE +; DRIVER ISSUES A SYSTEM WAIT REQUEST TO THE ROM. ON RETURN FROM THE ROM, IT +; RETURNS A 'CHAR-NOT-FOUND' TO THE DOS. +; +CONBUSJ: + ASSUME DS:NOTHING + JMP CONBUS + + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$RDND +CON$RDND: + MOV AL,[ALTAH] + OR AL,AL + JZ RD1 + JMP RDEXIT + +RD1: +;SB34CON002************************************************************** +;SB Keyboard I/O interrupt +;SB Get keystroke status (KEYSTS_Func) +;SB 2 LOCS + + mov ah,KEYSTS_Func + int 16h +;SB34CON002************************************************************** + JZ NOCHR + JMP GOTCHR +NOCHR: + CMP FHAVEK09,0 + JZ CONBUSJ + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + TEST [BX].STATUS,0400H ; SYSTEM WAIT ENABLED? + JZ CONBUSJ + +;******************************** +; NEED TO WAIT FOR IBM RESPONSE TO REQUEST FOR CODE ON HOW TO USE THE SYSTEM +; WAIT CALL. +;******************************** + MESSAGE FTESTCON,<"SYSTEM WAIT STAGE",CR,LF> + MOV AX,4100H ; WAIT ON AN EXTERNAL EVENT +; MOV BX,0300H ; NO TIMEOUT +; MOV DX,60H ; LOOK AT I/O PORT 60H + INT 15H ; CALL ROM FOR SYSTEM WAIT + MESSAGE FTESTCON,<"OUT OF WAIT. AX IS "> + MNUM FTESTCON,AX + MESSAGE FTESTCON, + JMP CONBUS + + ASSUME DS:CODE +GOTCHR: + OR AX,AX + JNZ NOTBRK ;CHECK FOR NULL AFTER BREAK +;SB34CON004************************************************************** +;SB Keyboard I/O interrupt +;SB Keyboard read function (KEYRD_Func) +;SB 2 LOCS + + mov ah,KEYRD_Func + int 16h +;SB34CON004************************************************************** + JUMP CON$RDND ;AND GET A REAL STATUS +NOTBRK: + CMP AX,7200H ;CHECK FOR CTRL-PRTSC + JNZ RD_Ext_Chk ;AN000; + MOV AL,16 + jmp RDEXIT ;AN000; +RD_Ext_Chk: ;AN000; + cmp KEYRD_Func, 0 ;AN000; Extended Keyboard function? + jz RDEXIT ;AN000; No. Normal exit. + cmp al,0E0h ;AN000; Extended key value or Greek Alpha? + jne RDEXIT ;AN000; + cmp ah, 0 ;AN000; Scan code exist? + jz RDEXIT ;AN000; Yes. Greek Alpha char. + mov al, 0 ;AN000; No. Extended key stroke. Change it for compatibility + PUBLIC RDEXIT +RDEXIT: + LDS BX,[PTRSAV] + ASSUME DS:NOTHING + MOV [BX].MEDIA,AL +EXVEC: + JUMP EXIT + +CONBUS: + ASSUME DS:NOTHING + JUMP BUS$EXIT +;-------------------------------------------------------------- +; +; KEYBOARD FLUSH ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$FLSH +CON$FLSH: + CALL FLUSH + JUMP EXIT + + PUBLIC FLUSH +FLUSH: + MOV [ALTAH],0 ;CLEAR OUT HOLDING BUFFER + +FLLOOP: +;SB33012**************************************************************** + ;SB ; Is there a char there? + mov AH, 1 ;SB ; command code for check status + int 16h ;SB ; call rom-bios keyboard routine +;SB33012**************************************************************** + JZ FLDONE +;SB33013**************************************************************** + xor AH, AH ;SB ; if zf is nof set, get character + int 16h ;SB ; call rom-bios to get character +;SB33013**************************************************************** + JMP FLLOOP +FLDONE: + + RET +;---------------------------------------------------------- +; +; CONSOLE WRITE ROUTINE +; + ASSUME DS:CODE ; THIS WAS SET BY THE CON DD ENTRY POINT + PUBLIC CON$WRIT +CON$WRIT: + JCXZ EXVEC +CON$LP: + MOV AL,ES:[DI] ;GET CHAR + INC DI + INT CHROUT ;OUTPUT CHAR + LOOP CON$LP ;REPEAT UNTIL ALL THROUGH + JUMP EXIT +;----------------------------------------------- +; +; BREAK KEY HANDLING +; + PUBLIC CBREAK +CBREAK: + MOV CS:ALTAH,3 ;INDICATE BREAK KEY SET + + PUBLIC INTRET +INTRET: + IRET + +;------------------------------------------------------------------------------ +;J.K. 4/29/86 - CONSOLE GENERIC IOCTL SUPPORT FOR DOS 3.3. +;CON$GENIOCTL supports Get mode information, Set mode information functions. +;It will only save the value from "Set mode information" and will return +;the value through "Get mode information". It is supposed to be set by +;the MODE.COM and other application program can retrieve information +;through "Get mode information" call. +;Initially, there is no valuable informaton until set by MODE command, so +;any attemp to "Get mode information" at that points will fail. (unknown +;command with carry set.) +;At entry: CS = DS = code +; CS:[PTRSAV] has seg, address of the Request Header saved in +; in Strategy routine. +; +; PUBLIC CON$GENIOCTL +; ASSUME DS:CODE +;CON$GENIOCTL: +; les di, CS:[PTRSAV] ;get the request header +; cmp es:[di].MajorFunction, IOC_SC +; je Major_SC_OK +;SC_CMDERR: +; stc +; jmp cmderr ;carry is set, exit to cmderr +;Major_SC_OK: +; mov al, es:[di].MinorFunction ;save minor function +; les di, es:[di].GenericIOCTL_Packet ;pointer of SC_MODE_INFO structure +; mov cx, es:[di].SC_INFO_LENGTH ;save length +; inc di +; inc di ;ES:DI -> SC_MODE in Info. Packet +; cmp cx, SC_INFO_PACKET_LENGTH ;currently 9. +; jne SC_CMDERR ;cannot accept the different packet +; cmp al, GET_SC_MODE ;minor function = 60h ? +; jne SC_SET_MODE_FUNC ;no, check if it is "Set mode function" +; cmp SAV_SC_MODE, 0 ;information set before? +; je SC_CMDERR ;no, cannot get the info. +;;SC_GET_MODE_FUNC: ;es:di -> SC_MODE in info. packet +; ;cx - length +; mov si, offset SAV_SC_INFO +; rep movsb ;ds:si -> sav_sc_info, es:di -> sc_mode +; jmp exit +; +;SC_SET_MODE_FUNC: ;es:di -> SC_MODE +; cmp al, SET_SC_MODE ;minor function = 40h ? +; jne SC_CMDERR +; mov si, offset SAV_SC_INFO +; xchg di, si +; push es +; push ds +; pop es +; pop ds +; rep movsb ;ds:si -> sc_mode, es:di -> sav_sc_info +; jmp exit +; +;J.K. 4/29/86 - End of CONSOLE GENERIC IOCTL SUPPORT FOR DOS 3.3. + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSDISK.ASM b/v4.0/src/BIOS/MSDISK.ASM new file mode 100644 index 0000000..f132e7f --- /dev/null +++ b/v4.0/src/BIOS/MSDISK.ASM @@ -0,0 +1,2443 @@ + PAGE ,132 ; + TITLE MSDISK - BIOS + %OUT ...MSDISK.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; d24 Multi Track enable/disable command in CONFIG.SYS 6/27/87 J.K. +;AN002; d9 Double word MOV instruction 7/1/87 J.K. +;AN003: d25 Change DASD ERP to that recommended by Storage systems 7/28/87 J.K. +;AN004; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN005; P985 Allow I/O access to unformatted media 9/14/87 J.K. +;AN006; P1535 Disallow I/O access to unformatted media. 10/15/87 J.K. +; (Give the user to control this - Generic IOCTL subfunction 64h/44h +;AN007; p2828 Do not retry for multi-track format request 12/08/87 J.K. +;AC008; p3197 Should reset change line after BPB set in BDS table 01/21/88 J.K. +;AN009; p3349 Should retry at hard file timeout error 02/03/88 J.K. +;AN010; p4696 ECC error handler should cover PC ATs for CMC disks 05/04/88 J.K. +;AN011; p5034 Possible virgin hard file problem with direct INT 13 06/03/88 J.K. +;AN012; P5049 Attempt to write at DISK BASE table in ROM BIOS 06/06/88 J.K. +;AN013; P5055 Diskcopy fails (Regression of P5049) 06/09/88 J.K. +;============================================================================== + +;for testing, set itest to 1. So as MSBIO1.ASM. + itest=0 + EXTRN NUMERR:ABS ;MSDATA + + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE PUSHPOP.INC + INCLUDE MSMACRO.INC + INCLUDE DEVSYM.INC + INCLUDE MSDSKPR.INC + include biostruc.inc + + EXTRN INT2F_DISK:FAR ;MSBIO2 + EXTRN MEDIACHECK:NEAR ;96TPI + EXTRN HASCHANGE:NEAR ;96TPI + EXTRN MEDIA_SET_VID:NEAR ;96TPI + EXTRN HIDENSITY:NEAR ;96TPI + EXTRN CHECKLATCHIO:NEAR ;96TPI + EXTRN CHECKIO:NEAR ;96TPI + EXTRN SET_CHANGED_DL:NEAR ;96TPI + EXTRN SET_VOLUME_ID:NEAR ;MSVOLID + EXTRN SWPDSK:NEAR ;MSBIO2 + EXTRN CMDERR:NEAR ;MSBIO1 + EXTRN STRATEGY:NEAR ;MSBIO1 + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN DSK$IN:NEAR ;MSBIO1 + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN BUS$EXIT:NEAR ;MSBIO1 + EXTRN ERR$EXIT:NEAR ;MSBIO1 + extrn ResetChanged:near ;AN000; MS96TPI + +;DATA + EXTRN OLD13:DWORD ;MSBIO2 + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN COM1DEV:WORD ;MSAUX + EXTRN DAYCNT:WORD ;MSCLOCK + EXTRN TIM_DRV:BYTE ;MSDATA + EXTRN ACCESSCOUNT:BYTE ;MSDATA + EXTRN SM92:BYTE ;MSDATA + EXTRN DISKSECTOR:BYTE ;MSDATA + EXTRN MEDIABYTE:BYTE ;MSDATA + EXTRN SECPERCLUSINSECTOR:BYTE ;MSDATA + EXTRN BPB_IN_SECTOR:WORD ;MSDATA + EXTRN DISKSECTOR:BYTE ;MSDATA + EXTRN STEP_DRV:BYTE ;MSDATA + EXTRN START_BDS:WORD ;MSDATA + EXTRN PHYS_DRV:BYTE ;MSDATA + EXTRN WRTVERIFY:WORD ;MSDATA + EXTRN FSETOWNER:BYTE ;MSDATA + EXTRN SINGLE:BYTE ;MSDATA + EXTRN RFLAG:BYTE ;MSDATA + EXTRN MEDBYT:BYTE ;MSDATA + EXTRN SPSAV:WORD ;MSDATA + EXTRN SECCNT:WORD ;MSDATA + EXTRN DPT:DWORD ;MSDATA + EXTRN CURSEC:BYTE,CURHD:BYTE ;MSDATA + EXTRN CURTRK:WORD ;MSDATA + EXTRN EOT:BYTE ;MSDATA + EXTRN MOTORSTARTUP:BYTE,SETTLECURRENT:BYTE,SETTLESLOW:BYTE ;MSDATA + EXTRN CURHD:BYTE ;MSDATA + EXTRN LSTERR:BYTE ;MSDATA + EXTRN ERRIN:BYTE,ERROUT:BYTE ;MSDATA + EXTRN PREVOPER:WORD ;MSDATA + EXTRN ORIG13:DWORD ;MSDATA + EXTRN FLAGBITS:WORD ;MSDATA + EXTRN NUMBER_OF_SEC:BYTE ;MSDATA + EXTRN FHAVE96:BYTE ;MSDATA + EXTRN NEW_ROM:BYTE ;MSDATA + EXTRN FORMT_EOT:BYTE,HDNUM:BYTE,TRKNUM:WORD,GAP_PATCH:BYTE ;MSDATA + EXTRN NEXT2F_13:WORD ;MSDATA + extrn Save_head_sttl:byte ;msbdata + extrn Secrete_Code:word ;msbdata J.K. 11/7/86 Secrete code for DOS 3.3 MSBIO + extrn Ext_Boot_Sig:byte ;AN000; msbdata + extrn Boot_Serial_L:word ;AN000; msbdata + extrn Boot_Serial_H:word ;AN000; msbdata + extrn Boot_Volume_Label:byte ;AN000; msbdata + extrn Boot_System_ID:byte ;AN000; msbdata + extrn Model_Byte:Byte ;MSBIO2 + extrn Secondary_Model_Byte:Byte ;MSBIO2 + +;----------------------------------------------------------------- +; +; DISK INTERFACE ROUTINES +; +; DEVICE ATTRIBUTE BITS: +; BIT 6 - GET/SET MAP FOR LOGICAL DRIVES AND GENERIC IOCTL. +; + +MAXERR = 5 +LSTDRV = 504H + +; SOME FLOPPIES DO NOT HAVE CHANGELINE. AS A RESULT, MEDIA-CHECK WOULD +; NORMALLY RETURN I-DON'T-KNOW, THE DOS WOULD CONTINUALLY REREAD THE FAT, AND +; DISCARD CACHED DATA. WE OPTIMIZE THIS BY IMPLEMENTING A LOGICAL DOOR- +; LATCH: IT IS PHYSICALLY IMPOSSIBLE TO CHANGE A DISK IN UNDER 2 SECONDS. WE +; RETAIN THE TIME OF THE LAST SUCCESSFUL DISK OPERATION AND COMPARE IT WITH +; THE CURRENT TIME DURING MEDIA-CHECK. IF < 2 SECONDS AND AT LEAST 1 TIMER +; TICK HAS PASSED, THE WE SAY NO CHANGE. IF > 2 SECONDS THEN WE SAY I- +; DON'T-KNOW. FINALLY, SINCE WE CANNOT TRUST THE TIMER TO BE ALWAYS +; AVAILABLE, WE RECORD THE NUMBER OF MEDIA CHECKS THAT HAVE OCCURRED WHEN NO +; APPARENT TIME HAS ELAPSED. WHILE THIS NUMBER IS < A GIVEN THRESHOLD, WE SAY +; NO CHANGE. WHEN IT EXCEEDS THAT THRESHOLD, WE SAY I-DON'T-KNOW AND RESET +; THE COUNTER TO 0. WHEN WE STORE THE TIME OF LAST SUCCESSFUL ACCESS, IF WE +; SEE THAT TIME HAS PASSED TOO, WE RESET THE COUNTER. +; +ACCESSMAX = 5 +; +; DUE TO VARIOUS BOGOSITIES, WE NEED TO CONTINUALLY ADJUST WHAT THE HEAD +; SETTLE TIME IS. THE FOLLOWING ALGORITHM IS USED: +; +; GET THE CURRENT HEAD SETTLE VALUE. +; IF IT IS 0, THEN +; SET SLOW = 15 +; ELSE +; SET SLOW = VALUE +; ... +;********************************************* +;************ OLD ALGORITHM ****************** +;* IF WE ARE SEEKING AND WRITING THEN +;* USE SLOW +;* ELSE +;* USE FAST +;********************************************* +;*********** IBM'S REQUESTED LOGIC *********** +; IF WE ARE SEEKING AND WRITING AND NOT ON AN AT THEN +; USE SLOW +; ELSE +; USE FAST +; ... +; RESTORE CURRENT HEAD SETTLE VALUE +; + +Set_ID_Flag db 0 ;AN000; If 1, GETBP routine will set the + ;Vol_Serial and FileSys_ID in BDS table + ;from the media Boot record, if it is > DOS 4.00 + ;formatted one. Then Set_ID_flag will be set to 2 + ;to signal that volume_label is set from the extended + ;boot record and do not set it from the root + ;directory as done in SET_VOLUME_ID routine. + ;For the old version, Vol_Serial + ;will be set to -1, and FileSys_ID will be set + ;to "FAT12 " if it is a floppy. + + public Fat_12_ID +Fat_12_ID DB "FAT12 ",0 ;AN000; Default System ID for floppy. + public Fat_16_ID +Fat_16_ID DB "FAT16 ",0 ;AN000; + public Vol_No_Name +Vol_No_Name db "NO NAME ",0 ;AN000; + public Temp_H +Temp_H dw 0 ;AN000; Temporary for 32 bit calculation. + + public Start_Sec_H +Start_Sec_H dw 0 ;AN000; Starting sector number high word. + ;Used as an input to DISKIO subroutine. +Saved_Word dw 0 ;AN000; Tempory saving place for a word. + +;--------------------------------------- +;J.K. 6/29/87 For Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + public MulTrk_Flag +MulTrk_Flag dw 0 ;AN001; +;J.K. 6/29/87 End of Multi-track definition. +;--------------------------------------------------------------------- + public EC35_Flag +EC35_Flag db 0 ; flags for electrically compatible 3.5 inch disk drives (mrw 4/88) +;--------------------------------------------------------------------- +VRetry_Cnt dw 0 ;AN003; +Soft_ECC_Cnt dw 0 ;AN003; +;--------------------------------------------------------------------- +MultiTrk_Format_Flag db 0 ;AN007;Testing. If 1, then Multi track format request +;--------------------------------------------------------------------- +; +; IF ID IS F9, HAVE A 96TPI DISK ELSE +; IF BIT 2 IS 0 THEN MEDIA IS NOT REMOVABLE AND COULD NOT HAVE CHANGED +; OTHERWISE IF WITHIN 2 SECS OF LAST DISK OPERATION MEDIA COULD NOT +; HAVE CHANGED, OTHERWISE DONT KNOW IF MEDIA HAS CHANGED +; + PUBLIC MEDIA$CHK +MEDIA$CHK PROC NEAR + MESSAGE FTESTDISK,<"DISK MEDIA CHECK "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, + CALL SETDRIVE + + cmp cs:Secrete_Code, 'jk' ;J.K.11/7/86 Secrete code for DOS 3.3 IBMBIO. + jne media$done ;J.K.11/7/86 + +; FOR NON-REMOVABLE DISKS ONLY RETURN CHANGED IF CHANGED BY FORMAT, OTHERWISE +; RETURN 'NOT CHANGED'. + MOV SI,1 ; ASSUME NO CHANGE + TEST WORD PTR [DI].FLAGS,FCHANGED_BY_FORMAT + JZ WEARENOTFAKINGIT + AND WORD PTR [DI].FLAGS,NOT FCHANGED_BY_FORMAT ; RESET FLAG +; IF MEDIA HAS BEEN CHANGED BY FORMAT, WE MUST ASK THE ROM. CANNOT RELY ON THE +; 2 SECOND TIME CHECK. + MOV CS:[TIM_DRV],-1 ; ENSURE THAT WE ASK THE ROM IF MEDIA + ; HAS CHANGED + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JZ WEHAVEAFLOPPY + MOV SI,-1 ; INDICATE MEDIA CHANGED + JMP SHORT MEDIA$DONE +; +; WE NEED TO RETURN 'NOT CHANGED' IF WE HAVE A HARD FILE. +; +WEARENOTFAKINGIT: + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ MEDIA$DONE +WEHAVEAFLOPPY: + XOR SI,SI ; PRESUME "I DON'T KNOW" +; +; IF WE HAVE A FLOPPY WITH CHANGELINE SUPPORT, WE ASK THE ROM TO DETERMINE IF +; MEDIA HAS CHANGED. WE DO NOT PERFORM THE 2 SECOND CHECK FOR THESE DRIVES. +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC MEDIA_PATCH ;| +MEDIA_PATCH: ;| + CALL MEDIACHECK ;| + JC ERR$EXITJ ;| + CALL HASCHANGE ;| + JNZ MEDIA$DONE ;| +;----------------------------------------| +; IF WE COME HERE, WE HAVE A FLOPPY WITH NO CHANGELINE SUPPORT + MOV SI,1 ; PRESUME NO CHANGE + MOV AL,CS:[TIM_DRV] ; LAST DRIVE ACCESSED + CMP AL,BYTE PTR [DI].DRIVENUM ;IS DRIVE OF LAST ACCESS THE SAME? + JNZ MEDIA$UNK ; NO, THEN "I DON'T KNOW" +; +; CHECK TO SEE IF THIS DRIVE HAS BEEN ACCESSED IN THE LAST 2 SECONDS. + CALL CHECK_TIME_OF_ACCESS ; SETS SI CORRECTLY + JMP SHORT MEDIA$DONE + +MEDIA$UNK: + DEC SI ; RETURN "I DON'T KNOW" +; +; SI NOW CONTAINS THE CORRECT VALUE FOR MEDIA CHANGE. CLEAN UP THE LEFT OVERS +; +MEDIA$DONE: + LES BX,CS:[PTRSAV] ; GET ORIGINAL PACKET + MOV WORD PTR ES:[BX].TRANS,SI + OR SI,SI + JS INIT_PATCH + JMP EXIT +MEDIA$CHK ENDP +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC INIT_PATCH ;| +INIT_PATCH PROC NEAR ;| + CALL MEDIA_SET_VID ;| +;----------------------------------------| + MOV CS:[TIM_DRV],-1 ; MAKE SURE WE ASK ROM FOR MEDIA CHECK +VOLIDOK: + JMP EXIT +INIT_PATCH ENDP + +ERR$EXITJ PROC NEAR + + MESSAGE FTESTCOM,<"ERR$EXITJ: "> + MNUM FTESTCOM,AX + MESSAGE FTESTCOM,<" == "> + CALL MAPERROR + MNUM FTESTCOM,AX + MESSAGE FTESTCOM, + JMP ERR$EXIT +ERR$EXITJ ENDP + +; +; PERFORM A CHECK ON THE TIME PASSED SINCE THE LAST ACCESS FOR THIS PHYSICEL +; DRIVE. +; WE ARE ACCESSING THE SAME DRIVE. IF THE TIME OF LAST SUCCESSFUL ACCESS WAS +; LESS THAN 2 SECONDS AGO, THEN WE MAY PRESUME THAT THE DISK WAS NOT CHANGED. +; RETURNS IN SI: +; 0 - IF TIME OF LAST ACCESS WAS >= 2 SECONDS +; 1 - IF TIME WAS < 2 SECONDS (I.E NO MEDIA CHANGE ASSUMED) +; REGISTERS AFFECTED AX,CX,DX, FLAGS. +; +CHECK_TIME_OF_ACCESS PROC NEAR + PUBLIC CHECK_TIME_OF_ACCESS + + MOV SI,1 ; PRESUME NO CHANGE. +;SB33014************************************************************* + xor AH,AH ; set command to read time + int 1Ah ; call rom-bios clock routine +;SB33014************************************************************* +; +; NOW THAT WE ARE READING THE TIME, WE MUST MAKE SURE THAT WE DO NOT LOSE A +; DATE WRAP. THE ROM WILL RETURN THE VALUE ONLY ONCE, SO WE NEED TO NOTE THIS +; FACT. +; + SHR AL,1 + ADC CS:[DAYCNT],0 ; ADD IT IN TO OUR REMEMBERED DAY COUNT +; +; COMPUTE ELAPSED TIME +; + MOV AX,WORD PTR DS:[DI].TIM_LO ; GET STORED TIME + SUB DX,AX + MOV AX,WORD PTR DS:[DI].TIM_HI + SBB CX,AX +; +; CX:DX IS THE ELAPSED TIME +; + JNZ TIMECHECK_UNK ; CX <> 0 => > 1 HOUR + OR DX,DX ; TIME MUST PASS + JNZ TIMEPASSED ; YES, EXAMINE MAX VALUE +; +; NO NOTICEABLE TIME HAS PASSED. WE CANNOT TRUST THE COUNTER TO BE ALWAYS +; AVAILABLE AS THERE ARE BOGUS PROGRAMS THAT GO AND REPROGRAM THE THING. WE +; KEEP A COUNT OF THE NUMBER OF MEDIA CHECKS THAT WE'VE SEEN THAT DO NOT HAVE +; ANY TIME PASSING. IF WE EXCEED A GIVE THRESHOLD, WE GIVE UP ON THE TIMER. +; + INC BYTE PTR CS:ACCESSCOUNT + CMP BYTE PTR CS:ACCESSCOUNT,ACCESSMAX + JB TIMECHECK_RET ; IF COUNT IS LESS THAN THRESHOLD, OK + DEC BYTE PTR CS:ACCESSCOUNT ; DON'T LET THE COUNT WRAP + JMP SHORT TIMECHECK_UNK ; "I DON'T KNOW" IF MEDIA CHANGED +; +; 18.2 TICS PER SECOND. +; +TIMEPASSED: + CMP DX,18 * 2 ; MIN ELAPSED TIME? + JBE TIMECHECK_RET ; YES, PRESUME NO CHANGE +; +; EVERYTHING INDICATES THAT WE DO NOT KNOW WHAT HAS HAPPENED. +; +TIMECHECK_UNK: + DEC SI ; PRESUME I DON'T KNOW +TIMECHECK_RET: + RET +CHECK_TIME_OF_ACCESS ENDP + +ERR$EXITJ2: JMP ERR$EXITJ +; +; BUILD A VALID BPB FOR THE DISK IN THE DRIVE. +; + PUBLIC GET$BPB +GET$BPB PROC NEAR + MESSAGE FTESTDISK,<"DISK BUILD BPB "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, + MOV AH,BYTE PTR ES:[DI] ;GET FAT ID BYTE READ BY DOS + CALL SETDRIVE ; GET THE CORRECT BDS FOR THE DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ ALREADY_GOTBPB ; NO NEED TO BUILD FOR FIXED DISKS +;J.K. Let's set the default value for VOLID,Vol_Serial,FileSys_ID in BDS table + call Clear_IDs ;AN000; + mov cs:[Set_ID_Flag],1 ;AN000; Indicate to set system id in BDS + CALL GETBP ;BUILD A BPB IF NECESSARY. + JC ERR$EXITJ2 ;AN000; If error, Set_ID_flag is set to 0 already. + cmp cs:[Set_ID_Flag],2 ;AN000; Already, volume_Label set from Boot record + mov cs:[Set_ID_Flag],0 ;AN000; to BDS table? + je Already_GotBPB ;AN000; Then do not set it again from Root directory. + ;AN000; Otherwise, conventional Boot record. +GET$BPB ENDP +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC SET_PATCH ;| +SET_PATCH PROC NEAR ;| + CALL SET_VOLUME_ID ;| +;----------------------------------------| + MESSAGE FTESTDISK,<"SET VOLUME ID"> + MNUM FTESTDISK,DI + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DS + MESSAGE FTESTDISK, + +ALREADY_GOTBPB: + ADD DI,BYTEPERSEC ; RETURN THE BPB THAT IS IN THE CURRENT BDS + + PUBLIC SETPTRSAV +SETPTRSAV: ; RETURN POINT FOR DSK$INIT + LES BX,CS:[PTRSAV] + MOV ES:[BX].MEDIA,AH + MOV ES:[BX].COUNT,DI + MOV ES:[BX].COUNT+2,DS + JMP EXIT +SET_PATCH ENDP + +;J.K. Clear IDs in BDS table. Only applied for Floppies. +;Input: DS:DI -> BDS table +;Output: VOLID set to "NO NAME " +; VOL_SERIAL set to 0. +; FileSys_ID set to "FAT12 " or "FAT16 " +; depending on the flag FATSIZE in BDS. +;All registers saved. + public Clear_IDs +Clear_IDs proc near ;AN000; + push ds ;AN000; + push di ;AN000; + push es ;AN000; + push si ;AN000; + push cx ;AN000; + + push ds ;AN000; + pop es ;AN000; es -> bds + push cs ;AN000; + pop ds ;AN000; ds = cs + + mov cx, 0 ;AN000; no serial number + mov word ptr es:[di.VOL_SERIAL],cx ;AN000; + mov word ptr es:[di.VOL_SERIAL]+2,cx ;AN000; + + mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000; =11 + mov si, offset VOL_NO_NAME ;AN000; + push di ;AN000; save BDS pointer + add di, VOLID ;AN000; points to VOLID field + rep movsb ;AN000; + pop di ;AN000; restore BDS pointer + test es:[di.FATSIZ], FBIG ;AN000; + jnz CI_BigFat ;AN000; small fat + mov si, offset FAT_12_ID ;AN000; + jmp CI_Filesys ;AN000; +CI_BigFat: ;AN000; + mov si, offset FAT_16_ID ;AN000; big fat +CI_Filesys: ;AN000; + mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8 + add di, FILESYS_ID ;AN000; points to FILESYS_ID field + rep movsb ;AN000; + + pop cx ;AN000; + pop si ;AN000; + pop es ;AN000; + pop di ;AN000; + pop ds ;AN000; + ret ;AN000; +Clear_IDs endp ;AN000; + + +; GETBP - RETURN BPB FROM THE DRIVE SPECIFIED BY THE BDS. +; IF THE RETURN_FAKE_BPB FLAG IS SET, THEN IT DOES NOTHING. +; NOTE THAT WE NEVER COME HERE FOR FIXED DISKS. +; FOR ALL OTHER CASES, +; - IT READS BOOT SECTOR TO PULL OUT THE BPB +; - IF NO VALID BPB IS FOUND, IT THEN READS THE FAT SECTOR, +; TO GET THE FAT ID BYTE TO BUILD THE BPB FROM THERE. +; +; INPUTS: DS:DI POINT TO CORRECT BDS. +; +; OUTPUTS: FILLS IN BPB IN CURRENT BDS IF VALID BPB OR FAT ID ON DISK. +; CARRY SET, AND AL=7 IF INVALID DISK. +; CARRY SET AND ERROR CODE IN AL IF OTHER ERROR. +; If failed to recognize the Boot Record, then will set the +; Set_ID_Flag to 0. +; J.K. This routine will only work for a floppy diskette. +; For a fixed disk, it will just return. + + PUBLIC GETBP +GETBP PROC NEAR +; IF RETURNING FAKE BPB THEN RETURN BPB AS IS. + TEST WORD PTR [DI].FLAGS,RETURN_FAKE_BPB OR FNON_REMOVABLE + JZ GETBP1 + JMP GETRET_EXIT + +GETBP1: + MESSAGE FTESTDISK,<"BUILDING BPB FROM SCRATCH",CR,LF> + SAVEREG +; +; ATTEMPT TO READ IN BOOT SECTOR AND DETERMINE BPB. +; WE ASSUME THAT THE 2.X AND GREATER DOS DISKS ALL HAVE A VALID BOOT SECTOR. +; +RDBOOT: + CALL READBOOTSEC + JC GETBP_ERR_RET_brdg ; CARRY SET IF THERE WAS ERROR. + CMP BX,0 ; BX IS 0 IF BOOT SECTOR IS VALID. + JNZ DOFATBPB + + CALL MOVBPB ; MOVE BPB INTO REGISTERS. + JMP HAS1 + +Getbp_err_ret_brdg: jmp Getbp_err_ret +; +; WE HAVE A 1.X DISKETTE. +; IN THIS CASE READ IN THE FAT ID BYTE AND FILL IN BPB FROM THERE. +; +DOFATBPB: + CALL READFAT ; PUTS MEDIA DESCRIPTOR BYTE IN AH + JC GETBP_ERR_RET_Brdg +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC GETBP1_PATCH ;| +GETBP1_PATCH: ;| + CALL HIDENSITY ;| +;----------------------------------------| +;TEST FOR A VALID 3.5" MEDIUM + CMP [DI].FORMFACTOR,FFSMALL + JNZ IS_FLOPPY + CMP AH,0F9H ; IS IT A VALID FAT ID BYTE FOR 3.5" ? + JNZ GOT_UNKNOWN_MEDIUM + MOV BX,OFFSET SM92 ; POINTER TO CORRECT BPB + PUSH CS + POP ES + + ASSUME ES:CODE +;J.K. DS points to segment of BDS. The following should be modified +;J.K. to get spf,csec,spa,spt correctly. It had been wrong if DRIVER.SYS +;J.K. is loaded since the BDS is inside the driver.sys. + MOV AL,es:[BX.SPF] + MOV CX,es:[BX.CSEC] + MOV DX,WORD PTR es:[BX.SPA] + MOV BX,WORD PTR es:[BX.SPT] + JMP SHORT HAS1 +; MUST BE A 5.25" FLOPPY IF WE COME HERE +IS_FLOPPY: + MOV CL,AH ;SAVE MEDIA + AND CL,0F8H ;NORMALIZE + CMP CL,0F8H ;COMPARE WITH GOOD MEDIA BYTE + JNZ GOT_UNKNOWN_MEDIUM + +GOODID: + MOV AL,1 ;SET NUMBER OF FAT SECTORS + MOV BX,64*256+8 ;SET DIR ENTRIES AND SECTOR MAX + MOV CX,40*8 ;SET SIZE OF DRIVE + MOV DX,01*256+1 ;SET HEAD LIMIT AND SEC/ALL UNIT + TEST AH,00000010B ;TEST FOR 8 OR 9 SECTOR + JNZ HAS8 ;NZ = HAS 8 SECTORS + INC AL ;INC NUMBER OF FAT SECTORS + INC BL ;INC SECTOR MAX + ADD CX,40 ;INCREASE SIZE +HAS8: + TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS + JZ HAS1 ;Z = 1 HEAD + ADD CX,CX ;DOUBLE SIZE OF DISK + MOV BH,112 ;INCREASE NUMBER OF DIRECTORY ENTRIES + INC DH ;INC SEC/ALL UNIT + INC DL ;INC HEAD LIMIT + +HAS1: + PUBLIC HAS1 + + MOV BYTE PTR DS:[DI].SECPERCLUS,DH + MOV BYTE PTR DS:[DI].CDIR,BH + MOV WORD PTR DS:[DI].DRVLIM,CX + MOV BYTE PTR DS:[DI].MEDIAD,AH + MOV BYTE PTR DS:[DI].CSECFAT,AL + MOV BYTE PTR DS:[DI].SECLIM,BL + MOV BYTE PTR DS:[DI].HDLIM,DL +;SB34DISK001******************************************************************* +;SB the HIDSEC_H field and DRVLIM_L field and the +;SB DRVLIM_H fields need to be set to 0 since this code here is for floppies +;SB 3 LOCS + + mov word ptr ds:[di].HIDSEC_H,0 + mov word ptr ds:[di].HIDSEC_L,0 + mov word ptr ds:[di].DRVLIM_H,0 + +;SB34DISK001******************************************************************* +GETRET: + POP BX + RESTOREREG + + ASSUME ES:NOTHING + +GETRET_EXIT: + RET + +GETBP_ERR_RET: +;J.K. Before doing anything else, set Set_ID_Flag to 0. + mov cs:Set_ID_Flag, 0 ;AN000; + CALL MAPERROR + JMP SHORT GETRET +; +; WE HAVE A 3.5" DISKETTE FOR WHICH WE CANNOT BUILD A BPB. WE DO NOT ASSUME ANY +; TYPE OF BPB FOR THIS MEDIUM. +; +GOT_UNKNOWN_MEDIUM: + mov cs:Set_ID_Flag, 0 ;AN000; + MOV AL,ERROR_UNKNOWN_MEDIA + STC + JMP SHORT GETRET +GETBP ENDP + +BPBTYPE STRUC +SPF DB ? +SPT DB ? +CDIRE DB ? +CSEC DW ? +SPA DB ? +CHEAD DB ? +BPBTYPE ENDS + +; +; READ IN THE BOOT SECTOR. SET CARRY IF ERROR IN READING SECTOR. +; BX IS SET TO 1 IF THE BOOT SECTOR IS INVALID, OTHERWISE IT IS 0. +; +READBOOTSEC PROC NEAR + MOV DH,0 ;HEAD 0 + MOV CX,0001 ;CYLINDER 0, SECTOR 1 + CALL READ_SECTOR + JC ERR_RET + XOR BX,BX ; ASSUME VALID BOOT SECTOR. + +;******************************************************************************* +; PUT A SANITY CHECK FOR THE BOOT SECTOR IN HERE TO DETECT BOOT SECTORS THAT +; DO NOT HAVE VALID BPBS. +; WE EXAMINE THE FIRST TWO BYTES - THEY MUST CONTAIN A LONG JUMP (69H) OR A +; SHORT JUMP (EBH) FOLLOWED BY A NOP (90H), OR A SHORT JUMP (E9H). +; IF THIS TEST IS PASSED, WE FURTHER CHECK BY EXAMINING THE SIGNATURE AT +; THE END OF THE BOOT SECTOR FOR THE WORD AA55H. +; IF THE SIGNATURE IS NOT PRESENT, WE EXAMINE THE MEDIA DESCRIPTOR BYTE TO +; SEE IF IT IS VALID. +;J.K. 10/15/86 DCR00012. For DOS 3.3, this logic is modified a little bit. +; We are not going to check Signature. Instead we are going to sanity +; check the media byte in BPB regardless of the validity of signature. +; This is to save the already developed commercial products that have +; good jump instruction and signature but with the false BPB informations +; that will crash the diskette drive operation. (For example, Symphony diskette). +;****************************************************************************** + CMP BYTE PTR CS:[DISKSECTOR],069H ; IS IT A DIRECT JUMP? + JE Check_bpb_MediaByte ; DON'T NEED TO FIND A NOP + CMP BYTE PTR CS:[DISKSECTOR],0E9H ; DOS 2.0 JUMP? + JE Check_bpb_MediaByte ; NO NEED FOR NOP + CMP BYTE PTR CS:[DISKSECTOR],0EBH ; HOW ABOUT A SHORT JUMP. + JNE INVALIDBOOTSEC + CMP BYTE PTR CS:[DISKSECTOR]+2,090H ; IS NEXT ONE A NOP? + JNE INVALIDBOOTSEC + + +;J.K. 10/15/86 Don't have to perform the following signature check since +; we need to check the media byte even with the good signatured diskette. +;CHECK_SIGNATURE: +; CMP WORD PTR CS:[DISKSECTOR+1FEH],0AA55H ; SEE IF NON-IBM DISK OR 1.X +; ; MEDIA. +; JZ CHECKSINGLESIDED ; GO SEE IF SINGLE SIDED MEDIUM. MAY +; ; NEED SOME SPECIAL HANDLING +; +; CHECK FOR NON-IBM DISKS WHICH DO NOT HAVE THE SIGNATURE AA55 AT THE +; END OF THE BOOT SECTOR, BUT STILL HAVE A VALID BOOT SECTOR. THIS IS DONE +; BY EXAMINING THE MEDIA DESCRIPTOR IN THE BOOT SECTOR. +; + +Check_bpb_MediaByte: + + MOV AL,BYTE PTR CS:MEDIABYTE + AND AL,0F0H + CMP AL,0F0H ; ALLOW FOR STRANGE MEDIA + JNZ INVALIDBOOTSEC +; +; THERE WERE SOME (APPARENTLY A LOT OF THEM) DISKETTES THAT HAD BEEN FORMATTED +; UNDER DOS 3.1 AND EARLIER VERSIONS WHICH HAVE INVALID BPBS IN THEIR BOOT +; SECTORS. THESE ARE SPECIFICALLY DISKETTES THAT WERE FORMATTED IN DRIVES +; WITH ONE HEAD, OR WHOSE SIDE 0 WAS BAD. THESE CONTAIN BPBS IN THE BOOT +; SECTOR THAT HAVE THE SEC/CLUS FIELD SET TO 2 INSTEAD OF 1, AS IS STANDARD +; IN DOS. IN ORDER TO SUPPORT THEM, WE HAVE TO INTRODUCE A "HACK" THAT WILL +; HELP OUR BUILD BPB ROUTINE TO RECOGNISE THESE SPECIFIC CASES, AND TO +; SET UP OUT COPY OF THE BPB ACCORDINGLY. +; WE DO THIS BY CHECKING TO SEE IF THE BOOT SECTOR IS OFF A DISKETTE THAT +; IS SINGLE-SIDED AND IS A PRE-DOS 3.20 DISKETTE. IF IT IS, WE SET THE +; SEC/CLUS FIELD TO 1. IF NOT, WE CARRY ON AS NORMAL. +CHECKSINGLESIDED: + MOV AL,BYTE PTR CS:MEDIABYTE + TEST AL,0001H ; IS LOW BIT SET? - INDICATES DOUBLE SIDED + JNZ GOODDSK + CMP WORD PTR CS:[DISKSECTOR+8],"." SHL 8 + "3" + JNZ MUSTBEEARLIER + CMP BYTE PTR CS:[DISKSECTOR+10],"2" + JAE GOODDSK + +; WE MUST HAVE A PRE-3.20 DISKETTE. SET THE SEC/CLUS FIELD TO 1 +MUSTBEEARLIER: + MOV BYTE PTR CS:[SECPERCLUSINSECTOR],1 + JMP SHORT GOODDSK +;****************************************************************************** + +INVALIDBOOTSEC: + INC BX ; INDICATE THAT BOOT SECTOR INVALID +GOODDSK: ; CARRY ALREADY RESET + CLC + RET + +ERR_RET: ; CARRY IS ALREADY SET ON ENTRY HERE + MESSAGE FTESTDISK,<"ERROR IN READBOOT",CR,LF> + RET +READBOOTSEC ENDP + +; MOVES THE BPB READ FROM THE BOOT SECTOR INTO REGISTERS FOR USE BY +; GETBP ROUTINE AT HAS1 +;J.K.- +; If the Set_ID_Flag is 1, and if an extended Boot Record, then set Volume +; Serial Number, Volume Label, File System ID in BDS according to +; the BOOT reocrd. After that, this routine will set the Set_ID_Flag to 2 +; to signal that VOLUME Label is set already from the Extended BOOT record +; (so, don't set it again by calling "SET_VOLUME_ID" routine which uses +; the volume label in the root directory. + +MOVBPB PROC NEAR + SAVEREG + PUSH CS + POP DS + MOV DI,OFFSET BPB_IN_SECTOR + MOV DH,BYTE PTR [DI].SECALL ;SECTORS PER UNIT + MOV BH,BYTE PTR [DI].DIRNUM ;NUMBER OF DIRECTORY ENTRIES + MOV CX,WORD PTR [DI].SECNUM ;SIZE OF DRIVE + MOV AH,BYTE PTR [DI].FATID ;MEDIA DESCRIPTOR + MOV AL,BYTE PTR [DI].FATSIZE ;NUMBER OF FAT SECTORS + MOV BL,BYTE PTR [DI].SLIM ;SECTORS PER TRACK + MOV DL,BYTE PTR [DI].HLIM ;NUMBER OF HEADS + RESTOREREG + cmp cs:[Set_ID_Flag], 1 ;AC008 called by GET$BPB? + jne MovBPB_Ret ;AC008 + call Mov_Media_IDs ;AC008 + jc MovBPB_Conv ;AC008 Conventional boot record? + mov cs:[Set_ID_Flag],2 ;AC008 signals that Volume ID is set. +MovBPB_Conv: ;AC008 + cmp cs:fHave96, 1 ;AC008 + jne MovBPB_Ret ;AC008 + call ResetChanged ;AC008 Reset Flags in BDS to NOT fCHANGED. +MovBPB_Ret: ;AC008 + clc ;AC008 + ret ;AC008 +MOVBPB ENDP ;AC008 + + +; + public Mov_Media_IDs +Mov_Media_IDs Proc near ;AN000; +;copy the boot_serial number, Volume id, and Filesystem id from the +;***Extended Boot record*** in cs:DiskSector to the BDS table pointed +;by DS:DI. +;In.) DS:DI -> BDS +; CS:DiskSector = Valid extended boot record. +;Out.) Vol_Serial, Volid and System_Id in BDS are set according to +; the boot record information. +; Carry flag set if not an extended BPB. +; All registers saved except the flag. + + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN000; = 41 + jne MMI_Not_Ext ;AN000; + push cx ;AN000; + mov cx, cs:[Boot_Serial_L] ;AN000; + mov word ptr ds:[di.VOL_SERIAL],cx ;AN000; + mov cx, cs:[Boot_Serial_H] ;AN000; + mov word ptr ds:[di.VOL_SERIAL+2],cx ;AN000; + push ds ;AN000; Save regs. + push di ;AN000; + push es ;AN000; + push si ;AN000; + + push ds ;AN000; ds-> cs, es-> bds + pop es ;AN000; + push cs ;AN000; + pop ds ;AN000; + + mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000; + mov si, offset Boot_Volume_Label;AN000; + push di + add di, VOLID ;AN000; + rep movsb ;AN000; + pop di + mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8 + mov si, offset Boot_System_ID ;AN000; + add di, FILESYS_ID ;AN000; + rep movsb ;AN000; + + pop si ;AN000; + pop es ;AN000; + pop di ;AN000; + pop ds ;AN000; + pop cx ;AN000; + clc ;AN000; +MMI_Ret: ;AN000; + ret ;AN000; +MMI_Not_Ext: ;AN000; + stc ;AN000; + ret ;AN000; +Mov_Media_IDs endp ;AN000; + + +; READ IN THE FAT SECTOR AND GET THE MEDIA BYTE FROM IT. +; INPUT : AL CONTAINS LOGICAL DRIVE. +; OUTPUT: +; CARRY SET IF AN ERROR OCCURS, AX CONTAINS ERROR CODE. +; OTHERWISE, AH CONTAINS MEDIA BYTE ON EXIT. AL IS PRESERVED. + +READFAT PROC NEAR + PUSH AX ; PRESERVE LOGICAL DRIVE IN AL + MOV DH,0 ; HEAD 0 + MOV CX,0002 ; CYLINDER 0, SECTOR 2 + CALL READ_SECTOR ; CS:BX POINTS TO FAT SECTOR + JC BAD_FAT_RET + POP AX ; RESET LOGICAL DRIVE + MOV AH,BYTE PTR CS:[BX] ; MEDIA BYTE + RET + +BAD_FAT_RET: ; CARRY SET ON ENTRY + MESSAGE FTESTDISK,<"ERROR IN FAT READ",CR,LF> + POP CX ; CLEAR STACK + RET +READFAT ENDP + +; READ A SINGLE SECTOR INTO THE TEMP BUFFER. +; PERFORM THREE RETRIES IN CASE OF ERROR. +; INPUTS: DRIVE HAS PHYSICAL DRIVE TO USE +; CX HAS SECTOR AND CYLINDER +; DH HAS HEAD +; OUTPUTS: CARRY CLEAR +; CS:BX POINT TO SECTOR +; CARRY SET +; AX HAS ROM ERROR CODE +; REGISTERS ES AND BP ARE PRESERVED. + +READ_SECTOR PROC NEAR + PUBLIC READ_SECTOR + + PUSH BP + MOV BP,3 ; MAKE 3 ATTEMPTS + PUSH ES +;SB33015***************************************************************** + mov DL, byte ptr ds:[di].DriveNum ;SB;3.30* + mov BX, offset DiskSector ; Get ES:BX to point to buffer ;SB;3.30* + push CS ; get the segment right ;SB;3.30* + pop ES ; now ES:BX is correct ;SB;3.30* +;SB33015***************************************************************** +RD_RET: +;SB33016***************************************************************** + mov AX, 0201h ; number of sectors to 1 (AL=1);SB;3.30* + int 13h ; call rom-bios disk routines ;SB;3.30* + +;SB33016***************************************************************** + JNC OKRET2 +Rd_rty: + CALL AGAIN ; RESET DISK, DECREMENT BP, PRESERVE AX + jz Err_RD_RET + test word ptr ds:[di].flags,fNon_Removable + JNZ RD_RET + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Rd_Skip1_DPT ;AN012; + push ds ;J.K. 11/7/86 For retry, set the head settle time + push ax ;to 0Fh. PTM845. + lds si,cs:DPT + mov al, ds:[si].disk_head_sttl + mov cs:[save_head_sttl],al + mov byte ptr ds:[si].disk_head_sttl, NormSettle + pop ax + pop ds +Rd_Skip1_DPT: ;AN012; +;SB33017***************************************************************** + ; SET CMD TO READ (AH=2) AND ;SB ;3.30 + MOV AX, 0201h ; NUM OF SECTORS TO 1 (AL=1) ;SB ;3.30 + INT 13h ; CALL ROM-BIOS DISK ROUTINES ;SB ;3.30 +;SB33017***************************************************************** + pushf ;AN012; + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Rd_Skip2_DPT ;AN012; + push ds + push ax + lds si,cs:DPT + mov al, cs:[save_head_sttl] + mov byte ptr ds:[si].disk_head_sttl, al + pop ax + pop ds +Rd_Skip2_DPT: ;AN012; + popf ;AN012; + jnc OKRET2 + jmp Rd_rty +ERR_RD_RET: + MOV DL,-1 ; MAKE SURE WE ASK ROM IF MEDIA HAS CHANGED + STC ; RETURN ERROR +; UPDATE INFORMATION PERTAINING TO LAST DRIVE ACCESSED, TIME OF ACCESS, LAST +; TRACK ACCESSED IN THAT DRIVE. +OKRET2: + MOV CS:[STEP_DRV],DL ; SET UP FOR HEAD SETTLE LOGIC IN DISK. + MOV CS:[TIM_DRV],DL ;SAVE DRIVE LAST ACCESSED + MOV BYTE PTR [DI].TRACK,CH ; SAVE LAST TRACK ACCESSED ON THIS DRIVE + PUSHF ; PRESERVE FLAGS IN CASE ERROR OCCURRED + CALL SET_TIM + POPF ; RESTORE FLAGS + POP ES + POP BP + RET +READ_SECTOR ENDP + +;----------------------------------------------------------- +; +; DISK REMOVABLE ROUTINE ARR 2.41 +; + +DSK$REM PROC NEAR ;ARR 2.41 + PUBLIC DSK$REM + + MESSAGE FTESTDISK,<"DISK REMOVABLE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK, +; AL IS UNIT # + CALL SETDRIVE ; GET BDS FOR THIS DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ NON_REM + JMP EXIT + +NON_REM: + JMP BUS$EXIT ;ARR 2.41 +DSK$REM ENDP + +; SETDRIVE SCANS THROUGH THE DATA STRUCTURE OF BDSS, AND RETURNS A POINTER TO +; THE ONE THAT BELONGS TO THE DRIVE SPECIFIED. CARRY IS SET IF NONE EXISTS FOR +; THE DRIVE. +; IF THE BYTE [PHYS_DRV] IS 0 THEN +; ON ENTRY, AL CONTAINS THE LOGICAL DRIVE NUMBER. +; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR. + +; ELSE IF THE BYTE [PHYS_DRV] IS 1 THEN (ONLY USED FOR FIXED DISKS WHEN AN ECC +; ERROR OCCURS) +; ON ENTRY, DL CONTAINS THE PYHSICAL DRIVE NUMBER. +; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR. + + PUBLIC SETDRIVE +SETDRIVE PROC NEAR + MESSAGE FTESTDISK,<"SETDRIVE",CR,LF> + PUSH BX + PUSH CS + POP DS + ASSUME DS:CODE + +; ASSUME FIRST BDS IS IN THIS SEGMENT + MOV DI,WORD PTR START_BDS +SCAN_LOOP: + CMP BYTE PTR CS:[PHYS_DRV],1 ; DOES AL HAVE PHYSICAL DRIVE? + JB USE_LOGICAL_DRV + CMP BYTE PTR [DI].DRIVENUM,AL + JE SETDRV + JMP SHORT GET_NXT_BDS +USE_LOGICAL_DRV: + CMP BYTE PTR [DI].DRIVELET,AL + JE SETDRV +GET_NXT_BDS: + MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + ASSUME DS:NOTHING + + CMP DI,-1 + JNZ SCAN_LOOP + STC +SETDRV: + POP BX + RET +SETDRIVE ENDP + +;----------------------------------------------------------- +; +; DISK I/O ROUTINES +; + +DSK$WRITV PROC NEAR + PUBLIC DSK$WRITV + + MESSAGE FTESTDISK,<"DISK WRITE WITH VERIFY "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + MOV CS:[WRTVERIFY],103H + JMP SHORT DSK$CL + +DSK$WRIT: + PUBLIC DSK$WRIT + MESSAGE FTESTDISK,<"DISK WRITE "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + MOV CS:[WRTVERIFY],ROMWRITE + +DSK$CL: + CALL DISKIO +DSK$IO: + JC DSKBAD + JMP EXIT +DSKBAD: + JMP ERR$CNT +DSK$WRITV ENDP + +DSK$READ PROC NEAR + PUBLIC DSK$READ + MESSAGE FTESTDISK,<"DISK READ "> + MNUM FTESTDISK,AX + MESSAGE FTESTDISK,<" "> + MNUM FTESTDISK,DX + MESSAGE FTESTDISK,<" FOR "> + MNUM FTESTDISK,CX + MESSAGE FTESTDISK, + CALL DISKRD + JMP DSK$IO +DSK$READ ENDP + +; MISCELLANEOUS ODD JUMP ROUTINES. MOVED OUT OF MAINLINE FOR SPEED. + + +; IF WE HAVE A SYSTEM WHERE WE HAVE VIRTUAL DRIVES, WE NEED TO PROMPT THE +; USER TO PLACE THE CORRECT DISK IN THE DRIVE. + +CHECKSINGLE PROC NEAR + PUBLIC CHECKSINGLE + + PUSH AX + PUSH BX + MOV BX,WORD PTR DS:[DI].FLAGS + ; IF HARD DRIVE, CANNOT CHANGE DISK. + ; IF CURRENT OWNER OF PHYSICAL DRIVE, NO NEED TO CHANGE DISKETTE. + TEST BL,FNON_REMOVABLE OR FI_OWN_PHYSICAL + JNZ SINGLERET + TEST BL,FI_AM_MULT ; IS THERE A DRIVE SHARING THIS + ; PHYSICAL DRIVE? + JZ SINGLERET +; LOOK FOR THE PREVIOUS OWNER OF THIS PHYSICAL DRIVE AND RESET ITS OWNERSHIP +; FLAG. + MOV AL,DS:[DI].DRIVENUM ; GET PHYSICAL DRIVE NUMBER + PUSH DS ; PRESERVE POINTER TO CURRENT BDS + PUSH DI + PUSH CS + POP DS + ASSUME DS:CODE + + MOV DI,OFFSET START_BDS +SCAN_LIST: + MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + ASSUME DS:NOTHING + + CMP DI,-1 ; END OF LIST? + JZ SINGLE_ERR_RET ; MUST BE ERROR + CMP BYTE PTR [DI].DRIVENUM,AL + JNZ SCAN_LIST + +CHECK_OWN: + MOV BX,WORD PTR [DI].FLAGS + TEST BL,FI_OWN_PHYSICAL + JZ SCAN_LIST + XOR BL,FI_OWN_PHYSICAL ; RESET OWNERSHIP FLAG + MOV WORD PTR DS:[DI].FLAGS,BX + POP DI ; RESTORE POINTER TO CURRENT BDS + POP DS + XOR BX,BX + OR BL,FI_OWN_PHYSICAL ; ESTABLISH CURRENT BDS AS OWNER + OR WORD PTR [DI].FLAGS,BX + +; +; WE EXAMINE THE FSETOWNER FLAG. IF IT IS SET, THEN WE ARE USING THE CODE IN +; CHECKSINGLE TO JUST SET THE OWNER OF A DRIVE. WE MUST NOT ISSUE THE PROMPT +; IN THIS CASE. +; + CMP BYTE PTR CS:[FSETOWNER],1 + JZ SINGLERET +; TO SUPPORT "BACKWARD" COMPATIBILITY WITH IBM'S "SINGLE DRIVE STATUS BYTE" +; WE NOW CHECK TO SEE IF WE ARE IN A SINGLE DRIVE SYSTEM AND THE APPLICATION +; HAS "CLEVERLY" DIDDLED THE SDSB + CMP CS:[SINGLE],2 ; IF (SINGLE_DRIVE_SYSTEM) + JNE SHORT IGNORE_SDSB + + SAVEREG ; THEN + MOV AL,DS:[DI].DRIVELET ; IF (CURR_DRV == REQ_DRV) + MOV AH,AL + XOR DI,DI + MOV DS,DI + XCHG AL,DS:BYTE PTR LSTDRV ; THEN SWAP(CURR_DRV,REQ_DRV) + CMP AH,AL ; ELSE + RESTOREREG ; SWAP(CURR_DRV,REQ_DRV) + JE SINGLERET ; ISSUE SWAP_DSK_MSG + +IGNORE_SDSB: + CALL SWPDSK ; ASK USER FOR CORRECT DISK +SINGLERET: + POP BX + POP AX + RET + +SINGLE_ERR_RET: + STC + POP DI ; RESTORE CURRENT BDS + POP DS + JMP SHORT SINGLERET + +BADDRIVE: + MOV AL,8 ;Sector not found + jmp short BadDrive_Ret ;AN004;AN005;AN006; +UnformattedDrive: ;AN004;AN005;AN006; + mov al,7 ;AN004;Unknown media;AN005;AN006; +BadDrive_Ret: + STC +IORET: RET + +BOGUSSETTLE: + MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE + JMP GOTSLOWSETTLE +CHECKSINGLE ENDP +;------------------------------------------------------------ +; +; DISK I/O HANDLER +; +; AL = DRIVE NUMBER (0-6) +; AH = MEDIA DESCRIPTOR +; CX = SECTOR COUNT +; DX = FIRST SECTOR (low) +; [Start_Sec_H] = FIRST SECTOR (high) ;J.K. 32 bit calculation. +; DS = CS +; ES:DI = TRANSFER ADDRESS +; [RFLAG]=OPERATION (2=READ, 3=WRITE) +; [VERIFY]=1 FOR VERIFY AFTER WRITE +; +; IF SUCCESSFUL CARRY FLAG = 0 +; ELSE CF=1 AND AL CONTAINS ERROR CODE +; + PUBLIC DISKRD +DISKRD PROC NEAR + MOV CS:[RFLAG],ROMREAD + +DISKIO: + MOV BX,DI ; ES:BX = TRANSFER ADDRESS + CALL SETDRIVE ; MAP LOGICAL AND PHYSICAL + MOV AL,BYTE PTR DS:[DI].MEDIAD + MOV CS:MEDBYT,AL ; PRESERVE MEDIA BYTE FOR DRIVE FOR USE + ; IN DETERMINING MEDIA CHANGE. + JCXZ IORET +;SB34DISK006****************************************************************** +;SB See if the Media is formatted or not by checking the flags field in +;SB in the BDS. If it is unformatted we cannot allow I/O, so we should +;SB go to the error exit at label UnformattedDrive. 2LOCS + + test word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA + jnz UnformattedDrive +;SB34DISK006****************************************************************** + mov cs:[SECCNT],CX ;save sector count + MOV CS:[SPSAV],SP ; SAVE SP + +; ENSURE THAT WE ARE TRYING TO ACCESS VALID SECTORS ON THE DRIVE +; + + mov ax,dx ;AN000; save DX to AX + xor si,si ;AN000; + add dx,cx ;AN000; + adc si,0 ;AN000; + cmp [di].DrvLim, 0 ;AN000; Is this drive > 32 bit sector ? + je Sanity32 ;AN000; + cmp si,0 ;AN000; + jne BADDRIVE ;AN000; + cmp dx, [di].DrvLim ;AN000; + ja BADDRIVE ;AN000; + jmp short SanityOK ;AN000; +Sanity32: ;AN000; + add si, cs:[Start_Sec_H] ;AN000; + cmp si, [di].DrvLim_H ;AN000; + jb SanityOK ;AN000; + ja BADDRIVE ;AN000; + cmp dx, [di].DrvLim_L ;AN000; + ja BADDRIVE ;AN000; +SanityOK: ;AN000; + mov dx,cs:[Start_Sec_H] ;AN000; + add ax,word ptr [di].HIDSEC_L ;AN000; + adc dx,word ptr [di].Hidsec_H ;AN000; +;J.K. Now DX;AX have the physical first sector. +;Since the following procedures is going to destroy AX, let's +;save it temporarily to SAVED_WORD. + mov cs:[Saved_Word], ax ;AN000; Save the sector number (low) + +; MOV SI,DX +; ADD SI,CX +; ADD DX,WORD PTR [DI].HIDSEC ; ADD IN THE HIDDEN SECTORS +; CMP SI,WORD PTR [DI].DRVLIM ; COMPARE AGAINST DRIVE MAX +; JA BADDRIVE + +; SET UP POINTER TO DISK BASE TABLE IN [DPT]. WE CANNOT ASSUME THAT IOSETUP +; WILL DO IT BECAUSE WE WILL SKIP THE SET UP STUFF WITH HARD DISKS. + PUSH DS + XOR AX,AX + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR]; CURRENT DISK PARM TABLE + MOV WORD PTR CS:DPT,SI + MOV WORD PTR CS:DPT+2,DS + POP DS + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ SKIP_SETUP + CALL CHECKSINGLE +; +; CHECK TO SEE IF WE HAVE PREVIOUSLY NOTED A CHANGE LINE. THE ROUTINE +; RETURNS IF EVERYTHING IS OK. OTHERWISE, IT POPS OFF THE STACK AND RETURNS +; THE PROPER ERROR CODE. +; +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC DISKIO_PATCH ;| +DISKIO_PATCH: ;| + CALL CHECKLATCHIO ;| +;----------------------------------------| +; +; SET UP TABLES AND VARIABLES FOR I/O + CALL IOSETUP +; +; NOW THE SETTLE VALUES ARE CORRECT FOR THE FOLLOWING CODE +; +SKIP_SETUP: +;J.K. 32 bit sector calculation. +; DX;[Saved_Word] = starting sector number. + mov ax,dx ;AN000; + xor dx,dx ;AN000; + DIV WORD PTR [DI].SECLIM ;DIVIDE BY SEC PER TRACK + mov cs:[Temp_H],ax ;AN000; + mov ax, cs:[Saved_Word] ;AN000; Restore the lower word + div word ptr [di].SecLim ;AN000; +;Now, [Temp_H],AX = track #, DX = sector + INC DL ;Sector number is 1 based. + MOV CS:[CURSEC],DL ;SAVE CURRENT SECTOR + MOV CX,WORD PTR [DI].HDLIM ;GET NUMBER OF HEADS + + push ax ;AN000; + XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER + mov ax, cs:[Temp_H] ;AN000; + DIV CX + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + div cx ;AN000; +;Now, [Temp_H],AX = cyliner #, DX = head + cmp cs:[Temp_H],0 ;AN000; + ja BADDRIVE_brdg ;AN000; + cmp AX, 1024 ;AN000; 2**10 currently maxium for track #. + ja BADDRIVE_brdg ;AN000; + MOV CS:[CURHD],DL ;SAVE CURRENT HEAD + MOV CS:[CURTRK],AX ;SAVE CURRENT TRACK + +; +; WE ARE NOW SET UP FOR THE I/O. NORMALLY, WE CONSIDER THE DMA BOUNDARY +; VIOLATIONS HERE. NOT TRUE. WE PERFORM THE OPERATION AS IF EVERYTHING IS +; SYMMETRIC; LET THE INT 13 HANDLER WORRY ABOUT THE DMA VIOLATIONS. +; + MOV AX, CS:[SECCNT] + CALL BLOCK + CALL DONE + RET +DISKRD ENDP + +; +BADDRIVE_Brdg:jmp Baddrive +; + +; SET THE DRIVE-LAST-ACCESSED FLAG FOR DISKETTE ONLY. WE KNOW THAT THE HARD +; DISK WILL NOT BE REMOVED. +; DS:DI -> CURRENT BDS. +; AX,CX,SI ARE DESTROYED. +; + PUBLIC IOSETUP +IOSETUP PROC NEAR + MOV AL,[DI].DRIVENUM + MOV CS:[TIM_DRV],AL ; SAVE DRIVE LETTER +; +; DETERMINE PROPER HEAD SETTLE VALUES +; + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne Skip_DPT_Setting ;AN012; + MOV CX,DS + LDS SI,DWORD PTR CS:[DPT] ; GET POINTER TO DISK BASE TABLE + MOV AL,CS:[EOT] + MOV [SI].DISK_EOT,AL ; BUMP FOR US + MOV AL,[SI].DISK_MOTOR_STRT ; PRESERVE OLD MOTOR START TIME + MOV CS:MOTORSTARTUP,AL +; +; FOR 3.5" DRIVES, BOTH EXTERNAL AS WELL AS ON THE K09, WE NEED TO SET THE +; MOTOR START TIME TO 4. THIS CHECKING FOR EVERY I/O IS GOING TO AFFECT +; PERFORMANCE ACROSS THE BOARD, BUT IS NECESSARY!! - RS +; + PUSH ES + MOV ES,CX ; ES:DI -> TO CURRENT BDS + CMP BYTE PTR ES:[DI].FORMFACTOR,FFSMALL + JNZ MOTOR_START_OK + MOV AL,4 + XCHG AL,[SI].DISK_MOTOR_STRT +MOTOR_START_OK: + POP ES +; +; DS:SI NOW POINTS TO DISK PARAMETER TABLE. GET CURRENT SETTLE AND SET FAST +; SETTLE +; + XOR AL,AL + INC AL ; IBM WANTS FAST SETTLE TO BE 1 - RS. + XCHG AL,[SI].DISK_HEAD_STTL ; GET SETTLE AND SET UP FOR FAST + MOV CS:SETTLECURRENT,AL + MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE +GOTSLOWSETTLE: + MOV DS,CX + MOV CS:SETTLESLOW,AL +Skip_DPT_Setting: ;AN012; + RET +; +; SET TIME OF LAST ACCESS, AND RESET DEFAULT VALUES IN THE DPT. +; +DONE: + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JNZ RETZ ; DO NOT SET FOR NON-REMOVABLE MEDIA + CALL SET_TIM ; SET TIME OF LAST ACCESS FOR DRIVE +; +; RESTORE HEAD SETTLE AND EOT VALUES +; +DIDDLEBACK: + pushf ;AN013;Save flag + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne NoDiddleBack ;AN012; + PUSH AX + MOV DX,DS + MOV AL,CS:SETTLECURRENT + MOV AH,CS:MOTORSTARTUP + LDS SI,CS:DPT +; MOV [SI].DISK_EOT,9 ;J.K. 4/25/86. Should not change the EOT value + ;of diskbase to 9. This cause a problem + ;with 1.44M diskette in Polaris when the user + ;issue INT 13 with the default system + ;diskbase. + mov [si].DISK_EOT,9 ;J.K. 11/5/86. For compatibility reason, return + ;back to set it to 9 ( PTM826 ). + MOV [SI].DISK_HEAD_STTL,AL + MOV [SI].DISK_SECTOR_SIZ,2 + MOV [SI].DISK_MOTOR_STRT,AH + MOV DS,DX + POP AX +NoDiddleBack: ;AN013; + popf ;AN013;Restore flag +RETZ: + RET + +;READ THE NUMBER OF SECTORS SPECIFIED IN AX, HANDLING TRACK BOUNDARIES +;DS:DI -> BDS FOR THIS DRIVE +BLOCK: + OR AX,AX ;SEE IF ANY SECTORS TO READ + JZ RETZ +;Fixed disk will not be restricted to the track-by-track basis. -J.K.4/10/86 + test word ptr [di].Flags, fNon_Removable ;J.K. Fixed disk? + jz BLOCK_FLOPPY ;J.K. +;SB34DISK002***************************************************************** +;SB Check to see if multi track operation is allowed. If not +;SB we have to go to the block_floppy below to break up the operation. +;SB 2 LOCS + test word ptr CS:MulTrk_Flag, MulTrk_ON + jz BLOCK_FLOPPY +;SB34DISK002***************************************************************** + call DISK ;J.K. + xor ax,ax + RET ;J.K. +BLOCK_FLOPPY: ;J.K.4/10/86 +; +; READ AT MOST 1 TRACK WORTH. PERFORM MINIMIZATION AT SECTOR / TRACK +; + MOV CL,BYTE PTR [DI].SECLIM + INC CL + SUB CL,CS:CURSEC ; LEEAC 3.20 ADD SEGMENT OVERRIDE + XOR CH,CH + CMP AX,CX + JAE GOTMIN + MOV CX,AX +GOTMIN: +; +; AX IS THE REQUESTED NUMBER OF SECTORS TO READ +; CX IS THE NUMBER THAT WE CAN DO ON THIS TRACK +; + PUSH AX + PUSH CX + MOV AX,CX ; AL IS NUMBER OF SECTORS TO READ + CALL DISK + POP CX + POP AX +; +; CX IS THE NUMBER OF SECTORS JUST TRANSFERRED +; + SUB AX,CX ; REDUCE SECTORS-REMAINING BY LAST I/O + SHL CL,1 + ADD BH,CL ; ADJUST TRANSFER ADDRESS + JMP BLOCK +IOSETUP ENDP + +DskErr_Brdg: jmp DskErr ;AN003; + +; +;PERFORM DISK I/O WITH RETRIES +; AL = NUMBER OF SECTORS (1-8, ALL ON ONE TRACK) +; DI POINT TO DRIVE PARAMETERS +; ES:BX = TRANSFER ADDRESS (MUST NOT CROSS A 64K PHYSICAL BOUNDARY) +; [RFLAG] = 2 IF READ, 3 IF WRITE +; [VERIFY] = 0 FOR NORMAL, 1 FOR VERIFY AFTER WRITE + + PUBLIC DISK +DISK PROC NEAR + MOV BP,MAXERR ; SET UP RETRY COUNT + mov cs:VRetry_Cnt, BP ;AN003;Verify op. retry cnt for Write-Verify. + mov cs:Soft_ECC_Cnt, BP ;AN003;Soft ECC error retry count. + MOV AH,CS:RFLAG ;GET READ/WRITE INDICATOR + +RETRY: + PUSH AX + + MOV DX,CS:[CURTRK] ;LOAD CURRENT CYLINDER + + test word ptr [di].FLAGS, fNon_Removable ;Fixed disk? - J.K. 4/7/86 + jz DISK_NOT_MINI ;no, skip this. - J.K. 4/7/86 + cmp [di].IsMini, 1 ;Is this a mini disk? - J.K. 4/7/86 + jnz DISK_NOT_MINI ;No. continue to next.- J.K. 4/7/86 + add dx, [di].Hidden_Trks ;else add hidden trks.- J.K. 4/7/86 +DISK_NOT_MINI: ;J.K. 4/7/86 + ROR DH,1 + ROR DH,1 + + OR DH,CS:[CURSEC] + MOV CX,DX + XCHG CH,CL ; CL = SECTOR, CH = CYLINDER + MOV DH,BYTE PTR CS:[CURHD] ; LOAD CURRENT HEAD NUMBER AND + MOV DL,BYTE PTR [DI].DRIVENUM ; PHYSICAL DRIVE NUMBER + CMP BYTE PTR [DI].FORMFACTOR,FFHARDFILE + JZ DO_FAST ; HARD FILES USE FAST SPEED +; IF WE HAVE [STEP_DRV] SET TO -1, WE USE THE SLOW SETTLE TIME. +; THIS HELPS WHEN WE HAVE JUST DONE A RESED DISK OPERATION AND THE HEAD HAS +; BEEN MOVED TO ANOTHER CYLINDER - THE PROBLEM CROPS UP WITH 3.5" DRIVES. + CMP CS:[STEP_DRV],-1 + JZ DO_WRITEJ + CMP AH,ROMREAD ; ARR 2.20 + JE DO_FAST + CMP AH, ROMVERIFY + JE DO_FAST +DO_WRITEJ: +; READS ALWAYS FAST, UNLESS WE HAVE JUST DONE A DISK RESET OPERATION + JMP DO_WRITE ; ARR 2.20 READS ALWAYS FAST +DO_FAST: ; ARR 2.20 + CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE +TESTERR: ; MZ 2.21 + JC DSKERR_brdg +; SET DRIVE AND TRACK OF LAST ACCESS + MOV CS:[STEP_DRV],DL ; ARR 2.20 SET DRIVE + MOV BYTE PTR [DI].TRACK,CH ; ARR 2.20 SAVE TRACK +NO_SET: + CMP CS:WRTVERIFY,103H ; CHECK FOR WRITE AND VERIFY + JZ DOVERIFY +NOVERIFY: + POP AX + +;SB34DISK003***************************************************************** +;SB Check the flags word in the BDS to see if the drive is non removable +;SB If not we needn't do anything special +;SB If it is a hard disk then check to see if multi-track operation +;SB is specified. If specified we don't have to calculate for the next +;SB track since we are already done. So we can go to the exit of this +;SB routine. 5 LOCS + + test word ptr [di].FLAGS, fNON_REMOVABLE + jz ITS_REMOVABLE + test CS:MulTrk_Flag, MulTrk_ON + jnz DISK_RET +ITS_REMOVABLE: +;SB34DISK003***************************************************************** + AND CL,03FH ; ELIMINATE CYLINDER BITS FROM SECTOR + XOR AH,AH + SUB CS:[SECCNT],AX ; REDUCE COUNT OF SECTORS TO GO + ADD CL,AL ; NEXT SECTOR + MOV CS:[CURSEC],CL + CMP CL,BYTE PTR [DI].SECLIM ; SEE IF SECTOR/TRACK LIMIT REACHED + JBE DISK_RET +NEXTTRACK: + MOV CS:[CURSEC],1 ; START WITH FIRST SECTOR OF NEXT TRACK + MOV DH,CS:[CURHD] + INC DH + CMP DH,BYTE PTR [DI].HDLIM + JB NOXOR + XOR DH,DH + INC CS:[CURTRK] ;NEXT TRACK +NOXOR: + MOV CS:[CURHD],DH +DISK_RET: + CLC ; LEEAC + RET +DISK ENDP + + +; THE REQUEST IS FOR WRITE. DETERMINE IF WE ARE TALKING ABOUT THE SAME +; TRACK AND DRIVE. IF SO, USE THE FAST SPEED. + +DO_WRITE PROC NEAR + CMP DL,CS:[STEP_DRV] ; ARR 2.20 + JNZ DO_NORM ; WE HAVE CHANGED DRIVES + + CMP CH,BYTE PTR [DI].TRACK ; ARR 2.20 + JZ DO_FAST ; WE ARE STILL ON THE SAME TRACK + +DO_NORM: + CALL NORMSPEED + JMP SHORT TESTERR ; MZ 2.21 TEST FOR ERROR +DO_WRITE ENDP +; +; WE HAVE A VERIFY REQUEST ALSO. GET STATE INFO AND GO VERIFY +; + +DOVERIFY PROC NEAR + POP AX ; RESTORE SECTOR COUNT + PUSH AX + MOV AH,ROMVERIFY ; REQUEST VERIFY + CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE + JNC NOVERIFY + +;SB34DISK004************************************************************** +;SB check the error returned in AH to see if it is a SOFT ECC error. +;SB If it is not we needn't do anything special. If it is a SOFT +;SB ECC error then decrement the SOFT_ECC_CNT error retry count. If +;SB this retry count becomes 0 then we just ignore the error and go to +;SB No_verify but if we can still try then we call the routine to reset +;SB the disk and go to DSKerr1 to retry the operation. 6 LOCS + + cmp ah,11h ;SOFT ECC error ? + jnz Not_SoftECC_Err + dec SOFT_ECC_CNT + jz NoVerify ;no more retry + call ResetDisk ;reset disk + jmp DskErr1 ;retry + +;SB34DISK004************************************************************** + +Not_SoftECC_Err: ;AN003;Other error. + call ResetDisk ;AN003; + dec VRetry_Cnt ;AN003; + jmp DskErr0 ;AN003; +DOVERIFY ENDP +; +; NEED TO SPECIAL CASE THE CHANGE-LINE ERROR AH=06H. IF WE GET THIS, WE +; NEED TO RETURN IT. +; +;----------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. ;| +; IT GETS PATCHED IN MSINIT ;| + PUBLIC DSKERR ;| +DSKERR PROC NEAR ;| + CALL CHECKIO ;| +;---------------------------------------;| + + cmp cs:MultiTrk_Format_Flag, 1 ;AN007;Multi trk format request? + jne DoChkAgain ;AN007; + mov bp, 1 ;AN007;No more retry. + mov cs:MultiTrk_Format_Flag, 0 ;AN007;Clear the flag. +DoChkAgain: ;AN007; + CALL AGAIN +DskErr0: ;AN003; + JZ HARDERR + test word ptr [di].FLAGS, fNon_Removable ;AN009; + jnz Skip_TimeOut_Chk ;AN009; + CMP AH,80H ;TIMEOUT? + JZ HARDERR ;*** +Skip_TimeOut_Chk: ;AN009; + cmp ah, 0cch ;AN003;Write Fault error? + jz Write_Fault_Err ;AN003; Then, don't retry. + mov cs:Soft_ECC_Cnt, MAXERR ;AN003;Set Soft_ECC_Cnt back to MAXERR +DSKERR1: + POP AX ;RESTORE SECTOR COUNT + JMP RETRY + +Write_Fault_Err: ;AN003; + mov bp, 1 ;AN003;Just retry only once for Write Fault error. + jmp DskErr1 ;AN003; + +HARDERR: + PUBLIC HARDERR + + CALL MAPERROR + +HARDERR2: ; FOR ROUTINES THAT CALL MAPERROR THEMSELVES + PUBLIC HARDERR2 + + MOV CS:[TIM_DRV],-1 ;FORCE A MEDIA CHECK THROUGH ROM + MOV CX,CS:SECCNT ;GET COUNT OF SECTORS TO GO + MOV SP,CS:[SPSAV] ;RECOVER ENTRY STACK POINTER +; +; SINCE WE ARE PERFORMING A NON-LOCAL GOTO, RESTORE THE DISK PARAMETERS +; +MEDBYT_OK: + CALL DIDDLEBACK + RET ;AND RETURN +DSKERR ENDP + +; +; CHANGE SETTLE VALUE FROM SETTLECURRENT TO WHATEVER IS APPROPRIATE +; NOTE THAT THIS ROUTINE IS NEVER CALLED FOR A FIXED DISK. +; +NORMSPEED PROC NEAR + cmp cs:[Media_Set_For_Format], 0 ;AN012; + jne FASTSPEED ;AN012; + PUSH DS + PUSH AX + MOV AL,CS:SETTLESLOW + LDS SI,CS:DPT ; CURRENT DISK PARM TABLE + MOV [SI].DISK_HEAD_STTL,AL + POP AX + POP DS + CALL FASTSPEED + PUSH DS + LDS SI,CS:DPT + MOV [SI].DISK_HEAD_STTL,1 ; 1 IS FAST SETTLE VALUE + POP DS + RET +NORMSPEED ENDP + +FASTSPEED PROC NEAR +; +; IF THE DRIVE HAS BEEN MARKED AS TOO BIG (I.E. STARTING SECTOR OF THE +; PARTITION IS > 16 BITS, THEN ALWAYS RETURN DRIVE NOT READY. +; + TEST BYTE PTR [DI].FATSIZ,FTOOBIG + IF iTEST + JZ READY + JMP NOTREADY +READY: + ELSE + JNZ NOTREADY + ENDIF + + MESSAGE FTESTINIT,<"<"> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,ES + MESSAGE FTESTINIT,<":"> + MNUM FTESTINIT + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,CX + MESSAGE FTESTINIT,<","> + MNUM FTESTINIT,DX + MESSAGE FTESTINIT,<">"> + INT 13H +DEATH: + RET +NOTREADY: + STC + MOV AH,80H + JMP DEATH +FASTSPEED ENDP + +; MAP ERROR RETURNED BY ROM IN AH INTO CORRESPONDING CODE TO BE RETURNED TO +; DOS IN AL. +; +MAPERROR PROC NEAR + PUBLIC MAPERROR + + PUSH CX ; SAVE CX + PUSH CS + POP ES ;MAKE ES THE LOCAL SEGMENT + MOV AL,AH ;PUT ERROR CODE IN AL + MOV CS:[LSTERR],AL ;TERMINATE LIST WITH ERROR CODE + MOV CX,NUMERR ;NUMBER OF POSSIBLE ERROR CONDITIONS + MOV DI,OFFSET ERRIN ;POINT TO ERROR CONDITIONS + REPNE SCASB + MOV AL,CS:[DI + NUMERR - 1] ;GET TRANSLATION + POP CX ; RESTORE CX + STC ;FLAG ERROR CONDITION + RET +MAPERROR ENDP + +; SET THE TIME OF LAST ACCESS FOR THIS DRIVE. THIS IS DONE ONLY FOR REMOVABLE +; MEDIA. + + PUBLIC SET_TIM +SET_TIM PROC NEAR + PUSH AX +;SB33018****************************************************************** + xor AH, AH ; set command to get time ;SB;3.30* + int 1Ah ; call rom-bios timer function ;SB;3.30* +;SB33018****************************************************************** + OR AL,AL + JZ NOROLL3 + INC CS:[DAYCNT] ; CATCH ROLLOVER +NOROLL3: +; WE HAVE THE NEW TIME. IF WE SEE THAT THE TIME HAS PASSED, THEN WE RESET +; THE THRESHOLD COUNTER... + CMP DX,WORD PTR [DI].TIM_LO + JNZ SETACCESS + CMP CX,WORD PTR [DI].TIM_HI + JZ DONE_SET +SETACCESS: + MOV BYTE PTR CS:[ACCESSCOUNT],0 + MOV WORD PTR [DI].TIM_LO,DX ;SAVE IT + MOV WORD PTR [DI].TIM_HI,CX +DONE_SET: + CLC + POP AX + RET +SET_TIM ENDP + + ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; THIS IS THE TRUE INT 13 HANDLER. WE PARSE THE REQUEST TO SEE IF THERE IS +; A DMA VIOLATION. IF SO, DEPENDING ON THE FUNCTION, WE: +; READ/WRITE BREAK THE REQUEST INTO THREE PIECES AND MOVE THE MIDDLE ONE +; INTO OUR INTERNAL BUFFER. +; FORMAT COPY THE FORMAT TABLE INTO THE BUFFER +; VERIFY POINT THE TRANSFER ADDRESS INTO THE BUFFER +; +; THIS IS THE BIGGEST BOGOSITY OF ALL. THE IBM CONTROLLER DOES NOT HANDLE +; OPERATIONS THAT CROSS PHYSICAL 64K BOUNDARIES. IN THESE CASES, WE COPY +; THE OFFENDING SECTOR INTO THE BUFFER BELOW AND DO THE I/O FROM THERE. +; +INT13FRAME STRUC +OLDBP DW ? +OLDAX DW ? +OLDBX DW ? +OLDCX DW ? +OLDDX DW ? +OLDDD DD ? +OLDF DW ? +INT13FRAME ENDS + +;J.K. 1/30/87 To handle the ps2_30 machine INT 13h, AH = 8 Problem. +;Save Registers here. +Save_AX DW ? +Save_BX DW ? +Save_CX DW ? +Save_DX DW ? +Save_DI DW ? +Save_SI DW ? +Save_BP DW ? +Save_DS DW ? +Save_ES DW ? +Prev_DX DW ? +Save_Flag DW ? + + +; ENTRY CONDITIONS: +; AH = FUNCTION +; AL = NUMBER OF SECTORS +; ES:BX = DMA ADDRESS +; CX = PACKED TRACK AND SECTOR +; DX = HEAD AND DRIVE +; OUTPUT CONDITIONS: +; NO DMA VIOLATION. +; + PUBLIC BLOCK13 +BLOCK13 PROC FAR +; +; LET THE OPPERATION PROCEED. IF THERE IS A DMA VIOLATION, THEN WE DO THINGS. +; + MOV CS:PREVOPER,AX ; SAVE REQUEST + PUSHF + CMP AH,ROMFORMAT + JNZ NOT_FORMAT +; SET CHANGED BY FORMAT BIT FOR ALL LOGICAL DRIVES USING THIS PHYSICAL DRIVE +;---------------------------------------------------------| +; WARNING: DO NOT CHANGE THE FOLLOWING. +; IT GETS PATCHED IN AT INIT TIME | + PUBLIC CHANGED_PATCH +CHANGED_PATCH: + MOV WORD PTR CS:[FLAGBITS],FCHANGED_BY_FORMAT+FCHANGED + CALL SET_CHANGED_DL ; INDICATE THAT MEDIA CHANGED BY FORMAT +; | +;---------------------------------------------------------| +NOT_FORMAT: + test dl, 80h ; floppy or hard disk? + jnz not_floppy ; if hard, skip this nonsense + cmp cs:EC35_Flag, 0 ; any electrically compat. drives? + jz not_floppy ; no; proceed unhindered + SAVEREG + mov cl, dl ; turn drive number into bit map: + mov al, 1 ; assume drive 0 + shl al, cl ; shift over correct number of times + test al, cs:EC35_Flag ; is THIS drive an electrically compatible 3.5 incher? + jz not_EC35 ; no; don't change anything + mov bl, dl ; which drive was it? + xor bh, bh ; need only one byte of index + push es ; need a segment register + mov ax, 40h ; the machine state byte is in the... + mov es, ax ; ...segment at 40h + mov byte ptr es:[90h+bx], 93H ; establish drive type as: (360k disk in 360k drive, no double-stepping, 250 kbs transfer rate) + pop es ; fix up register again +not_EC35: + RESTOREREG +not_floppy: + cmp cs:[model_byte], mdl_ps2_30 ; is this a ps2/30? + jne not_ps2_30 ; if not, just do normal call + cmp ah, 8 ;J.K. 1/30/87 Read Driver Parm ? + je ps2_30_Problem ;J.K. 1/30/87 + cmp ah, 15h + je ps2_30_Problem +not_ps2_30: + CALL ORIG13 ; SIMULATE INT 13 + JC GOTERR13_br ; ERROR? + RET 2 ; NO, RETURN AND CLEAR FLAGS + +GOTERR13_br: jmp Goterr13 + +;J.K.1/30/87 ps2_30 machine has some problem with AH=8h(Read Drive Parm), Int 13h. +;This function does not reset the common buses after the execution. +;To solve this problem, when we detect AH=8h, then we will save the result and +;will issue AH=1 (Read Status) call to reset the buses. + +ps2_30_Problem: ;J.K. 1/30/87; ps2_30 = PS2 Model 30. + mov cs:Prev_DX, DX ;save orignal drive number + call Orig13 ;Do "Read drive parm" + + mov cs:Save_AX, AX ;Save registers,flag + mov cs:Save_BX, BX + mov cs:Save_CX, CX + mov cs:Save_DX, DX + mov cs:Save_DI, DI + mov cs:Save_SI, SI + mov cs:Save_BP, BP + mov cs:Save_DS, DS + mov cs:Save_ES, ES + pushf + pop cs:Save_Flag + + mov dx, cs:Prev_DX ;restore orignal drive + pushf + mov ah, 1 ;Read Status. + call Orig13 ;Reset the bus as a side effect of this call. + + mov AX, cs:Save_AX ;restore registers,flag + mov BX, cs:Save_BX + mov CX, cs:Save_CX + mov DX, cs:Save_DX + mov DI, cs:Save_DI + mov SI, cs:Save_SI + mov BP, cs:Save_BP + mov DS, cs:Save_DS + mov ES, cs:Save_ES + push cs:Save_Flag + popf + jc GotErr13 ;AH=8 had been an error? + ret 2 + +; +; SOME KIND OF ERROR OCCURRED. SEE IF IT IS DMA VIOLATION +; +GOTERR13: + PUSHF + cmp ah, 09h ;AN011; DMA error? + je Chk_ValidMedia_ERR13 ;AN011; + cmp ah, 11h ;AN011; ECC error? + je Chk_ValidMedia_ERR13 ;AN011; + jmp Skip_Ecc_Check ;AN011; Other error. Just return back. + +Chk_ValidMedia_ERR13: ;AN011;If SetDrive fails, then just + push ds ;AN011; return back to INT 13h caller, + push di ;AN011; without performing ECC, DMA + push ax ;AN011; error handling. + mov byte ptr cs:[Phys_Drv], 1 ;AN011; + mov al, dl ;AN011; + call SetDrive ;AN011; + mov byte ptr cs:[Phys_Drv], 0 ;AN011; + pop ax ;AN011; + pop di ;AN011; + pop ds ;AN011; + jc Skip_Ecc_Check ;AN011; + +; TEST OF BIT PATTERN 08H LET OTHER ERRORS BE PASSED AS DMA ERRORS - PTR 32D0519 +; TEST AH,08H ; DMA BIT + CMP AH, 09H ; DMA ERROR CODE + JNZ CHECK_ECC + JMP GOTDMAERR +CHECK_ECC: +;J.K. AN003; Soft ECC bug is only applied to PC1 and PC-XT. So, we will enforce +;this ECC error handler for them. Also, since CMC hardfiles in PC AT also +;generate a lot of unnecessary ECC errors, we will still cover PC ATs as +;it is done in the earlier version of MSBIO. +;During Format/Verify operation, we are going to consider any Soft Ecc as a +;hard error. + +;SB34DISK005***************************************************************** +;SB See if the machine we are operating on is a PC, XT or AT by checking +;SB the model byte. The soft ECC bug is only on these machines and if +;SB the machine we are operating on is not one of these three then we +;SB needn't do anything special. If we are operating one these however +;SB we check to see if the error occured during format by checking +;SB media_set_for_format. If it did occur during format we cannot do +;SB anything but if not during format then check to see if the error +;SB returned in AH is the SOFT_ECC error and if so go to OK11 since +;SB the error can be ignored. 6 LOCS + + cmp cs:[Media_Set_For_Format], 1 ; formatting? + je Skip_Ecc_Check + cmp cs:[Model_Byte], 0FEh ; PC or XT? + jae Go_Chk_Ecc + cmp cs:[Model_Byte], 0FBh ; XT? + je Go_Chk_Ecc + cmp cs:[Model_Byte], 0FCh + jne Skip_Ecc_Check + cmp cs:[Secondary_Model_Byte], 2 ; AT? + ja Skip_Ecc_Check +Go_Chk_Ecc: ; for PC, XT, AT + CMP AH,11H + JZ OK11 +Skip_Ecc_Check: ;AN003; Just return back to INT 13h caller. + +;SB34DISK005***************************************************************** + + POPF + RET 2 +; +; WE HAVE AN ERROR STATUS 11H. THIS INDICATES AN ECC-CORRECTED ERROR. NOTE +; THAT THIS INDICATES THAT THE DATA IS PROBABLY CORRECT BUT NOT CERTAINLY +; CORRECT. THE ROMS ON PC-1S AND PC_XTS HAVE A 'BUG' IN THAT IF AN ECC ERROR +; OCCURS FOR A MULTI-SECTOR READ, ONLY THE SECTORS UP TO THE ONE WHERE THE +; ERROR OCCURRED ARE READ IN. WE HAVE NO WAY OF KNOWING HOW MANY WERE READ IN +; THIS CASE, SO WE REDO THE OPERATION, READING ONE SECTOR AT A TIME. IF WE +; GET AN ECC ERROR ON READING ONE SECTOR, WE IGNORE THE ERROR BECAUSE THE +; SECTOR HAS BEEN READ IN. +; + PUBLIC OK11 +OK11: +; POPF +;J.K. 8/29/86 Here, it is better reset the system. So, we are going to +;call Orig13 again + + xor ah, ah + call Orig13 ;reset. Don't care about the result + + MOV AX,CS:[PREVOPER] ; RETRIEVE REQUEST +; +; THIS WILL PROVIDE A TERMINATION POINT. +; + CMP AL,1 ; IF REQUEST FOR ONE SECTOR, ASSUME OK + JNZ ECC_ERR_HANDLE + XOR AH,AH ; CLEAR CARRY TOO! + RET 2 + + PUBLIC ECC_ERR_HANDLE +ECC_ERR_HANDLE: + SAVEREG + MOV CS:[NUMBER_OF_SEC],AL +LOOP_ECC: + MOV AX,CS:[PREVOPER] + MOV AL,1 ; REQUEST FOR ONE SECTOR ONLY +; +; WE DO READS ONE SECTOR AT A TIME. THIS ENSURES THAT WE WILL EVENTUALLY +; FINISH THE REQUEST SINCE ECC ERRORS ON ONE SECTOR DO READ IN THAT SECTOR. +; +; WE NEED TO PUT IN SOME "INTELLIGENCE" INTO THE ECC HANDLER TO HANDLE READS +; THAT ATTEMPT TO READ MORE SECTORS THAN ARE AVAILABLE ON A PARTICULAR +; TRACK. +; WE CALL CHECK_WRAP TO SET UP THE SECTOR #, HEAD # AND CYLINDER # FOR +; THIS REQUEST. +; AT THIS POINT, ALL REGISTERS ARE SET UP FOR THE CALL TO ORIG13, EXCEPT +; THAT THERE MAY BE A STARTING SECTOR NUMBER THAT IS BIGGER THAN THE NUMBER +; OF SECTORS ON A TRACK. +; + CALL CHECK_WRAP ; GET CORRECT PARAMETERS FOR INT 13 + PUSHF + CALL ORIG13 + JNC OK11_OP + CMP AH,11H ; ONLY ALLOW ECC ERRORS + JNZ OK11_EXIT_err ;J.K. 8/26/86 Other error? + mov ah, 0 ;J.K. ECC error. Reset the system again. + pushf + call Orig13 + xor ax, ax ; clear the error code so that if this + ; was the last sector, no error code + ; will be returned for the corrected + ; read. (clear carry too.) +OK11_OP: + DEC CS:[NUMBER_OF_SEC] + JZ OK11_EXIT ; ALL DONE? + INC CL ; ADVANCE SECTOR NUMBER + INC BH ; ADD 200H TO ADDRESS + INC BH + JMP SHORT LOOP_ECC +OK11_EXIT_err: + stc ;J.K. 8/28/86 Set carry bit again. +OK11_EXIT: + RESTOREREG + RET 2 +; +; WE TRULY HAVE A DMA VIOLATION. RESTORE REGISTER AX AND RETRY THE +; OPERATION AS BEST WE CAN. +; +GOTDMAERR: + POP AX ; CLEAN UP STACK + MOV AX,CS:PREVOPER + STI + CMP AH,ROMREAD ; SAVE USER FLAGS + JB INTDONE + CMP AH,ROMVERIFY + JZ INTVERIFY + CMP AH,ROMFORMAT + JZ INTFORMAT + JA INTDONE +; +; WE ARE DOING A READ/WRITE CALL. CHECK FOR DMA PROBLEMS +; + SAVEREG + PUSH BP + MOV BP,SP + MOV DX,ES ; CHECK FOR 64K BOUNDARY ERROR + + SHL DX,1 + SHL DX,1 + SHL DX,1 + SHL DX,1 ; SEGMENT CONVERTED TO ABSOLUTE ADDRESS + + ADD DX,BX ; COMBINE WITH OFFSET + ADD DX,511 ; SIMULATE A TRANSFER +; +; IF CARRY IS SET, THEN WE ARE WITHIN 512 BYTES OF THE END OF THE SEGMENT. +; WE SKIP THE FIRST TRANSFER AND PERFORM THE REMAINING BUFFERING AND TRANSFER +; + JNC NO_SKIP_FIRST + MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER + JMP BUFFER ;J.K. 4/10/86 +; JMP SHORT BUFFER +; +; DX IS THE PHYSICAL 16 BITS OF START OF TRANSFER. COMPUTE REMAINING +; SECTORS IN SEGMENT. +; +NO_SKIP_FIRST: + SHR DH,1 ; DH = NUMBER OF SECTORS BEFORE ADDRESS + MOV AH,128 ; AH = MAX NUMBER OF SECTORS IN SEGMENT + SUB AH,DH +; +; AH IS NOW THE NUMBER OF SECTORS THAT WE CAN SUCCESSFULLY WRITE IN THIS +; SEGMENT. IF THIS NUMBER IS ABOVE OR EQUAL TO THE REQUESTED NUMBER, THEN WE +; CONTINUE THE OPERATION AS NORMAL. OTHERWISE, WE BREAK IT INTO PIECES. +; + CMP AH,AL ; CAN WE FIT IT IN? + JB DOBLOCK ; NO, PERFORM BLOCKING. +; +; YES, THE REQUEST FITS. LET IT HAPPEN +; + MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER + CALL DOINT + JMP BAD13 +; +; VERIFY THE GIVEN SECTORS. PLACE THE BUFFER POINTER INTO OUR SPACE. +; +INTVERIFY: + SAVEREG + PUSH CS + POP ES +DOSIMPLE: + MOV BX,OFFSET DISKSECTOR + PUSHF + CALL ORIG13 + RESTOREREG + RET 2 + +; +; FORMAT OPERATION. COPY THE PARAMETER TABLE INTO MEMORY +; +INTFORMAT: + SAVEREG + SAVEREG + PUSH ES + PUSH CS + POP ES + POP DS + MOV SI,BX + MOV DI,OFFSET DISKSECTOR + CALL MOVE + RESTOREREG + JMP DOSIMPLE +; +; INLINE CONTINUATION OF OPERATION +; +INTDONE: + JMP ORIG13 + +; +; We can't fit the request into the entire block. Perform the operation on +; the first block. +; +; DoBlock is modified to correctly handle multi-sector disk I/O. -J.K. 4/10/86 +; Old DoBlock had added the number of sectors I/Oed (Ah in Old DoBlock) after +; the DoInt call to CL. Observing only the lower 6 bits of CL(=max. 64) can +; represent a starting sector, if AH was big, then CL would be clobbered. +; By the way, we still are going to use CL for this purpose since Checkwrap +; routine will use it as an input. To prevent CL from being clobbered, a +; safe number of sectors should be calculated like "63 - # of sectors/track". +; DoBlock will handle the first block of requested sectors within the +; boundary of this safe value. - J.K. 2/28/86 + +DoBlock: +;Try to get the # of sectors/track from BDS via Rom drive number. +;For any mini disks installed, here we have to pray that they have the +;same # of sector/track as the main DOS partition disk drive. + + Message ftestDisk,<"!!!DMA DoBlock!!!"> + + mov dx, word ptr [bp.olddx] ;set head # + push di + push ds + push ax ;AH - # of sectors before DMA boundary + ;AL - User requeseted # of sectors for I/O. + mov byte ptr CS:[phys_drv],1 + mov al, dl + call SetDrive ;get BDS pointer for this DISK. + pop ax + mov byte ptr CS:[phys_drv],0 + test word ptr [DI].Flags, fNon_Removable ;don't have to worry + jnz DoBlockHard ;about floppies. They are track by track operation. + mov al, ah ;set al = ah for floppies + jmp short DoBlockCont +DoBlockHard: + push cx + xor cx, cx + mov cx, [DI].SecLim ;# of sectors/track + mov ch, 63 + sub ch, cl + mov al, ch + xchg ah, al ;now ah - safe # of sectors + ;al - # of sectors before DMA boundary + pop cx +DoBlockCont: + pop ds + pop di +DoBlockContinue: + Message ftestDisk,<"%%DMA DoBlock Loop%%"> + cmp ah, al ;if safe_# >= #_of_sectors_to_go_before DMA, + jae DoBlocklast ;then #_of_sectors_to_go as it is for DoInt. + push ax ;save AH, AL + mov al, ah ;Otherwise, set al to ah to operate. + jmp short DoBlockDoInt ;DoInt will set AH to a proper function in [BP.Oldax] +DoBlocklast: + mov ah, al + push ax ;save AH +DoBlockDoInt: ;let AH = AL = # of sectors for this shot + CALL DoInt + JC BAD13 ;something happened, bye! + pop ax + SUB BYTE PTR [BP.oldax], AH ;decrement by the successful operation + ADD CL,AH ;advance sector number. Safety gauranteed. + ADD BH,AH ;advance DMA address + ADD BH,AH ;twice for 512 byte sectors. + cmp ah, al ;check the previous value + je Buffer ;if #_of_sectors_to_go < safe_#, then we are done already. + sub al, ah ;otherwise, #_sector_to_go = #_of_sector_to_go - safe_# + call Check_Wrap ;get new CX, DH for the next operation. + jmp short DoBlockContinue ;handles next sectors left. +;End of modificaion of DoBlock - J.K. 2/28/86 +;The following is the original one. +; PUSH AX +; MOV AL,AH ; get max to operate on +; MOV AH,BYTE PTR [BP.oldax+1]; get function +; mov dh,byte ptr [BP.olddx+1] ; set up head number +; CALL DoInt +; JC Bad13 ; something happened, bye! +; POP AX +; SUB BYTE PTR [BP.oldax],AH ; decrement by the successful operation +; ADD CL,AH ; advance sector number +; ADD BH,AH ; advance DMA address +; ADD BH,AH ; twice for 512 byte sectors. + +; +; THE NEXT REQUEST WILL WRAP THE 64K BOUNDARY. IF WE ARE WRITING, THEN COPY +; THE OFFENDING SECTOR INTO OUR SPACE. +; +; ES:BX POINTS TO THE SECTOR +; CX,DX CONTAIN THE CORRECT TRACK/SECTOR/HEAD/DRIVE INFO +; [BP.OLDAX] HAS CORRECT FUNCTION CODE +; +BUFFER: + PUSH BX + MOV AH,BYTE PTR [BP.OLDAX+1] + CMP AH,ROMWRITE + JNZ DOREAD +; +; COPY THE OFFENDING SECTOR INTO LOCAL BUFFER +; + SAVEREG + PUSH CS ; EXCHANGE SEGMENT REGISTERS + PUSH ES + POP DS + POP ES + MOV DI,OFFSET DISKSECTOR ; WHERE TO MOVE + PUSH DI ; SAVE IT + MOV SI,BX ; SOURCE + CALL MOVE + POP BX ; NEW TRANSFER ADDRESS + RESTOREREG + MOV AL,1 +; SEE IF WE ARE WRAPPING AROUND A TRACK OR HEAD + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND +; +; AH IS FUNCTION +; AL IS 1 FOR SINGLE SECTOR TRANSFER +; ES:BX IS LOCAL TRANSFER ADDRES +; CX IS TRACK/SECTOR NUMBER +; DX IS HEAD/DRIVE NUMBER +; SI,DI UNCHANGED +; + CALL DOINT + RESTOREREG + JC BAD13 ; GO CLEAN UP + JMP SHORT DOTAIL +; +; READING A SECTOR. DO INT FIRST, THEN MOVE THINGS AROUND +; +DOREAD: + SAVEREG + PUSH CS + POP ES + MOV BX,OFFSET DISKSECTOR + MOV AL,1 +; SEE IF OUR REQUEST WILL WRAP A TRACK OR HEAD BOUNDARY + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND +; +; AH = FUNCTION +; AL = 1 FOR SINGLE SECTOR +; ES:BX POINTS TO LOCAL BUFFER +; CX, DX ARE TRACK/SECTOR, HEAD/DRIVE +; + CALL DOINT + RESTOREREG + JC BAD13 ; ERROR => CLEAN UP + SAVEREG + PUSH CS + POP DS + MOV DI,BX + MOV SI,OFFSET DISKSECTOR + CALL MOVE + RESTOREREG +; +; NOTE THE FACT THAT WE'VE DONE 1 MORE SECTOR +; +DOTAIL: + POP BX ; RETRIEVE NEW DMA AREA + ADD BH,2 ; ADVANCE OVER SECTOR + INC CX + MOV AL,BYTE PTR [BP.OLDAX] + CLC + DEC AL + JZ BAD13 ; NO MORE I/O +; SEE IF WE WRAP AROUND A TRACK OR HEAD BOUNDARY WITH STARTING SECTOR +; WE ALREADY HAVE THE CORRECT HEAD NUMBER TO PASS TO CHECK_WRAP + MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER + CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND + CALL DOINT +; +; WE ARE DONE. AX HAS THE FINAL CODE; WE THROW AWAY WHAT WE GOT BEFORE +; +BAD13: + MOV SP,BP + RESTOREREG + RET 2 +BLOCK13 ENDP + PAGE + INCLUDE MSIOCTL.INC + PAGE +; CHECK_WRAP IS A ROUTINE THAT ADJUSTS THE STARTING SECTOR, STARTING HEAD +; AND STARTING CYLINDER FOR AN INT 13 REQUEST THAT REQUESTS I/O OF A LOT +; OF SECTORS. IT ONLY DOES THIS FOR FIXED DISKS. IT IS USED IN THE SECTIONS +; OF CODE THAT HANDLE ECC ERRORS AND DMA ERRORS. IT IS NECESSARY, BECAUSE +; ORDINARILY THE ROM WOULD TAKE CARE OF WRAPS AROUND HEADS AND CYLINDERS, +; BUT WE BREAK DOWN A REQUEST WHEN WE GET AN ECC OR DMA ERROR INTO SEVERAL +; I/O OF ONE OR MORE SECTORS. IN THIS CASE, WE MAY ALREADY BE BEYOND THE +; NUMBER OF SECTORS ON A TRACK ON THE MEDIUM, AND THE REQUEST WOULD FAIL. +; +; INPUT CONDITIONS: +; ALL REGISTERS SET UP FOR AN INT 13 REQUEST. +; +; OUTPUT: +; DH - CONTAINS STARTING HEAD NUMBER FOR REQUEST +; CX - CONTAINS STARTING SECTOR AND CYLINDER NUMBERS +; (THE ABOVE MAY OR MAY NOT HAVE BEEN CHANGED, AND ARE 0-BASED) +; ALL OTHER REGISTERS PRESERVED. +; + PUBLIC CHECK_WRAP +CHECK_WRAP: + Message ftestDisk,<"Entering Check_Wrap...",cr,lf> + SAVEREG + MOV BYTE PTR CS:[PHYS_DRV],1; USE PHYSICAL DRIVE IN AL TO GET BDS + MOV AL,DL ; AL HAS PHYSICAL DRIVE NUMBER + CALL SETDRIVE ; GET POINTER TO BDS FOR DRIVE + MOV BYTE PTR CS:[PHYS_DRV],0; RESTORE FLAG TO USE LOGICAL DRIVE + JC NO_WRAP ; DO NOTHING IF WRONG PHYSICAL DRIVE + TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE + JZ NO_WRAP ; NO WRAPPING FOR REMOVABLE MEDIA + MOV BX,[DI].SECLIM + MOV AX,CX + AND AX,003FH ; EXTRACT SECTOR NUMBER + CMP AX,BX ; ARE WE GOING TO WRAP? + JBE NO_WRAP + DIV BL ; AH=NEW SECTOR #, AL=# OF HEAD WRAPS +; WE NEED TO BE CAREFUL HERE. IF THE NEW SECTOR # IS 0, THEN WE ARE ON THE +; LAST SECTOR ON THAT TRACK. + OR AH,AH + JNZ NOT_ON_BOUND + MOV AH,BL ; SET SECTOR=SECLIM IF ON BOUNDARY + DEC AL ; ALSO DECREMENT # OF HEAD WRAPS +NOT_ON_BOUND: + AND CL,0C0H ; ZERO OUT SECTOR # + OR CL,AH ; OR IN NEW SECTOR # + XOR AH,AH ; AX = # OF HEAD WRAPS + INC AX + ADD AL,DH ; ADD IN STARTING HEAD # + ADC AH,0 ; CATCH ANY CARRY + CMP AX,[DI].HDLIM ; ARE WE GOING TO WRAP AROUND A HEAD? + JBE NO_WRAP_HEAD ; DO NOT LOSE NEW HEAD NUMBER!! + PUSH DX ; PRESERVE DRIVE NUMBER AND HEAD NUMBER + XOR DX,DX + MOV BX,[DI].HDLIM + DIV BX ; DX=NEW HEAD #, AX=# OF CYLINDER WRAPS +; CAREFUL HERE! IF NEW HEAD # IS 0, THEN WE ARE ON THE LAST HEAD. + OR DX,DX + JNZ NO_HEAD_BOUND + MOV DX,BX ; ON BOUNDARY. SET TO HDLIM +; IF WE HAD SOME CYLINDER WRAPS, WE NEED TO REDUCE THEM BY ONE!! + OR AX,AX + JZ NO_HEAD_BOUND + DEC AX ; REDUCE NUMBER OF CYLINDER WRAPS +NO_HEAD_BOUND: + MOV BH,DL ; BH HAS NEW HEAD NUMBER + POP DX ; RESTORE DRIVE NUMBER AND HEAD NUMBER + DEC BH ; GET IT 0-BASED + MOV DH,BH ; SET UP NEW HEAD NUMBER IN DH + MOV BH,CL + AND BH,3FH ; PRESERVE SECTOR NUMBER + MOV BL,6 + XCHG CL,BL + SHR BL,CL ; GET MS CYLINDER BITS TO LS END + ADD CH,AL ; ADD IN CYLINDER WRAP + ADC BL,AH ; ADD IN HIGH BYTE + SHL BL,CL ; MOVE UP TO MS END + XCHG BL,CL ; RESTORE CYLINDER BITS INTO CL + OR CL,BH ; OR IN SECTOR NUMBER + +NO_WRAP: + CLC ; RESET CARRY + RESTOREREG + RET + +NO_WRAP_HEAD: + MOV DH,AL ; DO NOT LOSE NEW HEAD NUMBER + DEC DH ; GET IT 0-BASED + JMP SHORT NO_WRAP + +; +; INT_2F_13: +; THIS CODE IS CHAINED INTO THE INT_2F INTERRUPT DURING BIOS +; INITIALIZATION. IT ALLOWS THE USER TO CHANGE THE ORIG13 INT_13 VECTOR +; AFTER BOOTING. THIS ALLOWS TESTING AND IMPLEMENTATION OF CUSTOM INT_13 +; HANDLERS, WITHOUT GIVING UP MS-DOS ERROR RECOVERY +; +; ENTRY CONDITIONS +; AH == RESET_INT_13 (13H) +; DS:DX == ADDRESS OF NEW INT_13 HANDLER +; ES:BX == ADDRESS OF NEW INT_13 VECTOR USED BY WARM BOOT +; (INT 19) +; +; EXIT CONDITIONS +; ORIG13 == ADDRESS OF NEW INT_13 HANDLER +; DS:DX == OLD ORIG13 VALUE +; ES:BX == OLD OLD13 VALUE + + ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUBLIC INT_2F_13 +INT_2F_13 PROC FAR + + CMP AH,13H ; IF (INTERRUPT_VALUE != RESET_INT_13) + JE CHG_ORIG13 + JMP CS:[NEXT2F_13] ; THEN CONTINUE ON INT_2F CHAIN + +CHG_ORIG13: ; ELSE + PUSH WORD PTR CS:[ORIG13] ; SAVE OLD VALUE OF OLD13 AND + PUSH WORD PTR CS:[ORIG13 + 2]; ORIG13 SO THAT WE CAN + + PUSH WORD PTR CS:[OLD13] ; RETURN THEM TO CALLER + PUSH WORD PTR CS:[OLD13 + 2] + + MOV WORD PTR CS:[ORIG13],DX ; ORIG13 := ADDR. OF NEW INT_13 + ; VECTOR + MOV WORD PTR CS:[ORIG13+2],DS + + MOV WORD PTR CS:[OLD13],BX ; OLD13 := ADDR. OF NEW + ; BOOT_13 VECTOR + MOV WORD PTR CS:[OLD13+2],ES + + POP ES ; ES:BX := OLD OLD13 VECTOR + POP BX + + POP DS ; DS:DX := OLD ORIG13 VECTOR + POP DX + + IRET ; END ELSE + +INT_2F_13 ENDP + +MOVE PROC NEAR + CLD + PUSH CX + MOV CX,512/2 +;J.K. Warning!!! Do not change the position of this label. +; The following three bytes will be NOPed out by MSINIT if the system +; does not support the DOUBLE WORD MOV instruction, i.e., (if +; not 386 base machine.) +;---------------------------------------------------------------------------- + public DoubleWordMov +DoubleWordMov: ;AN002; + shr cx, 1 ;AN002;Make it a double word. + db 66h ;AN002;Machine code for double word mov +;---------------------------------------------------------------------------- + REP MOVSW + POP CX + RET +MOVE ENDP + +DOINT PROC NEAR + MOV DL,BYTE PTR [BP.OLDDX] ; GET PHYSICAL DRIVE NUMBER + XOR AH,AH + OR AL,AL + JZ DOINTDONE + MOV AH,BYTE PTR [BP.OLDAX+1] ; GET REQUEST CODE + PUSH [BP.OLDF] + CALL ORIG13 + PUSHF + POP [BP.OLDF] +DOINTDONE: + RET +DOINT ENDP +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSDSKPR.INC b/v4.0/src/BIOS/MSDSKPR.INC new file mode 100644 index 0000000..6b24bff --- /dev/null +++ b/v4.0/src/BIOS/MSDSKPR.INC @@ -0,0 +1,22 @@ +; The following structure defines the disk parameter table +; pointed to by Interrupt vector 1EH (location 0:78H) + +DISK_PARMS STRUC +DISK_SPECIFY_1 DB ? +DISK_SPECIFY_2 DB ? +DISK_MOTOR_WAIT DB ? ; Wait till motor off +DISK_SECTOR_SIZ DB ? ; Bytes/Sector (2 = 512) +DISK_EOT DB ? ; Sectors per track (MAX) +DISK_RW_GAP DB ? ; Read Write Gap +DISK_DTL DB ? +DISK_FORMT_GAP DB ? ; Format Gap Length +DISK_FILL DB ? ; Format Fill Byte +DISK_HEAD_STTL DB ? ; Head Settle Time (MSec) +DISK_MOTOR_STRT DB ? ; Motor start delay +DISK_PARMS ENDS + +ROMStatus equ 1 +ROMRead equ 2 +ROMWrite equ 3 +ROMVerify equ 4 +ROMFormat equ 5 diff --git a/v4.0/src/BIOS/MSEQU.INC b/v4.0/src/BIOS/MSEQU.INC new file mode 100644 index 0000000..d45577b --- /dev/null +++ b/v4.0/src/BIOS/MSEQU.INC @@ -0,0 +1,76 @@ +%OUT MSEQU.INC... +;============================================================================== + +FTOOBIG EQU 80H +FBIG EQU 40H +ROMSTATUS EQU 1 +ROMREAD EQU 2 +ROMWRITE EQU 3 +ROMVERIFY EQU 4 +ROMFORMAT EQU 5 +VID_SIZE EQU 12 + +INCLUDE MSBDS.INC ; VARIOUS EQUATES FOR BDS + +;AN000; Extended BPB structure. +BPB_TYPE STRUC +SECSIZE DW ? +SECALL DB ? +RESNUM DW ? +FATNUM DB ? +DIRNUM DW ? +SECNUM DW ? +FATID DB ? +FATSIZE DW ? +SLIM DW ? +HLIM DW ? +HIDDEN_L DW ? +HIDDEN_H dw 0 ;J.K. +SECNUM_L dw 0 ;J.K. +SECNUM_H dw 0 ;J.K. +BPB_TYPE ENDS + +;;;;;;;;;;; +BOOT_SERIAL_SIZE equ 4 ;J.K. +BOOT_VOLUME_LABEL_SIZE equ 11 ;J.K. +BOOT_SYSTEM_ID_SIZE equ 8 ;J.K. +EXT_BOOT_SIGNATURE equ 41 ;J.K. +RSINIT=0A3H ;RS232 INITIALIZATION + ;9600 BAUD:NO PARITY:1 STOP:8 BIT WORD +LF=10 ;LINE FEED +CR=13 ;CARRIAGE RETURN +BACKSP=8 ;BACKSPACE +BRKADR=1BH * 4 ;006C 1BH BREAK VECTOR ADDRESS +TIMADR=1CH * 4 ;0070 1CH TIMER INTERRUPT +DSKADR=1EH * 4 ;ADDRESS OF PTR TO DISK PARAMETERS +SEC9=522H ;ADDRESS OF DISK PARAMETERS +HEADSETTLE=SEC9+9 ; ARR 2.20 ADDRESS OF HEAD SETTLE TIME +NORMSETTLE=15 ; ARR 2.20 NORMAL HEAD SETTLE +SPEEDSETTLE=0 ; ARR 2.20 SPEED UP SETTLE TIME +INITSPOT=534H ; ARR IBM WANTS 4 ZEROS HERE +AKPORT=20H +EOI=20H +CMDLEN = 0 ;LENGTH OF THIS COMMAND +UNIT = 1 ;SUB UNIT SPECIFIER +CMD = 2 ;COMMAND CODE +STATUS = 3 ;STATUS +MEDIA = 13 ;MEDIA DESCRIPTOR +TRANS = 14 ;TRANSFER ADDRESS +COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS +START = 20 ;FIRST BLOCK TO TRANSFER +EXTRA = 22 ;USUALLY A POINTER TO VOL ID FOR ERROR 15 +CHROUT = 29H +MAXERR = 5 +LSTDRV = 504H + +BOOTBIAS = 200H +NOTBUSYSTATUS = 10000000B ; NOT BUSY +ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?) +NOPAPERSTATUS = 00100000B ; NO MORE PAPER +SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED +IOERRSTATUS = 00001000B ; SOME KINDA ERROR +RESERVED = 00000110B ; NOPS +TIMEOUTSTATUS = 00000001B ; TIME OUT. +ERROR_UNKNOWN_MEDIA = 7 ; FOR USE IN BUILD BPB CALL + +PATHGEN = 1 diff --git a/v4.0/src/BIOS/MSEXTRN.INC b/v4.0/src/BIOS/MSEXTRN.INC new file mode 100644 index 0000000..b72d879 --- /dev/null +++ b/v4.0/src/BIOS/MSEXTRN.INC @@ -0,0 +1,97 @@ +; SCCSID = @(#)IBMEXTRN.ASM 1.11 85/11/18 +;This is for IBMINIT module. +;======================================================= +;REVISION HISTORY: +;AN000; - NEW Version 4.00. J.K. +;AC000; - Modified Line 4.00. J.K. +;ANxxx; - PTMyyy +;============================================================================== +;AN001; D486 SHARE installation for large media 2/23/88 J.K. +;============================================================================== + + EXTRN ORIG13:DWORD,ORIG19:DWORD + EXTRN COM2DEV:WORD,COM1DEV:WORD + EXTRN COM4DEV:WORD,COM3DEV:WORD + EXTRN LPT3DEV:WORD,LPT2DEV:WORD,LPT1DEV:WORD + EXTRN HARDDRV:BYTE,HARDNUM:BYTE,DRVMAX:BYTE,HDSKTAB:WORD + EXTRN DSKDRVS:WORD,HNUM:BYTE,EOT:BYTE,FHAVE96:BYTE + EXTRN REAL13:DWORD,DAYCNT:WORD,CONHEADER:WORD + EXTRN TWOHARD:BYTE,INT_2F_NEXT:DWORD + EXTRN BDSH:WORD,BDSX:WORD,START_BDS:DWORD + EXTRN FHAVEK09:BYTE, NEW_ROM:BYTE + EXTRN SINGLE:BYTE + EXTRN BDSMs:BYTE ;for Mini Disk -J.K. 4/7/86 + EXTRN HaveCMOSClock:byte ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN BinToBCD:word ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN DaycntToDay:word ;set by IBMINIT. Used by IBMCLOCK.ASM + EXTRN OLD13:DWORD + extrn Temp_H:word ;J.K. For 32 bit calculation. IBMDISK + extrn Start_Sec_H:word ;J.K. IBMDISK. + extrn KEYRD_Func:byte ;J.K. For IBMCON. Defined in IBMBDATA. + extrn KEYSTS_Func:byte ;J.K. For IBMCON. Defined in IBMBDATA. + extrn DiskSector:byte ;J.K. IBMBDATA + extrn Bpb_In_Sector:word ;J.K. IBMBDATA + extrn SecPerCLusInSector:Byte ;J.K. IBMBDATA + extrn NumberOfFats:byte ;J.K. IBMBDATA + extrn MediaByte:byte ;J.K. IBMBDATA + extrn Ext_Boot_Sig:Byte ;J.K. IBMBDATA + extrn Boot_Serial_L:Word ;J.K. IBMBDATA + extrn Boot_Serial_H:Word ;J.K. IBMBDATA + extrn Boot_Volume_Label:Byte ;J.K. IBMBDATA + extrn Boot_System_ID:Byte ;J.K. IBMBDATA + extrn Fat_12_ID:Byte ;J.K. IBMDISK + extrn Fat_16_ID:Byte ;J.K. IBMDISK + extrn Vol_No_Name:Byte ;J.K. IBMDISK + extrn MotorStartup:Byte ;J.K. IBMBDATA + extrn DoubleWordMov:Byte ;J.K. IBMDISK + extrn Model_Byte:Byte ;J.K. IBMBIO2 + extrn Secondary_Model_Byte:Byte ;J.K. IBMBIO2 + + IF iTEST + IFNDEF NUMBUF + EXTRN NUMBUF:BYTE,DIGITS:BYTE,FTESTBITS:WORD + ENDIF + ENDIF + + EXTRN START$:NEAR,ERROUT:NEAR,BLOCK13:FAR,INT19:FAR + EXTRN INTRET:NEAR,HDRIVE:NEAR,DRIVEX:NEAR,INT13:FAR,CBREAK:NEAR,OUTCHR:NEAR + EXTRN DISKRD:NEAR,MEDIA_PATCH:NEAR,GETBP1_PATCH:NEAR + EXTRN SET_PATCH:NEAR,DISKIO_PATCH:NEAR,DSKERR:NEAR,INIT_PATCH:NEAR + EXTRN TABLE_PATCH:NEAR,EXIT:NEAR,CHANGED_PATCH:NEAR + EXTRN ERRIN:NEAR,GETBP:NEAR,SWPDSK:NEAR + EXTRN OUTCHR:NEAR,WRMSG:NEAR,TIME_TO_TICKS:NEAR + EXTRN INT2F_DISK:NEAR,INSTALL_BDS:NEAR,SETDRIVE:NEAR + extrn Mov_Media_IDs:Near ;J.K. + extrn Clear_IDs:Near ;J.K. + IF iTEST + IFNDEF NUMBUF + EXTRN MSGNUM:NEAR,MSGOUT:NEAR,dumpbytes:near,hex_to_ascii:near + EXTRN outchar:near + ENDIF + ENDIF + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + ASSUME CS:SYSINITSEG + EXTRN CURRENT_DOS_LOCATION:WORD + EXTRN FINAL_DOS_LOCATION:WORD + EXTRN DEVICE_LIST:DWORD + EXTRN MEMORY_SIZE:WORD + EXTRN DEFAULT_DRIVE:BYTE + EXTRN BUFFERS:WORD + EXTRN SYSINIT:FAR + extrn Big_Media_Flag:Byte ;AN001; +SYSINITSEG ENDS + + ASSUME CS:CODE + +; END OF DISK MODULES FOR CONFIGURATION + + EXTRN END96TPI:BYTE + EXTRN ENDTWOHARD:BYTE + EXTRN ENDONEHARD:BYTE + EXTRN ENDSWAP:BYTE + EXTRN ENDFLOPPY:BYTE + +; IBM FIXED UP AT ROM + + EXTRN IBM_DISK_IO:FAR diff --git a/v4.0/src/BIOS/MSGROUP.INC b/v4.0/src/BIOS/MSGROUP.INC new file mode 100644 index 0000000..ac6202d --- /dev/null +++ b/v4.0/src/BIOS/MSGROUP.INC @@ -0,0 +1,46 @@ +EVBOUND = 1 ;THIS VALUE BEING 0 DOES NO BOUNDARY ALLIGNMENT, VALUE 1 ;3.30 + ; ALIGNS TO EVEN ;3.30 +; : : : : : : : : : : : : : : ;3.30 + IF EVBOUND ;;IF EVEN (WORD) ALLIGNMENT IS REQUESTED, ;3.30 +; : : : : : : : : : : : : : : ;3.30 +EVENB MACRO ;3.30 + EVEN ;;ADJUST TO EVEN BOUNDARY ;3.30 + ENDM ;3.30 + ;3.30 +ODD MACRO ;3.30 +;;GENERATE BOUNDARY PADDING TO FORCE ODD OFFSET ;3.30 + IF (($-CODE) MOD 2) EQ 0 ;3.30 + DB ? ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + ;3.30 +CODE_SEGMENT MACRO ;3.30 +;;ALLIGN THE SEGMENT ON WORD BOUNDARY TO ALLOW FOR EVEN ALLIGNMENT OF DATA;3.30 +CODE SEGMENT WORD PUBLIC 'CODE' ;3.30 ;3.30 + ENDM ;3.30 + ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ELSE ;;SINCE EVEN ALLIGNMENT IS NOT DESIRED, JUST USE BYTE ALLI;3.30 GNMENT +; : : : : : : : : : : : : : : ;3.30 + ;3.30 +EVENB MACRO ;3.30 +;;REQUEST FOR WORD ALLIGNMENT DOES NOTHING ;3.30 + ENDM ;3.30 + ;3.30 +ODD MACRO ;3.30 +;;REQUEST FOR ODD ALLIGNMENT DOES NOTHING ;3.30 + ENDM ;3.30 + ;3.30 +CODE_SEGMENT MACRO ;3.30 +;;SEGMENT IS ALLIGNED ON BYTE BOUNDARY FOR MINIMUM SIZE OF GENERATION ;3.30 +CODE SEGMENT BYTE PUBLIC 'CODE' ;3.30 + ENDM ;3.30 + ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ENDIF ;3.30 +; : : : : : : : : : : : : : : ;3.30 + ;3.30 + CODE_SEGMENT ;3.30 + ASSUME CS:CODE ;3.30 + ;3.30 + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSHARD.ASM b/v4.0/src/BIOS/MSHARD.ASM new file mode 100644 index 0000000..51c0dc8 --- /dev/null +++ b/v4.0/src/BIOS/MSHARD.ASM @@ -0,0 +1,427 @@ +;*** +; Title: Disk +; C: (C) Copyright 1988 by Microsoft corp. +; Date: 1/11/85 +; +; There is a bug in some versions of IBM's AT ROM BIOS. +; Interrupts are not disabled during read operations. +; +; Use: This program should be chained in line with the disk +; interupt 13h, it intercepts read calls to the hard disk +; and handles them appropriately. For other functions it +; passes controll to OLD13, which should contain the +; address of the AT ROM disk routine. The entry point for +; this program is IBM_DISK_IO. +; + + + .286c ;Use 80286 non-protected mode + +BIOSEG = 040h ;Segment for ROM BIOS Data +ROMSEG = 0F000h ;Segment of ROM + + +BAD_DISK = 01 + +HF_PORT = 01F0h +HF_REG_PORT = 03F6h + +;* Offsets into Fixed disk parameter table +FDP_PRECOMP = 5 +FDP_CONTROL = 8 + +DATA SEGMENT AT BIOSEG ;ROM BIOS data segment + + ORG 42h +CMD_BLOCK DB 6 DUP (?) + +;* Offsets into CMD_BLOCK for registers +PRE_COMP = 0 ;Write Pre-compensation +SEC_CNT = 1 ;Sector count +SEC_NUM = 2 ;Sector number +CYL_LOW = 3 ;Cylinder number, low part +CYL_HIGH = 4 ;Cylinder number, high part +DRV_HEAD = 5 ;Drive/Head (Bit 7 = ECC mode, Bit 5 = 512 byte sectors, + ; Bit 4 = drive number, Bits 3-0 have head number) +CMD_REG = 6 ;Command register + + + ORG 074h + +DISK_STATUS1 DB ? +HF_NUM DB ? +CONTROL_BYTE DB ? + +DATA ENDS + + + +;*** Define where the ROM routines are actually located +ROM SEGMENT AT ROMSEG + + ORG 02E1Eh +ROMCOMMAND PROC FAR +ROMCOMMAND ENDP + + ORG 02E7Fh +ROMWAIT PROC FAR +ROMWAIT ENDP + + ORG 02EE2h +ROMWAIT_DRQ PROC FAR +ROMWAIT_DRQ ENDP + + ORG 02EF8h +ROMCHECK_STATUS PROC FAR +ROMCHECK_STATUS ENDP + + ORG 02F69h +ROMCHECK_DMA PROC FAR +ROMCHECK_DMA ENDP + + ORG 02F8Eh +ROMGET_VEC PROC FAR +ROMGET_VEC ENDP + + ORG 0FF65h +ROMFRET PROC FAR ;Far return at F000:FF65 in AT ROM. +ROMFRET ENDP + +ROM ENDS + + +CODE SEGMENT BYTE PUBLIC 'code' + +EXTRN OLD13:DWORD ;Link to AT bios int 13h + +PUBLIC IBM_DISK_IO + + + ASSUME CS:CODE + ASSUME DS:DATA + + +;*** IBM_DISK_IO - main routine, fixes AT ROM bug +; +; ENTRY: (AH) = function, 02 or 0A for read. +; (DL) = drive number (80h or 81h). +; (DH) = head number. +; (CH) = cylinder number. +; (CL) = Sector number (high 2 bits has cylinder number). +; (AL) = number of sectors. +; (ES:BX) = address of read buffer. +; For more on register contents see ROM BIOS listing. +; Stack set up for return by an IRET. +; +; EXIT: (AH) = status of current operation. +; (CY) = 1 IF failed, 0 if successful. +; For other register contents see ROM BIOS listing. +; +; USES: +; +; +; WARNING: Uses OLD13 vector for non-read calls. +; Does direct calls to the AT ROM. +; Does segment arithmatic. +; +; EFFECTS: Performs DISK I/O operation. +; +IBM_DISK_IO PROC FAR + CMP DL, 80h + JB ATD1 ;Pass through floppy disk calls. + CMP AH, 02 + JE ATD2 ;Intercept call 02 (read sectors). + CMP AH, 0Ah + JE ATD2 ;and call 0Ah (read long). +ATD1: + JMP OLD13 ;Use ROM INT 13h handler. +ATD2: + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH DS + PUSH ES + PUSH AX + MOV AX,BIOSEG ;Establish BIOS segment addressing. + MOV DS,AX + MOV DISK_STATUS1, 0 ;Initially no error code. + AND DL, 07fh ;Mask to hard disk number + CMP DL, HF_NUM + JB ATD3 ;Disk number in range + MOV DISK_STATUS1, BAD_DISK + JMP SHORT ATD4 ;Disk number out of range error, return + +ATD3: + PUSH BX + MOV AX, ES ;Make ES:BX to Seg:000x form. + SHR BX, 4 + ADD AX, BX + MOV ES, AX + POP BX + AND BX,000Fh + PUSH CS + CALL CHECK_DMA + JC ATD4 ;Abort if DMA across segment boundary + + POP AX ;Restore AX register for SETCMD + PUSH AX + CALL SETCMD ;Set up command block for disk op + MOV DX, HF_REG_PORT + OUT DX, AL ;Write out command modifier + CALL DOCMD ;Carry out command +ATD4: +;; Old code - Carry cleared after set by logical or opearation +;; POP AX +;; MOV AH,DISK_STATUS1 ;On return AH has error code +;; STC +;; OR AH,AH +;; JNZ ATD5 ;Carry set if error +;; CLC +;;--------------------------------------------------- +;; New Code - Let Logical or clear carry and then set carry if ah!=0 +;; And save a couple bytes while were at it. + POP AX + MOV AH,DISK_STATUS1 ;On return AH has error code + OR AH,AH + JZ ATD5 ;Carry set if error + STC + +ATD5: + POP ES + POP DS + POP DI + POP DX + POP CX + POP BX + RET 2 ;Far return, dropping flags +IBM_DISK_IO ENDP + + + +;*** SETCMD - Set up CMD_BLOCK for the disk operation +; +; ENTRY: (DS) = BIOS Data segment. +; (ES:BX) in seg:000x form. +; Other registers as in INT 13h call +; +; EXIT: CMD_BLOCK set up for disk read call. +; CONTROL_BYTE set up for disk operation. +; (AL) = Control byte modifier +; +; +; Sets the fields of CMD_BLOCK using the register contents +; and the contents of the disk parameter block for the given drive. +; +; WARNING: (AX) destroyed. +; Does direct calls to the AT ROM. +; +SETCMD PROC NEAR + MOV CMD_BLOCK[SEC_CNT], AL + MOV CMD_BLOCK[CMD_REG], 020h ;Assume function 02 + CMP AH, 2 + JE SETC1 ;CMD_REG = 20h if function 02 (read) + MOV CMD_BLOCK[CMD_REG], 022h ;CMD_REG = 22h if function 0A (" long) +SETC1: ;No longer need value in AX + MOV AL, CL + AND AL, 03fh ;Mask to sector number + MOV CMD_BLOCK[SEC_NUM], AL + MOV CMD_BLOCK[CYL_LOW], CH + MOV AL, CL + SHR AL, 6 ;Get two high bits of cylender number + MOV CMD_BLOCK[CYL_HIGH], AL + MOV AX, DX + SHL AL, 4 ;Drive number + AND AH, 0Fh + OR AL, AH ;Head number + OR AL, 0A0h ;Set ECC and 512 bytes per sector + MOV CMD_BLOCK[DRV_HEAD], AL + PUSH ES ;GET_VEC destroys ES:BX + PUSH BX + PUSH CS + CALL GET_VEC + MOV AX, ES:FDP_PRECOMP[BX] ;Write pre-comp from disk parameters + SHR AX, 2 + MOV CMD_BLOCK[PRE_COMP],AL ;Only use low part + MOV AL, ES:FDP_CONTROL[BX] ;Control byte modifier + POP BX + POP ES + MOV AH, CONTROL_BYTE + AND AH, 0C0h ;Keep disable retry bits + OR AH, AL + MOV CONTROL_BYTE, AH + RET +SETCMD ENDP + + + +;*** DOCMD - Carry out READ operation to AT hard disk +; +; ENTRY: (ES:BX) = address for read in data. +; CMD_BLOCK set up for disk read. +; +; EXIT: Buffer at (ES:BX) contains data read. +; DISK_STATUS1 set to error code (0 if success). +; +; +; +; WARNING: (AX), (BL), (CX), (DX), (DI) destroyed. +; No check is made for DMA boundary overrun. +; +; EFFECTS: Programs disk controller. +; Performs disk input. +; +DOCMD PROC NEAR + MOV DI, BX ;(ES:DI) = data buffer addr. + PUSH CS + CALL COMMAND + JNZ DOC3 +DOC1: + PUSH CS + CALL WAITT ;Wait for controller to complete read + JNZ DOC3 + MOV CX, 100h ;256 words per sector + MOV DX, HF_PORT + CLD ;String op goes up + CLI ;Disable interrupts (BUG WAS FORGETTING THIS) + REPZ INSW ;Read in sector + STI + TEST CMD_BLOCK[CMD_REG], 02 + JZ DOC2 ;No ECC bytes to read. + PUSH CS + CALL WAIT_DRQ + JC DOC3 + MOV CX, 4 ;4 bytes of ECC + MOV DX, HF_PORT + CLI + REPZ INSB ;Read in ECC + STI +DOC2: + PUSH CS + CALL CHECK_STATUS + JNZ DOC3 ;Operation failed + DEC CMD_BLOCK[SEC_CNT] + JNZ DOC1 ;Loop while more sectors to read +DOC3: + RET +DOCMD ENDP + + + +;*** GET_VEC - Get pointer to hard disk parameters. +; +; ENTRY: (DL) = Low bit has hard disk number (0 or 1). +; +; EXIT: (ES:BX) = address of disk parameters table. +; +; USES: AX for segment computation. +; +; Loads ES:BX from interrupt table in low memory, vector 46h (disk 0) +; or 70h (disk 1). +; +; WARNING: (AX) destroyed. +; This does a direct call to the AT ROM. +; +GET_VEC PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMGET_VEC +GET_VEC ENDP + + + +;*** COMMAND - Send contents of CMD_BLOCK to disk controller. +; +; ENTRY: Control_byte +; CMD_BLOCK - set up with values for hard disk controller. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR for no error. +; +; +; WARNING: (AX), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +; EFFECTS: Programs disk controller. +; +COMMAND PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCOMMAND +COMMAND ENDP + + + +;*** WAITT - Wait for disk interrupt +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR if no error. +; +; +; WARNING: (AX), (BL), (CX) destroyed. +; Does a direct call to the AT ROM. +; +; EFFECTS: Calls int 15h, function 9000h. +; +WAITT PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMWAIT +WAITT ENDP + + + +;*** WAIT_DRQ - Wait for data request. +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; CY if error, NC if no error. +; +; +; WARNING: (AL), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +WAIT_DRQ PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMWAIT_DRQ +WAIT_DRQ ENDP + + + +;*** CHECK_STATUS - Check hard disk status. +; +; ENTRY: Nothing. +; +; EXIT: DISK_STATUS1 = Error code. +; NZ if error, ZR if no error. +; +; +; WARNING: (AX), (CX), (DX) destroyed. +; Does a direct call to the AT ROM. +; +CHECK_STATUS PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCHECK_STATUS +CHECK_STATUS ENDP + + + +;*** CHECK_DMA - check for DMA overrun 64k segment. +; +; ENTRY: (ES:BX) = addr. of memory buffer in seg:000x form. +; CMD_BLOCK set up for operation. +; +; EXIT: DISK_STATUS1 - Error code. +; CY if error, NC if no error. +; +; +; WARNING: Does a direct call to the AT ROM. +; +CHECK_DMA PROC NEAR + PUSH OFFSET ROMFRET + JMP ROMCHECK_DMA +CHECK_DMA ENDP + + +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSINIT.ASM b/v4.0/src/BIOS/MSINIT.ASM new file mode 100644 index 0000000..d00c8af --- /dev/null +++ b/v4.0/src/BIOS/MSINIT.ASM @@ -0,0 +1,2819 @@ + PAGE ,132 ; + %OUT ...MSINIT.ASM +;======================================================= +;REVISION HISTORY: +;AN000; - NEW Version 4.00. J.K. +;AC000; - Modified Line 4.00. J.K. +;ANxxx; - PTMyyy +;============================================================================== +;AN001; P87 Set the value of MOTOR START TIME Variable 6/25/87 J.K. +;AN002; P40 Boot from the system with no floppy diskette drives 6/26/87 J.K. +;AN003; D9 Double Word MOV instruction for 386 based machine 7/1/87 J.K. +;AN004; D64 Extend DOS 3.3 FAT tables to 64 K entries. 7/8/87 J.K. +;AN005; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN006; p941 D113 does not implemented properly. 9/11/87 J.K. +;AN007; p969 Should Honor OS2 boot record. 9/11/87 J.K. +;AN008; p985 Allow I/O access to unformtted media 9/14/87 J.K. +;AN009; p1535 Disallow I/O access to unformtted media 10/15/87 J.K. +;AN010; p2349 Cover DOS 3.3 and below FDISK bug 11/10/87 J.K. +;AN011; P2431 OS2 boot record version number is at offset 7 (not 8)11/12/87 J.K. +;AN012; P2900 DOS 4.0 does not recognize 3.0 formatted media 12/18/87 J.K. +;AN013; P3409 Extended keyboard not recognized 02/05/88 J.K. +;AN014; D486 Share installation for big media 02/23/88 J.K. +;AN015; P3929 Boot record buffer overlaps MSBIO code 03/18/88 J.K. +;============================================================================== + + itest = 0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSDSKPR.INC + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + INCLUDE MSEXTRN.INC + INCLUDE BIOSTRUC.INC + INCLUDE CMOSEQU.INC + include cputype.inc + +; THE FOLLOWING LABEL DEFINES THE END OF THE AT ROM PATCH. THIS IS USED AT +; CONFIGURATION TIME. +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + + PUBLIC ENDATROM ;NOT REFERENCES EXTERNALLY, BUT + ; JUST TO CAUSE ENTRY IN LINK MAP +ENDATROM LABEL BYTE + +;CMOS Clock setting support routines used by MSCLOCK. +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + + EXTRN base_century:byte + EXTRN base_year:byte + EXTRN month_tab:byte + + public Daycnt_to_day ;J.K. 4/30/86 for real time clock support +Daycnt_to_day proc near ;J.K. 4/30/86 for real time clock support +;Entry: [DAYCNT] = number of days since 1-1-80 +;Return: CH - centry in BCD, CL - year in BCD, DH - month in BCD, DL - day in BCD + + push [daycnt] ;save daycnt + cmp daycnt, (365*20+(20/4)) ;# of days from 1-1-1980 to 1-1-2000 + jae century20 + mov base_century, 19 + mov base_year, 80 + jmp years +century20: ;20th century + mov base_century, 20 + mov base_year, 0 + sub daycnt, (365*20+(20/4)) ;adjust daycnt +years: + xor dx, dx + mov ax, daycnt + mov bx, (366+365*3) ;# of days in a Leap year block + div bx ;AX = # of leap block, DX = daycnt + mov daycnt, dx ;save daycnt left +; or ah, ah ;ax should be less than 256 +; jz OK1 +; jmp Erroroccur +;OK1: + mov bl,4 + mul bl ;AX = # of years. Less than 100 years! + add base_year, al ;So, ah = 0. Adjust year accordingly. + inc daycnt ;set daycnt to 1 base + cmp daycnt, 366 ;the daycnt here is the remainder of the leap year block. + jbe Leapyear ;So, it should within 366+355+355+355 days. + inc base_year ;First if daycnt <= 366, then leap year + sub daycnt, 366 ;else daycnt--, base_year++; + ;And the next three years are regular years. + mov cx, 3 +Regularyear: + cmp daycnt, 365 ;for(i=1; i>3 or daycnt <=365;i++) + jbe YearDone ;{if (daycnt > 365) + inc base_year ; { daycnt -= 365 + sub daycnt, 365 ; } + loop regularyear ;} +; jmp Erroroccur ;cannot come to here +Leapyear: + mov byte ptr month_tab+1,29 ;leap year. change the month table. +Yeardone: + xor bx,bx + xor dx,dx + mov ax, daycnt + mov si, offset month_tab + mov cx, 12 +Months: + inc bl ; + mov dl, byte ptr ds:[si] ;compare daycnt for each month until fits + cmp ax, dx ;dh=0. + jbe Month_done + inc si ;next month + sub ax, dx ;adjust daycnt + loop Months +; jmp Erroroccur +Month_done: + mov byte ptr month_tab+1, 28 ;restore month table value + mov dl, bl + mov dh, base_year + mov cl, base_century ;now, al=day, dl=month,dh=year,cl=century + call word ptr BinToBCD ;Oh my!!! To save 15 bytes, Bin_To_BCD proc + ;was relocated seperately from Daycnt_to_Day proc. +; call Bin_to_bcd ;convert "day" to bcd + xchg dl, al ;dl = bcd day, al = month + call word ptr BinToBCD +; call Bin_to_bcd + xchg dh, al ;dh = bcd month, al = year + call word ptr BinToBCD +; call Bin_to_bcd + xchg cl, al ;cl = bcd year, al = century + call word ptr BinToBCD +; call Bin_to_bcd + mov ch, al ;ch = bcd century + pop [daycnt] ;restore original value + ret +Daycnt_to_day endp + + public EndDaycntToDay +EndDaycntToDay label byte + + public Bin_to_bcd +Bin_to_bcd proc near ;J.K. 4/30/86 for real time clock support +;Convert a binary input in AL (less than 63h or 99 decimal) +;into a bcd value in AL. AH destroyed. + push cx + xor ah, ah + mov cl, 10 + div cl ;al - high digit for bcd, ah - low digit for bcd + mov cl, 4 + shl al, cl ;mov the high digit to high nibble + or al, ah + pop cx + ret +Bin_to_bcd endp + + Public EndCMOSClockset ;End of supporting routines for CMOS clock setting. +EndCMOSClockset label byte +; + + EXTRN INT6C_RET_ADDR:DWORD ; RETURN ADDRESS FROM INT 6C + EXTRN BIN_DATE_TIME:BYTE + EXTRN MONTH_TABLE:WORD + EXTRN DAYCNT2:WORD + EXTRN FEB29:BYTE + EXTRN TimeToTicks:Word ;indirect intra-segment call address + + EVENB +; +; THE K09 REQUIRES THE ROUTINES FOR READING THE CLOCK BECAUSE OF THE SUSPEND/ +; RESUME FACILITY. THE SYSTEM CLOCK NEEDS TO BE RESET AFTER RESUME. +; + ASSUME ES:NOTHING + +; THE FOLLOWING ROUTINE IS EXECUTED AT RESUME TIME WHEN THE SYSTEM +; POWERED ON AFTER SUSPENSION. IT READS THE REAL TIME CLOCK AND +; RESETS THE SYSTEM TIME AND DATE, AND THEN IRETS. + +;J.K. 10/2/86 Waring!!! This code will be dynamically relocated by MSINIT. + +INT6C PROC FAR + PUSH CS + POP DS + + ASSUME DS:CODE + + POP WORD PTR INT6C_RET_ADDR ; POP OFF RETURN ADDRESS + POP WORD PTR INT6C_RET_ADDR+2 + POPF + CALL READ_REAL_DATE ; GET THE DATE FROM THE CLOCK + CLI + MOV DS:DAYCNT,SI ; UPDATE DOS COPY OF DATE + STI + CALL READ_REAL_TIME ; GET THE TIME FROM THE RTC + CLI +;SB33019*************************************************************** + MOV AH, 01h ; COMMAND TO SET THE TIME ;SB;3.30 + INT 1Ah ; CALL ROM-BIOS TIME ROUTINE ;SB;3.30 +;SB33019*************************************************************** + STI + JMP INT6C_RET_ADDR ; LONG JUMP + +INT6C ENDP + + + INCLUDE READCLOC.INC + INCLUDE CLOCKSUB.INC + + PUBLIC ENDK09 ;NOT REFERENCES EXTERNALLY, BUT + ; JUST TO CAUSE ENTRY IN LINK MAP +ENDK09 LABEL BYTE + ASSUME DS:NOTHING,ES:NOTHING + +;********************************************************* +; SYSTEM INITIALIZATION +; +; THE ENTRY CONDITIONS ARE ESTABLISHED BY THE BOOTSTRAP +; LOADER AND ARE CONSIDERED UNKNOWN. THE FOLLOWING JOBS +; WILL BE PERFORMED BY THIS MODULE: +; +; 1. ALL DEVICE INITIALIZATION IS PERFORMED +; 2. A LOCAL STACK IS SET UP AND DS:SI ARE SET +; TO POINT TO AN INITIALIZATION TABLE. THEN +; AN INTER-SEGMENT CALL IS MADE TO THE FIRST +; BYTE OF THE DOS +; 3. ONCE THE DOS RETURNS FROM THIS CALL THE DS +; REGISTER HAS BEEN SET UP TO POINT TO THE START +; OF FREE MEMORY. THE INITIALIZATION WILL THEN +; LOAD THE COMMAND PROGRAM INTO THIS AREA +; BEGINNING AT 100 HEX AND TRANSFER CONTROL TO +; THIS PROGRAM. +; +;******************************************************** + +;SYSIZE=200H ;NUMBER OF PARAGRAPHS IN SYSINIT MODULE +sysize=500h ;AC000; + +; DRVFAT MUST BE THE FIRST LOCATION OF FREEABLE SPACE! + EVENB +DRVFAT DW 0000 ;DRIVE AND FAT ID OF DOS +BIOS$_L DW 0000 ;FIRST SECTOR OF DATA (Low word) +bios$_H dw 0000 ;First sector of data (High word) +DOSCNT DW 0000 ;HOW MANY SECTORS TO READ +FBIGFAT DB 0 ; FLAGS FOR DRIVE +;an004 +;FATLEN DW ? ; NUMBER OF SECTORS IN FAT. +FATLOC DW ? ; SEG ADDR OF FAT SECTOR +Init_BootSeg dw ? ;AN015; seg addr of buffer for reading boot record +ROM_drv_num db 80h ;AN000; rom drv number +;Boot_Sec_Per_Fat dw 0 ;AN000; Boot media sectors/FAT +Md_SectorSize dw 512 ;AN004; Used by Get_Fat_Sector proc. +Temp_Cluster dw 0 ;AN004; Used by Get_Fat_Sector proc. +Last_Fat_SecNum dw -1 ;AN004; Used by Get_Fat_Sector proc. + +; THE FOLLOWING TWO BYTES ARE USED TO SAVE THE INFO RETURNED BY INT 13, AH = 8 +; CALL TO DETERMINE DRIVE PARAMETERS. +NUM_HEADS DB 2 ; NUMBER OF HEADS RETURNED BY ROM +SEC_TRK DB 9 ; SEC/TRK RETURNED BY ROM +NUM_CYLN DB 40 ; NUMBER OF CYLINDERS RETURNED BY ROM + +FakeFloppyDrv db 0 ;AN002; If 1, then No diskette drives in the system. + +BOOTBIAS = 200H +BOOT_ADDR = 7C00H +EXT_BOOT_SIG_OFF = 11+size BPB_TYPE ;AN000; 3 byte jmp+8 byte OEM +extended bpb + + + EVENB +DISKTABLE DW 512, 0100H, 64, 0 + DW 2048, 0201H, 112, 0 + DW 8192, 0402H, 256, 0 + DW 32680, 0803H, 512, 0 ;Warning !!! Old values +; DW 20740, 0803H, 512, 0 ;PTM P892 J.K. 12/3/86 DOS 3.3 will use this. + ;J.K.3/16/87 P54 Return back to old value for compatibility.!!! + DW 65535, 1004H, 1024, 0 + +;DISKTABLE2 DW 32680, 0803H, 512, 0 ;Warning !!! Old values ;J.K.3/16/87 P54 Return to old value!!! +;DISKTABLE2 DW 20740, 0803H, 512, 0 ;PTM p892 J.K. 12/3/86 DOS 3.3 will use this. +; DW 65535, 0402H, 512, FBIG +;AN000; +;DISKTABLE2 dw 0, 32680, 0803h, 512, 0 ;table with the assumption of the +; dw 2h, 0000h, 0402h, 512, FBIG ;total fat size <= 64KB. +; dw 4h, 0000h, 0803h, 512, FBIG ;-This will cover upto 134 MB +; dw 8h, 0000h, 1004h, 512, FBIG ;-This will cover upto 268 MB +; dw 10h, 0000h, 2005h, 512, FBIG ;-This will cover upto 536 MB + +;AN004 Default DiskTable under the assumption of Total FAT size <= 128 KB, and +; the maxium size of FAT entry = 16 Bit. +DiskTable2 dw 0, 32680, 0803h, 512, 0 ;For compatibility. + dw 4h, 0000h, 0402h, 512, FBIG ;Covers upto 134 MB media. + dw 8h, 0000h, 0803h, 512, FBIG ; upto 268 MB + dw 10h, 0000h, 1004h, 512, FBIG ; upto 536 MB + dw 20h, 0000h, 2005h, 512, FBIG ; upto 1072 MB + dw 40h, 0000h, 4006h, 512, FBIG ; upto 2144 MB + dw 80h, 0000h, 8007h, 512, FBIG ; upto 4288 MB... + +;****************************************************************************** +;Variables for Mini disk initialization - J.K. 4/7/86 +;****************************************************************************** +End_Of_BDSM dw ? ;offset value of the ending address + ;of BDSM table. Needed to figure out + ;the Final_DOS_Location. +numh db 0 ;number of hard files +mininum db 0 ;logical drive number for mini disk(s) +num_mini_dsk db 0 ;# of mini disk installed +Rom_Minidsk_num db 80h ;physical mini disk number +Mini_HDLIM dw 0 +Mini_SECLIM dw 0 +Mini_BPB_ptr dw 0 ;temporary variable used to save the + ;Mini Disk BPB pointer address in DskDrvs. +;J.K. 4/7/86 End of Mini Disk Init Variables ********************************** + + +BIOS_DATE DB '01/10/84',0 ;This is used for checking AT ROM BIOS date. + +; THE FOLLOWING ARE THE RECOMMENDED BPBS FOR THE MEDIA THAT WE KNOW OF SO +; FAR. + +; 48 TPI DISKETTES + EVENB +BPB48T DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 2*9*40 + DB 0FDH + DW 2 + DW 9 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + +; 96TPI DISKETTES + EVENB +BPB96T DW 512 + DB 1 + DW 1 + DB 2 + DW 224 + DW 2*15*80 + DB 0F9H + DW 7 + DW 15 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + +BPBSIZ = $-BPB96T + +; 3 1/2 INCH DISKETTE BPB + + EVENB +BPB35 DW 512 + DB 2 + DW 1 ; DOUBLE SIDED WITH 9 SEC/TRK + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DW 0 + dw 0 ;AN000; hidden sector High + dd 0 ;AN000; extended total sectors + + EVENB +BPBTABLE DW BPB48T ; 48TPI DRIVES + DW BPB96T ; 96TPI DRIVES + DW BPB35 ; 3.5" DRIVES + ;DW BPB48T ; NOT USED - 8" DRIVES + ;DW BPB48T ; NOT USED - 8" DRIVES + ;DW BPB48T ; NOT USED - HARD FILES + ;DW BPB48T ; NOT USED - TAPE DRIVES + ;DW BPB48T ; NOT USED - OTHER + +PATCHTABLE LABEL BYTE + DW 10,MEDIA_PATCH + DW 3,GETBP1_PATCH + DW 3,SET_PATCH + DW 3,DISKIO_PATCH + DW 3,DSKERR + DW 10,CHANGED_PATCH + DW 3,INIT_PATCH + DW 0 + + ASSUME DS:NOTHING,ES:NOTHING + +; +; ENTRY FROM BOOT SECTOR. THE REGISTER CONTENTS ARE: +; DL = INT 13 DRIVE NUMBER WE BOOTED FROM +; CH = MEDIA BYTE +; BX = FIRST DATA SECTOR ON DISK. +;J.K. +; AX = first data sector (High) +; DI = Sectors/FAT for the boot media. +; + PUBLIC INIT +INIT PROC NEAR + MESSAGE FTESTINIT,<"IBMBIO",CR,LF> + CLI + push ax + XOR AX,AX + MOV DS,AX + pop ax +;J.K. MSLOAD will check the extended boot record and set AX, BX accordingly. + +;SB34INIT000************************************************************* +;SB MSLOAD passes a 32 bit sector number hi word in ax and low in bx +;SB Save this in cs:BIOS$_H and cs:BIOS$_L. This is for the start of +;SB data sector of the BIOS. + + mov cs:BIOS$_H,ax + mov cs:BIOS$_L,bx + +;SB34INIT000************************************************************* + +;J.K. With the following information from MSLOAD, we don't need the +; Boot sector any more.-> This will solve the problem of 29 KB size +; limitation of MSBIO.COM file. +;J.K. AN004 - Don't need this information any more, since we are not going to +; read the whole FAT into memory. +; mov cs:Boot_Sec_Per_FAT, di ;sectors/FAT for boot media. ;AN000; + +; +; PRESERVE ORIGINAL INT 13 VECTOR +; WE NEED TO SAVE INT13 IN TWO PLACES IN CASE WE ARE RUNNING ON AN AT. +; ON ATS WE INSTALL THE IBM SUPPLIED ROM_BIOS PATCH DISK.OBJ WHICH HOOKS +; INT13 AHEAD OF ORIG13. SINCE INT19 MUST UNHOOK INT13 TO POINT TO THE +; ROM INT13 ROUTINE, WE MUST HAVE THAT ROM ADDRESS ALSO STORED AWAY. +; + MOV AX,DS:[13H*4] + MOV WORD PTR OLD13,AX + MOV WORD PTR ORIG13,AX + MOV AX,DS:[13H*4+2] + MOV WORD PTR OLD13+2,AX + MOV WORD PTR ORIG13+2,AX +; +; SET UP INT 13 FOR NEW ACTION +; + MOV WORD PTR DS:[13H*4],OFFSET BLOCK13 + MOV DS:[13H*4+2],CS +; +; PRESERVE ORIGINAL INT 19 VECTOR +; + MOV AX,DS:[19H*4] + MOV WORD PTR ORIG19,AX + MOV AX,DS:[19H*4+2] + MOV WORD PTR ORIG19+2,AX +; +; SET UP INT 19 FOR NEW ACTION +; + MOV WORD PTR DS:[19H*4],OFFSET INT19 + MOV DS:[19H*4+2],CS + STI + INT 11H ;GET EQUIPMENT STATUS +;J.K.6/24/87 We have to support a system that does not have any diskette +;drives but only hardfiles. This system will IPL from the hardfile. +;If the equipment flag bit 0 is 1, then the system has diskette drive(s). +;Otherwise, the system only have hardfiles. +;Important thing is that still, for compatibility reason, the drive letter +;for the hardfile start from "C". So, we still need to allocate dummy BDS +;drive A and driver B. In SYSINIT time, we are going to set CDS table entry +;of DPB pointer for these drives to 0, so any user attempt to access this +;drives will get "Invalid drive letter ..." message. We are going to +;establish "FAKEFLOPPYDRV" flag. ***SYSINIT module should call INT 11h to check +;if there are any diskette drivers in the system or not.!!!*** + +;SB34INIT001************************************************************** +;SB check the register returned by the equipment determination interrupt +;SB we have to handle the case of no diskettes in the system by faking +;SB two dummy drives. +;SB if the register indicates that we do have floppy drives we don't need +;SB to do anything special. +;SB if the register indicates that we don't have any floppy drives then +;SB what we need to do is set the FakeFloppyDrv variable, change the +;SB register to say that we do have floppy drives and then go to execute +;SB the code which starts at NOTSINGLE. This is because we can skip the +;SB code given below which tries to find if there are one or two drives +;SB since we already know about this. 6 LOCS + + test ax,1 + jnz DO_FLOPPY + mov cs:FakeFloppyDrv,1 ; fake floppy + mov ax,1 ; set to indicate 2 floppies + jmp short NOTSINGLE + +DO_FLOPPY: + +;SB34INIT001************************************************************** + ; + ; Determine if there are one or two diskette drives in system + ; + ROL AL,1 ;PUT BITS 6 & 7 INTO BITS 0 & 1 + ROL AL,1 + AND AX,3 ;ONLY LOOK AT BITS 0 & 1 + JNZ NOTSINGLE ;ZERO MEANS SINGLE DRIVE SYSTEM + INC AX ;PRETEND IT'S A TWO DRIVE SYSTEM + INC CS:SINGLE ;REMEMBER THIS +NOTSINGLE: + INC AX ;AX HAS NUMBER OF DRIVES, 2-4 + ;IS ALSO 0 INDEXED BOOT DRIVE IF WE + ; BOOTED OFF HARD FILE + MOV CL,AL ;CH IS FAT ID, CL # FLOPPIES + TEST DL,80H ;BOOT FROM FLOPPY ? + JNZ GOTHRD ;NO. + XOR AX,AX ;INDICATE BOOT FROM DRIVE A +GOTHRD: +; +; AX = 0-BASED DRIVE WE BOOTED FROM +; BIOS$_L, BIOS$_H set. +; CL = NUMBER OF FLOPPIES INCLUDING FAKE ONE +; CH = MEDIA BYTE +; + MESSAGE FTESTINIT,<"INIT",CR,LF> + XOR DX,DX + CLI + MOV SS,DX + MOV SP,700H ;LOCAL STACK + STI + ASSUME SS:NOTHING + + PUSH CX ;SAVE NUMBER OF FLOPPIES AND MEDIA BYTE + MOV AH,CH ;SAVE FAT ID TO AH + PUSH AX ;SAVE BOOT DRIVE NUMBER, AND MEDIA BYTE +;J.K. Let Model_byte, Secondary_Model_Byte be set here!!! +;SB33020****************************************************************** + mov ah,0c0h ; return system environment ;SB;3.30 + int 15h ; call ROM-Bios routine ;SB;3.30 +;SB33020****************************************************************** + jc No_Rom_System_Conf ; just use Model_Byte + cmp ah, 0 ; double check + jne No_Rom_System_Conf + mov al, ES:[BX.bios_SD_modelbyte] ;get the model byte + mov [Model_Byte], al + mov al, ES:[BX.bios_SD_scnd_modelbyte] ;secondary model byte + mov [Secondary_Model_Byte], al + jmp short Turn_Timer_On +No_Rom_System_Conf: + MOV SI,0FFFFH ;MJB001 + MOV ES,SI ;MJB001 + MOV AL,ES:[0EH] ; GET MODEL BYTE ARR 2.41 + MOV MODEL_BYTE,AL ; SAVE MODEL BYTE ARR 2.41 +Turn_Timer_On: + MOV AL,EOI + OUT AKPORT,AL ;TURN ON THE TIMER + +; NOP out the double word MOV instruction in MSDISK, if +; this is not a 386 machine... + Get_CPU_Type ; macro to determine cpu type + cmp ax, 2 ; is it a 386? + je Skip_Patch_DoubleWordMov; yes: skip the patch + +Patch_DoubleWordMov: + push es ;AN003; + push cs ;AN003; + pop es ;AN003;ES -> CS + mov di, offset DoubleWordMov ;AN003; + mov cx, 3 ;AN003; 3 bytes to NOP + mov al, 90h ;AN003; + rep stosb ;AN003; + pop es ;AN003; +Skip_Patch_DoubleWordMov: ;AN003; + MESSAGE FTESTINIT,<"COM DEVICES",CR,LF> +;SB33IN1********************************************************* + + mov si,offset COM4DEV + call AUX_INIT + mov si,offset COM3DEV + call AUX_INIT +;SB33IN1********************************************************* + MOV SI,OFFSET COM2DEV + CALL AUX_INIT ;INIT COM2 + MOV SI,OFFSET COM1DEV + CALL AUX_INIT ;INIT COM1 + + MESSAGE FTESTINIT,<"LPT DEVICES",CR,LF> + MOV SI,OFFSET LPT3DEV + CALL PRINT_INIT ;INIT LPT3 + MOV SI,OFFSET LPT2DEV + CALL PRINT_INIT ;INIT LPT2 + MOV SI,OFFSET LPT1DEV + CALL PRINT_INIT ;INIT LPT1 + + XOR DX,DX + MOV DS,DX ;TO INITIALIZE PRINT SCREEN VECTOR + MOV ES,DX + + XOR AX,AX + MOV DI,INITSPOT + STOSW ;INIT FOUR BYTES TO 0 + STOSW + + MOV AX,CS ;FETCH SEGMENT + + MOV DS:WORD PTR BRKADR,OFFSET CBREAK ;BREAK ENTRY POINT + MOV DS:BRKADR+2,AX ;VECTOR FOR BREAK + +;*********************************************** ARR 2.15 +; SINCE WE'RE FIRST IN SYSTEM, NO NEED TO CHAIN THIS. +; CLI ; ARR 2.15 DON'T GET BLOWN +; MOV DS:WORD PTR TIMADR,OFFSET TIMER ; ARR 2.15 TIMER ENTRY POINT +; MOV DS:TIMADR+2,AX ; ARR 2.15 VECTOR FOR TIMER +; STI +;*********************************************** ARR 2.15 + +; BAS DEBUG + MOV DS:WORD PTR CHROUT*4,OFFSET WORD PTR OUTCHR + MOV DS:WORD PTR CHROUT*4+2,AX + + MESSAGE FTESTINIT,<"INTERRUPT VECTORS",CR,LF> + MOV DI,4 + MOV BX,OFFSET INTRET ;WILL INITIALIZE REST OF INTERRUPTS + XCHG AX,BX + STOSW ;LOCATION 4 + XCHG AX,BX + STOSW ;INT 1 ;LOCATION 6 + ADD DI,4 + XCHG AX,BX + STOSW ;LOCATION 12 + XCHG AX,BX + STOSW ;INT 3 ;LOCATION 14 + XCHG AX,BX + STOSW ;LOCATION 16 + XCHG AX,BX + STOSW ;INT 4 ;LOCATION 18 + + MOV DS:WORD PTR 500H,DX ;SET PRINT SCREEN & BREAK =0 + MOV DS:WORD PTR LSTDRV,DX ;CLEAN OUT LAST DRIVE SPEC + + MESSAGE FTESTINIT,<"DISK PARAMETER TABLE",CR,LF> + +;;** MOV SI,WORD PTR DS:DSKADR ; ARR 2.41 +;;** MOV DS,WORD PTR DS:DSKADR+2 ; DS:SI -> CURRENT TABLE ARR 2.41 +;;** +;;** MOV DI,SEC9 ; ES:DI -> NEW TABLE ARR 2.41 +;;** MOV CX,SIZE DISK_PARMS ; ARR 2.41 +;;** REP MOVSB ; COPY TABLE ARR 2.41 +;;** PUSH ES ; ARR 2.41 +;;** POP DS ; DS = 0 ARR 2.41 + +;;** MOV WORD PTR DS:DSKADR,SEC9 ; ARR 2.41 +;;** MOV WORD PTR DS:DSKADR+2,DS ; POINT DISK PARM VECTOR TO NEW TABLE + ; ARR 2.41 +;SB34INIT002****************************************************************** +;SB We need to initalise the cs:MotorStartup variable from the disk +;SB parameter table at SEC9. The offsets in this table are defined in +;SB the DISK_PARMS struc in MSDSKPRM.INC. 2 LOCS + + mov al,ds:SEC9 + DISK_MOTOR_STRT + mov cs:MotorStartup,al +;SB34INIT002****************************************************************** + CMP MODEL_BYTE,0FDH ; IS THIS AN OLD ROM? ARR 2.41 + JB NO_DIDDLE ; NO ARR 2.41 + MOV WORD PTR DS:(SEC9 + DISK_HEAD_STTL),0200H+NORMSETTLE + ; SET HEAD SETTLE AND MOTOR START + ; ON PC-1 PC-2 PC-XT HAL0 ARR 2.41 + MOV DS:(SEC9 + DISK_SPECIFY_1),0DFH + ; SET 1ST SPECIFY BYTE + ; ON PC-1 PC-2 PC-XT HAL0 ARR 2.41 +NO_DIDDLE: ; ARR 2.41 + INT 12H ;GET MEMORY SIZE--1K BLOCKS IN AX + MOV CL,6 + SHL AX,CL ;CONVERT TO 16-BYTE BLOCKS(SEGMENT NO.) + POP CX ; RETREIVE BOOT DRIVE NUMBER, AND FAT ID + MOV DRVFAT,CX ;SAVE DRIVE TO LOAD DOS, AND FAT ID + + PUSH AX +;J.K. Don't have to look at the boot addr. +; MOV DX,DS:(7C00H + 16H) ; NUMBER OF SECTORS/FAT FROM BOOT SEC +;an004 +; mov dx, cs:Boot_Sec_Per_FAT ;AC000;Do not use the bpb info from Boot record any more. +; XOR DH,DH +; MOV FATLEN,DX +; +; CONVERT SECTOR COUNT TO PARAGRAPH COUNT:512 BYTES / SEC / 16 BYTES / PARA +; = 32 PARA /SECTOR +; + +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SHL DX,1 +; SUB AX,DX ; ROOM FOR FAT + sub ax, 64 ;AN004; Room for FATLOC segment. (1 KB buffer) + MOV FATLOC,AX ; LOCATION TO READ FAT + sub ax, 64 ;Room for Boot Record buffer segment (1 KB) + mov Init_BootSeg, ax ;AN015; + POP AX + + MOV DX,SYSINITSEG + MOV DS,DX + + ASSUME DS:SYSINITSEG + + MOV WORD PTR DEVICE_LIST,OFFSET CONHEADER + MOV WORD PTR DEVICE_LIST+2,CS + + MOV MEMORY_SIZE,AX + INC CL + MOV DEFAULT_DRIVE,CL ;SAVE DEFAULT DRIVE SPEC + +;DOSSEG = (((END$ - START$)+15)/16)+BIOSEG+SYSIZE + +; BAS DEBUG +;MOV CURRENT_DOS_LOCATION,(((END$ - START$)+15)/16)+SYSIZE + MOV AX, OFFSET END$ + SUB AX, OFFSET START$ + ADD AX, 15 + RCR AX, 1 ; DIVIDE BY 16 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + ADD AX, SYSIZE + ADD AX, CODE + MOV CURRENT_DOS_LOCATION, AX +; BAS DEBUG +; ADD CURRENT_DOS_LOCATION,CODE + +; IMPORTANT: SOME OLD IBM HARDWARE GENERATES SPURIOUS INT F'S DUE TO BOGUS +; PRINTER CARDS. WE INITIALIZE THIS VALUE TO POINT TO AN IRET ONLY IF + +; 1) THE ORIGINAL SEGMENT POINTS TO STORAGE INSIDE VALID RAM. + +; 2) THE ORIGINAL SEGMENT IS 0F000:XXXX + +; THESES ARE CAPRICIOUS REQUESTS FROM OUR OEM FOR REASONS BEHIND THEM, READ +; THE DCR'S FOR THE IBM DOS 3.2 PROJECT. + + PUSH AX + + ASSUME ES:SYSINITSEG, DS:NOTHING + + MOV AX,SYSINITSEG + MOV ES,AX + + XOR AX,AX ; AX := SEGMENT FOR INT 15 + MOV DS,AX + MOV AX,WORD PTR DS:(0FH*4+2) + + CMP AX,ES:MEMORY_SIZE ; CONDITION 1 + JNA RESETINTF + + CMP AX,0F000H ; CONDITION 2 + JNE KEEPINTF + +RESETINTF: + MOV WORD PTR DS:[0FH*4],OFFSET INTRET + MOV WORD PTR DS:[0FH*4+2],CS +KEEPINTF: + POP AX + +; END IMPORTANT + +;SB34INIT003**************************************************************** +;SB We will check if the system has IBM extended key board by +;SB looking at a byte at 40:96. If bit 4 is set, then extended key board +;SB is installed, and we are going to set KEYRD_Func to 10h, KEYSTS_Func to 11h +;SB for the extended keyboard function. Use cx as the temporary register. 8 LOCS + + xor cx,cx + mov ds,cx + assume ds:nothing + mov cl,ds:0496h ; get keyboard flag + test cl,00010000b + jz ORG_KEY ; orginal keyboard + mov byte ptr KEYRD_func,10h ; extended keyboard + mov byte ptr KEYSTS_func,11h ; change for extended keyboard functions +ORG_KEY: + +;SB34INIT003**************************************************************** + +;************************************************************** +; WILL INITIALIZE THE NUMBER OF DRIVES +; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL +; THE INDICATIONS ARE AS FOLLOWS: +; +; BITS 7 6 DRIVES +; 0 0 1 +; 0 1 2 +; 1 0 3 +; 1 1 4 +;************************************************************** + PUSH CS + POP DS + PUSH CS + POP ES + + ASSUME DS:CODE,ES:CODE + + call CMOS_Clock_Read ;Before doing anythig else if CMOS clock exists, + ;then set the system time according to that. + ;Also, reset the cmos clock rate. + + MESSAGE FTESTINIT,<"DISK DEVICES",CR,LF> + + XOR SI,SI + MOV WORD PTR [SI],OFFSET HARDDRV ;SET UP POINTER TO HDRIVE + + POP AX ;NUMBER OF FLOPPIES AND FAT ID + XOR AH,AH ; CHUCK FAT ID BYTE + MOV HARDNUM,AL ;REMEMBER WHICH DRIVE IS HARD DISK + MOV DRVMAX,AL ;AND SET INITIAL NUMBER OF DRIVES + SHL AX,1 ;TWO BYTES PER ADDRESS + MOV DI,OFFSET DSKDRVS + ADD DI,AX ;POINT TO HARDFILE LOCATION + MOV SI,OFFSET HDSKTAB + MOVSW ;TWO ADDRESSES TO MOVE + MOVSW + MESSAGE FTESTINIT,<"BEFORE INT 13",CR,LF> +;SB33021******************************************************************** + mov DL, 80h ;SB ; tell rom bios to look at hard drives + mov AH, 8h ;SB ; set command to get drive parameter + int 13h ;SB ; call ROM-BIOS to get number of drives +;SB33021******************************************************************** + JC ENDDRV ;CARRY INDICATES OLD ROM, SO NO HARDFILE + MOV HNUM,DL +ENDDRV: + MESSAGE FTESTINIT,<"SETTING UP BDSS",CR,LF> + +; +; SCAN THE LIST OF DRIVES TO DETERMINE THEIR TYPE. WE HAVE THREE FLAVORS OF +; DISKETTE DRIVES: +; +; 48TPI DRIVES WE DO NOTHING SPECIAL FOR THEM +; 96TPI DRIVES MARK THE FACT THAT THEY HAVE CHANGELINE SUPPORT. +; 3 1/4 DRIVES MARK CHANGELINE SUPPORT AND SMALL. +; +; THE FOLLOWING CODE USES REGISTERS FOR CERTAIN VALUES: +; DL - PHYSICAL DRIVE +; DS:DI - POINTS TO CURRENT BDS +; CX - FLAG BITS FOR BDS +; DH - FORM FACTOR FOR THE DRIVE (1 - 48TPI, 2 - 96TPI, 3 - 3.5" MEDIUM) +; + XOR DL,DL ; START OUT WITH DRIVE 0. + PUSH CS + POP DS + ASSUME DS:CODE + + MOV EOT,9 + MOV DI,OFFSET START_BDS +;J.K.6/24/87 Check if the system has no physical diskette drives. +;J.K. If it is, then we don't have to set BDS tables. But since we +;J.K. pretend that we have 2 floppies, we are going to reserve two +;J.K. BDS tables for the fake drive A, and B. and set the end of link +;J.K. pointer. + +;SB34INIT004********************************************************* +;SB Check to see if we are faking floppy drives. If not we don't +;SB do anything special. If we are faking floppy drives we need +;SB to set aside two BDSs for the two fake floppy drives. We +;SB don't need to initalise any fields though. So starting at START_BDS +;SB use the link field in the BDS structure to go to the second BDS +;SB in the list and initalise it's link field to -1 to set the end of +;SB the list. Then jump to the routine at DoHard to allocate/initialise +;SB the BDS for HardDrives. + + cmp cs:FakeFloppyDrv,1 + jnz LOOP_DRIVE ; system has floppy + mov di,word ptr [di].link ; di <- first BDS link + mov di,word ptr [di].link ; di <- second BDS link + mov word ptr [di].link,-1 ; set end of link + jmp DoHard ; allocate/initialise BDS for HardDrives +;SB34INIT004********************************************************* + +LOOP_DRIVE: + CMP DL,DRVMAX + JB GOT_MORE + JMP DONE_DRIVES +GOT_MORE: + XOR CX,CX ; ZERO ALL FLAGS + MOV DI,WORD PTR [DI].LINK ; GET NEXT BDS + MOV DH,FF48TPI ; SET FORM FACTOR TO 48 TPI + MOV NUM_CYLN,40 ; 40 TRACKS PER SIDE + + PUSH DS + PUSH DI + PUSH DX + PUSH CX + PUSH ES + +;SB33022******************************************************************** + MOV AH, 8h ;GET DRIVE PARAMETERS ;SB;3.30 + INT 13h ;CALL ROM-BIOS ;SB;3.30 +;SB33022******************************************************************** + JNC PARMSFROMROM + JMP NOPARMSFROMROM ; GOT AN OLD ROM +PARMSFROMROM: +;J.K. 10/9/86 If CMOS is bad, it gives ES,AX,BX,CX,DH,DI=0. CY=0. +;In this case, we are going to put bogus informations to BDS table. +;We are going to set CH=39,CL=9,DH=1 to avoid divide overflow when +;they are calculated at the later time. This is just for the Diagnostic +;Diskette which need MSBIO,MSDOS to boot up before it sets CMOS. +;This should only happen with drive B. + + CMP CH,0 ; if ch=0, then cl,dh=0 too. + JNE PFR_OK + MOV CH,39 ; ROM gave wrong info. + MOV CL,9 ; Let's default to 360K. + MOV DH,1 +PFR_OK: + INC DH ; MAKE NUMBER OF HEADS 1-BASED + INC CH ; MAKE NUMBER OF CYLINDERS 1-BASED + MOV NUM_HEADS,DH ; SAVE PARMS RETURNED BY ROM + AND CL,00111111B ; EXTRACT SECTORS/TRACK + MOV SEC_TRK,CL + MOV NUM_CYLN,CH ; ASSUME LESS THAN 256 CYLINDERS!! +; MAKE SURE THAT EOT CONTAINS THE MAX NUMBER OF SEC/TRK IN SYSTEM OF FLOPPIES + CMP CL,EOT ; MAY SET CARRY + JBE EOT_OK + MOV EOT,CL +EOT_OK: + POP ES + POP CX + POP DX + POP DI + POP DS + +; CHECK FOR CHANGELINE SUPPORT ON DRIVE +;SB33023******************************************************************** + mov AH, 15h ;SB ; set command to get DASD type + int 13h ;SB ; call ROM-BIOS +;SB33023******************************************************************** + JC CHANGELINE_DONE + CMP AH,02 ; CHECK FOR PRESENCE OF CHANGELINE + JNE CHANGELINE_DONE +; +; WE HAVE A DRIVE WITH CHANGE LINE SUPPORT. +; + MESSAGE FTESTINIT,<"96TPI DEVICES",CR,LF> + + OR CL,FCHANGELINE ; SIGNAL TYPE + MOV FHAVE96,1 ; REMEMBER THAT WE HAVE 96TPI DISKS +; +; WE NOW TRY TO SET UP THE FORM FACTOR FOR THE TYPES OF MEDIA THAT WE KNOW +; AND CAN RECOGNISE. FOR THE REST, WE SET THE FORM FACTOR AS "OTHER". +; +CHANGELINE_DONE: +; 40 CYLINDERS AND 9 OR LESS SEC/TRK, TREAT AS 48 TPI MEDIUM. + CMP NUM_CYLN,40 + JNZ TRY_80 + CMP SEC_TRK,9 + JBE GOT_FF +GOTOTHER: + MOV DH,FFOTHER ; WE HAVE A "STRANGE" MEDIUM + JMP SHORT GOT_FF + +; +; 80 CYLINDERS AND 9 SECTORS/TRACK => 720 KB DEVICE +; 80 CYLINDERS AND 15 SEC/TRK => 96 TPI MEDIUM +; +TRY_80: + CMP NUM_CYLN,80 + JNZ GOTOTHER + CMP SEC_TRK,15 + JZ GOT96 + CMP SEC_TRK,9 + JNZ GOTOTHER + MOV DH,FFSMALL + JMP SHORT GOT_FF + +GOT96: + MOV DH,FF96TPI + +GOT_FF: + JMP SHORT NEXTDRIVE + +; WE HAVE AN OLD ROM, SO WE EITHER HAVE A 48TPI OR 96TPI DRIVE. IF THE DRIVE +; HAS CHANGELINE, WE ASSUEM IT IS A 96TPI, OTHERWISE WE TREAT IT AS A 48TPI. + +NOPARMSFROMROM: + POP ES + POP CX + POP DX + POP DI + POP DS + +;SB33024**************************************************************** + MOV AH, 15h ; SET COMMAND TO GET DASD TYPE ;SB;3.30 + INT 13h ; CALL ROM-BIOS ;SB;3.30 +;SB33024**************************************************************** + JC NEXTDRIVE + CMP AH,2 ; IS THERE CHANGELINE? + JNZ NEXTDRIVE + OR CL,FCHANGELINE + MOV FHAVE96,1 ; REMEMBER THAT WE HAVE 96TPI DRIVES + MOV NUM_CYLN,80 + MOV DH,FF96TPI + MOV AL,15 ; SET EOT IF NECESSARY + CMP AL, EOT + JBE EOT_OK2 + MOV EOT,AL +EOT_OK2: + +NEXTDRIVE: + OR CL,FI_OWN_PHYSICAL ; SET THIS TRUE FOR ALL DRIVES + MOV BH,DL ;SAVE INT13 DRIVE NUMBER + +; WE NEED TO DO SPECIAL THINGS IF WE HAVE A SINGLE DRIVE SYSTEM AND ARE SETTING +; UP A LOGICAL DRIVE. IT NEEDS TO HAVE THE SAME INT13 DRIVE NUMBER AS ITS +; COUNTERPART, BUT THE NEXT DRIVE LETTER. ALSO RESET OWNERSHIP FLAG. +; WE DETECT THE PRESENCE OF THIS SITUATION BY EXAMINING THE FLAG SINGLE FOR THE +; VALUE 2. + + CMP SINGLE,2 + JNZ NOT_SPECIAL + DEC BH ; INT13 DRIVE NUMBER SAME FOR LOGICAL DRIVE + XOR CL,FI_OWN_PHYSICAL ; RESET OWNERSHIP FLAG FOR LOGICAL DRIVE +NOT_SPECIAL: +; THE VALUES THAT WE PUT IN FOR RHDLIM AND RSECLIM WILL ONLY REMAIN IF THE +; FORM FACTOR IS OF TYPE "FFOTHER". + XOR AX,AX + MOV AL,NUM_HEADS + MOV WORD PTR [DI].RHDLIM,AX + MOV AL,SEC_TRK + MOV WORD PTR [DI].RSECLIM,AX + MOV WORD PTR [DI].FLAGS,CX + MOV BYTE PTR [DI].FORMFACTOR,DH + MOV BYTE PTR [DI].DRIVELET,DL + MOV BYTE PTR [DI].DRIVENUM,BH + MOV BL,BYTE PTR NUM_CYLN + MOV BYTE PTR [DI].CCYLN,BL ; ONLY THE L.S. BYTE IS SET HERE + CMP SINGLE,1 ; SPECIAL CASE FOR SINGLE DRIVE SYSTEM + JNZ NO_SINGLE + MESSAGE FTESTINIT,<"SINGLE DRIVE SYSTEM",CR,LF> + MOV SINGLE,2 ; DON'T LOSE INFO THAT WE HAVE SINGLE SYSTEM + OR CX,FI_AM_MULT + OR WORD PTR [DI].FLAGS,CX + MOV DI,WORD PTR [DI].LINK ; MOVE TO NEXT BDS IN LIST + INC DL + JMP SHORT NEXTDRIVE ; USE SAME INFO FOR BDS A PREVIOUS +NO_SINGLE: + INC DL + JMP LOOP_DRIVE + +DONE_DRIVES: + MOV AX,-1 ; SET LINK TO NULL + MOV WORD PTR [DI].LINK,AX + +; SET UP ALL THE HARD DRIVES IN THE SYSTEM + +DOHARD: + MNUM FTESTINIT+FTESTHARD,AX + MESSAGE FTESTINIT+FTESTHARD,<" HARD DISK(S) TO INITIALIZE",CR,LF> + MESSAGE FTESTINIT+FTESTHARD,<"HARD DISK 1",CR,LF> + + CMP HNUM,0 ; IF (NO_HARD_FILES) + JLE STATIC_CONFIGURE ; THEN EXIT TO CONFIGURE + + MOV DL,80H + MOV DI,OFFSET BDSH ; SET UP FIRST HARD FILE. + MOV BL,HARDNUM + CALL SETHARD + assume es:nothing + JNC HARDFILE1_OK + + DEC HNUM ; FIRST HARD FILE IS BAD. + CMP HNUM,0 ; IF (SECOND_HARD_FILE) + JG SECOND_HARD ; THEN SET UP SECOND HARD FILE + JMP SHORT STATIC_CONFIGURE + +HARDFILE1_OK: + CALL INSTALL_BDS ; INSTALL BDS INTO LINKED LIST + CMP HNUM,2 ; IF (ONLY_ONE_HARDFILE) + JB SETIT ; THEN SETIT "IN PLACE" + + MOV BL,HARDNUM + INC BL ; NEXT DRIVE LETTER + MOV DI,OFFSET BDSX + +SECOND_HARD: ; SETUP SECOND HARD FILE + + MESSAGE FTESTINIT+FTESTHARD,<"HARD DISK 2",CR,LF> + MOV DL,81H ; NEXT HARD FILE + CALL SETHARD + assume es:nothing + JNC HARDFILE2_OK + DEC HNUM + JMP SHORT SETIT + +HARDFILE2_OK: + CALL INSTALL_BDS + +SETIT: + MOV AL,HNUM + OR AL,AL + JZ STATIC_CONFIGURE + ADD AL,HARDNUM + MOV DRVMAX,AL + +; End of physical drive initialization. +; *** Do not change the position of the following statement.-J.K.4/7/86 +; *** DoMini routine will use [DRVMAX] value for the start of the logical +; *** drive number of Mini disk(s). + + call DoMini ;For setting up mini disks, if found -J.K. + + assume es:nothing +; END OF DRIVE INITIALIZATION. + +;J.K. 9/24/86 We now decide, based on the configurations available so far, what +;code or data we need to keep as a stay resident code. The following table +;shows the configurations under consideration. They are listed in the order +;of their current position memory. +;Configuration will be done in two ways: +;First, we are going to set "Static configuration". Static configuration will +;consider from basic configuration to ENDOF96TPI configuration. The result +;of static configuration will be the address the Dynamic configuration will +;use to start with. +;Secondly, "Dynamic cofiguration" will be performed. Dynamic configuration +;involves possible relocation of CODE or DATA. Dynamic configuration routine +;will take care of BDSM tables and AT ROM Fix module thru K09 suspend/resume +;code individually. After these operation, FINAL_DOS_LOCATION will be set. +;This will be the place SYSINIT routine will relocate MSDOS module for good. +; +; 1. BASIC CONFIGURATION FOR IBMBIO (EndFloppy, EndSwap) +; 2. ENDONEHARD +; 3. ENDTWOHARD +; 4. END96TPI ;a system that supports "Change Line Error" +; 5. End of BDSM ;BDSM tables for mini disks. +; 6. ENDATROM ;Some of AT ROM fix module. +; 7. ENDCMOSCLOCKSET;Supporting program for CMOS clock write. +; 8. ENDK09 ;K09 CMOS Clock module to handle SUSPEND/RESUME operation. +; +;J.K. 9/24/86. + +; *** For mini disk configuration. -J.K. 4/7/86 +; *** END_OF_BDSM will contains the ending address(offset) of BDSM table for +; *** mini disks which is located right after the label END96TPI. +; *** The variable NUM_MINI_DSK will indicate the existance of the mini disk.-J.K. 4/7/86 + + +STATIC_CONFIGURE: + + + PUSH AX + mov ax, offset END96TPI ;let's start with the biggest one. + cmp fHave96, 0 ;Is change line support there? + jnz Config96 ;Yes. + + mov ax, offset ENDTWOHARD + cmp HNUM, 1 ;1 hard file? + jbe No_Two_HRD + jmp ConfigTwoHard +No_Two_HRD: + mov ax, offset ENDONEHARD + jnz Basic_Floppy + jmp ConfigOneHard +Basic_Floppy: + mov ax, offset ENDFLOPPY + jmp Dynamic_Configure ;static configuration is done! + +; +; KEEP THE 96TPI CODE +; +CONFIG96: +; +; SAVE OLD INT 13 VECTOR +; + PUSH AX + PUSH DS + XOR AX,AX + MOV DS,AX + ASSUME DS:NOTHING + + MOV AX,DS:[4 * 13H] + MOV WORD PTR CS:REAL13,AX + MOV AX,DS:[4 * 13H+2] + MOV WORD PTR CS:REAL13+2,AX +; +; INSERT NEW VECTOR +; + MOV WORD PTR DS:[4 * 13H],OFFSET INT13 + MOV DS:[4 * 13H + 2],CS + + POP DS + ASSUME DS:CODE + + POP AX + +; KEEP TWO HARD DISK BPBS + +CONFIGTWOHARD: + +; KEEP ONE HARD DISK BPB + +CONFIGONEHARD: + +; ADJUST THE NUMBER OF DRIVES TO INCLUDE THE HARD DISKS. + + PUSH AX + + MOV AL,HARDNUM + ADD AL,HNUM + add al, num_mini_dsk ;J.K. 4/7/86 for mini disks installed + ;if not installed, then num_mini_dsk = 0. + MOV DRVMAX,AL + POP AX ;now, static config is done. + + +DYNAMIC_CONFIGURE: + call Get_Para_Offset ;For dynamic allocation, we are + ;going to use offset address that + ;is in paragraph boundary. + push cs + pop es ;es -> code + assume es:code + cld ;clear direction + + cmp [num_mini_dsk], 0 ;Mini disk(s) installed ? + jz CheckATROM ;No. + mov ax, End_Of_BDSM ;set the new ending address + call Get_Para_Offset +CheckATROM: + cmp Model_Byte, 0FCh ;AT ? + jnz CheckCMOSClock + cmp HNUM, 0 ;No hard file? + jz CheckCMOSClock + + mov si, 0F000h + mov es, si ;ES -> BIOS segment + assume es:nothing ; + mov si, offset BIOS_DATE ; + mov di, 0FFF5H ;ROM BIOS string is at F000:FFF5 +Cmpbyte: ;Only patch ROM for bios dated 01/10/84 + cmpsb ; + jnz CheckCMOSClock ; + cmp byte ptr [si-1],0 ; + jnz Cmpbyte ; +SetRomCode: ;Now we have to install ROM fix + ;AX is the address to move. + push cs ; + pop es ;set ES to CODE seg + assume es:code + + mov word ptr ORIG13, ax + mov word ptr ORIG13+2, cs ;set new ROM bios int 13 vector + mov cx, offset ENDATROM + mov si, offset IBM_DISK_IO + sub cx, si ;size of AT ROM FIX module + mov di, ax ;destination + rep movsb ;relocate it + mov ax, di ;new ending address + call Get_Para_Offset ;in AX + +CheckCMOSClock: + push cs + pop es ;set ES to CODE seg + assume es:code + cmp HaveCMOSClock, 1 ;CMOS Clock exists? + jne CheckK09 + mov DaycntToDay, ax ;set the address for MSCLOCK + mov cx, offset EndDaycntToDay + mov si, offset Daycnt_To_Day + sub cx, si ;size of CMOS clock supporting routine + mov di, ax + rep movsb + mov ax, di + call Get_Para_Offset + mov BinToBCD, ax ;set the address for MSCLOCK + mov cx, offset EndCMOSClockSet + mov si, offset Bin_To_BCD + sub cx, si + mov di, ax + rep movsb + mov ax, di + call Get_Para_Offset + +CheckK09: +;SB33025**************************************************************** + push ax ;save ax ;SB ;3.30* + mov ax,4100h ;Q: is it a K09 ;SB ;3.30* + mov bl,0 ; ;SB ;3.30* + int 15h ; ;SB ;3.30* +;SB33025**************************************************************** + pop ax + jc CONFIGDONE + + mov si, offset INT6C + mov cx, offset ENDK09 + sub cx, si ;size of K09 routine + mov di, ax + push di ;save destination + rep movsb + mov ax, di ; + call Get_Para_Offset ;AX = new ending address + pop di + + push ax + push ds + mov fHaveK09, 1 ;remember we have a K09 type + xor ax,ax + mov ds, ax + assume ds:nothing + + mov word ptr ds:[4 * 6Ch], di ;new INT 6Ch handler + mov ds:[4 * 6Ch +2], cs + + pop ds + assume ds:code + pop ax ;restore the ending address + +; SET UP CONFIG STUFF FOR SYSINIT + +CONFIGDONE: ;AX is final ending address of MSBIO. + MOV DX,SYSINITSEG + MOV DS,DX + ASSUME DS:SYSINITSEG + + SUB AX,OFFSET START$ + ADD AX,15 + RCR AX,1 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + MOV FINAL_DOS_LOCATION, AX + POP AX + +GOINIT: + ADD FINAL_DOS_LOCATION,CODE + MESSAGE FTESTINIT,<"FINAL DOS LOCATION IS "> + MNUM FTESTINIT,FINAL_DOS_LOCATION + MESSAGE FTESTINIT, + PUSH CS + POP DS + + ASSUME DS:CODE,ES:NOTHING + + CMP BYTE PTR FHAVE96,0 + JNZ READDOS + CALL PURGE_96TPI ;MJB001 ELIMINATE CALLS TO 96TPI HOOHAH + +READDOS: + MESSAGE FTESTINIT,<"LOAD FAT",CR,LF> + MOV AX,DRVFAT ; GET DRIVE AND FAT ID + CALL SETDRIVE ; GET BDS FOR DRIVE + + CALL GETBP ; ENSURE VALID BPB IS PRESENT + +;AN004; J.K. Don't need this. We are not read the whole FAT at once. +; CALL GETFAT ;READ IN THE FAT SECTOR + + XOR DI,DI + MOV AL,ES:[DI] ;GET FAT ID BYTE + MOV BYTE PTR DRVFAT+1,AL ;SAVE FAT BYTE + MOV AX,DRVFAT + MESSAGE FTESTINIT,<"FATID READ "> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT, + CALL SETDRIVE ;GET CORRECT BDS FOR THIS DRIVE + + mov bx, [di].BYTEPERSEC + mov cs:Md_SectorSize, bx ;AN004;Used by Get_Fat_Sector proc. + MOV BL,[DI].FATSIZ ; GET SIZE OF FAT ON MEDIA + MOV FBIGFAT,BL + MOV CL,[DI].SECPERCLUS ;GET SECTORS/CLUSTER +;J.K.32 bit calculation + MOV AX,[DI].HIDSEC_L ;GET NUMBER OF HIDDEN SECTORS (low) + SUB BIOS$_L,AX ;SUBTRACT HIDDEN SECTORS since we + ;need a logical sector number that will + ;be used by GETCLUS(diskrd procedure) +;SB34INIT005****************************************************************** +;SB We have 32 bit sector number now though. SO the high word also needs +;SB to be adjusted. Update BIOS$_H too. 2 LOCS + + mov ax,[di].HIDSEC_H ;subtract upper 16 bits of sector num + sbb BIOS$_H,ax +;SB34INIT005****************************************************************** + XOR CH,CH ;CX = SECTORS/CLUSTER + +; THE BOOT PROGRAM HAS LEFT THE DIRECTORY AT 0:500 + + PUSH DS + XOR DI,DI + MOV DS,DI ; ES:DI POINTS TO LOAD LOCATION + MOV BX,DS:WORD PTR [53AH] ; CLUS=*53A; + POP DS ; + MESSAGE FTESTINIT,<"LOAD DOS",CR,LF> +; BAS DEBUG +;LOADIT: MOV AX,(((END$ - START$)+15)/16)+SYSIZE + +LOADIT: + MOV AX, OFFSET END$ + SUB AX, OFFSET START$ + ADD AX, 15 + RCR AX, 1 ; DIVIDE BY 16 + SHR AX, 1 + SHR AX, 1 + SHR AX, 1 + ADD AX, SYSIZE + + ADD AX,CODE + + MOV ES,AX ; + CALL GETCLUS ; CLUS = GETCLUS (CLUS); + +ISEOF: + TEST FBIGFAT,FBIG ; IF (FBIGFAT) + JNZ EOFBIG + MESSAGE FTESTINIT, + CMP BX,0FF7H ; RETURN (CLUS > 0FF7H); + JMP SHORT ISEOFX +EOFBIG: + MESSAGE FTESTINIT, + CMP BX,0FFF7H ; ELSE +ISEOFX: + JB LOADIT ; } WHILE (!ISEOF (CLUS)); + + CALL SETDRVPARMS + + MESSAGE FTESTINIT,<"SYSINIT",CR,LF> + ZWAIT + MESSAGE FTESTINIT,<"ON TO SYSINIT...",CR,LF> + JMP SYSINIT + +INIT ENDP + +;**************************** + +Get_Para_Offset proc near +;in: AX - offset value +;out: AX - offset value adjusted for the next paragraph boundary. + add ax, 15 ;make a paragraph + rcr ax, 1 + shr ax, 1 + shr ax, 1 + shr ax, 1 + shl ax, 1 ;now, make it back to offset value + shl ax, 1 + shl ax, 1 + shl ax, 1 + ret +Get_Para_Offset endp + +;AN004; Don't need this procedure. Get_FAT_Sector replace this. +; READ A FAT SECTOR INTO FAT LOCATION +;GETFAT PROC NEAR +; XOR DI,DI ; OFFSET +; MOV DX,1 ; RELATIVE SECTOR (1ST SECTOR OF FAT) +; MOV CX,FATLEN ; READ ENTIRE FAT. +; MOV AX,FATLOC ; +; MOV ES,AX ; LOCATION TO READ +; MOV AX,DRVFAT ; AH FAT ID BYTE, AL DRIVE +; JMP DISKRD +;GETFAT ENDP + +; READ A BOOT RECORD INTO 7C0:BOOTBIAS +;AN015; Read a boot record into Init_BootSeg:BOOTBIAS + +GETBOOT PROC NEAR +;SB33026**************************************************************** + mov AX, cs:Init_BootSeg ; prepare to load ES + mov ES, AX ;SB ; load ES segment register + assume es:nothing + mov BX, BootBias ;SB ; load BX, ES:BX is where sector goes + mov AX, 0201h ;SB ; command to read & num sec. to 1 + xor DH, DH ;SB ; head number zero + mov CX, 0001h ;SB ; cylinder zero and sector one + int 13h ;SB ; call rom bios +;SB33026**************************************************************** + JC ERRET + + CMP WORD PTR ES:[BOOTBIAS+1FEH],0AA55H ; DAVE L**** MAGIC BYTE? + JZ NORM_RET + MESSAGE FTESTHARD,<"SIGNATURE AA55 NOT FOUND",CR,LF> +ERRET: + MESSAGE FTESTHARD,<"ERROR IN GETBOOT",CR,LF> + STC +NORM_RET: + RET +GETBOOT ENDP + +; SETHARD - GENERATE BPB FOR A VARIABLE SIZED HARD FILE. IBM HAS A +; PARTITIONED HARD FILE; WE MUST READ PHYSICAL SECTOR 0 TO DETERMINE WHERE +; OUR OWN LOGICAL SECTORS START. WE ALSO READ IN OUR BOOT SECTOR TO +; DETERMINE VERSION NUMBER + +; INPUTS: DL IS ROM DRIVE NUMBER (80 OR 81) +; DS:DI POINTS TO BDS +; OUTPUTS: CARRY CLEAR -> BPB IS FILLED IN +; CARRY SET -> BPB IS LEFT UNINITIALIZED DUE TO ERROR + +SETHARD PROC NEAR + assume ds:code,es:nothing + PUSH DI + PUSH BX + PUSH DS + MOV BYTE PTR [DI].DRIVELET,BL + MOV BYTE PTR [DI].DRIVENUM,DL + XOR AX,AX + OR AL,FNON_REMOVABLE + OR WORD PTR [DI].FLAGS,AX + MOV BYTE PTR [DI].FORMFACTOR,FFHARDFILE + MOV FBIGFAT,0 ; ASSUME 12 BIT FAT + PUSH DX +;SB33027*************************************************************** + mov AH, 8 ;SB ; set command to get drive parameters + int 13h ;SB ; call rom-bios disk routine +;SB33027*************************************************************** +; DH IS NUMBER OF HEADS-1 +; DL IS NUMBER OF HARD DISKS ATTACHED +; LOW 6 BITS OF CL IS SECTORS/TRACK +; HIGH 2 BITS OF CL WITH CH ARE MAX # OF CYLINDERS + INC DH ; GET NUMBER OF HEADS + MOV BYTE PTR [DI].HDLIM,DH + POP DX + JC SETRET ; CARRY HERE MEANS NO HARD DISK + AND CL,3FH ; EXTRACT NUMBER OF SECTORS/TRACK + MOV BYTE PTR [DI].SECLIM,CL + CALL GETBOOT ; IF (GETBOOT ()) + assume es:nothing + JC SETRET ; RETURN -1; + MOV BX,1C2H+BOOTBIAS ; P = &BOOT[0X1C2]; +SET1: + CMP BYTE PTR ES:[BX],1 ; WHILE (P->PARTITIONTYPE != 1 && + JZ SET2 + + CMP BYTE PTR ES:[BX],4 ; P->PARTITIONTYPE != 4 && + JZ SET2 + +;SB34INIT006****************************************************************** +;SB we have a new partition type 6 now. add code to support this too. + + cmp byte ptr es:[bx],6 ; P->PARTITIONTYPE !=6 + jz set2 +;SB34INIT006****************************************************************** + + ADD BX,16 ; P += SIZEOF PARTITION; + CMP BX,202H+BOOTBIAS ; IF (P == &BOOT[0X202H]) + JNZ SET1 ; RETURN -1;} + +SETRET: + STC ;AN000; Note: Partitiontype 6 means either + JMP RET_HARD ;1).the partition has not been formatted yet, or + ;2).(# of sectors before the partition + + ; # of sectors in this partition) > word boundary + ; i.e., needs 32 bit sector calculation, or + ;3).the partition is not a FAT file system. + +;J.K. Until we get the real logical boot record and get the bpb, +;DRVLIM_H,DRVLIM_L will be used instead of DRVLIM for the convenience of +;the computation. +;At the end of this procedure, if a BPB information is gotten from +;the valid boot record, then we are going to use those BPB information +;without change. +;Otherwise, if (hidden sectors + total sectors) <= a word, then +;we will move DRVLIM_L to DRVLIM and zero out DRVLIM_L entry to make +;it a conventional BPB format. + +SET2: +; PUSH DX ;AN000; + mov cs:ROM_drv_num, dl ;AN000; save the ROM BIOS drive number we are handling now. + + MOV AX,WORD PTR ES:[BX+4] ;Hidden sectors + MOV DX,WORD PTR ES:[BX+6] + + + ;Decrement the sector count by 1 to make it zero based. Exactly 64k + ;sectors should be allowed + ; + SUB AX,1 ; PTM 901 12/12/86 MT + SBB DX,0 ; PTM 901 12/12/86 MT + + ADD AX,WORD PTR ES:[BX+8] ;Sectors in Partition + ADC DX,WORD PTR ES:[BX+10] +; JZ OKDRIVE + jnc Okdrive ;AC000; + MESSAGE FTESTHARD,<"PARTITION INVALID",CR,LF> + OR FBIGFAT,FTOOBIG +OKDRIVE: +; POP DX + MOV AX,WORD PTR ES:[BX+4] + + MOV [DI].HIDSEC_L,AX ; BPB->HIDSECCT = P->PARTITIONBEGIN; + mov ax,word ptr es:[bx+6] ;AN000; + mov [di].HIDSEC_H,ax ;AN000; + + mov dx,word ptr es:[bx+10] ;AN000; # of sectors (High) + MOV AX,WORD PTR ES:[BX+8] ;# of sectors (Low) + mov word ptr [di].DRVLIM_H,dx ;AN000; + MOV WORD PTR [DI].DRVLIM_L,AX ; BPB->MAXSEC = P->PARTITIONLENGTH; + cmp dx,0 ;AN000; + ja OKDrive_Cont ;AN000; + CMP AX,64 ; IF (P->PARTITIONLENGTH < 64) + JB SETRET ; RETURN -1; + +OKDrive_Cont: ;AN000; + ; PUSH DX ;AC000; + mov dx,[di].HIDSEC_H ;AN000; + MOV AX,[DI].HIDSEC_L ; BOOT SECTOR NUMBER - For mini disk,;J.K. +; XOR DX,DX ; this will be logical and equal to ;AC000; + xor bx,bx ;usUally equal to the # of sec/trk. ;J.K. +; MOV BH,DH ;AC000; + MOV BL,BYTE PTR [DI].SECLIM + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div bx ;AN000; + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV BX ;(Sectors)DX;AX / (Seclim)BX =(Track) Temp_H;AX + (Sector)DX + MOV CL,DL ; CL IS SECTOR NUMBER;J.K.Assume sector number < 255. + INC CL ; SECTORS ARE 1 BASED +; CWD ;AC000; + + xor bx,bx ;AN000; + MOV BL,BYTE PTR [DI].HDLIM + push ax ;AN000; + xor dx,dx ;AN000; + mov ax, cs:[Temp_H] ;AN000; + div bx ;AN000; + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV BX ; DL IS HEAD, AX IS CYLINDER + cmp cs:[Temp_H],0 ;AN000; + ja SetRet_brdg ;AN000; Exceeds the limit of Int 13h + cmp ax, 1024 ;AN000; + ja SetRet_brdg ;AN000; Exceeds the limit of Int 13h + +; DL IS HEAD. +; AX IS CYLINDER +; CL IS SECTOR NUMBER (assume less than 2**6 = 64 for INT 13h) + +;*** For Mini Disks *** J.K. 4/7/86 + cmp word ptr [di].ISMINI, 1 ;check for mini disk -J.K. 4/7/86 + jnz OKnotMini ;not mini disk. -J.K. 4/7/86 + add ax, [di].HIDDEN_TRKS ;set the physical track number -J.K. 4/7/86 +OKnotMini: ;J.K. 4/7/86 +;*** End of added logic for mini disk + ROR AH,1 ; MOVE HIGH TWO BITS OF CYL TO HIGH + ROR AH,1 ; TWO BITS OF UPPER BYTE + AND AH,0C0H ; TURN OFF REMAINDER OF BITS + OR CL,AH ; MOVE TWO BITS TO CORRECT SPOT + MOV CH,AL ; CH IS CYLINDER + +; CL IS SECTOR + 2 HIGH BITS OF CYLINDER +; CH IS LOW 8 BITS OF CYLINDER +; DL IS HEAD +; ROM_drv_num IS DRIVE + +; POP AX ;AC000; AL IS DRIVE + MOV DH,DL ; DH IS HEAD +; MOV DL,AL ;AC000; DL IS DRIVE + mov dl, cs:ROM_drv_num ;AN000; Set the drive number + +; CL IS SECTOR + 2 HIGH BITS OF CYLINDER +; CH IS LOW 8 BITS OF CYLINDER +; DH IS HEAD +; DL IS DRIVE +;J.K. For convenience, we are going to read the logical boot sector +;into cs:DiskSector area. + +;SB34INIT009************************************************************* +;SB Read in boot sector using BIOS disk interrupt. The buffer where it +;SB is to be read in is cs:Disksector. +;SB 5 LOCS + + push cs + pop es + mov bx,offset DiskSector + mov ax,0201h ; read, one sector + int 13h + +;SB34INIT009************************************************************* + +; cs:Disksec contains THE BOOT SECTOR. IN THEORY, (HA HA) THE BPB IN THIS THING +; IS CORRECT. WE CAN, THEREFORE, SUCK OUT ALL THE RELEVANT STATISTICS ON THE +; MEDIA IF WE RECOGNIZE THE VERSION NUMBER. + mov bx, offset DiskSector ;AN000; +; look for a signature for msdos... + cmp word ptr cs:[bx+3], "S" shl 8 + "M" + jnz notmssig + cmp word ptr cs:[bx+5], "O" shl 8 + "D" + jnz notmssig + cmp byte ptr cs:[bx+7], "S" + je sigfound +; ...or perhaps pcdos... +notmssig: + CMP WORD PTR cs:[bx+3], "B" SHL 8 + "I" + jnz notibmsig + CMP WORD PTR cs:[bx+5], " " SHL 8 + "M" + je sigfound +;---------------------------------------------------------------------- +; check for Microsoft OS/2 signature also. 7/29/88. HKN +notibmsig: + CMP WORD PTR cs:[bx+3], "S" SHL 8 + "O" + JNZ UNKNOWNJ + CMP WORD PTR cs:[bx+5], " " SHL 8 + "2" + JNZ UNKNOWNJ +;----------------------------------------------------------------------- + +sigfound: ; signature was found, now check version + CMP WORD PTR cs:[bx+8], "." SHL 8 + "2" + JNZ TRY5 + CMP BYTE PTR cs:[bx+10], "0" + JNZ TRY5 + MESSAGE FTESTHARD,<"VERSION 2.0 MEDIA",CR,LF> + JMP SHORT COPYBPB + +SetRet_Brdg: + jmp SETRET + +UNKNOWNJ: + JMP UNKNOWN ;Unformatted or illegal media. +UNKNOWN3_0_J: ;AN012;Legally formatted media, + jmp Unknown3_0 ;AN012; although, content might be bad. + +TRY5: + call Cover_Fdisk_Bug ;AN010; + CMP WORD PTR cs:[bx+8],"." SHL 8 + "3" + jb Unknown3_0_J ;AN012; Must be 2.1 boot record. Do not trust it, but still legal. + JNZ COPYBPB ;AN007; Honor OS2 boot record, or DOS 4.0 version + cmp byte ptr cs:[bx+10],"1" ;do not trust 3.0 boot record. But still legal J.K. 4/15/86 + jb UnKnown3_0_J ;AN012; if version >= 3.1, then O.K. + Message ftestHard,<"VERSION 3.1 OR ABOVE MEDIA",CR,LF> + +COPYBPB: +; WE HAVE A VALID BOOT SECTOR. USE THE BPB IN IT TO BUILD THE +; BPB IN BIOS. IT IS ASSUMED THAT ONLY SECPERCLUS, CDIR, AND +; CSECFAT NEED TO BE SET (ALL OTHER VALUES IN ALREADY). FBIGFAT +; IS ALSO SET. + +;If it is non FAT based system, then just copy the BPB from the BOOT sector +;into the BPB in BDS table, and also set the Boot serial number, Volume id, +;and System ID according to the Boot record. +;For the non_FAT system, don't need to set the other value. So just +;do GOODRET.- J.K. + + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN000; + jne COPYBPB_FAT ;AN000; Conventional Fat system + cmp cs:[NumberOfFats], 0 ;AN000; If (# of FAT <> 0) then + jne COPYBPB_FAT ;AN000; a Fat system. +;J.K. Non Fat based media. + push di ;AN000; Sav Reg. + push ds ;AN000; + + push ds ;AN000; + pop es ;AN000; now es:di -> bds + push cs ;AN000; + pop ds ;AN000; ds = cs + + mov si, offset Bpb_In_Sector ;AN000; ds:si -> BPB in Boot + add di, BYTEPERSEC ;AN000; es:di -> BPB in BDS + mov cx, size BPB_TYPE ;AN000; + rep movsb ;AN000; + + pop ds ;AN000; Restore Reg. + pop di ;AN000; + call Mov_Media_IDs ;AN000; Set Volume id, SystemId, Serial. + jmp GoodRet + +COPYBPB_FAT: ;AN000; Fat system + xor dx,dx ;AN000; + mov si, offset Bpb_In_Sector ;AN000; cs:bx -> bpb in boot + mov ax, cs:[si.SECNUM] ;AN000; total sectors + cmp ax,0 ;AN000; double word sector number? + jnz Fat_Big_Small ;AN000; No. Conventional BPB. + mov ax, word ptr cs:[si.SECNUM_L] ;AN000; Use double word + mov dx, word ptr es:[si.SECNUM_H] ;AN000; + +Fat_Big_Small: ;AN000; Determine Fat entry size. +;At this moment DX;AX = Total sector number +; DEC AX ; SUBTRACT # RESERVED (ALWAYS 1) + sub ax,1 ;AN000; Subtrack # reserved (always 1) + sbb dx,0 ;AN000; + mov bx, cs:[si.FATSIZE] ;AN000; BX = Sectors/Fat + mov [di.CSECFAT],bx ;AN000; Set in BDS BPB + shl bx,1 ;AN000; Always 2 FATS + sub ax,bx ;AN000; Sub # fat sectors + sbb dx,0 ;AN000; + mov bx, cs:[si.DIRNUM] ;AN000; # root entries + mov [di.cDIR],bx ;AN000; Set in BDS BPB + + MOV CL,4 + shr bx,cl ;AN000; Div by 16 ents/sector + sub ax,bx ;AN000; sub # dir sectors + sbb dx,0 ;AN000; + ;AN000; DX;AX now contains the # of data sectors + xor cx,cx ;AN000; + MOV CL, cs:[si.SECALL] ; SECTORS PER CLUSTER + MOV [DI.SECPERCLUS],CL ; SET IN BIOS BPB +; XOR DX,DX +; MOV CH,DH + MNUM FTESTHARD,CX + MESSAGE FTESTHARD,<" SECPERCLUS",CR,LF> +;J.K. 3/16/87 P54 Returning back to old logic for compatibility reason. +;So, use the old logic again that once had been commented out!!!!!!!!!!!! +;Old logic to determine FAT Entry Size J.K. 12/3/86 + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; cx = sectors per cluster + mov cs:[Temp_H],ax ;AN000; + pop ax ;AN000; + DIV CX ;AN000; [Temp_H];AX NOW CONTAINS THE # CLUSTERS. + cmp cs:[Temp_H],0 ;AN000; + ja TooBig_Ret ;AN000; Too big cluster number + CMP AX,4096-10 ; IS THIS 16-BIT FAT? + JB CopyMediaID ; NO, small FAT + OR FBIGFAT,FBIG ; 16 BIT FAT +;End of Old logic +CopyMediaID: + call Mov_Media_IDs ;AN000; Copy Filesys_ID, Volume label, + ;and Volume serial to BDS table, if extended + ;boot record. + JMP Massage_bpb ;AN000; Now final check for BPB info. and return. + +TooBig_Ret: ;AN000; + OR cs:FBIGFAT,FTOOBIG + JMP GOODRET ;AN000; Still drive letter is assigned + ;AN000; But useless. To big for + ;AN000; current PC DOS FAT file system +UNKNOWN: +; or [di].FLAGS, UNFORMATTED_MEDIA ;AN005; Set unformatted media flag. + ; preceeding line commented out 10/88 by MRW-- The boot signature + ; may not be recognizable, but we should TRY and read it anyway. + ;AN006; + ;AN008; For the time being, allow it. + ;AN009; Now implemented again +Unknown3_0: ;AN012;Skip setting UNFORMATTED_MEDIA bit + MESSAGE FTESTHARD,<"UNKNOWN HARD MEDIA. ASSUMING 3.0.",CR,LF> + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + MOV SI,OFFSET DISKTABLE2 +SCAN: +; CMP AX,[SI] +; JBE GOTPARM +; ADD SI,4 * 2 + + cmp dx, word ptr cs:[si] ;AN000; + jb GotParm ;AN000; + ja Scan_Next ;AN000; + cmp ax, word ptr cs:[si+2] ;AN000; + jbe GotParm ;AN000; +Scan_Next: ;AN000; + add si, 5 * 2 ;AN000; + JMP SCAN ;AN000; Covers upto 512 MB media +GOTPARM: +; MOV CL,BYTE PTR [SI+6] + mov cl,byte ptr [si+8] ;AN000; Fat size for FBIGFAT flag + OR FBIGFAT,CL +; MOV CX,[SI+2] +; MOV DX,[SI+4] + mov cx, word ptr cs:[SI+4] ;AN000; + mov dx, word ptr cs:[SI+6] ;AN000; + +; DX = NUMBER OF DIR ENTRIES, +; CH = NUMBER OF SECTORS PER CLUSTER +; CL = LOG BASE 2 OF CH + +; NOW CALCULATE SIZE OF FAT TABLE + + MNUM FTESTHARD,AX + MESSAGE FTESTHARD,<" SECTORS "> + MNUM FTESTHARD,DX + MESSAGE FTESTHARD,<" DIRECTORY ENTRIES "> + MNUM FTESTHARD,CX + MESSAGE FTESTHARD,<" SECPERCLUS|CLUSSHIFT"> + + MOV WORD PTR CDIR[DI],DX ;SAVE NUMBER OF DIR ENTRIES + +;Now, CX = SecPerClus|Clusshift +; [DI.CDIR] = number of directory entries. + + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + MOV BYTE PTR SECPERCLUS[DI],CH ;SAVE SECTORS PER CLUSTER + TEST FBIGFAT,FBIG ; IF (FBIGFAT) + JNZ DOBIG ; GOTO DOBIG; + MESSAGE FTESTHARD,<" SMALL FAT",CR,LF> +;J.K. We don't need to change "small fat" logic since it is gauranteed +;that double word total sector will not use 12 bit fat (unless +;it's sectors/cluster >= 16 which will never be in this case.) +;So in this case we assume DX = 0 !!!. + + XOR BX,BX + MOV BL,CH + DEC BX + ADD BX,AX ;AN000; DX=0 + SHR BX,CL ; BX = 1+(BPB->MAXSEC+SECPERCLUS-1)/ + INC BX ; SECPERCLUS + AND BL,11111110B ; BX &= ~1; (=NUMBER OF CLUSTERS) + MOV SI,BX + SHR BX,1 + ADD BX,SI + ADD BX,511 ; BX += 511 + BX/2 + SHR BH,1 ; BH >>= 1; (=BX/512) + MOV BYTE PTR [DI].CSECFAT,BH ;SAVE NUMBER OF FAT SECTORS + JMP SHORT Massage_BPB +DOBIG: +;J.K. For BIGFAT we do need to extend this logic to 32 bit sector calculation. + MESSAGE FTESTHARD,<" BIG FAT",CR,LF> + MOV CL,4 ; 16 (2^4) DIRECTORY ENTRIES PER SECTOR + push dx ;AN000; Save total sectors (high) + mov dx, CDIR[DI] ;AN000; + SHR DX,CL ; CSECDIR = CDIR / 16; + SUB AX,DX ; DX;AX -= CSECDIR; DX;AX -= CSECRESERVED; + pop dx ;AN000; + SBB dx,0 ;AN000; +; DEC AX ; AX = T - R - D + SUB ax,1 ;AN000; DX;AX = T - R - D + SBB dx,0 ;AN000; + MOV BL,2 + MOV BH,SECPERCLUS[DI] ; BX = 256 * SECPERCLUS + 2 +; XOR DX,DX +;J.K. I don't understand why to add BX here!!! + ADD AX,BX ; AX = T-R-D+256*SPC+2 + ADC DX,0 + SUB AX,1 ; AX = T-R-D+256*SPC+1 + SBB DX,0 +;J.K. Assuming DX in the table will never be bigger than BX. + DIV BX ; CSECFAT = CEIL((TOTAL-DIR-RES)/ + ; (256*SECPERCLUS+2)); + MOV WORD PTR [DI].CSECFAT,AX ; NUMBER OF FAT SECTORS +;J.K. Now, set the default FileSys_ID, Volume label, Serial number + MOV BL,FBIGFAT + MOV [DI].FATSIZ,BL ; SET SIZE OF FAT ON MEDIA + call Clear_IDs ;AN000; + +;J.K. At this point, in BPB of BDS table, DRVLIM_H,DRVLIM_L which were +;set according to the partition information. We are going to +;see if (hidden sectors + total sectors) > a word. If it is true, +;then no change. Otherwise, DRVLIM_L will be moved to DRVLIM +;and DRVLIM_L will be set to 0. +;We don't do this for the bpb information from the boot record. We +;are not going to change the BPB information from the boot record. +Massage_bpb: ;AN000; + mov dx, [di.DRVLIM_H] ;AN000; + mov ax, [di.DRVLIM_L] ;AN000; + cmp dx,0 ;AN000; Double word total sector? + ja GOODRET ;AN000; don't have to change it. + cmp [di.HIDSEC_H], 0 ;AN000; + ja GOODRET ;AN000; don't have to change it. + add ax, [di.HIDSEC_L] ;AN000; + jc GOODRET ;AN000; bigger than a word boundary + mov ax, [di.DRVLIM_L] ;AN000; + mov [di.DRVLIM], ax ;AN000; + mov [di.DRVLIM_L], 0 ;AN000; +GOODRET: + cmp [di].DRVLIM_H, 0 ;AN014; Big media? + jbe Not_BigMedia ;AN014; No. + push es ;AN014; + push ax ;AN014; + mov ax, SYSINITSEG ;AN014; + mov es, ax ;AN014; + mov es:Big_Media_Flag, 1 ;AN014; Set the flag in SYSINITSEG. + pop ax ;AN014; + pop es ;AN014; +Not_BigMedia: ;AN014; + MOV BL,FBIGFAT + MOV [DI].FATSIZ,BL ; SET SIZE OF FAT ON MEDIA + CLC +RET_HARD: + POP DS + POP BX + POP DI + RET + +SETHARD ENDP + +Cover_FDISK_Bug proc ;AN010; +;FDISK of PC DOS 3.3 and below, OS2 1.0 has a bug. The maximum number of +;sector that can be handled by PC DOS 3.3 ibmbio should be 0FFFFh. +;Instead, sometimes FDISK use 10000h to calculate the maximum number. +;So, we are going to check that if SECNUM + Hidden sector = 10000h +;then subtrack 1 from SECNUM. + push ax ;AN010; + push dx ;AN010; + push si ;AN010; + cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN010; + je CFB_Retit ;AN010;if extended BPB, then >= PC DOS 4.00 + cmp word ptr cs:[bx+7], "0" shl 8 + "1" ;AN011; OS2 1.0 ? = IBM 10.0 + jne CFB_Chk_SECNUM ;AN010; + cmp byte ptr cs:[bx+10], "0" ;AN010; + jne CFB_Retit ;AN010; +CFB_Chk_SECNUM: ;AN010; + mov si, offset BPB_In_Sector ;AN010; + cmp cs:[si.SECNUM], 0 ;AN010;Just to make sure. + je CFB_Retit ;AN010; + mov ax, cs:[si.SECNUM] ;AN010; + add ax, cs:[si.HIDDEN_L] ;AN010; + jnc CFB_Retit ;AN010; + xor ax, ax ;AN010;if carry set and AX=0? + jnz CFB_Retit ;AN010; + dec cs:[si.SECNUM] ;AN010; then decrease SECNUM by 1. + dec [di].DRVLIM_L ;AN010; +CFB_Retit: ;AN010; + pop si ;AN010; + pop dx ;AN010; + pop ax ;AN010; + ret ;AN010; +Cover_FDISK_Bug endp ;AN010; + + +; SETDRVPARMS SETS UP THE RECOMMENDED BPB IN EACH BDS IN THE SYSTEM BASED ON +; THE FORM FACTOR. IT IS ASSUMED THAT THE BPBS FOR THE VARIOUS FORM FACTORS +; ARE PRESENT IN THE BPBTABLE. FOR HARD FILES, THE RECOMMENDED BPB IS THE SAME +; AS THE BPB ON THE DRIVE. + +; NO ATTEMPT IS MADE TO PRESERVE REGISTERS SINCE WE ARE GOING TO JUMP TO +; SYSINIT STRAIGHT AFTER THIS ROUTINE. + +SETDRVPARMS PROC NEAR + MESSAGE FTESTINIT,<"SETTING DRIVE PARAMETERS",CR,LF> + XOR BX,BX + LES DI,DWORD PTR CS:[START_BDS] ; GET FIRST BDS IN LIST +NEXT_BDS: + CMP DI,-1 + JNZ DO_SETP +DONE_SETPARMS: + RET + +DO_SETP: + PUSH ES + PUSH DI ; PRESERVE POINTER TO BDS + MOV BL,ES:[DI].FORMFACTOR + CMP BL,FFHARDFILE + JNZ NOTHARDFF + + xor dx,dx ;AN000; + MOV AX,ES:[DI].DRVLIM + cmp ax,0 ;AN000; + jne GET_cCYL ;AN000; + mov dx,es:[di].DRVLIM_H ;AN000; Use Double word sector number + MOV AX,ES:[DI].DRVLIM_L ;AN000; +GET_cCYL: + push dx ;AN000; + PUSH AX + MOV AX,WORD PTR ES:[DI].HDLIM + MUL WORD PTR ES:[DI].SECLIM ;Assume Sectorsp per cyl. < 64K. + MOV CX,AX ; CX HAS # SECTORS PER CYLINDER + POP AX ; + pop dx ;AN000; Restore drvlim. + push ax ;AN000; + mov ax,dx ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; + mov cs:[Temp_H],ax ;AN000; AX be 0 here. + pop ax ;AN000; + DIV CX ; DIV #SEC BY SEC/CYL TO GET # CYL. + OR DX,DX + JZ NO_CYL_RND ; CAME OUT EVEN + INC AX ; ROUND UP +NO_CYL_RND: + MOV ES:[DI].CCYLN,AX + MESSAGE FTESTINIT,<"CCYLN "> + MNUM FTESTINIT,AX + MESSAGE FTESTINIT, + PUSH ES + POP DS + LEA SI,[DI].BYTEPERSEC ; DS:SI -> BPB FOR HARD FILE + JMP SHORT SET_RECBPB + +NOTHARDFF: +;J.K. We don't use the extended BPB for a floppy. + PUSH CS + POP DS + assume ds:code +;J.K.6/24/87 + +;SB34INIT007****************************************************************** +;SB If Fake floppy drive variable is set then we don't have to handle this +;SB BDS. We can just go and deal with the next BDS at label Go_To_Next_BDS. + + cmp cs:FakeFloppyDrv,1 + jz Go_To_Next_BDS +;SB34INIT007****************************************************************** + + CMP BL,FFOTHER ; SPECIAL CASE "OTHER" TYPE OF MEDIUM + JNZ NOT_PROCESS_OTHER +PROCESS_OTHER: + XOR DX,DX + MOV AX,[DI].CCYLN + MOV BX,[DI].RHDLIM + MUL BX + MOV BX,[DI].RSECLIM + MUL BX + MOV [DI].RDRVLIM,AX ; HAVE THE TOTAL NUMBER OF SECTORS + DEC AX + +;J.K. Old logic was... +; MOV BX,515 +; DIV BX +; OR DX,DX +; JZ NO_ROUND_UP +; INC AX ; ROUND UP NUMBER OF FAT SECTORS + +;J.K. New logic to get the sectors/fat area. + ;Fat entry is assumed to be 1.5 bytes!!! + mov bx, 3 + mul bx + mov bx,2 + div bx + xor dx, dx + mov bx, 512 + div bx + inc ax + +NO_ROUND_UP: + MOV [DI].RCSECFAT,AX + JMP SHORT GO_TO_NEXT_BDS +NOT_PROCESS_OTHER: + SHL BX,1 ; BX IS WORD INDEX INTO TABLE OF BPBS + MOV SI,OFFSET BPBTABLE + MOV SI,WORD PTR [SI+BX] ; GET ADDRESS OF BPB +SET_RECBPB: + LEA DI,[DI].RBYTEPERSEC ; ES:DI -> RECBPB + MOV CX,BPBSIZ + REP MOVSB ; MOVE BPBSIZ BYTES +GO_TO_NEXT_BDS: + POP DI + POP ES ; RESTORE POINTER TO BDS + MOV BX,WORD PTR ES:[DI].LINK+2 + MOV DI,WORD PTR ES:[DI].LINK + MOV ES,BX + JMP NEXT_BDS + +SETDRVPARMS ENDP + +; READ CLUSTER SPECIFIED IN BX +; CX = SECTORS PER CLUSTER +; DI = LOAD LOCATION +; +GETCLUS PROC NEAR + PUSH CX + PUSH DI + MOV DOSCNT,CX ;SAVE NUMBER OF SECTORS TO READ + MOV AX,BX + DEC AX + DEC AX + MUL CX ;CONVERT TO LOGICAL SECTOR +;J.K. Now DX;AX = matching logical sector number starting from the data sector. +;SB34INIT008************************************************************* +;SB Add the BIOS start sector to the sector number in DX:AX. The BIOS +;SB start sector number is in BIOS$_H:BIOS$_L + + add ax,cs:BIOS$_L + adc dx,cs:BIOS$_H +;SB34INIT008************************************************************* +;J.K. Now DX;AX = first logical sector to read +; MOV DX,AX ;DX = FIRST SECTOR TO READ +GETCL1: + MNUM FTESTINIT + MESSAGE FTESTINIT,<" => "> +; ;SI = BX, BX = NEXT ALLOCATION UNIT + +; GET THE FAT ENTRY AT BX + +UNPACK: + PUSH DS + push ax ;AN004;Save First logical sector (Low) + PUSH BX + MOV SI,FATLOC + MOV DS,SI ;DS -> FATLOC segment + mov si, bx ;AN004; + TEST cs:FBIGFAT,FBIG ;16 bit fat? + JNZ UNPACK16 +; MOV SI,BX + SHR SI,1 ;12 bit fat. si=si/2 + add si, bx ;AN004; si = clus + clus/2 + call Get_Fat_Sector ;AN004; offset of FAT entry in BX + mov ax, [bx] ;AN004;Save it into AX + jne Even_Odd ;AN004;IF not a splitted FAT, check even-odd. + mov al, byte ptr [bx] ;AN004;Splitted FAT. + mov byte ptr cs:Temp_Cluster, al ;AN004; + inc si ;AN004; + call Get_Fat_Sector ;AN004; + mov al, byte ptr ds:[0] ;AN004; + mov byte ptr cs:Temp_Cluster+1, al ;AN004; + mov ax, cs:Temp_Cluster ;AN004; +Even_Odd: ;AN004; + pop bx ;AN004;Restore old Fat entry value + push bx ;AN004;Save it right away. + shr bx, 1 ;AN004;Was it even or odd? + jnc HAVCLUS ;It was even. + SHR ax,1 ;Odd. Massage FAT value and keep + SHR ax,1 ;the highest 12 bits. + SHR ax,1 + SHR ax,1 +HAVCLUS: + mov bx, ax ;AN004; Now BX = New FAT entry. + AND BX,0FFFH ;AN004; keep low 12 bits. + JMP SHORT UNPACKX +UNPACK16: ;16 bit fat. + shl si, 1 ;Get the offset value. + call Get_Fat_Sector ;AN004; + mov bx, [bx] ;AN004; Now BX = New FAT entry. +UNPACKX: + POP SI ;Retore Old BX value into SI + pop ax ;AN004;Restore logical sector (low) + POP DS + + MNUM FTESTINIT + MESSAGE FTESTINIT,<" "> + SUB SI,BX + CMP SI,-1 ;ONE APART? + JNZ GETCL2 + ADD DOSCNT,CX + JMP GETCL1 + +GETCL2: + PUSH BX + push dx ;AN000; Sector to read (High) + push ax ;AN000; Sector to read (low) + MOV AX,DRVFAT ;GET DRIVE AND FAT SPEC + MOV CX,DOSCNT + pop dx ;AN000; Sector to read for DISKRD (Low) + pop cs:[Start_Sec_H] ;AN000; Sector to read for DISKRD (High) + CALL DISKRD ;READ THE CLUSTERS + + POP BX + POP DI + MOV AX,DOSCNT ;GET NUMBER OF SECTORS READ + XCHG AH,AL ;MULTIPLY BY 256 + SHL AX,1 ;TIMES 2 EQUAL 512 + ADD DI,AX ;UPDATE LOAD LOCATION + POP CX ;RESTORE SECTORS/CLUSTER + RET + +GETCLUS ENDP ; RETURN; + +Get_FAT_Sector proc near ;AN004; +;Function: FInd and read the corresponding FAT sector into DS:0 +;In). SI - offset value (starting from FAT entry 0) of FAT entry to find. +; DS - FATLOC segment +; cs:DRVFAT - Logical drive number, FAT id +; cs:Md_SectorSize +; cs:Last_Fat_SecNum - Last FAT sector number read in. +;Out). Corresponding FAT sector read in. +; BX = offset value from FATLOG segment. +; Other registera saved. +; Zero flag set if the FAT entry is splitted, i.e., wehn 12 bit FAT entry +; starts at the last byte of the FAT sector. In this case, the caller +; should save this byte, and read the next FAT sector to get the rest +; of the FAT entry value. (This will only happen with the 12 bit fat.) + + push ax ;AN004; + push cx ;AN004; + push dx ;AN004; + push di ;AN004; + push si ;AN004; + push es ;AN004; + push ds ;AN004; + xor dx, dx ;AN004; + mov ax, si ;AN004; + mov cx, cs:Md_SectorSize ;AN004; =512 bytes + div cx ;AN004; AX=sector number, dx = offset + inc ax ;AN004; Make AX to relative logical sector number + cmp ax, cs:Last_Fat_SecNum ;AN004; by adding Reserved sector number. + je GFS_Split_Chk ;AN004; Don't need to read it again. + mov cs:Last_Fat_SecNum, ax ;AN004; Update Last_Fat_SecNum + push dx ;AN004; save offset value. + mov cs:[Start_Sec_H],0 ;AN004; Prepare to read the FAT sector + mov dx, ax ;AN004; Start_Sec_H is always 0 for FAT sector. + mov cx, 1 ;AN004; 1 sector to read + mov ax, cs:DrvFAT ;AN004; + push ds ;AN004; + pop es ;AN004; + xor di, di ;AN004; es:di -> FatLoc segment:0 + call DiskRD ;AN004; cross your finger. + pop dx ;AN004; restore offset value. + mov cx, cs:Md_SectorSize ;AN004; +GFS_Split_Chk: ;AN004; + dec cx ;AN004;if offset points to the + cmp dx, cx ;AN004;last byte of this sector, then splitted entry. + mov bx, dx ;AN004;Set BX to DX + pop ds ;AN004; + pop es ;AN004; + pop si ;AN004; + pop di ;AN004; + pop dx ;AN004; + pop cx ;AN004; + pop ax ;AN004; + ret ;AN004; +Get_FAT_Sector endp ;AN004; + +; +; SI POINTS TO DEVICE HEADER +; J.K. 4/22/86 - print_init, aux_init is modified to eliminate the self-modifying +; J.K. code. + +PRINT_INIT: + call Get_device_number +;SB33028***************************************************************** + mov ah,1 ;initalize printer port ;SB;3.30 + int 17h ;call ROM-Bios routine ;SB;3.30 +;SB33028***************************************************************** + ret + +AUX_INIT: + call Get_device_number +;SB33028***************************************************************** + mov al,RSINIT ;2400,N,1,8 (MSEQU.INC) ;SB ;3.30* + mov ah,0 ;initalize AUX port ;SB ;3.30* + int 14h ;call ROM-Bios routine ;SB ;3.30* +;SB33028***************************************************************** + ret + +GET_DEVICE_NUMBER: +;SI -> device header + MOV AL,CS:[SI+13] ;GET DEVICE NUMBER FROM THE NAME + SUB AL,"1" + CBW + MOV DX,AX + RET + +; +; PURGE_96TPI NOP'S CALLS TO 96TPI SUPPORT. +; +PURGE_96TPI PROC NEAR ;MJB001 + PUSH DS + PUSH ES + + PUSH CS ;MJB001 + POP ES ;MJB001 + PUSH CS ;MJB001 + POP DS ;MJB001 + ASSUME DS:CODE,ES:CODE + + MOV SI,OFFSET PATCHTABLE +PATCHLOOP: + LODSW + MOV CX,AX + JCXZ PATCHDONE + LODSW + MOV DI,AX + MOV AL,90H + REP STOSB + JMP PATCHLOOP + +PATCHDONE: +;**************NOT NEEDED ANY MORE*********************** +; MOV DI,OFFSET FORMAT_PATCH ; ARR 2.42 +; MOV AL,CS:INST_FAR_RET +; STOSB +;******************************************************** + MOV DI,OFFSET TABLE_PATCH ; ARR 2.42 + MOV AX,OFFSET EXIT + STOSW + STOSW + + POP ES + POP DS + RET ;MJB001 +PURGE_96TPI ENDP + +;Mini disk initialization routine. Called right after DoHard - J.K. 4/7/86 +; DoMini ********************************************************************** +; **CS=DS=ES=code +; **DoMini will search for every extended partition in the system, and +; initialize it. +; **BDSM stands for BDS table for Mini disk and located right after the label +; End96Tpi. End_Of_BDSM will have the offset value of the ending +; address of BDSM table. +; **BDSM is the same as usual BDS structure except that TIM_LO, TIM_HI entries +; are overlapped and used to identify mini disk and the number of Hidden_trks. +; Right now, they are called as IsMini, Hidden_Trks respectively. +; **DoMini will use the same routine in SETHARD routine after label SET1 to +; save coding. +; **DRVMAX determined in DoHard routine will be used for the next +; available logical mini disk drive number. +; +; Input: DRVMAX, DSKDRVS +; +; Output: MiniDisk installed. BDSM table established and installed to BDS. +; num_mini_dsk - the number of mini disks installed in the system. +; End_Of_BDSM - ending offset address of BDSM. +; +; +; Called modules: +; GetBoot, WRMSG, int 13h (AH=8, Rom) +; FIND_MINI_PARTITION (new), Install_BDSM (new), +; SetMini (new, it will use SET1 routine) +; Variables used: End_Of_BDSM, numh, mininum, num_mini_dsk, +; Rom_Minidsk_num, Mini_HDLIM, Mini_SECLIM +; BDSMs, BDSM_type (struc), Start_BDS +;****************************************************************************** +; + +DoMini: + push cs + pop es + push cs + pop ds + assume ds:code,es:code + Message fTestHard,<"Start of DoMini...",cr,lf> + + push ax ;Do I need to do this? + + mov di, offset BDSMs ;from now on, DI points to BDSM +;SB33028******************************************************************** + mov dl, 80h ;look at first hard drive ;SB ;3.30* + mov ah, 8h ;get drive parameters ;SB ;3.30* + int 13h ;call ROM-Bios ;SB ;3.30* +;SB33028******************************************************************** + cmp dl, 0 + jz DoMiniRet ;no hard file? Then exit. + mov numh, dl ;save the number of hard files. + xor ax,ax + mov al, drvmax + mov mininum, al ;this will be the logical drive letter + ;for mini disk to start with. + + shl ax, 1 ;ax=number of devices. make it to word boundary + push bx + mov bx, offset DSKDRVS + add bx, ax + mov Mini_BPB_ptr, BX ;Mini_BPB_ptr points to the first available + ;spot in DskDrvs for Mini disk which + ;points to BPB area of BDSM. + pop bx + + mov Rom_Minidsk_num, 80h +DoMiniBegin: + inc dh ;Get # of heads (convert it to 1 based) + xor ax, ax + mov al, dh + mov Mini_HDLIM, ax ;save it. + xor ax, ax + and cl, 3fh ;Get # of sectors/track + mov al, cl + mov Mini_SECLIM, ax ;and save it. + + mov dl, Rom_Minidsk_num ;drive number
+ call GETBOOT ;read master boot record into 7c0:BootBias + assume es:nothing + jc DoMiniNext + call FIND_MINI_PARTITION +DoMiniNext: + dec numh + jz DoMiniRet + inc Rom_MiniDsk_Num ;Next hard file +;SB33028******************************************************************** + mov dl, Rom_MiniDsk_Num ;look at next hard drive ;SB ;3.30* + mov ah, 8h ;get drive parameters ;SB ;3.30* + int 13h ;call ROM-Bios ;SB ;3.30* +;SB33028******************************************************************** + jmp DoMiniBegin + +DoMiniRet: + pop ax + ret + + +;Find_Mini_Partition tries to find every Extended partition on a disk. +;At entry: DI -> BDSM entry +; ES:BX -> 07c0:BootBias - Master Boot Record +; Rom_MiniDsk_Num - ROM drive number +; MiniNum - Logical drive number +; Mini_HDLIM, Mini_SECLIM +; +;Called routine: SETMINI which uses SET1 (in SETHARD routine) +;Variables & equates used from original BIOS - flags, fNon_Removable, fBigfat +; +; +FIND_MINI_PARTITION: + + add bx, 1C2h ;BX -> system id. + +FmpNext: + cmp byte ptr ES:[BX], 5 ; 5 = extended partition ID. + jz FmpGot + add bx, 16 ; for next entry + cmp bx, 202h+BootBias + jnz FmpNext + jmp FmpRet ;not found extended partition + +FmpGot: ;found my partition. + Message ftestHard,<"Found my partition...",cr,lf> + xor ax,ax + or al, fNon_Removable + or word ptr [DI].Flags, ax + mov byte ptr [DI].FormFactor, ffHardFile + mov fBigFat, 0 ;assume 12 bit Fat. + mov ax, Mini_HDLIM + mov [DI].HDLIM, ax + mov ax, Mini_SECLIM + mov [DI].SECLIM, ax + mov al, Rom_MiniDsk_Num + mov [DI].DRIVENUM, al ;set physical number + mov al, Mininum + mov [DI].DRIVELET, al ;set logical number + + cmp word ptr es:[bx+10], 0 ;AN000; + ja FmpGot_Cont ;AN000; + cmp word ptr ES:[BX+8], 64 ;**With current BPB, only lower word + ; is meaningful. + jb FmpRet ;should be bigger than 64 sectors at least +FmpGot_Cont: ;AN000; + sub bx, 4 ;let BX point to the start of the entry + mov dh, byte ptr ES:[BX+2] + and dh, 11000000b ;get higher bits of cyl + rol dh, 1 + rol dh, 1 + mov dl, byte ptr ES:[BX+3] ;cyl byte + mov [DI].HIDDEN_TRKS, dx ;set hidden trks +;** Now, read the volume boot record into BootBias. +;SB33029****************************************************************** + mov cx,ES:[BX+2] ;cylinder,cylinder/sector ;SB ;3.30* + mov dh,ES:[BX+1] ;head ;SB ;3.30* + mov dl,Rom_MiniDsk_Num ;drive ;SB ;3.30* + mov bx,BOOTBIAS ;buffer offset ;SB ;3.30* + mov ax,0201h ;read,1 sector ;SB ;3.30* + int 13h ;call ROM-Bios routine ;SB ;3.30* +;SB33029****************************************************************** + jc FmpRet ;cannot continue. + mov bx, 1c2h+BOOTBIAS + + push es ;;DCL/KWC 8/2/87 addressability to + ;; next minidisk + + call SetMini ;install a mini disk. BX value saved. + + pop es ;;DCL/KWC 8/2/87 + + jc FmpnextChain + + call Install_BDSM ;install the BDSM into the BDS table +; call Show_Installed_Mini ;show the installed message. 3/35/86 - Don't show messages. J.K. + inc mininum ;increase the logical drive number for next + inc num_mini_dsk ;increase the number of mini disk installed. + + push bx ;now, set the DskDrvs pointer to BPB info. + mov bx, Mini_BPB_ptr + lea si, [di].BYTEPERSEC ;points to BPB of BDSM + mov [bx], si + inc Mini_BPB_ptr ;advance to the next address + inc Mini_BPB_ptr + pop bx + + add DI, type BDSM_type ;adjust to the next BDSM table entry. + mov End_OF_BDSM, DI ;set the ending address of BDSM table to this. +; Message fTestHard,<"Mini disk installed.",cr,lf> +FmpnextChain: jmp FmpNext ;let's find out if we have any chained partition +FmpRet: + ret + +SetMini: + push di + push bx + push ds + jmp SET1 ;will be returned to Find mini partition routine. + ;Some logic has been added to SET1 to + ;deal with Mini disks. + +; +;Install BDSM installs a BDSM (pointed by DS:DI) into the end of the current +;linked list of BDS. +;Also, set the current BDSM pointer segment to DS. +;At entry: DS:DI -> BDSM +; +Install_BDSM: +assume ds:code,es:nothing + push ax + push si + push es + + les si, dword ptr cs:Start_BDS ;start of the beginning of list +I_BDSM_Next: + cmp word ptr es:[si], -1 ;end of the list? + jz I_BDSM_New + mov si, word ptr es:[si].LINK + mov ax, word ptr es:[si].LINK+2 ;next pointer + mov es, ax + jmp short I_BDSM_Next +I_BDSM_New: + mov ax, ds + mov word ptr ds:[di].LINK+2, ax ;BDSM segment had not been initialized. + mov word ptr es:[si].LINK+2, ax + mov word ptr es:[si].LINK, di + mov word ptr ds:[di].LINK, -1 ;make sure it is a null ptr. + +I_BDSM_ret: + pop es + pop si + pop ax + ret + +;***The following code is not needed any more. Don't show any +;***messages to be compatible with the behavior of IBMBIO.COM. +;;Show the message "Mini disk installed ..." +;;This routine uses WRMSG procedure which will call OUTCHR. +;Show_Installed_Mini: +; push ax +; push bx +; push ds +; +; mov al, Mininum ;logical drive number +; add al, Drv_Letter_Base ;='A' +; mov Mini_Drv_Let, al +; mov si, offset Installed_Mini +; call WRMSG +; +; pop ds +; pop bx +; pop ax +; ret +;**End of mini disk initialization** ;J.K. 4/7/86 + + +CMOS_Clock_Read proc near + + assume ds:code,es:code +; IN ORDER TO DETERMINE IF THERE IS A CLOCK PRESENT IN THE SYSTEM, THE FOLLOWING +; NEEDS TO BE DONE. + PUSH AX + PUSH CX + PUSH DX + PUSH BP + + XOR BP,BP +LOOP_CLOCK: + XOR CX,CX + XOR DX,DX +;SB33030******************************************************************** + MOV AH,2 ;READ REAL TIME CLOCK ;SB ;3.30 + INT 1Ah ;CALL ROM-BIOS ROUTINE ;SB ;3.30 +;SB33030******************************************************************** + CMP CX,0 + JNZ CLOCK_PRESENT + + CMP DX,0 + JNZ CLOCK_PRESENT + + CMP BP,1 ; READ AGAIN AFTER A SLIGHT DELAY, IN CASE CLOCK + JZ NO_READDATE ; WAS AT ZERO SETTING. + + INC BP ; ONLY PERFORM DELAY ONCE. + MOV CX,4000H +DELAY: + LOOP DELAY + JMP LOOP_CLOCK + +CLOCK_PRESENT: + mov cs:HaveCMOSClock, 1 ;J.K. Set the flag for cmos clock + + call CMOSCK ;J.K. Reset CMOS clock rate that may be + ;possibly destroyed by CP DOS and POST routine did not + ;restore that. + + PUSH SI + MESSAGE FTESTINIT,<"CLOCK DEVICE",CR,LF> + CALL READ_REAL_DATE ;MJB002 READ REAL-TIME CLOCK FOR DATE + + CLI ;MJB002 + MOV DAYCNT,SI ;MJB002 SET SYSTEM DATE + STI ;MJB002 + POP SI ;MJB002 +NO_READDATE: + POP BP + POP DX + POP CX + POP AX + RET + +CMOS_Clock_Read endp +; +;J.K. 10/28/86 +;J.K. THE FOLLOWING CODE IS WRITTEN BY JACK GULLEY IN ENGINEERING GROUP. +;J.K. CP DOS IS CHANGING CMOS CLOCK RATE FOR ITS OWN PURPOSES AND IF THE +;J.K. USE COLD BOOT THE SYSTEM TO USE PC DOS WHILE RUNNING CP DOS, THE CMOS +;J.K. CLOCK RATE ARE STILL SLOW WHICH SLOW DOWN DISK OPERATIONS OF PC DOS +;J.K. WHICH USES CMOS CLOCK. PC DOS IS PUT THIS CODE IN MSINIT TO FIX THIS +;J.K. PROBLEM AT THE REQUEST OF CP DOS. +;J.K. THE PROGRAM IS MODIFIED TO BE RUN ON MSINIT. Equates are defined in CMOSEQU.INC. +;J.K. This program will be called by CMOS_Clock_Read procedure. +; +; The following code CMOSCK is used to insure that the CMOS has not +; had its rate controls left in an invalid state on older AT's. +; +; It checks for an AT model byte "FC" with a submodel type of +; 00, 01, 02, 03 or 06 and resets the periodic interrupt rate +; bits incase POST has not done it. This initilization routine +; is only needed once when DOS loads. It should be ran as soon +; as possible to prevent slow diskette access. +; +; This code exposes one to DOS clearing CMOS setup done by a +; resident program that hides and re-boots the system. +; +CMOSCK PROC NEAR ; CHECK AND RESET RTC RATE BITS + assume ds:nothing,es:nothing + +;Model byte and Submodel byte were already determined in MSINIT. + push ax + cmp cs:Model_byte, 0FCh ;check for PC-AT model byte + ; EXIT IF NOT "FC" FOR A PC-AT + JNE CMOSCK9 ; Exit if not an AT model + + CMP cs:Secondary_Model_Byte,06H ; Is it 06 for the industral AT + JE CMOSCK4 ; Go reset CMOS periodic rate if 06 + CMP cs:Secondary_Model_Byte,04H ; Is it 00, 01, 02, or 03 + JNB CMOSCK9 ; EXIT if problem fixed by POST + ;J.K. Also,Secondary_model_byte = 0 when AH=0c0h, int 15h failed. +CMOSCK4: ; RESET THE CMOS PERIODIC RATE + ; Model=FC submodel=00,01,02,03 or 06 +;SB33IN2*********************************************************************** + + mov al,CMOS_REG_A or NMI ;NMI disabled on return + mov ah,00100110b ;Set divider & rate selection + call CMOS_WRITE + +;SB33IN2*********************************************************************** + + ; CLEAR SET,PIE,AIE,UIE AND SQWE + mov al,CMOS_REG_B or NMI ;NMI disabled on return + call CMOS_READ + and al,00000111b ;clear SET,PIE,AIE,UIE,SQWE + mov ah,al + mov al,CMOS_REG_B ;NMI enabled on return + call CMOS_WRITE + +;SB33IN3*********************************************************************** + +CMOSCK9: ; EXIT ROUTINE + pop ax + RET ; RETurn to caller + ; Flags modifyied +CMOSCK ENDP +PAGE +;--- CMOS_READ ----------------------------------------------------------------- +; READ BYTE FROM CMOS SYSTEM CLOCK CONFIGURATION TABLE : +; : +; INPUT: (AL)= CMOS TABLE ADDRESS TO BE READ : +; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : +; BITS 6-0 = ADDRESS OF TABLE LOCATION TO READ : +; : +; OUTPUT: (AL) VALUE AT LOCATION (AL) MOVED INTO (AL). IF BIT 7 OF (AL) WAS : +; ON THEN NMI LEFT DISABLED. DURING THE CMOS READ BOTH NMI AND : +; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : +; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : +; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : +; ONLY THE (AL) REGISTER AND THE NMI STATE IS CHANGED. : +;------------------------------------------------------------------------------- + +CMOS_READ PROC NEAR ; READ LOCATION (AL) INTO (AL) + assume es:nothing,ds:nothing + PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS +;SB33IN4******************************************************************** + + cli + push bx + push ax ;save user NMI state + or al,NMI ;disable NMI for us + out CMOS_PORT,al + nop ;undocumented delay needed + in al,CMOS_DATA ;get data value + + ;set NMI state to user specified + mov bx,ax ;save data value + pop ax ;get user NMI + and al,NMI + or al,CMOS_SHUT_DOWN + out CMOS_PORT,al + nop + in al,CMOS_DATA + + mov ax,bx ;data value + pop bx + +;SB33IN4******************************************************************** + PUSH CS ; *PLACE CODE SEGMENT IN STACK AND + CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 + RET ; RETURN WITH FLAGS RESTORED + +CMOS_READ ENDP + +CMOS_POPF PROC NEAR ; POPF FOR LEVEL B- PARTS + IRET ; RETURN FAR AND RESTORE FLAGS + +CMOS_POPF ENDP + +;--- CMOS_WRITE ---------------------------------------------------------------- +; WRITE BYTE TO CMOS SYSTEM CLOCK CONFIGURATION TABLE : +; : +; INPUT: (AL)= CMOS TABLE ADDRESS TO BE WRITTEN TO : +; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : +; BITS 6-0 = ADDRESS OF TABLE LOCATION TO WRITE : +; (AH)= NEW VALUE TO BE PLACED IN THE ADDRESSED TABLE LOCATION : +; : +; OUTPUT: VALUE IN (AH) PLACED IN LOCATION (AL) WITH NMI LEFT DISABLED : +; IF BIT 7 OF (AL) IS ON. DURING THE CMOS UPDATE BOTH NMI AND : +; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : +; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : +; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : +; ONLY THE CMOS LOCATION AND THE NMI STATE IS CHANGED. : +;------------------------------------------------------------------------------- + +CMOS_WRITE PROC NEAR ; WRITE (AH) TO LOCATION (AL) + assume es:nothing,ds:nothing + PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS + PUSH AX ; SAVE WORK REGISTER VALUES + + cli + push ax ;save user NMI state + or al,NMI ;disable NMI for us + out CMOS_PORT,al + nop + mov al,ah + out CMOS_DATA,al ;write data + + ;set NMI state to user specified + pop ax ;get user NMI + and al,NMI + or al,CMOS_SHUT_DOWN + out CMOS_PORT,al + nop + in al,CMOS_DATA + +;SB33IN5******************************************************************** + POP AX ; RESTORE WORK REGISTERS + PUSH CS ; *PLACE CODE SEGMENT IN STACK AND + CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 + RET + +CMOS_WRITE ENDP +; + + +END$: +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSIOCTL.INC b/v4.0/src/BIOS/MSIOCTL.INC new file mode 100644 index 0000000..9967605 --- /dev/null +++ b/v4.0/src/BIOS/MSIOCTL.INC @@ -0,0 +1,1362 @@ + %OUT MSIOCTL.SIL... + INCLUDE IOCTL.INC +; $SALUT $ioctl$ + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 - P58 Diskcopy format fails when error occurs during format op.6/26/87 J.K. +;AN002; - d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; - p155 Format intermittant failre due to haed settle time 8/18/87 J.K. +;AN004; D113 Disable I/O access to unformatted media 9/03/87 J.K. +;AN005; P985 Allow I/O access to unformtted media 9/14/87 J.K. +;AN006; D241 Provide support of Multi-track Format/Verify 9/23/87 J.K. +;AN007; P1535 Unformatted hard file problem 10/15/87 J.K. +;AN008; P2590 Change the recommended BPB info. after AFS format 11/20/87 J.K. +;AN009; P2828 Do not retry for multi-track format request 12/08/87 J.K. +;AN010; P2781 Changeline error behavior incompatibile with DOS 3.3. 1/06/88 J.K. +;AN011; P3178 Set Media ID should update media info in BDS table. 1/21/88 J.K. +;AN012; D490 IOCTL subfunction 63h,43h,64h,44h conflicts with OS2 2/26/88 J.K. +;============================================================================== + +;J.K. 10/15/87 +;NOTE: GetAccessFlag/SetAccessFlag is unpublished function. +; This function is intended to give the user to control the +; BDS table FLAGS of UNFORMATTED_MEDIA bit. +; GetAccessFlag will show the status - +; A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 DISK I/O not allowed +; 1 DISK I/O allowed +; SetAccessFlag will Set/Reset the UNFORMATTED_MEDIA bit in FLAGS - +; A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 Allow disk I/O +; 1 Disallow disk I/O +;------------------------------------------------------------------------------ + +; GENERIC IOCTL DISPATCH TABLES +; +IOREADJUMPTABLE DB 7 ;AN012;maximum number (0 based) + DW OFFSET GETDEVICEPARAMETERS ;60h + DW OFFSET READTRACK ;61h + DW OFFSET VERIFYTRACK ;62h + dw Cmd_Err_Proc ;AN012;Overlapped with OS2 subfunction + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw GetMediaID ;AN000;AN012;66h + dw GetAccessFlag ;AN007;AN012;67h Unpublished function + +IOWRITEJUMPTABLE DB 7 ;AN012; + DW OFFSET SETDEVICEPARAMETERS ;40h + DW OFFSET WRITETRACK ;41h + DW OFFSET FORMATTRACK ;42h + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw Cmd_Err_Proc ;AN012; + dw SetMediaID ;AN000;AN012;46h + dw SetAccessFlag ;AN007;AN012;47h Unpublished function +; +; TRACKTABLE CONTAINS A 4-TUPLES (C,H,R,N) FOR EACH SECTOR IN A TRACK +; C = CYLINDER NUMBER, H = HEAD NUMBER, R = SECTOR ID, N = BYTES PER SECTOR +; N BYTES PER SECTOR +; --- ---------------- +; 0 128 +; 1 256 +; 2 512 +; 3 1024 +; +MAX_SECTORS_CURR_SUP EQU 63 ; CURRENT MAXIMUM SEC/TRK THAT + ; WE SUPPORT (Was 40 in DOS 3.2) +SECTORSPERTRACK DW 36 +TRACKTABLE DB 0,0,1,2 + DB 0,0,2,2 + DB 0,0,3,2 + DB 0,0,4,2 + DB 0,0,5,2 + DB 0,0,6,2 + DB 0,0,7,2 + DB 0,0,8,2 + DB 0,0,9,2 + DB 0,0,10,2 + DB 0,0,11,2 + DB 0,0,12,2 + DB 0,0,13,2 + DB 0,0,14,2 + DB 0,0,15,2 + db 0,0,16,2 + db 0,0,17,2 + db 0,0,18,2 + db 0,0,19,2 + db 0,0,20,2 + db 0,0,21,2 + db 0,0,22,2 + db 0,0,23,2 + db 0,0,24,2 + db 0,0,25,2 + db 0,0,26,2 + db 0,0,27,2 + db 0,0,28,2 + db 0,0,29,2 + db 0,0,30,2 + db 0,0,31,2 + db 0,0,32,2 + db 0,0,33,2 + db 0,0,34,2 + db 0,0,35,2 + db 0,0,36,2 + DB 4*MAX_SECTORS_CURR_SUP - ($ - TRACKTABLE) DUP (0) + +; THIS IS A REAL UGLY PLACE TO PUT THIS +; IT SHOULD REALLY GO IN THE BDS +MEDIATYPE DB 0 + +MEDIA_SET_FOR_FORMAT DB 0 ; 1 IF WE HAVE DONE AN INT 13 SET MEDIA + ; TYPE FOR FORMAT CALL +Had_Format_Error db 0 ; 1 if the previous format operation + ; failed. - J.K. 7/8/86 +Dsk_time_out_Err equ 80h ; Time out error (No media present). +Dsk_change_line_Err equ 6h ; Change line error +Dsk_illegal_combination equ 0Ch ; Return code of ah=18h function. + +; TEMP DISK BASE TABLE. IT HOLDS THE THE CURRENT DPT WHICH IS THEN REPLACED BY +; THE ONE PASSED BY "NEW ROMS" BEFORE WE PERFORM A FORMAT OPERATION. THE OLD +; DPT IS RESTORED IN RESTOREOLDDPT. THE FIRST ENTRY (DISK_SPECIFY_1) IS -1 IF +; THIS TABLE DOES NOT CONTAIN THE PREVIOUSLY SAVED DPT. +TEMPDPT DD -1 + +; +; GENERIC$IOCTL: +; PERFORM GENERIC IOCTL REQUEST +; INPUT: +; AL - UNIT NUMBER +; OUTPUT: +; IF CARRY SET THEN AL CONTAINS ERROR CODE +; + PUBLIC GENERIC$IOCTL +GENERIC$IOCTL: + MESSAGE FTESTDISK,<"GENERIC IOCTL",CR,LF> + LES BX,CS:[PTRSAV] ; ES:BX POINTS TO REQUEST HEADER. + CALL SETDRIVE ; DS:DI POINTS TO BDS FOR DRIVE. +; +; AT THIS POINT: +; ES:BX - POINTS TO THE REQUEST HEADER +; DS:DI POINTS TO THE BDS FOR THE DRIVE +; + CMP ES:[BX].MAJORFUNCTION, RAWIO + JNE IOCTL_FUNC_ERR + MOV AL, ES:[BX].MINORFUNCTION + MOV SI, OFFSET IOREADJUMPTABLE + TEST AL, GEN_IOCTL_FN_TST ; TEST OF REQ. FUNCTION + JNZ NOTGENERICIOCTLWRITE ; FUNCTION IS A READ. + MOV SI, OFFSET IOWRITEJUMPTABLE +NOTGENERICIOCTLWRITE: +; AND AL, 0FH + and al, 9fH ;AN000; Try to check other than 6x, 4x. + CMP AL, CS:[SI] + JA IOCTL_FUNC_ERR + CBW + SHL AX, 1 + INC SI + ADD SI,AX + LES BX, ES:[BX].GENERICIOCTL_PACKET + CALL CS:[SI] + JC FAILGENERIC$IOCTL + JMP EXIT + +FAILGENERIC$IOCTL: + JMP ERR$EXIT + +IOCTL_FUNC_ERR: + JMP CMDERR +Cmd_Err_Proc: ;AN012; + pop dx ;AN012;clear up stack + pop dx ;AN012;clear up stack + jmp IOCTL_FUNC_ERR ;AN012;Cmd error +; +; GETDEVICEPARAMETERS: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO DEVICE PARAMETER PACKET +; + PUBLIC GETDEVICEPARAMETERS +GETDEVICEPARAMETERS PROC NEAR +; COPY INFO FROM BDS TO THE DEVICE PARAMETERS PACKET + MOV AL, BYTE PTR DS:[DI].FORMFACTOR + MOV BYTE PTR ES:[BX].DP_DEVICETYPE, AL + MOV AX, WORD PTR DS:[DI].FLAGS + AND AX,FNON_REMOVABLE+FCHANGELINE ; MASK OFF OTHER BITS + MOV WORD PTR ES:[BX].DP_DEVICEATTRIBUTES, AX + MOV AX, WORD PTR DS:[DI].CCYLN + MOV WORD PTR ES:[BX].DP_CYLINDERS, AX + +; SET MEDIA TYPE TO DEFAULT + XOR AL, AL + MOV BYTE PTR ES:[BX].DP_MEDIATYPE, AL + +; COPY RECOMMENDED BPB + LEA SI, BYTE PTR [DI].RBYTEPERSEC + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, BUILD_DEVICE_BPB + JZ USE_BPB_PRESENT +; GET THE CORRECT DISK IN THE DRIVE + CALL CHECKSINGLE +; BUILD THE BPB FROM SCRATCH + CALL GETBP + JC GET_PARM_RET + LEA SI,BYTE PTR [DI].BYTEPERSEC +USE_BPB_PRESENT: + LEA DI, BYTE PTR [BX].DP_BPB + MOV CX, SIZE BPB_TYPE ; FOR NOW USE 'SMALL' BPB + REP MOVSB + CLC +GET_PARM_RET: + RET +GETDEVICEPARAMETERS ENDP + +; +; SETDEVICEPARAMETERS: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO DEVICE PARAMETER PACKET +; + PUBLIC SETDEVICEPARAMETERS +SETDEVICEPARAMETERS PROC NEAR +; MAKE SURE THE FCHANGED_BY_FORMAT FLAG GETS SET TO KICK DOS INTO LOOKING AT +; THE BPB + OR WORD PTR DS:[DI].FLAGS, FCHANGED_BY_FORMAT OR FCHANGED + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, ONLY_SET_TRACKLAYOUT + JZ SHORT SETDEVPARM_1 + JMP SETTRACKTABLE ; ORIGINALLY TRACKLAYOUT + +SETDEVPARM_1: +; COPY INFO FROM THE DEVICE PARAMETERS PACKET TO BDS + MOV AL, BYTE PTR ES:[BX].DP_DEVICETYPE + MOV BYTE PTR DS:[DI].FORMFACTOR, AL + + MOV AX, WORD PTR ES:[BX].DP_CYLINDERS + MOV WORD PTR DS:[DI].CCYLN, AX + +; IF CHANGE LINE IS NOT LOADED THEN IGNORE CHANGELING FLAG + MOV AX, WORD PTR ES:[BX].DP_DEVICEATTRIBUTES + CMP CS:[FHAVE96],0 + JNZ HAVE_CHANGE + AND AX,NOT FCHANGELINE +HAVE_CHANGE: +; IGNORE ALL BITS EXCEPT NON_REMOVABLE AND CHANGELINE + AND AX,FNON_REMOVABLE OR FCHANGELINE + MOV CX, WORD PTR DS:[DI].FLAGS +; AND CX, NOT (FNON_REMOVABLE OR FCHANGELINE OR GOOD_TRACKLAYOUT) + AND CX, NOT (FNON_REMOVABLE OR FCHANGELINE OR GOOD_TRACKLAYOUT or UNFORMATTED_MEDIA) ;AN004;AN005;AN007; + OR AX, CX + MOV WORD PTR DS:[DI].FLAGS, AX + +; SET MEDIA TYPE + MOV AL, BYTE PTR ES:[BX].DP_MEDIATYPE + MOV CS:MEDIATYPE, AL +; THE MEDIA CHANGED (MAYBE) SO WE WILL HAVE TO DO A SETDASD THE NEXT TIME +; WE FORMAT A TRACK + OR WORD PTR DS:[DI].FLAGS, SET_DASD_TRUE + + SAVEREG +; FIGURE OUT WHAT WE ARE SUPPOSED TO DO WITH THE BPB + +; WERE WE ASKED TO INSTALL A FAKE BPB? + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, INSTALL_FAKE_BPB + JNZ SHORT INSTALLFAKEBPB + +; WERE WE RETURNING A FAKE BPB WHEN ASKED TO BUILD A BPB? + TEST WORD PTR DS:[DI].FLAGS, RETURN_FAKE_BPB + JZ SHORT INSTALLRECOMMENDEDBPB + +; WE WERE RETURNING A FAKE BPB BUT WE CAN STOP NOW + AND WORD PTR DS:[DI].FLAGS, NOT RETURN_FAKE_BPB +; JMP DONEWITHBPBSTUFF ;AN008; Comment out this instruction. + +INSTALLRECOMMENDEDBPB: + MOV CX, SIZE A_BPB + LEA DI, BYTE PTR [DI].RBYTEPERSEC + JMP SHORT COPYTHEBPB + +INSTALLFAKEBPB: + or word ptr ds:[di].flags, return_fake_bpb ;AN000; Problem + ;reported by WHS. + MOV CX, SIZE BPB_TYPE ; MOVE 'SMALLER' BPB + LEA DI, BYTE PTR [DI].BYTEPERSEC +COPYTHEBPB: + LEA SI, BYTE PTR [BX].DP_BPB +; EXCHANGE ES AND DS + PUSH ES + PUSH DS + POP ES + POP DS + + REP MOVSB + +DONEWITHBPBSTUFF: + CALL RESTOREOLDDPT ; RESTORE THE OLD DPT FROM TEMPDPT + RESTOREREG + +; SET UP TRACK TABLE (IF NECCESSARY) +SETTRACKTABLE: + MOV CX, WORD PTR ES:[BX].DP_TRACKTABLEENTRIES + MOV CS:SECTORSPERTRACK, CX + AND WORD PTR DS:[DI].FLAGS, NOT GOOD_TRACKLAYOUT + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS, TRACKLAYOUT_IS_GOOD + JZ UGLYTRACKLAYOUT + OR WORD PTR DS:[DI].FLAGS, GOOD_TRACKLAYOUT + +UGLYTRACKLAYOUT: + CMP CX, MAX_SECTORS_IN_TRACK + JA TOOMANYSECTORSPERTRACK + JCXZ SECTORINFOSAVED + MOV DI, OFFSET TRACKTABLE + LEA SI, ES:[BX].DP_SECTORTABLE + PUSH ES + POP DS + PUSH CS + POP ES +STORESECTORINFO: + INC DI ; SKIP OVER CYLINDER + INC DI ; SKIP OVER HEAD + LODSW ; GET SECTOR ID + PUSH AX ; SAVE IT + LODSW ; GET SECTOR SIZE + CALL SECTORSIZETOSECTORINDEX + POP DX ; GET SECTOR ID BACK + MOV AL, DL ; AH = SECTOR SIZE INDEX + ; AL = SECTOR ID + STOSW + LOOP STORESECTORINFO + +SECTORINFOSAVED: + CLC + RET + +TOOMANYSECTORSPERTRACK: + MOV AL, 0CH + STC + RET + +SETDEVICEPARAMETERS ENDP + +; +; SET MEDIA TYPE FOR FORMAT +; PERFORMS THE INT 13 WITH AH = 18H TO SEE IF THE MEDIUM DESCRIBED IN THE +; BPB AREA IN THE BDS CAN BE HANDLED BY THE ROM. +; ON INPUT, DS:DI -> CURRENT BDS. +; THE STATUS OF THE OPERATION IS RETURNED IN AL +; - 0 - IF THE SUPPORT IS AVAILABLE, AND THE COMBINATION IS VALID. +; - 1 - NO ROM SUPPORT +; - 2 - ILLEGAL COMBINATION +; - 3 - No media present (ROM support exists but cannot determine now) +; FLAGS ALSO MAY BE ALTERED. ALL OTHER REGISTERS PRESERVED. +; IF THE CALL TO ROM RETURNS NO ERROR, THEN THE CURRENT DPT IS "REPLACED" BY +; THE ONE RETURNED BY THE ROM. THIS IS DONE BY CHANGING THE POINTER IN [DPT] +; TO THE ONE RETURNED. THE ORIGINAL POINTER TO THE DISK BASE TABLE IS STORED +; IN TEMPDPT, UNTIL IT IS RESTORED. +; + PUBLIC SET_MEDIA_FOR_FORMAT +SET_MEDIA_FOR_FORMAT PROC NEAR + SAVEREG + XOR AX,AX + cmp cs:[Had_Format_Error],1 ;Did we have a format error before? + jne No_Form_Err ;AN001; + call ResetDisk +No_Form_Err: ;AN001; + CMP BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 + jnz Do_Set_Media_for_Format + jmp SET_MED_RET ; MEDIA ALREADY SET +Do_Set_Media_for_Format: + SAVEREG + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR] ; GET POINTER TO DISK BASE TABLE + MOV WORD PTR CS:[DPT],SI + MOV WORD PTR CS:[DPT+2],DS ; SAVE POINTER TO TABLE +;SB34IOCTL000****************************************************************** +;SB Initialise the head settle time to 0fh. See the offsets given in +;SB DSKPRM.INC. 1 LOC. + + mov ds:[si].DISK_HEAD_STTL, 0Fh +;SB34IOCTL000****************************************************************** + RESTOREREG + mov cs:[New_Rom], 1 ;assume a new ROM. + XOR AL,AL +;SB33031**************************************************************** + mov cx,ds:[di.ccyln] ;get number of cylinders ;SB ;3.30* + dec cx ;cylinder must be zero based ;SB ;3.30* + and ch,03h ; blank out unnecessary bits + ror ch,1 ;put in int form ;SB ;3.30* + ror ch,1 ; ;SB ;3.30* + xchg ch,cl ; ;SB ;3.30* + or cl,byte ptr ds:[di.seclim] ;get number of sectors ;SB ;3.30* + mov dl,ds:[di.drivenum] ;get drive number ;SB ;3.30* + mov ah,18h ;set media for format ;SB ;3.30* + SAVEREG + int 13h ;call rom bios ;SB ;3.30* +;SB33031**************************************************************** + JC FORMAT_STAT_ERR +; ES:DI POINTS TO A DISK BASE TABLE FOR THIS COMBINATION FOR THIS DRIVE. + XOR CX,CX + MOV DS,CX ; HAVE DS -> SEGMENT 0 + LDS SI,DWORD PTR DS:[DSKADR] ; GET CURRENT DISK BASE TABLE + MOV WORD PTR CS:[TEMPDPT],SI + MOV WORD PTR CS:[TEMPDPT+2],DS ; SAVE IT + MOV WORD PTR DS:[DSKADR],DI + MOV WORD PTR DS:[DSKADR+2],ES ; REPLACE WITH ONE RETURNED BY ROM + MOV BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 +Skip_Disk_Base_setting: + XOR AL,AL ; LEGAL COMBINATION + ROM SUPPORT CODE + mov cs:[Had_Format_Error],al ;reset the flag + JMP SHORT POP_STAT_RET + +FORMAT_STAT_ERR: + cmp ah, Dsk_illegal_combination ;J.K. illegal combination = 0ch + je Format_stat_illegal_comb + cmp ah, Dsk_Time_Out_Err ;J.K. = 80h + je Format_stat_Time_out + mov al, 1 ;Function not supported. + mov cs:[New_Rom], 0 ;So, it is an old rom. + jmp short Pop_stat_ret +Format_stat_illegal_comb: ;J.K. Function supported, but + MOV AL,2 ;J.K. illegal sect/trk, trk combination. + jmp short Pop_stat_ret +Format_stat_Time_out: ;J.K. Function supported, but + mov al, 3 ;J.K. media not present. +POP_STAT_RET: + RESTOREREG +SET_MED_RET: + RESTOREREG + RET + +SET_MEDIA_FOR_FORMAT ENDP + +; +; FORMATTRACK: +; IF SPECIALFUNCTION BYTE IS 1, THEN THIS IS A STATUS CALL TO SEE IF THERE IS +; ROM SUPPORT FOR THE COMBINATION OF SEC/TRK AND # OF CYLN, AND IF THE +; COMBINATION IS LEGAL. IF SPECIALFUNCTION BYTE IS 0, THEN FORMAT THE TRACK. +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO FORMAT PACKET +; +; OUTPUT: +; FOR STATUS CALL: +; SPECIALFUNCTION BYTE SET TO: +; 0 - ROM SUPPORT + LEGAL COMBINATION +; 1 - NO ROM SUPPORT +; 2 - ILLEGAL COMBINATION +; 3 - no media present ;J.K. 7/8/86 +; CARRY CLEARED. +; +; FOR FORMAT TRACK: +; CARRY SET IF ERROR +; + PUBLIC FORMATTRACK +FORMATTRACK PROC NEAR + TEST BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS,STATUS_FOR_FORMAT + JZ DO_FORMAT_TRACK + CALL SET_MEDIA_FOR_FORMAT ; ALSO MOVES CURRENT DPT TO TEMPDPT +STAT_RET: + MOV BYTE PTR ES:[BX].DP_SPECIALFUNCTIONS,AL + CLC + RET + +DO_FORMAT_TRACK: + CMP BYTE PTR DS:[DI].FORMFACTOR, DEV_HARDDISK + jne Do_Format_Diskette + jmp DoVerifyTrack +Do_Format_Diskette: + SAVEREG +;SB34IOCTL001************************************************************* +;SB check the special functions word to see if DO_FAST_FORMAT has been +;SB specified. If so it is an error and we need to finish this operation +;SB by indicating the error value 1 in register ah and going to the +;SB the code at DO_MAP_IT to map the error. This is because we cannot +;SB allow multitrack format on floppies - 5 LOCS + + test byte ptr es:[bx].FP_SPECIALFUNCTIONS,DO_FAST_FORMAT + jz NO_FAST_FORMAT + mov ah, 1 + jmp DO_MAP_IT +NO_FAST_FORMAT: +;SB34IOCTL001************************************************************* + CALL SET_MEDIA_FOR_FORMAT ; ALSO MOVES CURRENT DPT TO TEMPDPT + CMP AL,1 ; DO WE HAVE ROM SUPPORT FOR sector/trk, # trks combination? + JZ Need_Set_DASD ;Old ROM. + cmp al,3 ;time out error? + jnz No_Set_DASD ;No, fine.(At this point, don't care about the illegal combination.) + jmp Format_Failed +Need_Set_DASD: + CALL SETDASD ;AH=17h, INT 13h +; +; STORE CYLINDER,HEAD IN TRACK TABLE +; ***** ASSUMPTION ******* +; SINCE FORMAT REQUESTS ON FIXED MEDIA ARE CONVERTED TO VERIFIES, WE +; ASSUME THAT WE ARE FORMATTING A FLOPPY AND HENCE HAVE 255 OR LESS +; TRACKS AND HEADS. WE THEREFORE MUST CHANGE THE CYLINDER, HEAD DATA +; FROM THE REQUEST PACKET SIZE TO THAT OF THE TRACKTABLE (SEE INT 13 +; INTERFACE IN IBM'S TECH REF.). + +NO_SET_DASD: +; CHECK TO ENSURE CORRECT DISK IS IN DRIVE + CALL CHECKSINGLE + + MOV AX, WORD PTR ES:[BX].FP_CYLINDER + MOV WORD PTR CS:[TRKNUM],AX + MOV CX, WORD PTR ES:[BX].FP_HEAD + MOV BYTE PTR CS:[HDNUM],CL + MOV AH,CL + + PUSH DI ; SAVE PTR TO BDS + MOV DI, OFFSET TRACKTABLE + PUSH CS + POP ES + MOV CX, CS:SECTORSPERTRACK +STORECYLINDERHEAD: + STOSW + INC DI ; SKIP SECTOR ID + INC DI ; SKIP SECTOR SIZE + LOOP STORECYLINDERHEAD + POP DI ; RESTORE PTR TO BDS + + MOV CX, MAXERR ; SET UP RETRY COUNT +FORMATRETRY: + PUSH CX + MOV BX, OFFSET TRACKTABLE + PUSH CS + POP ES + MOV AX, CS:SECTORSPERTRACK + MOV AH, ROMFORMAT + CALL TO_ROM + POP CX + JNC FORMATOK + call resetdisk + mov cs:[Had_Format_Error],1 + push ax + push cx + push dx + call Set_Media_For_Format + cmp al, 1 + jnz While_Err + call SetDASD +While_Err: + pop dx + pop cx + pop ax + LOOP FORMATRETRY +;SB33106******************************************************************* +Format_Failed: + mov cs:[Had_Format_Error], 1 ;set the format error flag. + cmp ah, Dsk_Change_Line_Err ;=06h. Convert change line + jne Do_Map_it ;error to Time Out error. + mov ah, Dsk_Time_Out_Err ;=80h +;SB33106******************************************************************* +Do_Map_it: + CALL MAPERROR + RESTOREREG + RET + +FORMATOK: + mov cs:[Had_Format_Error],0 ;reset the format error flag. + RESTOREREG + +DOVERIFYTRACK: + CALL VERIFYTRACK + RET + +FORMATTRACK ENDP + +VerifyTrack_Err: ;AN006; + mov ah, 1 ;AN006; + call MapError ;AN006; + ret ;AN006; + +; +; VERIFYTRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO VERIFY PACKET +; + PUBLIC VERIFYTRACK +VERIFYTRACK PROC NEAR + MOV CS:RFLAG, ROMVERIFY + MOV AX, WORD PTR ES:[BX].VP_CYLINDER + MOV CS:CURTRK, AX + MOV AX, WORD PTR ES:[BX].VP_HEAD + +; ****** ASSUMPTION ****** +; WE ASSUME THAT WE HAVE LESS THAN 256 HEADS, AND THAT THE REQUEST +; HEADER DATA STRUCTURE IS UNNECCESSARILY BIG + MOV CS:CURHD, AL + MOV CX, CS:SECTORSPERTRACK ;CL = sectors/track +;SB34IOCTL005************************************************************* +;SB +;SB Check SPECIALFUNCTIONS to see if DO_FAST_FORMAT has been specified +;SB If not we should go to the normal track verification routine. If +;SB fast format has been specified we should get the number of tracks +;SB to be verified and check it to see if it is > 255. If it is then +;SB it is an error and we should go to VerifyTrack_Err. If not multiply +;SB the number of tracks by the sectors per track to get the total +;SB number of sectors to be verified. This should also be less than +;SB equal to 255 otherwise we go to same error exit. If everything +;SB is okay we initalise cx to the total sectors. use ax as a temporary +;SB register. 9 LOCS + + test byte ptr es:[bx].FP_SPECIALFUNCTIONS,DO_FAST_FORMAT + jz Norm_VerifyTrack + mov ax,es:[bx].FP_TRACKCOUNT ;ax <- tracks to be verify + cmp ax,0FFh + ja VerifyTrack_Err ;#tracks > 255 + mul cl + cmp ax,0FFh ;#sectors > 255 + ja VerifyTrack_Err + mov cx,ax ;#sectors to verify +;SB34IOCTL005************************************************************* + +;Set the multi track request flag + test word ptr [di].Flags, fNON_REMOVABLE ;AN009;hard disk? + jz Norm_VerifyTrack ;AN009; + test cs:Multrk_Flag, MULTRK_ON ;AN009;MultiTrack operation = on? + jz Norm_VerifyTrack ;AN009; + mov cs:Multitrk_Format_Flag, 1 ;AN009; then set the flag +Norm_VerifyTrack: ;AN006; + XOR AX, AX ;1st sector +; USE 0:0 AS THE TRANSFER ADDRESS FOR VERIFY + XOR BX, BX + MOV ES, BX + CALL TRACKIO + mov cs:Multitrk_Format_Flag, 0 ;AN009;Reset the flag. + RET +VERIFYTRACK ENDP + +; +; READTRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO READ PACKET +; + PUBLIC READTRACK +READTRACK: + MOV CS:RFLAG, ROMREAD + JMP READWRITETRACK + +; +; WRITETRACK: +; +; INPUT: DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO WRITE PACKET +; + PUBLIC WRITETRACK +WRITETRACK: + MOV CS:RFLAG, ROMWRITE + JMP READWRITETRACK +; +; READWRITETRACK: +; +; INPUT: +; DS:DI POINTS TO BDS FOR DRIVE +; ES:BX POINTS TO WRITE PACKET +; RFLAG - 2 FOR READ, 3 FOR WRITE +; + PUBLIC READWRITETRACK +READWRITETRACK PROC NEAR + MOV AX, WORD PTR ES:[BX].TRWP_CYLINDER + MOV CS:CURTRK, AX + MOV AX, WORD PTR ES:[BX].TRWP_HEAD + +; ****** ASSUMPTION ****** +; WE ASSUME THAT WE HAVE LESS THAN 256 HEADS, AND THAT THE REQUEST +; HEADER DATA STRUCTURE IS UNNECCESSARILY BIG + MOV CS:CURHD, AL + MOV AX, WORD PTR ES:[BX].TRWP_FIRSTSECTOR + MOV CX, WORD PTR ES:[BX].TRWP_SECTORSTOREADWRITE + LES BX, ES:[BX].TRWP_TRANSFERADDRESS + CALL TRACKIO + RET +READWRITETRACK ENDP + + +; +; TRACKIO: +; PERFORMS TRACK READ/WRITE/VERIFY +; +; INPUT: +; RFLAG - 2 = READ +; 3 = WRITE +; 4 = VERIFY +; AX - INDEX INTO TRACK TABLE OF FIRST SECTOR TO IO +; CX - NUMBER OF SECTORS TO IO +; ES:BX - TRANSFER ADDRESS +; DS:DI - POINTER TO BDS +; CURTRK - CURRENT CYLINDER +; CURHD - CURRENT HEAD +; + PUBLIC TRACKIO +TRACKIO PROC NEAR +; PROCEDURE `DISK' WILL POP STACK TO SPSAV AND RETURN IF ERROR + MOV CS:SPSAV, SP +; ENSURE CORRECT DISK IS IN DRIVE + CALL CHECKSINGLE +; SEE IF WE HAVE ALREADY SET THE DISK BASE TABLE + CMP BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],1 + JZ DPTALREADYSET +; +; SET UP TABLES AND VARIABLES FOR I/O +; + SAVEREG + CALL IOSETUP + RESTOREREG +; +; POINT SI AT THE TABLE ENTRY OF THE FIRST SECTOR TO BE IO'D +; +DPTALREADYSET: + MOV SI, OFFSET TRACKTABLE + SHL AX, 1 + SHL AX, 1 + ADD SI, AX +; +; WE WANT: +; CX TO BE THE NUMBER OF TIMES WE HAVE TO LOOP +; DX TO BE THE NUMBER OF SECTORS WE READ ON EACH ITERATION + MOV DX, 1 + TEST WORD PTR DS:[DI].FLAGS, GOOD_TRACKLAYOUT + JZ IONEXTSECTOR + +; HEY! WE CAN READ ALL THE SECTORS IN ONE BLOW + XCHG DX, CX + +IONEXTSECTOR: + PUSH CX + PUSH DX +; SKIP OVER THE CYLINDER AND HEAD IN THE TRACK TABLE + INC SI + INC SI +; GET SECTOR ID FROM TRACK TABLE + LODS BYTE PTR CS:[SI] + MOV CS:CURSEC, AL +;*** For a Fixed disk multi-track disk I/O - J.K. 4/14/86 +;Assumptions: 1). In the input CX (# of sectors to go) to TRACKIO, only CL is +;valid. 2). Sector size should be set to 512 bytes. 3). GOODTRACKLAYOUT. +; + test word ptr [di].Flags, fNon_Removable ;Fixed disk? - J.K. + jz IOREMOVABLE ;no -J.K. + test cs:MulTrk_Flag, MULTRK_ON ;AN002; Allow multi-track operation? + jz IORemovable ;AN002; No, don't do that. + mov cs:[seccnt], dx ;# of sectors to I/O -J.K. + mov ax, dx ;J.K. + call disk ;J.K. + pop dx ;J.K. + pop cx ;J.K. + clc ;J.K. + ret ;J.K. +IOREMOVABLE: ;J.K. +; GET SECTOR SIZE INDEX FROM TRACK TABLE AND SAVE IT + LODS BYTE PTR CS:[SI] + PUSH AX +; PATCH SECTOR SIZE IN DPT + PUSH SI + PUSH DS + LDS SI, CS:DPT + MOV BYTE PTR DS:[SI].DISK_SECTOR_SIZ,AL + MOV AL,CS:[EOT] + MOV [SI].DISK_EOT,AL ; SET UP THE MAX NUMBER OF SEC/TRACK + POP DS + MOV AL, DL +DOTHEIO: + MOV CS:[SECCNT],AX ; SET UP THE COUNT OF SECTORS TO I/O + CALL DISK +; ADVANCE BUFFER POINTER BY ADDING SECTOR SIZE + POP SI + POP AX + CALL SECTORSIZEINDEXTOSECTORSIZE + ADD BX, AX + POP DX + POP CX + LOOP IONEXTSECTOR + cmp byte ptr cs:[Media_Set_For_Format], 1 ;AN001; + je No_Need_Done ;AN001; + CALL DONE ; SET TIME OF LAST ACCESS, AND RESET +No_Need_Done: ;AN001; + CLC ; ENTRIES IN DPT. + RET + +TRACKIO ENDP +; +; THE SECTOR SIZE IN BYTES NEEDS TO BE CONVERTED TO AN INDEX VALUE FOR THE IBM +; ROM. (0=>128, 1=>256,2=>512,3=>1024). IT IS ASSUMED THAT ONLY THESE VALUES +; ARE PERMISSIBLE. +; ON INPUT AX CONTAINS SECTOR SIZE IN BYTES +; ON OUTPUT AL CONTAINS INDEX +; + PUBLIC SECTORSIZETOSECTORINDEX +SECTORSIZETOSECTORINDEX PROC NEAR + CMP AH,2 ; EXAMINE UPPER BYTE ONLY + JA ONEK + MOV AL,AH ; VALUE IN AH IS THE INDEX! + RET +ONEK: + MOV AL,3 + RET +SECTORSIZETOSECTORINDEX ENDP + +SECTORSIZEINDEXTOSECTORSIZE PROC NEAR + MOV CL, AL + MOV AX,128 + SHL AX, CL + RET +SECTORSIZEINDEXTOSECTORSIZE ENDP + +; +; SET UP THE ROM FOR FORMATTING. +; WE HAVE TO TELL THE ROM BIOS WHAT TYPE OF DISK IS IN THE DRIVE. +; ON INPUT - DS:DI - POINTS TO BDS +; + PUBLIC SETDASD +SETDASD: +; SEE IF WE HAVE PREVIOUSLY SET DASD TYPE +;SB33114****************************************************************** + cmp cs:[Had_Format_Error],1 + je DoSetDasd +;SB33114****************************************************************** + TEST WORD PTR DS:[DI].FLAGS, SET_DASD_TRUE + JZ DASDHASBEENSET + AND WORD PTR DS:[DI].FLAGS, NOT SET_DASD_TRUE +;SB33115****************************************************************** +DoSetDasd: + mov cs:[Had_Format_Error],0 ;reset it +;SB33115****************************************************************** + MOV CS:[GAP_PATCH],50H ; FORMAT GAP FOR 48TPI DISKS + MOV AL,4 + CMP BYTE PTR DS:[DI].FORMFACTOR,DEV_3INCH720KB + JZ DO_SET + CMP BYTE PTR DS:[DI].FORMFACTOR, DEV_5INCH96TPI + JZ GOT_BIG + MOV AL,1 ; 160/320K IN A 160/320K DRIVE + JMP SHORT DO_SET +GOT_BIG: + MOV AL,2 ; 160/320K IN A 1.2 MEG DRIVE + CMP CS:MEDIATYPE, 0 + JNE DO_SET + MOV AL,3 ; 1.2MEG IN A 1.2MEG DRIVE + MOV CS:[GAP_PATCH],54H +DO_SET: + push ds ;AN003; + push si ;AN003; +;SB34IOCTL002**************************************************************** +;SB Get the disk parameter table address (dword address) from the location +;SB 0:[DSKADR] and fix the head settle time in this to be 0fh. 4 LOCS + + xor si, si + mov ds, si + lds si, dword ptr ds:[DSKADR] + mov ds:[si].DISK_HEAD_STTL, 0Fh +;SB34IOCTL002**************************************************************** + pop si ;AN003; + pop ds ;AN003; +;SB33032****************************************************************** + mov AH, 17h ; set command to Set DASD type;SB ;3.30* + mov DL, [di].DriveNum ; set drive number ;SB ;3.30* + int 13h ; call rom-bios ;SB ;3.30* +;SB33032****************************************************************** +DASDHASBEENSET: + MOV AH,BYTE PTR [DI].SECLIM + MOV CS:[FORMT_EOT],AH + RET + +; +; THIS ROUTINE IS CALLED IF AN ERROR OCCURS WHILE FORMATTING OR VERIFYING. +; IT RESETS THE DRIVE, AND DECREMENTS THE RETRY COUNT. +; ON ENTRY - DS:DI - POINTS TO BDS FOR THE DRIVE +; BP - CONTAINS RETRY COUNT +; ON EXIT FLAGS INDICATE RESULT OF DECREMENTING RETRY COUNT +; +AGAIN: + CALL RESETDISK + +;(deleted section here, as requested by D.L.) + + DEC BP ; DECREMENT RETRY COUNT + RET + + +; RESET THE DRIVE. +; WE ALSO SET [STEP_DRV] TO -1 TO FORCE THE MAIN DISK ROUTINE TO USE THE +; SLOW HEAD SETTLE TIME FOR THE NEXT OPERATION. THIS IS BECAUSE THE RESET +; OPERATION MOVES THE HEAD TO CYLINDER 0, SO WE NEED TO DO A SEEK THE NEXT +; TIME AROUND - THERE IS A PROBLEM WITH 3.5" DRIVES IN THAT THE HEAD DOES +; NOT SETTLE DOWN IN TIME, EVEN FOR READ OPERATIONS!! +; + PUBLIC RESETDISK +RESETDISK: + SAVEREG +;SB33033****************************************************************** + xor AH, AH ; set command to reset disk ;SB ;3.30* + int 13h ; call the rom-bios ;SB ;3.30* +;SB33033****************************************************************** + MOV CS:[STEP_DRV],-1 ; ZAP UP THE SPEED + RESTOREREG + RET + +; +; THIS ROUTINE SETS UP THE DRIVE PARAMETER TABLE WITH THE VALUES NEEDED FOR +; FORMAT, DOES AN INT 13. VALUES IN DPT ARE RESTORED AFTER A VERIFY IS DONE. +; +; ON ENTRY - DS:DI - POINTS TO BDS FOR THE DRIVE +; ES:BX - POINTS TO TRKBUF +; AL - NUMBER OF SECTORS +; AH - INT 13 FUNCTION CODE +; CL - SECTOR NUMBER FOR VERIFY +; ON EXIT - DS,DI,ES,BX REMAIN UNCHANGED. +; AX AND FLAGS ARE THE RESULTS OF THE INT 13 +; + PUBLIC TO_ROM +TO_ROM: + SAVEREG + TEST BYTE PTR CS:[NEW_ROM],1 + JNZ GOT_VALID_DPT + PUSH AX + MOV DX,DS ; SAVE DS:DI-> BDS + XOR AX,AX + MOV DS,AX + LDS SI,DWORD PTR DS:[DSKADR] ; GET POINTER TO DISK BASE TABLE + MOV WORD PTR CS:[DPT],SI + MOV WORD PTR CS:[DPT+2],DS ; SAVE POINTER TO TABLE + MOV AL,CS:[FORMT_EOT] + MOV [SI].DISK_EOT,AL + MOV AL,CS:[GAP_PATCH] + MOV [SI].DISK_FORMT_GAP,AL ; IMPORTANT FOR FORMAT + MOV [SI].DISK_HEAD_STTL,15 ; ASSUME WE ARE DOING A SEEK OPERATION +; SET UP MOTOR START CORRECTLY FOR 3.5" DRIVES. + PUSH ES + MOV ES,DX + CMP BYTE PTR ES:[DI].FORMFACTOR,FFSMALL ; IS IT A 3.5" DRIVE? + JNZ MOTORSTRTOK + MOV AL,4 + XCHG AL,[SI].DISK_MOTOR_STRT +MOTORSTRTOK: + POP ES +;---------------------------------------------------------------------------- +; THE FOLLOWING TWO LINES ARE NO LONGER NECESSARY SINCE THEY ARE ONLY USEFUL +; FOR A VERIFY OPERATION. +; MOV AL,CS:[SECTOR_SIZ_IND] +; MOV [SI].DISK_SECTOR_SIZ,AL ; IMPORTANT FOR VERIFY +;---------------------------------------------------------------------------- + MOV DS,DX ; RESTORE DS:DI-> BDS + POP AX +GOT_VALID_DPT: +;SB33034******************************************************************* + mov dx, cs:[trknum] ; set track number ;SB ;3.30* + mov ch,dl ; set low 8 bits in ch ;SB ;3.30* + mov DL, ds:[di].DriveNum ; set drive number ;SB ;3.30* + mov DH, CS:[HDNUM] ; set head number ;SB ;3.30* + int 13h ; call the rom-bios routines ;SB ;3.30* +;SB33034******************************************************************* + RESTOREREG + RET + +; +; GET THE OWNER OF THE PHYSICAL DRIVE REPRESENTED BY THE LOGICAL DRIVE IN BL. +; THE ASSUMPTION IS THAT WE **ALWAYS** KEEP TRACK OF THE OWNER OF A DRIVE!! +; IF THIS IS NOT THE CASE, THE SYSTEM MAY HANG, JUST FOLLOWING THE LINKED LIST. +; + PUBLIC IOCTL$GETOWN +IOCTL$GETOWN: + CALL SETDRIVE + MOV AL,BYTE PTR [DI].DRIVENUM ; GET PHYSICAL DRIVE NUMBER + PUSH CS + POP DS + MOV DI,WORD PTR START_BDS +OWN_LOOP: + CMP BYTE PTR [DI].DRIVENUM,AL + JNE GETNEXTBDS + TEST WORD PTR [DI].FLAGS,FI_OWN_PHYSICAL + JNZ DONE_GETOWN +GETNEXTBDS: + MOV BX,WORD PTR [DI].LINK+2 + MOV DI,WORD PTR [DI].LINK + MOV DS,BX + JMP SHORT OWN_LOOP +DONE_GETOWN: + JMP SHORT EXIT_OWN + +; +; SET THE OWNERSHIP OF THE PHYSICAL DRIVE REPRESENTED BY THE LOGICAL DRIVE IN +; BL TO BL. +; + PUBLIC IOCTL$SETOWN +IOCTL$SETOWN: + CALL SETDRIVE + MOV BYTE PTR CS:[FSETOWNER],1 ; SET FLAG FOR CHECKSINGLE TO + ; LOOK AT. + CALL CHECKSINGLE ; SET OWNERSHIP OF DRIVE + MOV BYTE PTR CS:[FSETOWNER],0 ; RESET FLAG + XOR BX,BX + MOV ES,BX + MOV CL,-1 + MOV BYTE PTR ES:[LSTDRV],CL ; SET UP SDSB AS WELL + +EXIT_OWN: +; IF THERE IS ONLY ONE LOGICAL DRIVE ASSIGNED TO THIS PHYSICAL DRIVE, RETURN +; 0 TO USER TO INDICATE THIS. + XOR CL,CL + TEST WORD PTR [DI].FLAGS,FI_AM_MULT + JZ EXIT_NO_MULT + MOV CL,BYTE PTR [DI].DRIVELET ; GET LOGICAL DRIVE NUMBER + INC CL ; GET IT 1-BASED +EXIT_NO_MULT: + LDS BX,CS:[PTRSAV] + MOV BYTE PTR [BX].UNIT,CL + JMP EXIT + + +; +; MOVES THE OLD DPT THAT HAD BEEN SAVED IN TEMPDPT BACK TO DPT. THIS IS DONE +; ONLY IF THE FIRST BYTE OF TEMPDPT IS NOT -1. +; ALL REGISTERS (INCLUDING FLAGS) ARE PRESERVED. +; + PUBLIC RESTOREOLDDPT +RESTOREOLDDPT: +; IF WE HAVE ALREADY RESTORED THE DISK BASE TABLE EARLIER, DO NOT DO IT +; AGAIN. + PUSH AX + XOR AL,AL +; RESET FLAG AND GET CURRENT FLAG SETTING + mov cs:[Had_Format_Error],al + XCHG BYTE PTR CS:[MEDIA_SET_FOR_FORMAT],AL + OR AL,AL + JZ DONTRESTORE + SAVEREG + LDS SI,CS:[TEMPDPT] + XOR AX,AX + MOV ES,AX ; HAVE ES -> SEGMENT 0 + MOV WORD PTR ES:[DSKADR],SI + MOV WORD PTR ES:[DSKADR+2],DS +GOTCURRENTDPT: + RESTOREREG +DONTRESTORE: + POP AX + CLC ; CLEAR CARRY + RET + +;****************************************************************************** +;AN000; Get Media ID +;******************************************************************************* +; * +; Function: Get the volume label, the system id and the serial number from * +; the media that has the extended boot record. * +; For the conventional media, this routine will return "Unknown * +; media type" error to DOS. * +; * +; Input : DS:DI -> BDS table for this drive. * +; ES:BX -> Request packet (= A_Media_ID_INFO structure) * +; * +; Output: The request packet filled with the information, if not carry. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; Register DS,DX,AX,CX,DI,SI destroyed. * +; Subroutines to be called: * +; BOOT_IO:NEAR * +; * +; Logic: * +; /*To recognize the extended boot record, this logic will actually */ * +; /*access the boot sector even if it is a hard disk. */ * +; /*NOTE:the valid extended bpb is recognized by looking at the mediabyte* +; /*field of BPB and the extended Boot Signature. * +; * +; { * +; Get logical drive number from BDS table; * +; RFLAG = Read operation; * +; BOOT_IO; /*Get the media boot record into the buffer*/ * +; IF (no error) THEN * +; IF (extended boot record) THEN * +; { set Volume Label, Volume Serial number and System id * +; of the Request packet to those of the boot record; * +; }; * +; ELSE /*Not an extended BPB */ * +; { set Register AL to "Unknown media.." error code; * +; set Carry bit; * +; }; * +; ELSE * +; Exit; /*Already error code is set in the register AL* +; * +; Expected LOC: 40 (New) * +;******************************************************************************* + +GetMediaID proc near ;AN000; + call Changeline_Chk ;AN010; + mov al, DS:[DI].DRIVELET ;AN000; logical drive number + mov cs:RFlag, ROMREAD ;AN000; read operation + call Boot_IO ;AN000; read boot sector into cs:DiskSector +; $IF NC ;AN000; + JC $IOCTL$IF1 + mov cl, cs:MediaByte ;AN000; Mediabyte in BPB + and cl, 0F0h ;AN000; + cmp cl, 0F0h ;AN000; Is it a valid BPB? +; $IF E,AND ;AN000; + JNE $IOCTL$IF2 + cmp cs:Ext_Boot_Sig, EXT_BOOT_SIGNATURE ;AN000; =90h +; $IF E ;AN000; Extended Boot Record + JNE $IOCTL$IF2 + push cs ;AN000; + pop ds ;AN000; + mov si, offset Boot_Serial_L ;AN000; + mov di, bx ;AN000; + add di, MI_SERIAL ;AN000; + mov cx, BOOT_SERIAL_SIZE+BOOT_VOLUME_LABEL_SIZE+BOOT_SYSTEM_ID_SIZE + rep movsb ;AN000; +; $ELSE ;AN000; + JMP SHORT $IOCTL$EN2 +$IOCTL$IF2: + mov al, ERROR_UNKNOWN_MEDIA ;AN000; =7 + stc ;AN000; +; $ENDIF ;End Extended Boot Record check. +$IOCTL$EN2: +; $ENDIF ;Read boot sector failed. Hard error. +$IOCTL$IF1: + ret ;AN000; +GetMediaID endp + +;****************************************************************************** +;AN000; Set Media ID +;******************************************************************************* +; * +; Function: Set the volume label, the system id and the serial number of * +; the media that has the extended boot record. * +; For the conventional media, this routine will return "Unknown * +; media.." error to DOS. * +; This routine will also set the corresponding informations in * +; the BDS table. * +; * +; Input : DS:DI -> BDS table for this drive. * +; ES:BX -> Request packet (= A_Media_ID_INFO structure) * +; * +; Output: The extended boot record in the media will be set according to * +; the Request packet. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; * +; Subroutines to be called: * +; BOOT_IO:NEAR * +; * +; Logic: * +; * +; * +; { * +; Get Drive_Number from BDS; * +; RFLAG = "Read operation"; * +; BOOT_IO; * +; IF (no error) THEN * +; IF (extended boot record) THEN * +; { set Volume Label, Volume Serial number and System id * +; of the boot record to those of the Request packet; * +; RFLAG = "Write operation"; * +; Get Drive Number from BDS; * +; BOOT_IO; /*Write it back*/ * +; }; * +; ELSE /*Not an extended BPB */ * +; { set Register AL to "Unknown media.." error code; * +; set Carry bit; * +; Exit; /*Return back to caller */ * +; }; * +; ELSE * +; Exit; /*Already error code is set */ * +; * +; Expected LOC: 45 (New) * +;******************************************************************************* + +SetMediaID proc near + call Changeline_Chk ;AN010; + mov al, DS:[DI].DRIVELET ;AN000; logical drive number + mov dl, al ;AN000; save it for the time being. + mov cs:RFlag, ROMREAD ;AN000; read operation + push dx ;AN000; save drive number + call Boot_IO ;AN000; read boot sector into cs:DiskSector + pop dx ;AN000; restore drive number +; $IF NC ;AN000; + JC $IOCTL$IF6 + mov cl, cs:MediaByte ;AN000; Mediabyte in BPB + and cl, 0F0h ;AN000; + cmp cl, 0F0h ;AN000; Is it a valid BPB? +; $IF E,AND ;AN000; + JNE $IOCTL$IF7 + cmp cs:Ext_Boot_Sig, EXT_BOOT_SIGNATURE ;AN000; =41 (=29h) +; $IF E ;AN000; Extended Boot Record + JNE $IOCTL$IF7 + push ds ;AN011; save BDS pointer + push di ;AN011; + push es ;AN000; + pop ds ;AN000;Now DS-> Request packet + push cs ;AN000; + pop es ;AN000;Now ES -> Boot Record + mov di, offset Boot_Serial_L ;AN000; + mov si, bx ;AN000; + add si, MI_Serial ;AN000; + mov cx, BOOT_SERIAL_SIZE+BOOT_VOLUME_LABEL_SIZE+BOOT_SYSTEM_ID_SIZE + rep movsb ;AN000; + pop di ;AN011;Restore BDS pointer + pop ds ;AN011; + call Mov_Media_IDs ;AN011; Update the BDS media ID info. + mov al, dl ;AN000; set drive number for Boot_IO + mov cs:RFlag, ROMWRITE ;AN000; + call Boot_IO ;AN000; write it back. + mov cs:[TIM_DRV], -1 ;AN011; Make sure chk$media check the driver +; $ELSE ;AN000; + JMP SHORT $IOCTL$EN7 +$IOCTL$IF7: + mov al, ERROR_UNKNOWN_MEDIA ;AN000; =7 + stc ;AN000; +; $ENDIF ;End Extended Boot Record check. +$IOCTL$EN7: +; $ENDIF ;Read boot sector failed. Hard error. +$IOCTL$IF6: + ret ;AN000; +SetMediaID endp + +;****************************************************************************** +;AN000; Boot_IO +;******************************************************************************* +; * +; Function: Read/Write the boot record into Boot sector. * +; * +; Input : * +; AL=logical drive number * +; RFLAG = operation (read/write) * +; * +; Output: For read operation, the boot record of the drive specified in BDS * +; be read into the DISKSECTOR buffer. * +; For write operation, the DISKSECTOR buffer image will be written * +; to the drive specified in BDS. * +; If carry set, then AL contains the device driver error number * +; that will be returned to DOS. * +; AX,CX,DX register destroyed. * +; If carry set, then AL will contain the error code from DISKIO. * +; * +; Subroutines to be called: * +; DISKIO:NEAR * +; * +; Logic: * +; * +; { * +; First_Sector = 0; /*logical sector 0 is the boot sector */ * +; SectorCount = 1; /*read 1 sector only */ * +; Buffer = DISKSECTOR; /*read it into the disksector buffer */ * +; Call DISKIO (RFLAG, Drive_Number,First_Sector,SectorCount,Buffer); * +; } * +; Expected LOC: 6 (New) * +;******************************************************************************* +Boot_IO proc near ;AN000; + push ds ;AN000; + push es ;AN000; + push di ;AN000; + push bx ;AN000; +;SB34IOCTL003************************************************************** +;SB Call DISKIO to read/write the boot sector. The parameters which +;SB need to be initialised for this subroutine out here are +;SB - transfer address to cs:DiskSector +;SB - low sector needs to be initalised to 0. This is a reg. param +;SB - hi sector in cs:[Start_Sec_H] needs to be initialised to 0. +;SB - number of sectors <-- 1 +;SB 7 LOCS + + mov di, cs + mov ds, di + mov es, di + mov di, offset DiskSector ;es:di -> transfer address + xor dx, dx ;first sector (H) -> 0 + mov [Start_Sec_H], dx ;start sector (H) -> 0 + mov cx, 01 ;one sector + call DISKIO +;SB34IOCTL003************************************************************** + pop bx ;AN000; + pop di ;AN000; + pop es ;AN000; + pop ds ;AN000; + ret ;AN000; +Boot_IO endp ;AN000; + +;******************************************************************************* +;AN010; Changeline_Chk +;******************************************************************************* +;When the user calls Get/Set media ID call before DOS establishes the media * +;by calling "Media$Chk", the change line activity of the drive is going to be * +;lost. This routine will check the change line activity and will save the * +;history in the flags. * +; * +; Function: Check the change line error activity * +; * +; Input : DS:DI -> BDS table. * +; * +; Output: FLAG in BDS table will be updated if change line occurs. * +; * +; Subroutines to be called: * +; SET_CHANGED_DL * +; * +;******************************************************************************* +Changeline_Chk proc near ;AN010; + mov dl, byte ptr ds:[di].DRIVENUM ;AN010; + or dl, dl ;AN010;Fixed disk? + js Chln_Chk_Ret ;AN010;Yes, skip it. + cmp cs:[fHave96], 1 ;AN011;This ROM support change line? + jne Chln_Chk_Ret ;AN011; + call HasChange ;AN011;This drive support change line? + jz Chln_Chk_Ret ;AN011;do nothing +;SB34IOCTL004***************************************************************** +;SB Execute the ROM disk interrupt to check changeline activity. 2 LOCS + + mov ah, 16h + int 13h +;SB34IOCTL004***************************************************************** + jnc Chln_Chk_Ret ;AN010;no change line activity? + mov word ptr cs:[FLAGBITS], FCHANGED ;AN010; + call SET_CHANGED_DL ;AN010;Update FLAG in BDS for this physical drive +Chln_Chk_Ret: ;AN010; + ret ;AN010; +Changeline_Chk endp ;AN010; + +;****************************************************************************** +;AN007; GetAccessFlag +;******************************************************************************* +; * +; Function: Get the status of UNFORMATTED_MEDIA bit of FLAGS in BDS table * +; * +; Input : * +; es:bx -> A_DISKACCESS_CONTROL structure * +; ds:di -> BDS table * +; * +; Output: A_DISKACCESS_CONTROL.DAC_ACCESS_FLAG = 0 if disk I/O not allowed. * +; = 1 if disk I/O allowed. * +;******************************************************************************* +GetAccessFlag proc ;AN007; + test word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA ;AN007;Is it unformtted media? + jz GAF_Allowed ;AN007;No, formatted media + mov es:[bx].DAC_ACCESS_FLAG, 0 ;AN007; + jmp short GAF_Done ;AN007; +GAF_Allowed: ;AN007; + mov es:[bx].DAC_ACCESS_FLAG, 1 ;AN007; +GAF_Done: ;AN007; + ret ;AN007; +GetAccessFlag endp ;AN007; + +;****************************************************************************** +;AN007; SetAccessFlag +;******************************************************************************* +; * +; Function: Set/Reset the UNFORMATTED_MEDIA bit of FLAGS in BDS table * +; * +; Input : * +; es:bx -> A_DISKACCESS_CONTROL structure * +; ds:di -> BDS table * +; * +; Output: UNFORMTTED_MEDIA bit modified according to the user request * +;******************************************************************************* +SetAccessFlag proc ;AN007; + cmp es:[bx].DAC_ACCESS_FLAG, 0 ;AN007; + jne SAF_Allow_Access ;AN007; + or word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA ;AN007; + jmp short SAF_Done ;AN007; +SAF_Allow_Access: ;AN007; + and word ptr ds:[di].FLAGS, not UNFORMATTED_MEDIA ;AN007; +SAF_Done: ;AN007; + ret ;AN007; +SetAccessFlag endp ;AN007; + + \ No newline at end of file diff --git a/v4.0/src/BIOS/MSLOAD.ASM b/v4.0/src/BIOS/MSLOAD.ASM new file mode 100644 index 0000000..859a318 --- /dev/null +++ b/v4.0/src/BIOS/MSLOAD.ASM @@ -0,0 +1,1090 @@ + +page ,132; +title Non-Contiguous IBMBIO Loader (MSLOAD) +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTMs for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; - P1820 New Message SKL file 10/20/87 J.K. +;AN002; - D381 For SYS.COM, put the version number 01/06/88 J.K. +;============================================================================== +;JK, 1987 - +; For DOS 4.00, MSLOAD program has been changed to allow: +; 1. 32 bit calculation, +; 2. Reading a FAT sector when needed, instead of reading the whole FAT +; sectors at once. This will make the Boot time faster, and eliminate +; the memory size limitation problem, +; 3. Solving the limitation of the file size (29 KB) of IBMBIO.COM, +; 4. Adding the boot error message. Show the same boot error message +; and do the same behavior when the read operation of IBMBIO.COM +; failes as the MSBOOT program, since MSLOAD program is the +; extention of MSBOOT program. +; + +IF1 + %OUT ASSEMBLING: Non-Contiguous IBMBIO Loader (MSLOAD) + %OUT + +ENDIF + + +DSKADR = 1Eh * 4 ;ROM bios diskette table vector position + +bootseg segment at 0h + + + org 7C00h +Boot_Sector label byte +bootseg ends + + +dosloadseg segment at 70h + org 00h +IBMBIO_Address label byte + +dosloadseg ends + + +cseg segment public para 'code' + assume cs:cseg,ds:nothing,es:nothing,ss:nothing + +include MSload.inc +include Bootform.inc ;AN000; Extended bpb, boot record defintion. +include versiona.inc ;AN001; Version number for SYS.COM + +sec9 equ 522h ;;** 8/3/87 DCL + +BIOOFF equ 700h +; +org 0h + +start: + jmp Save_Input_Values +SYS_Version dw EXPECTED_VERSION ;AN001; From VERSIONA.INC file +Mystacks dw 64 dup (0) ;AN000; local stack +MyStack_ptr label word + +;local data +Number_Of_Heads dw 0 +Size_Cluster dw 0 +Start_Sector_L dw 0 +Start_Sector_H dw 0 ;J.K. +Temp_H dw 0 ;J.K. For 32 bit calculation +Temp_Cluster dw 0 ;J.K. Temporary place for cluster number +Last_Fat_SecNum dw -1 ;Fat sector number starting from the first fat entry. +Sector_Count dw 0 +Number_Of_FAT_Sectors dw 0 +Hidden_Sectors_L dw 0 +Hidden_Sectors_H dw 0 ;J.K. +Sector_Size dw 0 +Reserved_Sectors dw 0 +Last_Found_Cluster dw 0 +Next_BIO_Location dw 0 +First_Sector_L dw 0 +First_Sector_H dw 0 ;J.K. +Drive_Lim_L dw 0 ;J.K. Max. number of sectors +Drive_Lim_H dw 0 ;J.K. +Sectors_Per_Track dw 0 +Drive_Number db 0 +FAT_Size db 0 +Media_Byte db 0 +EOF db 0 +Org_Rom_Disktable dd 0 +FAT_Segment dw 0 +Sectors_Per_Cluster db 0 + +subttl Save Input Values +page +;*********************************************************************** +; Save_Input_Values +;*********************************************************************** +; +; Input: none +; +; DL = INT 13 drive number we booted from +; CH = media byte +; BX = First data sector (low) on disk (0-based) +; DS:SI = Original ROM BIOS DISKETTE Parameter table. +;J.K. 6/2/87 If an extended Boot Record, then AX will be the First data sector +;J.K. high word. Save AX and set First_Sector_H according to AX if it is an +;J.K. extended boot record. +; AX = First data sector (High) on disk ; +; Output: +; +; BX = first data sector on disk +; +; Media_Byte = input CH +; Drive_Number = input DL +; First_Sector_L = input BX +; First_Sector_H = input AX, if an extended Boot record.;J.K. +; Drive_Lim_L = maximum sector number in this media ;J.K. +; Drive_Lim_H = high word of the above +; Hidden_Sectors_L = hidden secotrs +; Hidden_Sectors_H +; Reserved_Sectors = reserved sectors +; Sectors_Per_Track = Sectors/track +; Number_Of_Heads = heads/cylinder +; +; DS = 0 +; AX,DX,SI destroyed +; +; Calls: none +;----------------------------------------------------------------------- +;Function: +; Save input information and BPB informations from the boot record. +; +;---------------------------------------------------------------------- +Save_Input_Values: + + + mov First_Sector_L,bx ;AC000; + mov media_Byte,ch + mov Drive_Number,dl + mov word ptr Org_Rom_Disktable, si + push ds + pop word ptr Org_Rom_Disktable+2 + xor cx,cx ;Segment 0 + mov ds,cx + assume ds:Bootseg + + push es ;;** DCL 8/3/87 + mov es,cx ;;** DCL 8/3/87 + assume es:Bootseg ;;** DCL 8/3/87 + + MOV SI,WORD PTR DS:DSKADR ; ARR 2.41 + MOV DS,WORD PTR DS:DSKADR+2 ; DS:SI -> CURRENT TABLE ARR 2.41 + + MOV DI,SEC9 ; ES:DI -> NEW TABLE ARR 2.41 + MOV CX,11 ; taken from ibmboot.asm ARR 2.41 + CLD ; + REP MOVSB ; COPY TABLE ARR 2.41 + PUSH ES ; ARR 2.41 + POP DS ; DS = 0 ARR 2.41 + + MOV WORD PTR DS:DSKADR,SEC9 ; ARR 2.41 + MOV WORD PTR DS:DSKADR+2,DS ; POINT DISK PARM VECTOR TO NEW TABLE + pop es ;;** DCL 8/3/87 + assume es:nothing + + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AN000; + mov cs:Sector_Size, cx ;AN000; + mov cl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; + mov cs:Sectors_Per_Cluster, cl ;AN000; + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERTRACK ;Get Sectors per track + mov cs:Sectors_Per_Track,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_HEADS ;Get BPB heads per cylinder + mov cs:Number_Of_Heads,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERFAT ;Get sectors per FAT + mov cs:Number_Of_FAT_Sectors,cx + mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_RESERVEDSECTORS ;Get Reserved Sectors + mov cs:Reserved_Sectors,cx + mov cx,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR ;Get hidden sectors + mov cs:Hidden_Sectors_L,cx + mov cx, Boot_Sector.EXT_BOOT_BPB.EBPB_TOTALSECTORS ;AN000; + mov cs:Drive_Lim_L, cx ;AN000; + +;J.K. First of all, check if it the boot record is an extended one. +;J.K. This is just a safe guard in case some user just "copy" the 4.00 IBMBIO.COM +;J.K. to a media with a conventional boot record. + + cmp Boot_Sector.EXT_BOOT_SIG, EXT_BOOT_SIGNATURE ;AN000; + jne Relocate ;AN000; + mov cs:First_Sector_H, AX ;AN000; start data sector (high) + mov ax,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR+2 ;AN000; + mov cs:Hidden_Sectors_H,ax ;AN000; + cmp cx, 0 ;AN000; CX set already before (=Totalsectors) + jne Relocate ;AN000; + mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS ;AN000; + mov cs:Drive_Lim_L, ax ;AN000; + mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS+2 ;AN000; + mov cs:Drive_Lim_H, ax ;AN000; +subttl Relocate +page +; +;*********************************************************************** +; RELOCATE +;*********************************************************************** +; +; Notes: +; +; Relocate the loader code to top-of-memory. +; +; Input: none +; +; Output: Code and data relocated. +; ax,cx,si,di destroyed +; +; Calls: none +;----------------------------------------------------------------------- +; Copy code from Start to Top of memory. +; +; The length to copy is Total_length +; +; Jump to relocated code +;----------------------------------------------------------------------- +; +Relocate: + assume ds:nothing + cld ;AN000; + xor si,si ;AN000; + mov di,si ;AN000; +;SB34LOAD000**************************************************************** +;SB Determine the number of paragraphs (16 byte blocks) of memory. +;SB This involves invoking the memory size determination interrupt, +;SB which returns the number of 1K blocks of memory, and then +;SB converting this to the number of paragraphs. +;SB Leave the number of paragraphs of memory in AX. + + int 12h ;get system memory size in Kbytes + mov cl,6 ; + shl ax,cl ;memory size in paragraphs +;SB34LOAD000**************************************************************** + mov cl,4 ;AN000; + mov dx, cs:Sector_Size ;AN000; + shr dx,cl ;AN000; + inc dx ;AN000; + sub ax, dx ;AN000; + mov cs:Fat_Segment, ax ;AN000;This will be used for FAT sector + mov dx, offset total_length ;AN000; + shr dx, cl ;AN000; + inc dx ;AN000; + sub ax, dx ;AN000; + mov es, ax ;AN000;es:di -> place be relocated. + push cs ;AN000; + pop ds ;AN000;ds:si -> source + mov cx, offset total_length ;AN000; + rep movsb ;AN000; + + push es ;AN000; + mov ax, offset Setup_stack ;AN000; + push ax ;AN000;massage stack for destination of cs:ip +Dumbbb proc far ;AN000; + ret ;AN000; +Dumbbb endp ;AN000; + + +; push cs ;Set up ds segreg +; pop ds +; xor ax,ax ;Set up ES segreg +; mov es,ax +; +; assume es:bootseg,ds:cseg +; +; mov si,offset Start ;Source +; mov di,offset Relocate_Start ;Target +; mov cx,Relocate_Length ;Length +; rep movsb ;Go do it +; jmp far ptr Relocate_Start + + + +subttl Setup Stack +page +;*********************************************************************** +; Setup_Stack +;*********************************************************************** +; +; Input: none +; +; Output: +; +; SS:SP set +; AX destroyed +;----------------------------------------------------------------------- +; First thing is to reset the stack to a better and more known place. +; +; Move the stack to just under the boot record and relocation area (0:7C00h) +; +; Preserve all other registers +;---------------------------------------------------------------------- + +Setup_Stack: + assume ds:nothing, es:nothing, ss:nothing +; CLI ;Stop interrupts till stack ok + mov ax,cs + MOV SS,AX ;Set up the stack to the known area. + mov sp, offset MyStack_Ptr +; MOV SP,7C00h - 50 ;Leave room for stack frame +; MOV BP,7C00h - 50 ;Point BP as stack index pointer +; STI + +subttl Find_Cluster_Size +page +;*********************************************************************** +; Find_Cluster_Size +;*********************************************************************** +; +; Input: BPB information in loaded boot record at 0:7C00h +; +; Output: +; +; DS = 0 +; AX = Bytes/Cluster +; BX = Sectors/Cluster +; SI destroyed +; Calls: none +;----------------------------------------------------------------------- +; +; Get Bytes/sector from BPB +; +; Get sectors/cluster from BPB +; +; Bytes/cluster = Bytes/sector * sector/cluster +;---------------------------------------------------------------------- +Find_Cluster_Size: + +;For the time being just assume the boot record is valid and the BPB +;is there. + + xor ax,ax ;Segment 0 + mov ds,ax + + assume ds:bootseg + + mov ax,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AC000;Get BPB bytes/sector + xor bx,bx + mov bl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AC000;Get sectors/cluster + mul bx ;Bytes/cluster + mov cs:Size_Cluster,ax ;Save it + + +subttl Determine FAT size +page +;*********************************************************************** +; Determine_FAT_Size +;*********************************************************************** +; +; Notes: +; +; Determine if FAT is 12 or 16 bit FAT. 12 bit FAT if floppy, read MBR +; to find out what system id byte is. +; +; Input: +; +; Output: +; +; cs:Fat_Size = FAT12_bit or FAT16_bit +; All other registers destroyed +; +;---------------------------------------------------------------------- +Determine_FAT_Size: + mov cs:FAT_Size,FAT12_bit ;AN000;Assume 12 bit fat + mov dx, cs:Drive_Lim_H ;AN000; + mov ax, cs:Drive_Lim_L ;AN000; + sub ax, cs:Reserved_Sectors ;AN000; + sbb dx, 0 ;AN000;now, dx;ax = available total sectors + mov bx, cs:Number_Of_FAT_Sectors ;AN000; + shl bx, 1 ;AN000;2 FATs + sub ax, bx ;AN000; + sbb dx, 0 ;AN000;now, dx;ax = tatal sectors - fat sectors + mov bx, Boot_Sector.EXT_BOOT_BPB.EBPB_ROOTENTRIES ;AN000; + mov cl, 4 ;AN000; + shr bx, cl ;AN000;Sectors for dir entries = dir entries / Num_DIR_Sector + sub ax, bx ;AN000; + sbb dx, 0 ;AN000; + xor cx, cx ;AN000; + mov cl, Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + div cx ;AN000; + mov cs:Temp_H, ax ;AN000; + pop ax ;AN000; +;J.K. We assume that cx > dx. + div cx ;AN000; + cmp ax, 4096-10 ;AN000; +; jb Determine_First_Cluster ;AN000; + jb Read_In_FirstClusters + mov cs:FAT_Size, FAT16_Bit ;AN000;16 bit fat + +; cmp cs:Media_Byte,0F8h ;Is it floppy +; jne FAT_Size_Found ;Yep, all set +; mov cs:Logical_Sector,0 ;Got hardfile, go get MBR +; xor ax,ax +; mov es,ax +; mov di,offset Relocate_Start +; mov cs:Sector_Count,1 +; call Disk_Read +; mov si,offset Relocate_Start+1C2h +; mov cx,4 +; xor ax,ax +; mov ds,ax +;Find_Sys_Id: +; mov cs:FAT_Size,FAT12_bit ;Assume 12 bit fat +; cmp byte ptr [si],1 +; je FAT_Size_Found +; mov cs:FAT_Size,FAT16_bit ;Assume 12 bit fat +; cmp byte ptr [si],4 +; je Fat_Size_Found +; add si,16 +; loop Find_Sys_Id +; ;xxxxxxxxxxxxxxxxxxxxxxxxxx error +;FAT_Size_Found: + + +subttl Read_In_FirstClusters +page +;*********************************************************************** +; Read_In_FirstClusters +;*********************************************************************** +; +; Notes: Read the start of the clusters that covers at least IBMLOADSIZE +; fully. For example, if sector/cluster = 2, and IBMLOADSIZE=3 +; then we are going to re-read the second cluster to fully cover +; MSLOAD program in the cluster boundary. +; +; Input: +; IBMLOADSIZE - Make sure this value is the same as the one in +; MSBOOT program when you build the new version!!!!! +; +; Sectors_Per_Cluster +; Size_Cluster +; First_Sector_L +; First_Sector_H +; +; Output: MSLOAD program is fully covered in a cluster boundary. +; AX = # of clusters we read in so far. +; +; Calls: Disk_Read +; Logic: +; AX; DX = IBMLOADSIZE / # of sector in a cluster. +; if DX = 0 then Ok. (MSLOAD is in a cluster boundary.) +; else (Has to read (AX+1)th cluster to cover MSLOAD) +; read (AX+1)th cluster into the address after the clusters we +; read in so far. +;----------------------------------------------------------------------- + +Read_In_FirstClusters: + mov ax, IBMLOADSIZE ;AN000; + div cs:Sectors_Per_Cluster ;AN000; + cmp ah, 0 ;AN000; + je Set_Next_Cluster_Number ;AN000; + xor ah, ah ;AN000; + push ax ;AN000; + mov cx, cs:First_Sector_L ;AN000; + mov cs:Start_Sector_L, cx ;AN000; + mov cx, cs:First_Sector_H ;AN000; + mov cs:Start_Sector_H, cx ;AN000; + mul cs:Sectors_Per_Cluster ;AN000; Now, AX=# of sectors + add cs:Start_Sector_L, ax ;AN000; + adc cs:Start_Sector_H, 0 ;AN000; + pop ax ;AN000; + push ax ;AN000; + mov di, BIOOFF ;AN000; + mul cs:Size_Cluster ;AN000;AX = # of bytes read in before this cluster + add di, ax ;AN000; + xor ax, ax ;AN000; + mov es, ax ;AN000; + mov al, cs:Sectors_Per_Cluster ;AN000; + mov cs:Sector_Count, ax ;AN000; + call Disk_Read ;AN000; + pop ax ;AN000; + inc ax ;AN000;# of clusters read in so far. + +subttl Set_Next_Cluster_Number +page +;*********************************************************************** +; Set_Next_Cluster_Number +;*********************************************************************** +; +; Notes: Set LAST_Found_Cluster for the next use. +; Last_Found_Cluster is the cluster number we are in now. +; Since cluster number is 0 based and there are 2 clusters int +; the beginning of FAT table used by the system, we just add +; 1 to set Last_Found_Cluster. +; +; Input: +; AX = # of clusters read in so far. +; +; Output: +; +; cs:Last_Found_Cluster +; +; Calls: none +;------------------------------------------------------------------ +Set_Next_Cluster_Number: + inc ax ;AN000; For Last_Found_Cluster + mov cs:Last_Found_Cluster,ax ;2 is the first data cluster number(0 based) + +subttl Read In FAT +page +;*********************************************************************** +; Read_In_FAT +;*********************************************************************** +; +; Notes: +; +; Reads in the entire FAT at 800:0. This gives the relocated portion +; of this loader a maximum size of 768 bytes (8000 - 7D00). +; With 64 KB memory system, this can support maximum size of FAT to +; be 32 KB. We assumes that the system memory size be 128 KB, if +; the system has a big media with the total fat size bigger than +; 32 KB. +; +; Input: none +; +; Output: +; +; ES = 0 +; All sectors destroyed +; +; Calls: READ DISK +;----------------------------------------------------------------------- +; Get number of sectors in FAT +; +; Set ES:DI to 800:0 +; +; Read in the sectors +; +;---------------------------------------------------------------------- +;Read_In_FAT: +; mov ax,cs:Number_Of_FAT_Sectors ;Get sectors/FAT +; mov cs:Sector_Count,ax ;Number of sectors to read +; mov ax,cs:Hidden_Sectors_L ;Hidden+Reserved = start of FAT sector +; mov dx,cs:Hidden_Sectors_H ;AN000; +; add ax,cs:Reserved_Sectors +; adc dx, 0 +; mov cs:Start_Sector_L,ax ;AC000;Save it, setup for disk read +; mov cs:Start_Sector_H,dx ;AN000; +; mov di, 800h ;AC000; +; mov es, di ;AC000; +; xor di, di ;AC000; +; assume es:nothing +; call Disk_Read +; +subttl Keep Loaded BIO +page +;*********************************************************************** +; KEEP LOADED BIO +;*********************************************************************** +; +; Notes: +; +; Determine how much of IBMBIO was loaded in when the loader was loaded +; by the boot record (only the portion that is guaranteed to be contiguous) +; +; Input: +; +; cs:Last_Found_Cluster = number of clusters used for loader+2 +; +; Output: +; ES=70h +; DI = Next offset to load IBMBIO code +; AX,BX,CX,DX,SI destroyed +; +; cs:Next_BIO_Location = DI on output +; cs:Last_Cluster = last cluster loaded +; +; Calls: none +;----------------------------------------------------------------------- +;Number of clusters loaded+2 is in cs:Last_Found_Cluster +; +;Multiply cluster * cluster size in bytes to get total loaded for MSLOAD +; +;Subtract TOTAL_LOADED - LOADBIO_SIZE to get loaded IBMBIO in last cluster +; +;Relocate this piece of IBMBIO down to 70:0 +; +;---------------------------------------------------------------------- +Keep_Loaded_BIO: + push ds + mov ax,cs:Last_Found_Cluster ;Point to last cluster loaded + sub ax,1 ;Get number of clusters loaded + mul cs:Size_Cluster ;Get total bytes loaded by + ;This is always < 64k, so + ;lower 16 bits ok + sub ax,LoadBio_Size ;Get portion of IBMBIO loaded + mov cx,ax ;Save length to move + mov ax,70h ;Segment at 70h + mov ds,ax + mov es,ax + mov si,offset Total_Length ;Point at IBMBIO + mov di,0 ;Point at 70:0 + rep movsb ;Relocate this code + mov cs:Next_Bio_Location,di ;Save where to load next + pop ds + +subttl Get Contiguous Clusters +page +;*********************************************************************** +; Get_Contiguous_Clusters +;*********************************************************************** +; +; Notes: Go find clusters as long as they are contiguous +; +; +; Input: +; +; cs:Next_BIO_Location +; cs: +; +; +; Output: +; +; +; Calls: Get_Next_FAT_Entry +;----------------------------------------------------------------------- +; +;Set cs:Sector_Count to Sectors per cluster +; +;Call Get_Next_FAT_Entry to get next cluster in file +; +;Call Check_for_EOF +; +;IF (NC returned) +; +; {Call Get_Next_FAT_Entry +; +; IF (New cluster is contig to old cluster) +; {Add sectors per cluster to cs:Sector_Count +; +; Call Check_For_EOF +; +; IF (NC returned) +; +; +;---------------------------------------------------------------------- +Get_Contiguous_Cluster: + xor ah,ah + mov al,cs:Sectors_Per_Cluster ;Assume we will get one cluster + mov cs:Sector_Count,ax + push cs:Sector_Count + call Get_Next_Fat_Entry ;Go get it in AX + pop cs:Sector_Count + mov cs:Last_Found_Cluster,ax ;Update the last one found + cmp cs:EOF,END_OF_FILE + je GO_IBMBIO + +; je GOTO_IBMBIO +;Got_Contig_Clusters: + + xor dx,dx ;AN000; + sub ax,2 ;Zero base the cluster + xor ch,ch + mov cl,cs:Sectors_Per_Cluster ;Get sectors per cluster + mul cx ;Get how many + add ax,cs:First_Sector_L ;AC000;See where the data sector starts + adc dx,cs:First_Sector_H ;AN000; + mov cs:Start_Sector_L,ax ;AC000;Save it + mov cs:Start_Sector_H,dx ;AN000; + mov di,cs:Next_Bio_Location ;Get where to put code + push cs:Sector_Count ;Save how many sectors + mov ax,dosloadseg ;Get area to load code + mov es,ax + call Disk_Read + pop ax ;Get back total sectors read in +; jc ########## + mul cs:Sector_Size ;AC000;Get number of bytes we loaded +; mul Boot_Sector.ByteSec + add cs:Next_Bio_Location,ax ;Point to where to load next + jmp Get_Contiguous_Cluster + +subttl GOTO IBMBIO +page +;*********************************************************************** +; GOTO_IBMBIO +;*********************************************************************** +; +; Notes: +; +; Set up required registers for IBMBIO, then jump to it (70:0) +; +; Input: none +; +; cs:Media_Byte = media byte +; cs:Drive_Number = INT 13 drive number we booted from +; cs:First_Sector_L = First data sector on disk (Low) (0-based) +; cs:First_Sector_H = First data sector on disk (High) +; +; Output: +; +; Required by MSINIT +; DL = INT 13 drive number we booted from +; CH = media byte +; BX = First data sector on disk (0-based) +; AX = First data sector on disk (High) +; DI = Sectors/FAT for the boot media. +; +; Calls: none +;----------------------------------------------------------------------- +; +; Set up registers for MSINIT then do Far Jmp +; +;---------------------------------------------------------------------- +GO_IBMBIO: + mov ch,cs:Media_Byte ;Restore regs required for MSINT + mov dl,cs:Drive_Number ;Physical Drive number we booted from. + mov bx,cs:First_Sector_L ;AC000; + mov ax,cs:First_Sector_H ;AN000; AX will be the First data sector (High) +;J.K. Don't need this information any more. +; mov di,cs:Number_Of_FAT_Sectors ;AN000 + jmp far ptr IBMBIO_Address + + +subttl Disk Read +page +;*********************************************************************** +; Disk_Read +;*********************************************************************** +; +; Notes: +; +; Read in the cs:Sector_Count number of sectors at ES:DI +; +; +; Input: none +; +; DI = Offset of start of read +; ES = Segment of read +; cs:Sector_Count = number of sectors to read +; cs:Start_sector_L = starting sector (Low) +; cs:Start_sector_H = starting sector (High) +; Following is BPB info that must be setup prior to call +; cs:Number_Of_Heads +; cs:Number_Of_Sectors +; cs:Drive_Number +; cs:Sectors_Per_Track +; +; Output: +; +; AX,BX,CX,DX,SI,DI destroyed +;----------------------------------------------------------------------- +; Divide start sector by sectors per track +; The remainder is the actual sector number, 0 based +; +; Increment actual sector number to get 1 based +; +; The quotient is the number of tracks - divide by heads to get the cyl +; +; The remainder is actual head, the quotient is cylinder +; +; Figure the number of sectors in that track, set AL to this +; +; Do the read +; +; If Error, Do RESET, then redo the INT 13h +; +; If successful read, Subtract # sectors read from Sector_Count, Add to Logical +; Sector, add #sectors read * Sector_Size to BX; +; +; If Sector_Count <> 0 Do next read +;---------------------------------------------------------------------- +Disk_Read: + +; +; convert a logical sector into Track/sector/head. AX has the logical +; sector number +; +DODIV: + MOV cx,5 ;5 retries + +Try_Read: + PUSH cx ;Save it + MOV AX,cs:Start_Sector_L ;AC000; Get starting sector + mov dx, cs:Start_Sector_H ;AN000; +; XOR DX,DX + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + DIV word ptr cs:Sectors_Per_Track + mov cs:Temp_H, ax ;AN000; + pop ax ;AN000; + div word ptr cs:Sectors_Per_Track ;AN000;[temp_h];AX = track, DX = sector number + MOV bx,cs:Sectors_Per_Track ;Get number of sectors we can read in + sub bx,dx ;this track + mov si,bx + cmp cs:Sector_Count,si ;Is possible sectors in track more + jae Got_Length ;than what we need to read? + mov si,cs:Sector_Count ;Yes, only read what we need to +Got_Length: + INC DL ; sector numbers are 1-based + MOV bl,dl ;Start sector in DL + mov dx, cs:Temp_H ;AN000;now, dx;ax = track +; XOR DX, DX + push ax ;AN000; + mov ax, dx ;AN000; + xor dx, dx ;AN000; + DIV word ptr cs:Number_Of_Heads ;Start cyl in ax,head in DL + mov cs:Temp_h, ax ;AN000; + pop ax ;AN000; + div word ptr cs:Number_of_Heads ;AN000;now [temp_h];AX = cyliner, dx = head +;J.K. At this moment, we assume that Temp_h = 0, AX <= 1024, DX <= 255 + MOV DH,DL +; +; Issue one read request. ES:BX have the transfer address, AL is the number +; of sectors. +; + MOV CL,6 + SHL AH,CL ;Shift cyl high bits up + OR AH,BL ;Mix in with sector bits + MOV CH,AL ;Setup Cyl low + MOV CL,AH ;Setup Cyl/high - Sector + mov bx,di ;Get back offset + MOV DL,cs:Drive_Number ;Get drive + mov ax,si ;Get number of sectors to read (AL) + + MOV AH,2 ;Read + push ax ;Save length of read + push di +; Issue one read request. ES:BX have the transfer address, AL is the number +; of sectors. + INT 13H + pop di + pop ax + pop cx ;Get retry count back + jnc Read_OK + mov bx,di ;Get offset + xor ah,ah + push cx + mov dl,cs:Drive_Number + push di + int 13h + pop di + pop cx +; loop Try_Read ;AC000; + ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error + dec cx ;AN000; + jz Read_Error ;AN000; + jmp Try_Read ;AN000; +Read_Error: ;AN000; + jmp ErrorOut ;AN000; + +Read_OK: + xor ah,ah ;Mask out read command, just get # read + sub cs:Sector_Count,ax ;Bump number down + jz Read_Finished + add cs:Start_Sector_L,ax ;AC000;Where to start next time + adc cs:Start_Sector_H, 0 ;AN000; + xor bx,bx ;Get number sectors read + mov bl,al + mov ax,cs:Sector_Size ;Bytes per sector + mul bx ;Get total bytes read + add di,ax ;Add it to offset + jmp DODIV +Read_Finished: + RET + +subttl GET NEXT FAT ENTRY +page +;*********************************************************************** +; GET_NEXT_FAT_ENTRY +;*********************************************************************** +; +; Notes: +; +; Given the last cluster found, this will return the next cluster of +; IBMBIO. If the last cluster is (F)FF8 - (F)FFF, then the final cluster +; of IBMBIO has been loaded, and control is passed to GOTO_IBMBIO +; MSLOAD can handle maximum FAT area size of 64 KB. +; +; Input: +; +; cs:Last_Found_Cluster +; cs:Fat_Size +; +; Output: +; +; cs:Last_Found_Cluster (updated) +; +; Calls: Get_Fat_Sector +;----------------------------------------------------------------------- +; Get Last_Found_Cluster +; +; IF (16 bit FAT) +; {IF (Last_Found_Cluster = FFF8 - FFFF) +; {JMP GOTO_IBMBIO} +; ELSE +; {Get offset by multiply cluster by 2} +; +; ELSE +; {IF (Last_Found_Cluster = FF8 - FFF) +; {JMP GOTO_IBMBIO} +; ELSE +; {Get offset by - multiply cluster by 3 +; +; Rotate right to divide by 2 +; +; IF (CY set - means odd number) +; {SHR 4 times to keep high twelve bits} +; +; ELSE +; {AND with 0FFFh to keep low 12 bits} +; } +; } +; +; +;---------------------------------------------------------------------- +Get_Next_FAT_Entry: + + push es ;AN000; + mov ax, cs:FAT_Segment ;AN000; + mov es, ax ;AN000; es-> Fat area segment + assume es:nothing + + mov cs:EOF,End_Of_File ;Assume last cluster + mov ax,cs:Last_Found_Cluster ;Get last cluster + cmp cs:Fat_Size,FAT12_bit + jne Got_16_Bit + mov si, ax ;AN000; + shr ax, 1 ;AN000; + add si, ax ;AN000; si = ax*1.5 = ax+ax/2 + call Get_Fat_Sector ;AN000; + jne Ok_cluster ;AN000; + mov al, byte ptr es:[bx] ;AN000; + mov byte ptr cs:Temp_cluster, al ;AN000; + inc si ;AN000; + call Get_Fat_Sector ;AN000;read next FAT sector + mov al, byte ptr es:[0] ;AN000; + mov byte ptr cs:Temp_cluster+1, al ;AN000; + mov ax, cs:Temp_cluster ;AN000; + jmp short Even_Odd ;AN000; +Ok_cluster: ;AN000; + mov ax, es:[bx] ;AN000; +Even_Odd: ;AN000; + +; xor bx,bx +; mov bl,3 ;Mult by 3 +; mul bx +; shr ax,1 ;Div by 2 to get 1.5 +; mov si,ax ;Get the final buffer offset +; mov ax,[si]+8000h ;Get new cluster + + test cs:Last_Found_Cluster,1 ;Was last cluster odd? + jnz Odd_Result ;If Carry set it was odd + and ax,0FFFh ;Keep low 12 bits + jmp short Test_EOF ; + +Odd_Result: + mov cl,4 ;AN000;Keep high 12 bits for odd + shr ax,cl +Test_EOF: + cmp ax,0FF8h ;Is it last cluster? + jae Got_Cluster_Done ;Yep, all done here + jmp short Not_Last_CLuster + +Got_16_Bit: + shl ax,1 ;Multiply cluster by 2 + mov si,ax ;Get the final buffer offset + call Get_Fat_Sector ;AN000; + mov ax, es:[bx] ;AN000; +; mov ax,[si]+8000h ;Get new cluster + cmp ax,0FFF8h + jae Got_Cluster_Done + +Not_Last_Cluster: + mov cs:EOF,not END_OF_FILE ;Assume last cluster + +Got_Cluster_Done: + pop es + ret + + +Get_Fat_Sector proc near +;Function: Find and read the corresponding FAT sector into ES:0 +;In). SI = offset value (starting from FAT entry 0) of FAT entry to find. +; ES = FAT sector segment +; cs:Sector_Size +;Out). Corresponding FAT sector read in. +; BX = offset value of the corresponding FAT entry in the FAT sector. +; CX destroyed. +; Zero flag set if the FAT entry is splitted, i.e. when 12 bit FAT entry +; starts at the last byte of the FAT sector. In this case, the caller +; should save this byte, and read the next FAT sector to get the rest +; of the FAT entry value. (This will only happen with the 12 bit fat). + + push ax ;AN000; + push si ;AN000; + push di ;AN000; + push dx ;AN000; + xor dx, dx ;AN000; + mov ax, si ;AN000; + mov cx, cs:Sector_Size ;AN000; + div cx ;AN000;ax = sector number, dx = offset + cmp ax, cs:Last_Fat_SecNum ;AN000;the same fat sector? + je GFS_Split_Chk ;AN000;don't need to read it again. + mov cs:Last_Fat_SecNum, ax ;AN000; + push dx ;AN000; + xor dx, dx ;AN000; + add ax, cs:Hidden_Sectors_L ;AN000; + adc dx, cs:Hidden_Sectors_H ;AN000; + add ax, cs:Reserved_Sectors ;AN000; + adc dx, 0 ;AN000; + mov cs:Start_Sector_L, ax ;AN000; + mov cs:Start_Sector_H, dx ;AN000;set up for Disk_Read + mov cs:Sector_Count, 1 ;AN000;1 sector + xor di, di ;AN000; + call Disk_Read ;AN000; + pop dx ;AN000; + mov cx, cs:Sector_Size ;AN000; +GFS_Split_Chk: ;AN000; + dec cx ;AN000;now, cx= sector size - 1 + cmp dx, cx ;AN000;if the last byte of the sector, then splitted entry. + mov bx, dx ;AN000;Set BX to DX + pop dx ;AN000; + pop di ;AN000; + pop si ;AN000; + pop ax ;AN000; + ret ;AN000; +Get_Fat_Sector endp ;AN000; + + +Errorout: ;AN000; + push cs ;AN000; + pop ds ;AN000; + mov si, offset Sysmsg ;AN000; + call write ;AN000; +;SB34LOAD001**************************************************************** +;SB Wait for a keypress on the keyboard. Use the BIOS keyboard interrupt. +;SB 2 LOCS + + xor ah,ah + int 16h ;read keyboard +;SB34LOAD001**************************************************************** + +;SB34LOAD002**************************************************************** +;SB We have to restore the address of the original rom Disk parameter table +;SB to the location at [0:DSKADR]. The address of this original table has been +;SB saved previously in 0:Org_Rom_DiskTable and 0:Org_Rom_Disktable+2. +;SB After this table address has been restored we can reboot by +;SB invoking the bootstrap loader BIOS interrupt. + + xor bx, bx + mov ds, bx + les bx, dword ptr ds:Org_Rom_DiskTable + mov si, DSKADR + mov word ptr ds:[si], bx ;restore offset + mov word ptr ds:[si+2], es ;restore segment + int 19h ;reboot +;SB34LOAD002**************************************************************** + +Write proc near ;show error messages +;In) DS:SI -> ASCIIZ string. + + lodsb ;AN000; + or al, al ;AN000; + jz Endwr ;AN000; +;SB34LOAD003**************************************************************** +;SB Write the character in al to the screen. +;SB Use Video service 'Write teletype to active page' (ROM_TELETYPE) +;SB Use normal character attribute + mov ah, ROM_TELETYPE + mov bl, 7 ;"normal" attribute ? + int 10h ;video write +;SB34LOAD003**************************************************************** + jmp Write ;AN000; +Endwr: ;AN000; + ret ;AN000; +Write endp +; + +;include MSbtmes.inc ;AN000; +include MSbio.cl1 ;AN001; + +Relocate_Length equ $ - start +Total_Length label byte +LoadBIO_Size equ $ - Start + +cseg ends + end start diff --git a/v4.0/src/BIOS/MSLOAD.INC b/v4.0/src/BIOS/MSLOAD.INC new file mode 100644 index 0000000..1f8d73c --- /dev/null +++ b/v4.0/src/BIOS/MSLOAD.INC @@ -0,0 +1,7 @@ +;MSLOAD.INC +End_Of_File equ 0FFh +FAT12_Bit equ 01h +FAT16_Bit equ 04h +ROM_TELETYPE equ 14 ;INT 10h, Teletype function + +NUM_DIR_PER_SECTOR equ 16 ; number of directory entries per sector diff --git a/v4.0/src/BIOS/MSLPT.ASM b/v4.0/src/BIOS/MSLPT.ASM new file mode 100644 index 0000000..ad858a0 --- /dev/null +++ b/v4.0/src/BIOS/MSLPT.ASM @@ -0,0 +1,270 @@ + PAGE ,132 ; + TITLE MSLPT - BIOS + %OUT ...MSLPT.ASM + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 - P156 KBMLPT device driver's retry logic. 8/18/87 J.K. +;============================================================================== + itest=0 + INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT + INCLUDE MSEQU.INC + INCLUDE MSMACRO.INC + INCLUDE DEVSYM.INC + INCLUDE IOCTL.INC + + EXTRN BUS$EXIT:NEAR ;MSBIO1 + EXTRN ERR$CNT:NEAR ;MSBIO1 + EXTRN CMDERR:NEAR ;MSBIO1 + EXTRN GETDX:NEAR ;MSBIO1 + EXTRN EXIT:NEAR ;MSBIO1 + EXTRN ERR$EXIT:NEAR ;MSBIO1 +;DATA + EXTRN PTRSAV:DWORD ;MSBIO1 + EXTRN TIMDEV:WORD ;MSCLOCK + EXTRN LPT2DEV:WORD ;MSBIO2 + EXTRN WAIT_COUNT:WORD ;MSDATA + EXTRN PRINTDEV:BYTE ;MSDATA +; IBM ROM STATUS BITS (I DON'T TRUST THEM, NEITHER SHOULD YOU) + +NOTBUSYSTATUS = 10000000B ; NOT BUSY +ACKSTATUS = 01000000B ; ACKNOWLEDGE (FOR WHAT?) +NOPAPERSTATUS = 00100000B ; NO MORE PAPER +SELECTEDSTATUS = 00010000B ; THE PRINTER SAID IT WAS SELECTED +IOERRSTATUS = 00001000B ; SOME KINDA ERROR +RESERVED = 00000110B ; NOPS +TIMEOUTSTATUS = 00000001B ; TIME OUT. + + +; WARNING!!! THE IBM ROM DOES NOT RETURN JUST ONE BIT. IT RETURNS A +; WHOLE SLEW OF BITS, ONLY ONE OF WHICH IS CORRECT. + +;---------------------------------------------------------- +;J.K. AN001; PRN$WRIT will retry only if error code is TIMEOUT. + +; WRITE TO PRINTER DEVICE + +; CX HAS COUNT OF BYTES +; ES:DI POINT TO DESTINATION +; AUXNUM HAS PRINTER NUMBER + + PUBLIC PRN$WRIT +PRN$WRIT PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + jcxz Prn$Done ;No char to output +Prn$Loop: + mov bx, 2 ;Initialize retry count +Prn$Out: +;SB34LPT000**************************************************************** +;SB Print the character at ES:[DI] +;SB Call the function PrnOP to do this +;SB The character to be printed goes in AL and the function code +;SB for 'Output character' goes in AH +;SB Check for error in printing. +;SB If there is no error go to print the next character. +;SB If there is an error indicated see if it is due to TIMEOUT. If the +;SB error is not TIMEOUT then we can do nothing about it. Just go to +;SB print the next character. If it is due to timeout we can execute +;SB the code to retry the print which follows this piece of code +;SB LOCS: 6 + + mov al,es:[di] ; assume AX disposible since enter + xor ah,ah ; via int 21h + call PrnOp ; print to printer + jz Prn$Con ; no error - continue + test ah,TIMEOUTSTATUS + jz Prn$Con ; NOT time out - continue + +;SB34LPT000**************************************************************** + dec bx ;Retry until count is exhausted. + jnz Prn$Out ;Retry it. + jmp short Pmessg ;Return with error. + ; + ; next character + ; +Prn$Con: + inc di ;point to next char and continue + loop Prn$Loop +Prn$Done: + jmp Exit +Pmessg: + jmp Err$Cnt +PRN$WRIT endp + +; JCXZ EXVEC3 ; NO CHARS TO OUTPUT.. +;PRN$LOOP: +; MOV BX,2 ; INITIALIZE RETRY FLAG +;PRN$OUT: +; MOV AL,ES:[DI] ; GET CHAR INTO AL +; INC DI ; POINT TO NEXT CHAR +; XOR AH,AH ; AH=0 => OUTPUT CHAR IN DL +; CALL PRNOP ; TO INDICATE PRINT CHAR IN AL +; JNZ PRRETRY +; LOOP PRN$LOOP +;EXVEC3: +; JMP EXIT +;PRRETRY: +; DEC DI ; UNDO THE INC ABOVE... +; DEC BX +; JNZ PRN$OUT +;PMESSG: +; JMP ERR$CNT ;RETURN WITH THE ERROR +;PRN$WRIT ENDP + +;-------------------------------------------------------- + +; PRINTER STATUS ROUTINE + + PUBLIC PRN$STAT +PRN$STAT PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + CALL PRNSTAT ;DEVICE IN DX + JNZ PMESSG ; OTHER ERRORS WERE FOUND +;J.K. The next three lines are commented out, since it is a dead code. +; MOV AL,9 ; AGAIN, ASSUME OUT OF PAPER... +; TEST AH,NOPAPERSTATUS +; JNZ PMESSG + TEST AH,NOTBUSYSTATUS + jnz Prn$Done ;No error. Exit + JMP BUS$EXIT +PRN$STAT ENDP + +; TAKE THE APPROPRIATE PRINTER AND DO THE OPERATION. TRIAGE THE STATUS +; RETURNED IN AH INTO SOME MEANINGFUL ERROR. + +PRNSTAT PROC NEAR +;SB33037********************************************************************** + mov AH, 2 ; set command for get status ;SB ;3.30* +PRNOP: ;SB ;3.30* + call GETDX ; determine which printer ;SB ;3.30* + int 17h ; call ROM-BIOS printer routine ;SB;3.30* + +;SB33037********************************************************************** + +; EXAMINE THE STATUS BITS TO SEE IF AN ERROR OCCURRED. UNFORTUNATELY, SEVERAL +; OF THE BITS ARE SET SO WE HAVE TO PICK AND CHOOSE. WE MUST BE EXTREMELY +; CAREFUL ABOUT BREAKING BASIC. + + TEST AH,IOERRSTATUS ; I/O ERROR? + JZ CHECKNOTREADY ; NO, TRY NOT READY + +; AT THIS POINT, WE KNOW WE HAVE AN ERROR. THE CONVERSE IS NOT TRUE. + + MOV AL,9 ; FIRST, ASSUME OUT OF PAPER + TEST AH,NOPAPERSTATUS ; OUT OF PAPER SET? + JNZ RET1 ; YES, ERROR IS SET + INC AL ; INDICATE I/O ERROR +RET1: + +; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) + + RET ; RETURN WITH ERROR + +; THE BITS SAID NO ERROR. UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK +; HERE. + +CHECKNOTREADY: + MOV AL,2 ; ASSUME NOT-READY + TEST AH,TIMEOUTSTATUS ; IS TIME-OUT SET? + ; IF NZ THEN ERROR, ELSE OK??? +PRNOP2: + RET +PRNSTAT ENDP + +; OUTPUT UNTIL BUSY. THIS ENTRY POINT IS USED EXCLUSIVELY BY THE PRINT +; SPOOLERS. UNDER NO CURCUMSTANCES SHOULD THE DEVICE DRIVER BLOCK WAITING FOR +; THE DEVICE TO BECOME READY. + +; INPUTS: CX HAS COUNT OF BYTES TO OUTPUT. +; ES:DI POINTS TO SOURCE BUFFER +; OUTPUTS: SET THE NUMBER OF BYTES TRANSFERRED APPROPRIATELY + PUBLIC PRN$TILBUSY +PRN$TILBUSY PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + PUSH DS + PUSH ES + POP DS ; NOW ES AND DS BOTH POINT TO SOURCE BUFFER + ASSUME DS:NOTHING + + MOV SI,DI ; EVERYTHING IS SET FOR LODSB +PRN$TILBLOOP: + PUSH CX + PUSH BX + XOR BX,BX + MOV BL,CS:[PRINTDEV] + SHL BX,1 + MOV CX,CS:WAIT_COUNT[BX] ; WAIT COUNT TIMES TO COME READY + POP BX +PRN$GETSTAT: + CALL PRNSTAT ; GET STATUS + JNZ PRN$BPERR ; ERROR + TEST AH,10000000B ; READY YET? + LOOPZ PRN$GETSTAT ; NO, GO FOR MORE + POP CX ; GET ORIGINAL COUNT + JZ PRN$BERR ; STILL NOT READY => DONE + LODSB + XOR AH,AH + CALL PRNOP + JNZ PRN$BERR ; ERROR + LOOP PRN$TILBLOOP ; GO FOR MORE +PRN$B: + POP DS + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + JMP EXIT +PRN$TILBUSY ENDP + +PRN$BPERR PROC NEAR + ASSUME DS:CODE + POP CX +PRN$BERR: + POP DS + LDS BX,CS:[PTRSAV] + ASSUME DS:NOTHING + + SUB WORD PTR [BX].COUNT,CX ;# OF SUCCESSFUL I/O'S + JMP ERR$EXIT +PRN$BPERR ENDP +; +; MANIPULATES THE VALUE IN WAIT_COUNT DEPENDING ON THE VALUE PASSED IN THE +; GENERIC IOCTL PACKET. +; IT EITHER SETS OR RETURNS THE CURRENT VALUE FOR THE RETRY COUNT FOR THE +; DEVICE. +; + PUBLIC PRN$GENIOCTL +PRN$GENIOCTL PROC NEAR + ASSUME DS:CODE ; SET BY PRINTER DEVICE DRIVER ENTRY + + LES DI,[PTRSAV] + CMP ES:[DI].MAJORFUNCTION,IOC_PC + JE PRNFUNC_OK +PRNFUNCERR: + JMP CMDERR + +PRNFUNC_OK: + MOV AL,ES:[DI].MINORFUNCTION + LES DI,ES:[DI].GENERICIOCTL_PACKET + XOR BX,BX + MOV BL,[PRINTDEV] ; GET INDEX INTO RETRY COUNTS + SHL BX,1 + MOV CX,WAIT_COUNT[BX] ; PULL OUT RETRY COUNT FOR DEVICE + CMP AL,GET_RETRY_COUNT + JZ PRNGETCOUNT + CMP AL,SET_RETRY_COUNT + JNZ PRNFUNCERR + MOV CX,ES:[DI].RC_COUNT +PRNGETCOUNT: + MOV WAIT_COUNT[BX],CX ; PLACE "NEW" RETRY COUNT + MOV ES:[DI].RC_COUNT,CX ; RETURN CURRENT RETRY COUNT + JMP EXIT +PRN$GENIOCTL ENDP +CODE ENDS + END diff --git a/v4.0/src/BIOS/MSMACRO.INC b/v4.0/src/BIOS/MSMACRO.INC new file mode 100644 index 0000000..efc034c --- /dev/null +++ b/v4.0/src/BIOS/MSMACRO.INC @@ -0,0 +1,192 @@ +; +; This file contains three macros used in debugging the system. If the +; variable "itest" (in msbio.asm) is nonzero code is included in the +; modules to print debugging messages. The level of debugging is controlled +; by the value of the variable fTestBits in msbio.asm. Specific bits in +; the variable determine which messages to print. The equ's below tell +; which bits control which funcitons. For example the fifth bit +; cooresponds to disk activity (see fTestDisk equ below). +; +; The macros in the file are: +; +; message Prints an ascii string on the screen. +; Example usage: +; +; message fTestDisk, <"Start Disk Write", CR, LF> +; message fTestINIT, <"Begin BDS initialization"> +; +; +; MNUM Print the value in a register or memory location on +; the screen. Value is displayed in hex. +; Usage: +; MNUM bitpattern, valueLocation +; +; valueLocation is typically a regester: +; +; mnum fTestCom, AX +; mnum fTestDisk, DX +; +; ValueLocation can also be a memory location: +; +; mnum fTestINIT, Final_Dos_Location +; +; If no valueLocation is given the macro defaults to +; the BX register. +; +; ZWAIT Stops the program until any key is pressed. +; +; +; The three macros preserve all register values. If "test" is zero +; defined during assembly then the marco produce no code. +; + + IF iTEST ;3.30 + IFNDEF MSGOUT ;3.30 + EXTRN MSGOUT:NEAR,MSGNUM:NEAR ;3.30 + ENDIF ;3.30 + IFNDEF NUMBUF ;3.30 + EXTRN NUMBUF:BYTE,DIGITS:BYTE,FTESTBITS:WORD ;3.30 + ENDIF ;3.30 + IFNDEF DUMPBYTES ;3.30 + EXTRN DUMPBYTES:NEAR,OUTCHAR:NEAR,HEX_TO_ASCII:NEAR ;3.30 + ENDIF ;3.30 + + + +fTestALL equ 1111111111111111b ; watch everything +fTestHARD equ 0000000000000001b ; watch hard disk initialization +fTest96 equ 0000000000000010b ; watch 96 tpi activity +FTEST13 EQU 0000000000000100B ; WATCH INT 13 ACTIVITY ;3.30 +FTESTCOM EQU 0000000000001000B ; WATCH PACKET ACTIVITY ;3.30 +FTESTINIT EQU 0000000000010000B ; WATCH INITIALIZATION MESSAGES ;3.30 +FTESTDISK EQU 0000000000100000B ; WATCH DISK DEVICE DRIVER CALLS ;3.30 +FTESTCON EQU 0000000001000000B ; WATCH SYSTEM WAIT ACTIVITY IN CO;3.30 NSOLE +FtestClock equ 0000000010000000b ; wathc clock device 5/2/86 ;3.30 + + +; +; message macro -- see above for description +; + +MESSAGE MACRO Bits,msg + LOCAL A,B ;3.30 + jmp SHORT b +a: db msg,0 +b: push SI + push AX + mov AX,Bits + mov SI,OFFSET a + call MSGOUT + pop AX + pop SI +endm + + +; +; mnum macro -- see above for description +; + +MNum MACRO Bits,num + push AX +ifb + mov AX,Bits + call MSGNUM +else + push BX + mov BX,num + mov AX,Bits + call MSGNUM + pop BX +endif + pop AX +endm + + +; +; zwait macro -- see above for description +; + +ZWAIT MACRO + Message fTestALL,<"? "> + CALL ZWAITrtn +ENDM + +ZWAITrtn: + pushf ; save the flags + push AX ; preserve AX + xor AH, AH ; set command to get character ;3.30* + int 16h ; call rom keyboard routine ;3.30* + pop AX ; restore AX + popf ; restore the flags + ret + +;Dump_byte dumps the memory contents in hex. ;3.30 +;DUMPOFFLABEL should be a label or a variable defined in DUMPSEG. ;3.30 +DUMP_BYTE MACRO DUMPSEG, DUMPOFFLABEL, BYTELENGTH ;3.30 + push es ;3.30 + PUSH DS ;3.30 + PUSH SI ;3.30 + PUSH CX ;3.30 + ;3.30 + MOV CX, DUMPSEG ;3.30 + MOV DS, CX ;3.30 + MOV SI, OFFSET DUMPOFFLABEL ;3.30 + MOV CX, BYTELENGTH ;3.30 + call dumpbytes ;3.30 + ;3.30 + POP CX ;3.30 + POP SI ;3.30 + POP DS ;3.30 + pop es ;3.30 + ENDM ;3.30 + ;3.30 +;Dump_Byte_Reg dumps the memory contents in hex. - 4/9/86 ;3.30 +;DUMPOFFREG should be a register contains the offset value in DUMPSEG. ;3.30 +DUMP_BYTE_REG MACRO DUMPSEG, DUMPOFFREG, BYTELENGTH ;3.30 + push es ;3.30 + PUSH DS ;3.30 + PUSH SI ;3.30 + PUSH CX ;3.30 + ;3.30 + MOV CX, DUMPSEG ;3.30 + MOV DS, CX ;3.30 + MOV SI, DUMPOFFREG ;3.30 + MOV CX, BYTELENGTH ;3.30 + call dumpbytes ;3.30 + ;3.30 + POP CX ;3.30 + POP SI ;3.30 + POP DS ;3.30 + pop es ;3.30 + ENDM ;3.30 + +else + ; if test is not defined then make macro into null statements +Message macro +ENDM + +MNUM macro +ENDM + +ZWAIT macro +ENDM + +DUMP_BYTE MACRO ;3.30 + ENDM ;3.30 +DUMP_BYTE_REG MACRO ;3.30 + ENDM ;3.30 + ENDIF ;3.30 + ;3.30 +PATHSTART MACRO INDEX,ABBR ;3.30 + IFDEF PATHGEN ;3.30 + PUBLIC ABBR&INDEX&S,ABBR&INDEX&E ;3.30 + ABBR&INDEX&S LABEL BYTE ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + ;3.30 +PATHEND MACRO INDEX,ABBR ;3.30 + IFDEF PATHGEN ;3.30 + ABBR&INDEX&E LABEL BYTE ;3.30 + ENDIF ;3.30 + ENDM ;3.30 + diff --git a/v4.0/src/BIOS/MSSTACK.INC b/v4.0/src/BIOS/MSSTACK.INC new file mode 100644 index 0000000..21a2095 --- /dev/null +++ b/v4.0/src/BIOS/MSSTACK.INC @@ -0,0 +1,306 @@ +; MSStack.inc +; +; Interrupt level 2, 3, 4, 5, 6, 7,(10, 11, 12, 14, 15 - AT level) +; should follow the standard Interrupt Sharing Scheme which has +; a standard header structure. +; Fyi, the following shows the relations between +; the interrupt vector and interrupt level. +; VEC(Hex) 2 8 9 A B C D E 70 72 73 74 76 77 +; LVL(Deci) 9 0 1 2 3 4 5 6 8 10 11 12 14 15 +; MSSTACK module modifies the following interrupt vectors +; to meet the standard Interrupt Sharing standard; +; A, B, C, D, E, 72, 73, 74, 76, 77. +; Also, for interrupt level 7 and 15, the FirstFlag in a standard header +; should be initialized to indicat whether this interrupt handler is +; the first (= 80h) or not. The FirstFlag entry of INT77h's +; program header is initialized in STKINIT.INC module. +; FirstFlag is only meaningful for interrupt level 7 and 15. +; + +; User specifies the number of stack elements - default = 9 +; minimum = 8 +; maximum = 64 +; +; Intercepts Asynchronous Hardware Interrupts only +; +; Picks a stack from pool of stacks and switches to it +; +; Calls the previously saved interrupt vector after pushing flags +; +; On return, returns the stack to the stack pool +; + + +; This is a modification of STACKS: +; 1. To fix a bug which was causing the program to take up too much space. +; 2. To dispense stack space from hi-mem first rather than low-mem first. +; . Clobbers the stack that got too big instead of innocent stack +; . Allows system to work if the only stack that got too big was the most +; deeply nested one +; 3. Disables NMI interrupts while setting the NMI vector. +; 4. Does not intercept any interupts on a PCjr. +; 5. Double checks that a nested interrupt didn't get the same stack. +; 6. Intercepts Ints 70, 72-77 for PC-ATs and other future products + +;The following variables are for MSSTACK.inc + EVEN + dw 0 ; SPARE FIELD BUT LEAVE THESE IN ORDER +StackCount dw 0 +StackAt dw 0 +StackSize dw 0 +Stacks dw 0 + dw 0 + +FirstEntry dw Stacks +LastEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize +NextEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize + +;End of variables defined for MSSTACK. + +;******************************************************************* +;Macro Interrupt handler for the ordinary interrupt vectors and +;the shared interrupt vectors. +;***************************** +Stack_Main MACRO AA + ASSUME DS:NOTHING + ASSUME ES:NOTHING + ASSUME SS:NOTHING +PUBLIC Int&AA +PUBLIC Old&AA +;----------------------------- + ife IntSharingFlag ;if not IntSharingFlag +;----------------------------- + Old&AA DD 0 +Int&AA PROC FAR +;----------------------------- + else ;for shared interrupt. A Header exists. + +PUBLIC FirstFlag&AA +Int&AA PROC FAR + jmp short Entry_Int&AA&_Stk + Old&AA dd 0 ;Forward pointer + dw 424Bh ;compatible signature for Int. Sharing + FirstFlag&AA db 0 ;the firstly hooked. + jmp short Intret_&AA ;Reset routine. We don't care this. + db 7 dup (0) ;Reserved for future. +Entry_Int&AA&_Stk: +;----------------------------- + endif +;----------------------------- + +; +; Keyboard interrupt must have a three byte jump, a NOP and a zero byte +; as its first instruction for compatibility reasons + ifidn <&aa>,<09> + jmp Keyboard_lbl + nop + db 0 +Keyboard_lbl label near + endif + +; This patches INTERRUPT 75h to be "unhooked". We do this Wierdness, +; rather than never hooking INT 75h, to maintain maximum compat. with IBMs +; post production patch. + push ax + + ifidn <&aa>,<02> + +; ********************************************************************* +; +; This is special support for the PC Convertible / NMI handler +; +; On the PC Convertible, there is a situation where an NMI can be +; caused by using the "OUT" instructions to certain ports. When this +; occurs, the PC Convertible hardware *GUARANTEES* that **NOTHING** +; can stop the NMI or interfere with getting to the NMI handler. This +; includes other type of interrupts (hardware and software), and +; also includes other type of NMI's. When any NMI has occured, +; no other interrtupt (hardware, software or NMI) can occur until +; the software takes specific steps to allow further interrupting. +; +; For PC Convertible, the situation where the NMI is generated by the +; "OUT" to a control port requires "fixing-up" and re-attempting. In +; otherwords, it is actually a "restartable exception". In this +; case, the software handler must be able to get to the stack in +; order to figure out what instruction caused the problem, where +; it was "OUT"ing to and what value it was "OUT"ing. Therefore, +; we will not switch stacks in this situation. This situation is +; detected by interrogating port 62h, and checking for a bit value +; of 80h. If set, *****DO NOT SWITCH STACKS*****. +; +; ********************************************************************* + + push es + mov ax,0f000h + mov es,ax + cmp byte ptr es:[0fffeh],mdl_convert ;check if convertible + pop es + jne Normal&aa + + in al,62h + test al,80h + jz Normal&aa + +Special&aa: + pop ax + jmp dword ptr Old&aa + +Normal&aa: + +; ********************************************************************* + + endif + + push bp + push es + mov es, cs:[STACKS+2] ; Get segment of stacks + + mov bp,NextEntry ; get most likely candidate + mov al,Allocated + xchg AllocByte,al ; grab the entry + cmp al,Free ; still avail? + jne NotFree&aa + + sub NextEntry,EntrySize ; set for next interrupt + +Found&aa: + mov SavedSP,sp ; save sp value + mov SavedSS,ss ; save ss also +; mov IntLevel,aa&h ; save the int level + + mov ax,bp ; temp save of table offset + + mov bp,NewSP ; get new SP value + cmp es:[bp],ax ; check for offset into table + jne FoundBad&aa + + mov ax,es ; point ss,sp to the new stack + mov ss,ax + mov sp,bp + + pushf ; go execute the real interrupt handler + call dword ptr old&aa ; which will iret back to here + + mov bp,sp ; retrieve the table offset for us + mov bp,es:[bp] ; but leave it on the stack + mov ss,SavedSS ; get old stack back + mov sp,SavedSP + +; cmp AllocByte,Allocated ; If an error occured, +; jne NewError&aa ; do not free us + + mov AllocByte,Free ; free the entry + mov NextEntry,bp ; setup to use next time + +NewError&aa: + pop es + pop bp ; saved on entry + pop ax ; saved on entry + +INTRET_&AA: ;3.30 + iret ; done with this interrupt + +NotFree&aa: + cmp al,Allocated ; error flag + je findnext&aa ; no, continue + xchg AllocByte,al ; yes, restore error value + +FindNext&aa: + call LongPath + jmp Found&aa + +FoundBad&aa: + cmp bp,FirstEntry + jc findnext&aa + mov bp,ax ; flag this entry + mov AllocByte,Clobbered +; add bp,EntrySize ; and previous entry +; mov AllocByte,Overflowed +; sub bp,EntrySize + jmp findnext&aa ; keep looking + +int&aa endp + + + endm + +;***************************** ;3.30 +;End of Macro definition ;3.30 +;******************************************************************** ;3.30 +; THESE ARE THE INDIVIDUAL INTERRUPT HANDLERS ;3.30 + ;3.30 + IRP A,<02,08,09,70> ;3.30 + IntSharingFlag=0 ;3.30 + Stack_Main &A ;3.30 + ENDM ;3.30 + ;3.30 + IRP A,<0A,0B,0C,0D,0E,72,73,74,76,77> ;3.30 + IntSharingFlag=1 ;3.30 + Stack_Main &A ;3.30 + ENDM ;3.30 + ;3.30 +;******************************************************************** ;3.30 +;Common routines ;3.30 + +longpath: + mov bp,LastEntry ; start with last entry in table + +LPLOOPP: ;3.30 + cmp AllocByte,Free ; is entry free? + jne inuse ; no, try next one + + mov al,Allocated + xchg AllocByte,al ; allocate entry + cmp al,Free ; is it still free? + je found ; yes, go use it + + cmp al,Allocated ; is it other than Allocated or Free? + je inuse ; no, check the next one + + mov AllocByte,al ; yes, put back the error state + +inuse: + cmp bp,FirstEntry + je Fatal + sub bp,EntrySize + JMP LPLOOPP ;3.30 + +found: + ret + + page + +fatal proc near + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? ;3.30 + pop ds ;3.30 + jne Skip_NMIS ;3.30 + ;3.30 + mov al,07h ; disable PC Convertible NMIs + out 72h,al + +Skip_NMIS: ;3.30 + cli ; disable and mask + mov al,0ffh ; all other ints + out 021h,al + out 0a1h,al + + mov si,cs + mov ds,si + mov si,offset fatal_msg + +fatal_loop: + lodsb + cmp al,'$' + je fatal_done + + mov bl,7 ;3.30* + mov ah,14 ;3.30* + int 010h ; whoops, this enables ints ;3.30* + jmp fatal_loop + +fatal_done: + jmp fatal_done +fatal endp diff --git a/v4.0/src/BIOS/MSVOLID.INC b/v4.0/src/BIOS/MSVOLID.INC new file mode 100644 index 0000000..d1a9588 --- /dev/null +++ b/v4.0/src/BIOS/MSVOLID.INC @@ -0,0 +1,297 @@ +;------------------------------------------------------------------------- +; +; File: msvolid.asm +; This file contains the volume_id subroutines and data structures. +; +; Routines in this file are: +; Set_Volume_ID - main routine, calls other routines. +; read_volume_id - read the volume ID and tells if it has +; been changed. +; Transfer_volume_id - copy the volume ID from TMP to special +; drive. +; Check_Volume_ID - compare volume ID in TMP area with one +; expected for drive. +; Fat_Check - see of the fatID has changed in the +; specified drive. +; Init_Vid_loop - set up for VID scan or move +; +; +;------------------------------------------------------------------------- + +; +; length of the volume id +; + +vid_size equ 12 + + PATHSTART 001,VOLID ;3.30 + +; +; null volume id +; + +nul_vid db "NO NAME ",0 + +; +; data scratch area used to hold volume ids +; + +tmp_vid db "NO NAME ",0 + + PATHEND 001,VOLID ;3.30 + +; +; Set_Volume_ID +; If drive has changeline support, read in and set the volume_ID +; and the last FAT_ID byte. If no change line support then do nothing. +; +; On entry: +; DS:DI points to the BDS for this disk. +; AH contains media byte +; +; On Exit: +; Carry clear: +; Successful call +; Carry set +; Error and AX has error code +; + +Set_Volume_ID: + PUBLIC SET_VOLUME_ID ;3.30 + push dx ; save registers + push ax + CALL HasChange ; does drive have changeline support? + jz setvret ; no, get out + push di + call read_volume_ID ; read the volume ID + pop di + jc SetErr ; if error go to error routine + call transfer_volume_ID ; copy the volume id to special drive + call ResetChanged ; restore value of change line + +setvret: ; SET Volume RETurn + clc ; no error, clear carry flag + pop ax ; restore registers + pop dx + ret +SetErr: + pop dx ; pop stack but don't overwrite AX + pop dx ; restore DX + ret + + + +root_sec DW ? ;Root sector # + + + + +; +; read_volume_id read the volume ID and tells if it has been changed. +; +; On entry: +; DS:DI points to current BDS for drive. +; On Exit: +; Carry Clear +; SI = 1 No change +; SI = 0 ? +; SI = -1 Change +; +; Carry Set: +; Error and AX has error code. +; + +read_volume_id: + push ES ; preserve registers + push DX + push CX + push BX + push AX + push DS ; Preserve Current BDS + push DI + push cs ; get ES segment correct + pop es + push cs ; get DS segment correct + pop ds + mov di,offset tmp_vid + mov si,offset nul_vid + mov cx,vid_size + rep movsb ; initialize tmp_vid to null vi_id + + pop DI ; Restore Current BDS + pop DS + mov al,byte ptr ds:[di].cFAT ; # of fats + mov cx,word ptr ds:[di].csecfat ; sectors / fat + mul cl ; size taken by fats + add ax,word ptr ds:[di].ressec ; add on reserved sectors + ; AX is now sector # (0 based) + mov cs:[root_sec],ax ; set initial value + mov ax,[di].cDir ; # root dir entries + mov cl,4 ; 16 entries/sector + shr ax,cl ; divide by 16 + mov cx,ax ; cx is # of sectors to scan +next_sec: + push cx ; save outer loop counter + mov ax,cs:[root_sec] ; get sector # + mov cx,word ptr ds:[di].seclim ; sectors / track + xor DX,DX + div cx + ; set up registers for call to read_sector + inc DX ; dx= sectors into track, ax= track count from 0 + mov cl,dl ; sector to read + xor DX,DX + div word ptr ds:[di].hdlim ; # heads on this disc + mov dh,dl ; Head number + mov ch,al ; Track # + call read_sector ; get first sector of the root directory, + ; ES:BX -> BOOT + jc ReadVIDErr ; error on read + mov cx,16 ; # of dir entries in a block of root + mov al,08h ; volume label bit +fvid_loop: + cmp byte ptr es:[bx],0 ; End of dir? + jz no_vid ; yes, no vol id + cmp byte ptr es:[bx],0E5h ; empty entry? + jz ent_loop ; yes, skip + test es:[bx+11],al ; is volume label bit set in fcb? + jnz found_vid ; jmp yes +ent_loop: + ADD BX,32 ;MJB003 ADD LENGTH OF DIRECTORY ENTRY ;3.30 + loop fvid_loop + pop cx ; outer loop + inc cs:[root_sec] ; next sector + loop next_sec ; continue +NotFound: + XOR SI,SI + jmp short fvid_ret + +found_vid: + pop cx ; clean stack of outer loop counter + mov si,bx ; point to volume_id + push ds ; preserve currnet BDS + push di + push es ; es:si points to volume id. + pop ds ; source segment + push cs + pop es ; destination segment + mov di,offset tmp_vid ; dest of volume_id + mov cx,vid_size -1 ; length of string minus NUL + rep movsb ; mov volume label to tmp_vid + xor al,al + stosb ; Null terminate + XOR SI,SI + pop DI ; restore current BDS + pop DS +fvid_ret: + pop ax + clc +RVIDRet: + pop BX ; restore register + pop CX + pop DX + pop ES + ret +no_vid: + pop cx ; clean stack of outer loop counter + jmp NotFound ; not found +ReadVIDErr: + pop SI + pop SI + jmp RVIDRet + + + +; +; Transfer_volume_id - copy the volume ID from TMP to special drive +; +; Inputs: DS:DI nas current BDS +; Outputs: BDS for drive has volume ID from TMP +; + +transfer_volume_ID: + push DS ; preserve current BDS + push DI + push ES + push SI + push CX + call init_vid_loop + cld + rep MOVSB ; transfer + pop CX + pop SI + pop ES + pop DI ; restore current BDS + pop DS + ret + + +; +; Check_Volume_ID - compare volume ID in TMP area with one expected for +; drive +; +; Inputs: DS:DI has current BDS for drive +; Outputs: SI = 0 if compare succeeds +; SI = -1 if compare fails. + +check_volume_id: + push DS ; preserve current BDS for drive + push DI + push ES + push CX + call init_vid_loop + cld + repz cmpsb ; are the 2 volume_ids the same? + mov si,0 ; assume unknown + jz check_vid_ret ; carry clear if jump taken + mov si,-1 ; failure +check_vid_ret: + pop CX + pop ES + pop DI ; restore current BDS + pop DS + ret + +; +; Fat_Check - see of the fatID has changed in the specified drive. +; - uses the FAT ID obtained from the boot sector. +; +; Inputs: MedByt is expected FAT ID +; DS:DI points to current BDS +; Output: Carry Clear +; SI = -1 if fat ID different, +; SI = 0 otherwise +; No other registers changed. + +FAT_CHECK: + push AX + xor SI, SI ; say FAT ID's are same. + mov AL, cs:MedByt + cmp AL, byte ptr [DI].Mediad ; compare it with the BDS medbyte + jz OKRET1 ; carry clear + dec SI +OkRet1: clc + pop AX + ret + + +; +; Init_Vid_loop - set up for VID scan or move +; +; Inputs: DS:DI pionts to BDS for the drive +; Outputs: DS:SI points to tmp_vid +; ES:DI points to vid for drive +; CX has size for VID compare +; + +init_vid_loop: + push ax + push ds + pop es + push cs + pop ds + mov si,offset tmp_vid ; source + add di,volid + mov cx,vid_size + pop ax + ret + diff --git a/v4.0/src/BIOS/PSOPTION.INC b/v4.0/src/BIOS/PSOPTION.INC new file mode 100644 index 0000000..d7f56d4 --- /dev/null +++ b/v4.0/src/BIOS/PSOPTION.INC @@ -0,0 +1,63 @@ +;******************************************************************* +; Parser Options set for IBMBIO SYSCONF module +;******************************************************************* +; +;**** Default assemble swiches definition ************************** + +IFNDEF FarSW +FarSW equ 0 ; Near call expected +ENDIF + +IFNDEF DateSW +DateSW equ 0 ; Check date format +ENDIF + +IFNDEF TimeSW +TimeSW equ 0 ; Check time format +ENDIF + +IFNDEF FileSW +FileSW equ 1 ; Check file specification +ENDIF + +IFNDEF CAPSW +CAPSW equ 0 ; Perform CAPS if specified +ENDIF + +IFNDEF CmpxSW +CmpxSW equ 0 ; Check complex list +ENDIF + +IFNDEF NumSW +NumSW equ 1 ; Check numeric value +ENDIF + +IFNDEF KeySW +KeySW equ 0 ; Support keywords +ENDIF + +IFNDEF SwSW +SwSW equ 1 ; Support switches +ENDIF + +IFNDEF Val1SW +Val1SW equ 1 ; Support value definition 1 +ENDIF + +IFNDEF Val2SW +Val2SW equ 0 ; Support value definition 2 +ENDIF + +IFNDEF Val3SW +Val3SW equ 1 ; Support value definition 3 +ENDIF + +IFNDEF DrvSW +DrvSW equ 1 ; Support drive only format +ENDIF + +IFNDEF QusSW +QusSW equ 0 ; Support quoted string format +ENDIF + + \ No newline at end of file diff --git a/v4.0/src/BIOS/PUSHPOP.INC b/v4.0/src/BIOS/PUSHPOP.INC new file mode 100644 index 0000000..aaa76eb --- /dev/null +++ b/v4.0/src/BIOS/PUSHPOP.INC @@ -0,0 +1,20 @@ + IF1 ;3.30 + +SaveReg MACRO reglist ;; push those registers +IRP reg, + ?stackdepth = ?stackdepth + 1 + PUSH reg +ENDM +ENDM +.xcref SaveReg + + +RestoreReg MACRO reglist ;; pop those registers +IRP reg, + ?stackdepth = ?stackdepth - 1 + POP reg +ENDM +ENDM +.xcref RestoreReg + + ENDIF ;3.30 diff --git a/v4.0/src/BIOS/READCLOC.INC b/v4.0/src/BIOS/READCLOC.INC new file mode 100644 index 0000000..700f0aa --- /dev/null +++ b/v4.0/src/BIOS/READCLOC.INC @@ -0,0 +1,165 @@ +; SCCSID = @(#)readclock.asm 1.2 85/07/25 +;************************************************************************ +; +; read_real_date reads real-time clock for date and returns the number +; of days elapsed since 1-1-80 in si +; +read_real_date: ;mjb002 + assume ds:code,es:nothing + PUSH AX + PUSH CX + PUSH DX + XOR AH,AH ; throw away clock roll over ;3.30* + INT 1AH ;3.30* + POP DX + POP CX + POP AX + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV CS:DAYCNT2,1 ;MJB002 REAL TIME CLOCK ERROR FLAG (+1 DA;3.30Y) + mov ah,4 ;mjb002 read date function code ;3.30* + int 1ah ;mjb002 read real-time clock ;3.30* + jnc read_ok ;mjb002 jmp success + jmp r_d_ret ;mjb002 jmp error +read_ok: ;mjb002 ******* get bcd values in binary ***** + mov byte ptr bin_date_time+0,ch ;mjb002 store as hex value + mov byte ptr bin_date_time+1,cl ;mjb002 ... + mov byte ptr bin_date_time+2,dh ;mjb002 ... + mov byte ptr bin_date_time+3,dl ;mjb002 ... + MOV CS:DAYCNT2,2 ;MJB002 READ OF R-T CLOCK SUCCESSFUL ;3.30 + call bcd_verify ;mjb002 verify bcd values in range + jc r_d_ret ;mjb002 jmp some value out of range + MOV CS:DAYCNT2,3 ;MJB002 READ OF R-T CLOCK SUCCESSFUL ;3.30 + call date_verify ;mjb002 verify date values in range + jc r_d_ret ;mjb002 jmp some value out of range + MOV CS:DAYCNT2,0 ;MJB002 VERIFY SUCCESSFUL ;3.30;3.30 + call in_bin ;mjb002 convert date to binary + ;mjb002 ******* years since 1-1-80 ********* + mov al,byte ptr bin_date_time+1 ;mjb002 get years into century + cbw ;mjb002 + cmp byte ptr bin_date_time+0,20 ;mjb002 20th century? + jnz century_19 ;mjb002 jmp no + add ax,100 ;mjb002 add in a century +century_19: ;mjb002 + sub ax,80 ;mjb002 subtract off 1-1-80 + mov cl,4 ;mjb002 leap year every 4 + div cl ;mjb002 al= # leap year blocks, ah= remainder + mov bl,ah ;mjb002 save odd years + cbw ;mjb002 zero ah + mov cx,366+3*365 ;mjb002 # of days in leap year blocks + mul cx ;mjb002 dx:ax is result + MOV CS:DAYCNT2,AX ;MJB002 SAVE COUNT OF DAYS ;3.30 + mov al,bl ;mjb002 get odd years count + cbw ;mjb002 + or ax,ax ;mjb002 is ax= 0? + jz leap_year ;mjb002 jmp if none + mov cx,365 ;mjb002 days in year + mul cx ;mjb002 dx:ax is result + ADD CS:DAYCNT2,AX ;MJB002 ADD ON DAYS IN ODD YEARS ;3.30 + jmp short leap_adjustment ;mjb002 account for leap year +leap_year: ;mjb002 possibly account for a leap day + cmp byte ptr bin_date_time+2,2 ;mjb002 is month february + jbe no_leap_adjustment ;mjb002 jan or feb. no leap day yet. +leap_adjustment: ;mjb002 account for leap day + INC CS:DAYCNT2 ;MJB002 ... ;3.30 +no_leap_adjustment: ;mjb002 ******* get days of month ******* + mov cl,byte ptr bin_date_time+3 ;mjb002 ... + xor ch,ch ;mjb002 + dec cx ;mjb002 because of offset from day 1, not day 0 + ADD CS:DAYCNT2,CX ;MJB002 ******* GET DAYS IN MONTHS PRECEE;3.30DING ***** + mov cl,byte ptr bin_date_time+2 ;mjb002 get month + xor ch,ch ;mjb002 + dec cx ;mjb002 january starts at offset 0 + shl cx,1 ;mjb002 word offset + mov si,offset month_table ;mjb002 beginning of month_table + add si,cx ;mjb002 point into month table + mov ax,word ptr [si];mjb002 get # days in previous months + ADD CS:DAYCNT2,AX ;MJB002 ... ;3.30 +r_d_ret: ;mjb002 + MOV SI,CS:DAYCNT2 ;MJB002 RESULT IN SI ;3.30 + POP DX + POP CX + POP BX + POP AX + ret ;mjb002 + +r_t_retj: + xor cx,cx + xor dx,dx + jmp r_t_ret +; +; Read_Real_Time reads the time from the RTC. on exit, it has the number of +; ticks (at 18.2 ticks per sec.) in CX:DX. +; +Read_Real_Time: + mov ah,2 ;3.30* + int 1AH ;3.30* + jc r_t_retj +oktime: + mov byte ptr bin_date_time,ch ; hours + mov byte ptr bin_date_time+1,cl ; minutes + mov byte ptr bin_date_time+2,dh ; seconds + mov byte ptr bin_date_time+3,0 ; unused for time + call bcd_verify + jc r_t_retj + call time_verify + jc r_t_retj + call in_bin + MOV ch,byte ptr bin_date_time + MOV cl,byte ptr bin_date_time+1 + MOV dh,byte PTR bin_date_time+2 + MOV dl,byte PTR bin_date_time+3 + message ftestinit,<"Read Time "> + mnum ftestinit,cx + message ftestinit,<" "> + mnum ftestinit,dx + message ftestinit, +; get time in ticks in CX:DX + CALL word ptr cs:TimeToTicks ;3.30 + message ftestinit,<"Conv Time "> + mnum ftestinit,cx + message ftestinit,<" "> + mnum ftestinit,dx + message ftestinit, +r_t_ret: + ret + +; +; in_bin converts bin_date_time values from bcd to bin +; +in_bin: ;mjb002 + assume ds:code,es:nothing + mov al,byte ptr bin_date_time+0 ; century or hours + call bcd_to_bin ; ... + mov byte ptr bin_date_time+0,al ; + mov al,byte ptr bin_date_time+1 ; years or minutes + call bcd_to_bin ; ... + mov byte ptr bin_date_time+1,al ; + mov al,byte ptr bin_date_time+2 ; months or seconds + call bcd_to_bin ; ... + mov byte ptr bin_date_time+2,al ; + mov al,byte ptr bin_date_time+3 ; days (not used for time) + call bcd_to_bin ; ... + mov byte ptr bin_date_time+3,al ; + ret ; +; +; bcd_to_bin converts two bcd nibbles in al (value <= 99.) to +; a binary representation in al +; ah is destroyed +; +bcd_to_bin: ;mjb002 + assume ds:nothing,es:nothing + mov ah,al ;mjb002 copy bcd number to ah + and ax,0f00fh ;mjb002 clear unwanted nibbles + mov bl,al ;mjb002 save units place + xchg ah,al ;mjb002 10's place to al + xor ah,ah ;mjb002 ah not wanted + mov cl,4 ;mjb002 shift count + shr ax,cl ;mjb004 swap nibbles + mov cl,10 ;mjb002 convert al to ... + mul cl ;mjb002 ... its binary value + add al,bl ;mjb002 add in units + ret ;mjb002 diff --git a/v4.0/src/BIOS/STKINIT.INC b/v4.0/src/BIOS/STKINIT.INC new file mode 100644 index 0000000..8298fb8 --- /dev/null +++ b/v4.0/src/BIOS/STKINIT.INC @@ -0,0 +1,271 @@ +; +; To follow the standard interrupt sharing scheme, MSSTACK.ASM ;3.30 +; has been modified. This initialization routine also has to ;3.30 +; be modified because for the interrupt level 7 and 15, FirstFlag ;3.30 +; should be set to signal that this interrupt handler is the ;3.30 +; first handler hooked to this interrupt vector. ;3.30 +; We determine this by looking at the instruction pointed by ;3.30 +; this vector. If it is IRET, then this handler should be the ;3.30 +; first one. In our case, only the interrupt vector 77h is the ;3.30 +; interrupt level 15. (We don't hook interrupt level 7.) ;3.30 +; 9/10/1986 ;3.30 +; The followings are mainly due to M.R.T; PTM fix of P886 12/3/86;3.30 +; Some design changes are needed to the above interrupt sharing ;3.30 +; method. The above sharing scheme assumes that 1). Interrupt ;3.30 +; sharing is NEVER done on levels that have BIOS support. 2). "Phantom" ;3.30 +; interrupts would only be generated on levels 7 and 15. ;3.30 +; These assumptions are not true any more. We have to use the FirstFlag ;3.30 +; for EVERY level of interrupt. We will set the firstFlag on the following;3.30 +; conditions: ;3.30 +; a. if the CS portion of the vector is 0000, then "first" ;3.30 +; b. else if CS:IP points to valid shared header, then NOT "first" ;3.30 +; c. else if CS:IP points to an IRET, then "first" ;3.30 +; d. else if CS:IP points to DUMMY, then "first" ;3.30 +; where DUMMY is - the CS portion must be F000, and the IP portion must ;3.30 +; be equal to the value at F000:FF01. This location is the initial value ;3.30 +; from VECTOR_TABLE for interrupt 7, one of the preserved addresses in all;3.30 +; the BIOSes for all of the machines. ;3.30 +; ;3.30 +; System design group requests BIOS to handle the phantom interrupts. ;3.30 +; ;3.30 +; The "Phantom" interrupt is an illegal interrupt such as an interrupt ;3.30 +; produced by the bogus adapter card even without interrupt request is ;3.30 +; set. More specifically, 1). The 8259 has a feature when running in ;3.30 +; edge triggered mode to latch a pulse and present the interrupt when ;3.30 +; the processor indicates interrupt acknowledge (INTA). The interrupt ;3.30 +; pulse was exist at the time of INTA to get a "phantom" interrupt. ;3.30 +; 2). or, this is caused by adapter cards placing a glitch on the ;3.30 +; interrupt line. ;3.30 +; ;3.30 +; To handle those "phantom" interrupts, the main stack code will check ;3.30 +; the own FirstFlag, and if it is not "first" (which means the forward ;3.30 +; pointer points to the legal shared interrupt handler), then pass the ;3.30 +; control. If it is the first, then the following action should be ;3.30 +; taken. We don't have to implement skack logic in this case. ;3.30 +; ;3.30 +; To implement this logic, we rather choose a simple method. ;3.30 +; If ont of the above "FirstFlag" conditions is met, we are not ;3.30 +; going to hook this interrupt vector. The reason is if the original ;3.30 +; vector points to "IRET" and do nothing, we don't need ;3.30 +; to implement the stack logic for it. This will simplify implementation;3.30 +; while maintaining compatibility with the old version of DOS. ;3.30 +; This implies that in the main stack code, there might be a stack code ;3.30 +; that will never be used, a dead code. ;3.30 +; ;3.30 +; 12/3/86 ;3.30 + ;3.30 +;In - CS, DS -> sysinitseg, ES -> relocated stack code & data. ;3.30 + ;3.30 + PAGE ;3.30 + assume ds:sysinitseg ; sunilp SB340 +StackInit proc near ;3.30 + ;3.30 + PUSH AX ;SAVE ALL ;3.30 + PUSH DS ;3.30 + PUSH ES ;3.30 + PUSH BX ;3.30 + PUSH CX ;3.30 + PUSH DX ;3.30 + PUSH DI ;3.30 + PUSH SI ;3.30 + PUSH BP ;3.30 + ;3.30 +;Currently ES -> stack code area ;3.30 + MOV AX, cs:[STACK_COUNT] ;defined in CS ;3.30 + MOV es:[STACKCOUNT], AX ;defined in STACK CODE AREA ;3.30 + MOV AX, [STACK_SIZE] ;in CS ;3.30 + MOV es:[STACKSIZE], AX ; ;3.30 + MOV AX, WORD PTR cs:[STACK_ADDR] ; OFFSET ;3.30 + MOV WORD PTR es:[STACKS], AX ;3.30 + MOV AX, WORD PTR cs:[STACK_ADDR+WORD] ; SEGMENT ;3.30 + MOV WORD PTR es:[STACKS+WORD], AX ;3.30 + ;3.30 +; INITIALIZE THE DATA FIELDS WITH THE PARAMETERS ;3.30 + ;3.30 +; "FIRSTENTRY" WILL ALWAYS BE AT STACKS ;3.30 + ;3.30 + MOV BP, word ptr es:STACKS ; GET OFFSET OF STACK ;3.30 + MOV es:FIRSTENTRY,BP ;3.30 + ;3.30 +; THE STACKS WILL ALWAYS IMMEDIATELY FOLLOW THE TABLE ENTRIES ;3.30 + ;3.30 + MOV AX,ENTRYSIZE ;3.30 + MOV CX,es:STACKCOUNT ;3.30 + MUL CX ;3.30 + ADD AX,BP ;3.30 + MOV es:STACKAT,AX ;3.30 + MOV BX,AX ;3.30 + SUB BX,2 ;3.30 + ;3.30 +; ZERO THE ENTIRE STACK AREA TO START WITH ;3.30 + ;3.30 + MOV DI,es:STACKAT ;3.30 + MOV AX,es:STACKSIZE ;3.30 + MUL CX ;3.30 + MOV CX,AX ;3.30 + xor ax,ax ;3.30 + push es ;3.30 + pop ds ;ds = Relocated stack code seg.;3.30 + assume ds:nothing ;3.30 +;Now, DS -> stack code area ;3.30 + MOV ES, word ptr ds:[STACKS+2] ; GET SEGMENT OF STACK AREA.;3.30 + CLD ;3.30 + REP STOSB ;3.30 + ;3.30 + MOV CX, ds:STACKCOUNT ;3.30 + ;3.30 +; LOOP FOR "COUNT" TIMES, BUILDING A TABLE ENTRY ;3.30 +; cs = sysinitseg, ds = Relocated stack code seg , es = segment of stack space;3.30 +; CX = NUMBER OF ENTRIES ;3.30 +; ES:BP => BASE OF STACKS - 2 ;3.30 +; ES:BX => FIRST TABLE ENTRY ;3.30 + ;3.30 +BUILDLOOP: ;3.30 + MOV ALLOCBYTE,FREE ;3.30 + MOV INTLEVEL,AL ;AX = 0 ;3.30 + MOV SAVEDSP,AX ;3.30 + MOV SAVEDSS,AX ;3.30 + ADD BX,ds:STACKSIZE ;3.30 + MOV NEWSP,BX ;3.30 + MOV ES:[BX],BP ;3.30 + ADD BP,ENTRYSIZE ;3.30 + ;3.30 + LOOP BUILDLOOP ;3.30 + ;3.30 + SUB BP,ENTRYSIZE ;3.30 + MOV ds:LASTENTRY,BP ;3.30 + MOV ds:NEXTENTRY,BP ;3.30 + ;3.30 + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? ;3.30 + pop ds ;3.30 + jne Skip_disableNMIS ;3.30 + ;3.30 + MOV AL,07H ; DISABLE Convertible NMIS ;3.30 + OUT 72H,AL ;3.30 + ;3.30 +Skip_disableNMIS: ;3.30 + XOR AX,AX ;3.30 + MOV es,AX ;es - SEGID OF VECTOR TABLE AT 0;3.30 + ASSUME es:NOTHING ;ds - Relocated Stack code segment;3.30 + ;3.30 + CLI ;3.30 + ;3.30 + IRP AA,<02,08,09,70> ;3.30 + ;3.30 + MOV SI,AA&H*4 ;PASS WHERE VECTOR IS TO BE ADJUSTED ;3.30 + mov di, offset Int19OLD&AA ;we have to set OLD&AA for Int19 handler too.;3.30 + MOV BX,OFFSET OLD&AA ;PASS WHERE TO SAVE ORIGINAL OWNER POINTER;3.30 + MOV DX,OFFSET INT&AA ;PASS WHERE NEW HANDLER IS ;3.30 + CALL NEW_INIT_LOOP ;ADJUST THE VECTOR TO NEW HANDLER, ;3.30 + ; SAVING POINTER TO ORIGINAL OWNER ;3.30 + ENDM ;3.30 + ;3.30 + IRP AA,<0A,0B,0C,0D,0E,72,73,74,76,77> ;shared interrupts ;3.30 + ;3.30 + MOV SI,AA&H*4 ;PASS WHERE VECTOR IS TO BE ADJUSTED ;3.30 + push ds ;save relocated stack code segment ;3.30 + lds bx, es:[si] ;ds:bx -> original interrupt handler ;3.30 + push ds ;3.30 + pop dx ;dx = segment value ;3.30 + + cmp dx,0 + jz int&AA&_first + + cmp byte ptr ds:[bx],0cfh ;Does vector point to an IRET? + jz int&AA&_first + + cmp word ptr ds:[bx.6],424Bh ;Magic offset (see INT&AA, msstack.inc) + jz int&AA&_Not_first + + cmp dx,0f000h ;ROM BIOS segment + jnz int&AA&_Not_first + + push es + push dx + mov dx,0f000h + mov es,dx + cmp bx,word ptr es:0ff01h + pop dx + pop es + jz int&AA&_first + +int&AA&_Not_first: ;Not the first. We are going to hook vector.;3.30 + pop ds ;3.30 + mov di, offset Int19OLD&AA ;we have to set OLD&AA for Int19 handler too.;3.30 + mov BX, OFFSET OLD&AA ;PASS WHERE TO SAVE ORIGINAL OWNER POINTER;3.30 + MOV DX, OFFSET INT&AA ;PASS WHERE NEW HANDLER IS ;3.30 + CALL NEW_INIT_LOOP ;ADJUST THE VECTOR TO NEW HANDLER, SAVING;3.30 + ;POINTER TO ORIGINAL OWNER. ;3.30 + jmp short int&AA&_end ;3.30 +int&AA&_first: ;the first. Don't have to hook stack code.;3.30 + pop ds ;3.30 +int&AA&_end: ;3.30 + ;3.30 + ENDM ;3.30 + ;3.30 + push ds ;3.30 + mov ax, 0f000h ;loook at the model byte ;3.30 + mov ds, ax ;3.30 + cmp ds:byte ptr [0fffeh], mdl_convert ;PC convertible? ;3.30 + pop ds ;3.30 + jne Skip_EnableNMIS ;3.30 + ;3.30 + MOV AL,27H ; ENABLE Convertible NMIS ;3.30 + OUT 72H,AL ;3.30 + ;3.30 +Skip_EnableNMIS: ;3.30 + STI ;3.30 + MOV AX,code ;3.30 + MOV DS,AX ;3.30 + ASSUME DS:CODE ;3.30 + ;3.30 +; MOV SI,OFFSET STKMSG1 ;3.30 +; CALL WRMSG ;3.30 + ;3.30 + mov [INT19SEM],1 ; INDICATE THAT INT 19 ;3.30 + ; INITIALIZATION IS COMPLETE ;3.30 + ;3.30 + POP BP ; RESTORE ALL ;3.30 + POP SI ;3.30 + POP DI ;3.30 + POP DX ;3.30 + POP CX ;3.30 + POP BX ;3.30 + ;3.30 + POP ES ;3.30 + POP DS ;3.30 + assume ds:sysinitseg ;3.30 + POP AX ;3.30 + RET ;3.30 +STACKINIT ENDP ;3.30 +; ;3.30 + ;3.30 +NEW_INIT_LOOP PROC NEAR ;3.30 +;INPUT: SI=OFSET INTO VECTOR TABLE OF THE PARTICULAR INT VECTOR BEING ADJUSTED ;3.30 +; BX=ds:OFFSET OF OLDxx, WHERE WILL BE SAVED THE POINTER TO ORIGINAL OWNER;3.30 +; DX=ds:OFFSET OF INTxx, THE NEW INTERRUPT HANDLER ;3.30 +; di=offset value of Int19OLD&AA variable in BIOS. ;3.30 +; es=ZERO, SEGID OF VECTOR TABLE ;3.30 +; ds=Relocated Stack code segment ;3.30 + ;3.30 + MOV AX,es:[SI+0] ;REMEMBER OFFSET IN VECTOR ;3.30 + MOV WORD PTR ds:[BX],AX ; TO ORIGINAL OWNER in DS ;3.30 + MOV AX,es:[SI+2] ;REMEMBER SEGID IN VECTOR ;3.30 + MOV WORD PTR ds:[BX]+2,AX ; TO ORIGINAL OWNER in DS ;3.30 + push ds ;3.30 + mov ax, code ;3.30 + mov ds, ax ;Set Int19OLDxx value in BIOS for ;3.30 + mov ax,es:[si+0] ;Int 19 handler ;3.30 + mov word ptr ds:[di],ax ;3.30 + mov ax,es:[si+2] ;3.30 + mov word ptr ds:[di]+2,ax ;3.30 + pop ds ;3.30 + ;3.30 + MOV WORD PTR es:[SI+0],DX ;SET VECTOR TO POINT TO NEW INT HANDLER ;3.30 + MOV es:[SI+2],ds ;3.30 + RET ;3.30 +NEW_INIT_LOOP ENDP ;3.30 + ;3.30 diff --git a/v4.0/src/BIOS/SYSCONF.ASM b/v4.0/src/BIOS/SYSCONF.ASM new file mode 100644 index 0000000..7de3d30 --- /dev/null +++ b/v4.0/src/BIOS/SYSCONF.ASM @@ -0,0 +1,3392 @@ + PAGE ,132 ; +; SCCSID = @(#)sysconf.asm 0.0 86/10/20 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSCONF + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; P132 Multiple character device installation problem. 06/27/87 J.K. +;AN002; D24 MultiTrack= command added. 06/29/87 J.K. +;AN003; D41 REM command in CONFIG.SYS. 07/6/87 J.K. +;AN004; D184 Set DEVMARK for MEM command 08/25/87 J.K. +;AN005; P568 CONFIG.SYS parsing error with FCBS=10,15 08/31/87 J.K. +;AN006; P887 STACKS=0 does not show "ERROR in CONFIG.SYS..." 09/09/87 J.K. +;AN007; D246, P976 Show "Bad command or parameters - ..." msg 09/22/87 J.K. +;AN008; P1299 Set the second entry of DEVMARK for MEM command 09/25/87 J.K. +;AN009; P1326 New Extended attribute 09/28/87 J.K. +;AN010; P1820 New message SKL file 10/20/87 J.K. +;AN011; P1970 AUTOTEST FCBS= command error msg inconsistent 10/23/87 J.K. +;AN012; P2211 Setting the EA=7 for ANSI.SYS hangs the system 11/02/87 J.K. +;AN013; P2342 REM not allowed after INSTALL command 11/09/87 J.K. +;AN014; P2546 DEVICE= command still allowed after IFS= 11/17/87 J.K. +;AN015; D358 New device driver INIT function package 12/03/87 J.K. +;AN016; D285 Undo the extended error handling 12/17/87 J.K. +;AN017; P3170 Do not call block device driver when drive # > 26 01/20/88 J.K. +;AN018; P3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN019; D479 New option to disable extended INT 16h function call 02/12/88 J.K. +;AN020; P3607 MEM does not give correct filename 02/24/88 J.K. +;AN021; D493 Undo D358 & do not show error message for device driv 02/24/88 J.K. +;AN022; P3807 Single buffer unprotected - System hangs 03/10/88 J.K. +;AN023; P3797 An INSTALL cmd right after Bad cmd is not executed 03/10/88 J.K. +;AN024; D503 Version change to 4.0 - IBMCACHE.SYS is an exception 03/15/88 J.K. +;AN025; D474 Change BUFFERS= /E option to /X for expanded memory 03/16/88 J.K. +;AN026; D506 Take out the order dependency of the IFS= 03/28/88 J.K. +;AN027; P3957 Undo D503 - IBMCACHE.SYS version check problem 03/30/88 J.K. +;AN028; P4086 Memory allocation error when loading share.exe 03/31/88 J.K. +;AN029; D528 Install XMAEM.SYS first before everything else 04/29/88 J.K. +;AN030; P4759 INT2f, INT 67h handlers for XMA 05/11/88 J.K. +;AN031; P4889 Should check the validity of INT 67h call 05/17/88 G.A. +;AN032; P4934 P4759 INT 2fh number should be changed to 1Bh 05/20/88 J.K. +;AN033; P5002 EMS w/single page allocated now works 05/20/88 G.A. +;AN034; P5128 EMS INT 2FH HANDLER BUG 06/24/88 +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +LF equ 10 +CR equ 13 +TAB equ 9 +SEMICOLON equ ';' + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE + +HAVE_INSTALL_CMD equ 00000001b ;AN018; CONFIG.SYS has INSTALL= commands +HAS_INSTALLED equ 00000010b ;AN018; SYSINIT_BASE installed. + +IS_IFS equ 00000001b ;IFS command? +NOT_IFS equ 11111110b +; +;AN016; Undo the extended attribute handling +;;Extended attribute value +;EA_UNSPECIFIED equ 0 ;AN009; +;EA_DEVICE_DRIVER equ 6 ;AN009; +;EA_IFS_DRIVER equ 7 ;AN009; + +DEFAULT_FILENUM = 8 +; + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H +;dossize equ 0C000H ;J.K. for the debugging version of IBMDOS. + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include BIOSTRUC.INC + include smifssym.inc ;AN000; Reduced version of IFSSYM.INC. + include DEVMARK.inc ;AN004; + include version.inc +.list + + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + +; + +;J.K. 6/29/87 External variable defined in IBMBIO module for Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + +CODE segment public 'code' + EXTRN MulTrk_flag:word ;AN002; + extrn KEYRD_Func:byte ;AN019; + extrn KEYSTS_Func:byte ;AN019; +CODE ends +;J.K. 6/29/87 End of Multi-track definition. + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE + EXTRN BADSIZ_PRE:BYTE,BADLD_PRE:BYTE +; EXTRN BADSIZ_POST:BYTE,BADLD_POST:BYTE + EXTRN BADSTACK:BYTE,BADCOUNTRYCOM:BYTE + EXTRN SYSSIZE:BYTE,BADCOUNTRY:BYTE,INSUFMEMORY:BYTE + EXTRN CONDEV:BYTE,AUXDEV:BYTE,PRNDEV:BYTE,COMMND:BYTE,CONFIG:BYTE + EXTRN Cntry_Drv:BYTE,Cntry_Root:BYTE,Cntry_Path:BYTE + EXTRN DeviceParameters:byte + EXTRN MEMORY_SIZE:word + EXTRN BUFFERS:word + EXTRN FILES:byte,NUM_CDS:byte + EXTRN DOSINFO:dword,ENTRY_POINT:dword + EXTRN FCBS:byte,KEEP:byte + EXTRN CONFBOT:word,ALLOCLIM:word,COMMAND_LINE:byte + EXTRN ZERO:byte,SEPCHR:byte + EXTRN COUNT:word,CHRPTR:word,CNTRYFILEHANDLE:word + EXTRN MEMLO:word,MEMHI:word,PRMBLK:word,LDOFF:word + EXTRN PACKET:byte,UNITCOUNT:byte,BREAK_ADDR:dword + EXTRN BPB_ADDR:dword,DRIVENUMBER:byte,SYSI_COUNTRY:dword + extrn Config_Size:word ;AN000; + extrn Install_Flag:word ;AN000; + extrn BadOrder:byte ;AN000; + extrn Errorcmd:byte ;AN000; + extrn LineCount:word ;AN000; + extrn ShowCount:byte ;AN000; + extrn Buffer_LineNum:word ;AN000; + extrn IFS_Flag:word ;AN000; + extrn IFS_RH:byte ;AN000; + extrn H_Buffers:word ;AN000; + extrn Buffer_Slash_X:byte ;AN000;AN025; + extrn Badparm:byte ;AN007; + extrn ConfigMsgFlag:Word ;AN015; + extrn Org_Count:Word ;AN018; + extrn Multi_Pass_Id:byte ;AN026; + + EXTRN MEM_ERR:NEAR,SetDOSCountryInfo:NEAR + EXTRN PARAROUND:NEAR,TEMPCDS:NEAR + EXTRN Set_Country_Path:NEAR,Move_ASCIIZ:NEAR,DELIM:NEAR + EXTRN BADFIL:NEAR,ROUND:NEAR + extrn Do_Install_Exec:NEAR ;AN018; + extrn SetDevMark:NEAR ;AN030; + +;AN016; Undo the extended attribute handling +; extrn Get_Ext_Attribute:near ;AN009; + + IF STACKSW + +; Internal Stack Parameters + EntrySize equ 8 + + MinCount equ 8 + DefaultCount equ 9 + MaxCount equ 64 + + MinSize equ 32 + DefaultSize equ 128 + MaxSize equ 512 + + extrn stack_count:word + extrn stack_size:word + extrn stack_addr:dword + + ENDIF + + PUBLIC DOCONF + PUBLIC GETCHR + public Multi_Pass ;AN018;AN026; + + public MultDeviceFlag +MultDeviceFlag db 0 ;AN001; + public DevMark_Addr +DevMark_Addr dw ? ;AN004;Segment address for DEVMARK. + public SetDevMarkFlag +SetDevMarkFlag db 0 ;AN004;Flag used for DEVMARK + +EMS_Stub_Installed db 0 ;AN030; + +Badparm_Ptr label dword +Badparm_Off dw 0 ;AN007; +Badparm_Seg dw 0 ;AN007; + +XMAEM_file db 'XMAEM.SYS',0 ;AN029; + +;IBMCACHE_file db 'IBMCACHE.SYS',0;AN024;AN026;To cope with the IBMCACHE.SYS + ; problem of DOS version checking. + +;****************************************************************************** +;Take care of Config.sys file. +;SYSTEM parser data and code. +;****************************************************************************** +.xlist + include PSOPTION.INC ;Parsing options for SYSCONF. + include PARSE.ASM ;together with PSDATA.INC +.list +;Control block definitions for PARSER. +;--------------------------------------------------- +; BUFFER = [n | n,m] {/E} + +Buf_Parms label byte ;AN000; + dw Buf_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Buf_Parmsx label byte ;AN000; + db 1,2 ;AN000; Min 1, Max 2 positional + dw Buf_Pos1 ;AN000; + dw Buf_Pos2 ;AN000; + db 1 ;AN000; 1 switch + dw SW_X_Ctrl ;AN000;AN025; /X control + db 0 ;AN000; no keywords + +Buf_Pos1 label word ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no function + dw Result_Val ;AN000; Result value buffer + dw Buf_Range_1 ;AN000; value list + db 0 ;AN000; no switches/keywords + +Buf_Range_1 label byte ;AN000; value definition + db 1 ;AN000; range definition + db 1 ;AN000; 1 definition of range + db 1 ;AN000; item tag for this range + dd 1,10000 ;AN000; from 1 to 10000 + +Buf_Pos2 label word ;AN000; + dw 8001h ;AN000; Numeric value, Optional + dw 0 ;AN000; no function + dw Result_Val ;AN000; Result value buffer + dw Buf_Range_2 ;AN000; value list + db 0 ;AN000; no switches/keywords + +Buf_Range_2 label byte ;AN000; value definition + db 1 ;AN000; range definition + db 1 ;AN000; 1 definition of range + db 1 ;AN000; item tag for this range + dd 0,8 ;AN000; from 0 to 8. + +SW_X_Ctrl label word ;AN000;AN025; + dw 0 ;AN000; no matching flag + dw 0 ;AN000; no function + dw Result_Val ;AN000; return value + dw NoVal ;AN000; no value definition + db 1 ;AN000; # of switches +Switch_X label byte ;AN000;AN025; + db '/X',0 ;AN000;AN025; +;local variables +P_Buffers dw 0 ;AN000; +P_H_Buffers dw 0 ;AN000; +P_Buffer_Slash_X db 0 ;AN000;AN025; +Buffer_Pre_Scan db 0 ;AN030; + +;Common definitions ------------- +NoVal db 0 ;AN000; + +Result_Val label byte ;AN000; + db ? ;AN000; type returned + db ? ;AN000; item tag returned + dw ? ;AN000; ES:offset of the switch defined +RV_Byte label byte ;AN000; +RV_Dword label dword ;AN000; + dd ? ;AN000; value if number, or seg:offset to string. +;-------------------------------- + +; BREAK = [ ON | OFF ] + +Brk_Parms label byte ;AN000; + dw Brk_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Brk_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw Brk_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Brk_Pos label word ;AN000; + dw 2000h ;AN000; Simple string + dw 0 ;AN000; No functions + dw Result_Val ;AN000; + dw On_Off_String ;AN000; ON,OFF string descriptions + db 0 ;AN000; no keyword/switch synonyms + +On_Off_String label byte ;AN000; + db 3 ;AN000; signals that there is a string choice + db 0 ;AN000; no range definition + db 0 ;AN000; no numeric values choice + db 2 ;AN000; 2 strings for choice + db 1 ;AN000; the 1st string tag + dw On_String ;AN000; + db 2 ;AN000; the 2nd string tag + dw Off_String ;AN000; + +On_String db "ON",0 ;AN000; +Off_String db "OFF",0 ;AN000; +;local variable +P_Ctrl_Break db 0 ;AN000; local variable + +;-------------------------------- + +; COUNTRY = n {m {path}} +; or +; COUNTRY = n,,path + +Cntry_Parms label byte ;AN000; + dw Cntry_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Cntry_Parmsx label byte ;AN000; + db 1,3 ;AN000; Min 1, Max 3 positional + dw Cntry_Pos1 ;AN000; + dw Cntry_Pos2 ;AN000; + dw Cntry_Pos3 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Cntry_Pos1 label word ;AN000; control definition for positional 1 + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Cntry_Codepage_Range ;AN000; country id code range description + db 0 ;AN000; no switch/keyword synonyms + +Cntry_Codepage_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 1,999 ;AN000; + +Cntry_Pos2 label word ;AN000; control definition for positional 2 + dw 8001h ;AN000; Numeric value, optional + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Cntry_Codepage_Range ;AN000; code page range descriptions. + db 0 ;AN000; no switch/keyword synonyms + +Cntry_Pos3 label word ;AN000; control definition for positional 3 + dw 0201h ;AN000; File spec, optional + dw 0 ;AN000; No functions. Don't need to CAP. + dw Result_Val ;AN000; + dw NoVal ;AN000; no value list + db 0 ;AN000; no switch/keyword synonyms + +;Local variables +P_Cntry_Code dw 0 ;AN000; +P_Code_Page dw 0 ;AN000; + +;-------------------------------- + +; FILES = n + +Files_Parms label byte ;AN000; + dw Files_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +Files_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw Files_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +Files_Pos label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw Files_Range ;AN000; Files range description + db 0 ;AN000; no switch/keyword synonyms + +Files_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 8,255 ;AN000; +;local variable +P_Files db 0 ;AN000; + +;-------------------------------- + +; FCBS = n,m + +FCBS_Parms label byte ;AN000; + dw FCBS_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +FCBS_Parmsx label byte ;AN000; + db 2,2 ;AN000; Min 2, Max 2 positional + dw FCBS_Pos_1 ;AN000; + dw FCBS_Pos_2 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +FCBS_Pos_1 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw FCBS_Range ;AN000; FCBS range descriptions + db 0 ;AN000; no switch/keyword synonyms + +FCBS_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 1,255 ;AN000; + +FCBS_Pos_2 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw FCBS_Keep_Range ;AN000; FCBS KEEP range descriptions + db 0 ;AN000; no switch/keyword synonyms + +FCBS_Keep_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,255 ;AN000; + +;local variable +P_Fcbs db 0 ;AN000; +P_Keep db 0 ;AN000; +;-------------------------------- + +; LASTDRIVE = x + +LDRV_Parms label byte ;AN000; + dw LDRV_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +LDRV_Parmsx label byte ;AN000; + db 1,1 ;AN000; Min 1, Max 1 positional + dw LDRV_Pos ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +LDRV_Pos label byte ;AN000; + dw 0110h ;AN000; Drive only, Ignore colon. + dw 0010h ;AN000; Remove colon at end + dw Result_Val ;AN000; + dw NoVal ;AN000; No value list + db 0 ;AN000; no switch/keyword synonyms + +;local variable +P_Ldrv db 0 ;AN000; +;-------------------------------- + +; STACKS = n,m + +STKS_Parms label byte ;AN000; + dw STKS_Parmsx ;AN000; + db 1 ;AN000; An extra delimeter list + db 1 ;AN000; length is 1 + db SEMICOLON ;AN000; + +STKS_Parmsx label byte ;AN000; + db 2,2 ;AN000; Min 2, Max 2 positional + dw STKS_Pos_1 ;AN000; + dw STKS_Pos_2 ;AN000; + db 0 ;AN000; no switches + db 0 ;AN000; no keywords + +STKS_Pos_1 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw STKS_Range ;AN000; number of stack range descriptions + db 0 ;AN000; no switch/keyword synonyms + +STKS_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,64 ;AN000; + +STKS_Pos_2 label byte ;AN000; + dw 8000h ;AN000; Numeric value + dw 0 ;AN000; no functions + dw Result_Val ;AN000; + dw STK_SIZE_Range ;AN000; stack size range descriptions + db 0 ;AN000; no switch/keyword synonyms + +STK_SIZE_Range label byte ;AN000; + db 1 ;AN000; # of value definitions + db 1 ;AN000; # of ranges + db 1 ;AN000; Tag for this range + dd 0,512 ;AN000; +;local variables +P_Stack_Count dw 0 ;AN000; +P_Stack_Size dw 0 ;AN000; + +;-------------------------------- + +; MULTITRACK = [ ON | OFF ] + +MTrk_Parms label byte ;AN002; + dw MTrk_Parmsx ;AN002; + db 1 ;AN002; An extra delimeter list + db 1 ;AN002; length is 1 + db SEMICOLON ;AN002; + +MTrk_Parmsx label byte ;AN002; + db 1,1 ;AN002; Min 1, Max 1 positional + dw MTrk_Pos ;AN002; + db 0 ;AN002; no switches + db 0 ;AN002; no keywords + +MTrk_Pos label word ;AN002; + dw 2000h ;AN002; Simple string + dw 0 ;AN002; No functions + dw Result_Val ;AN002; + dw On_Off_String ;AN002; ON,OFF string descriptions + db 0 ;AN002; no keyword/switch synonyms + +;local variables +P_Mtrk db 0 ;AN002; +;-------------------------------- + +; CPSW = [ ON | OFF ] + +CPSW_Parms label byte ;AN002; + dw CPSW_Parmsx ;AN002; + db 1 ;AN002; An extra delimeter list + db 1 ;AN002; length is 1 + db SEMICOLON ;AN002; + +CPSW_Parmsx label byte ;AN002; + db 1,1 ;AN002; Min 1, Max 1 positional + dw CPSW_Pos ;AN002; + db 0 ;AN002; no switches + db 0 ;AN002; no keywords + +CPSW_Pos label word ;AN002; + dw 2000h ;AN002; Simple string + dw 0 ;AN002; No functions + dw Result_Val ;AN002; + dw On_Off_String ;AN002; ON,OFF string descriptions + db 0 ;AN002; no keyword/switch synonyms + +;local variables +P_CPSW db 0 ;AN002; + +;-------------------------------- +; SWITCHES=/K + +Swit_Parms label byte ;AN019; + dw Swit_Parmsx ;AN019; + db 1 ;AN019; An extra delimeter list + db 1 ;AN019; length is 1 + db SEMICOLON ;AN019; + +Swit_Parmsx label byte ;AN019; + db 0,0 ;AN019; No positionals + db 1 ;AN019; 1 switch for now. + dw Swit_K_Ctrl ;AN019; /K control + db 0 ;AN019; no keywords + +Swit_K_Ctrl label word ;AN019; + dw 0 ;AN019; no matching flag + dw 0 ;AN019; no function + dw Result_Val ;AN019; return value + dw NoVal ;AN019; no value definition + db 1 ;AN019; # of switches +Swit_K label byte ;AN019; + db '/K',0 ;AN019; +;local variables +P_Swit_K db 0 ;AN019; + +;****************************************************************************** + +DOCONF: + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + MOV AX,(CHAR_OPER SHL 8) ;GET SWITCH CHARACTER + INT 21H + MOV [COMMAND_LINE+1],DL ; Set in default command line + + MOV DX,OFFSET CONFIG ;NOW POINTING TO FILE DESCRIPTION + MOV AX,OPEN SHL 8 ;OPEN FILE "CONFIG.SYS" + STC ;IN CASE OF INT 24 + INT 21H ;FUNCTION REQUEST +; JC ENDCONF ;Wasn't there, or couldn't open (sickness) + jc No_Config_sys ;AN028; + JMP NOPROB ;PROBLEM WITH OPEN +No_Config_sys: ;AN028; + mov Multi_Pass_Id, 11 ;AN028; set it to unreasonable number +ENDCONF: + return + + +BADOP: MOV DX,OFFSET BADOPM ;WANT TO PRINT COMMAND ERROR "Unrecognized command..." + invoke PRINT + call Error_Line ;show "Error in CONFIG.SYS ..." . + JMP COFF + +Badop_p proc near ;AN000; +;Same thing as BADOP, but will make sure to set DS register back to SYSINITSEG +;and return back to the calller. + push cs + pop ds ;set ds to CONFIGSYS seg. + mov dx, offset badopm + invoke PRINT + call Error_Line + ret +Badop_p endp + +Badparm_p proc near ;AN007; +;Show "Bad command or parameters - xxxxxx" +;In Badparm_seg, Badparm_off -> xxxxx +; + cmp cs:Buffer_Pre_Scan, 1 ;AN030; Pre scanning Buffers ... /X? + je BadParmp_Ret ;AN030; then do not show any message. + push ds ;AN007; + push dx ;AN007; + push si ;AN007; + + push cs ;AN007; + pop ds ;AN007; + mov dx, offset Badparm ;AN007; + invoke PRINT ;AN007;"Bad command or parameters - " + lds si, Badparm_ptr ;AN007; +Badparm_Prt: ;AN007;print "xxxx" until CR. + mov dl, byte ptr [si] ;AN007; + mov ah,STD_CON_OUTPUT ;AN007; + int 21h ;AN007; + inc si ;AN007; + cmp dl, CR ;AN007; + jne Badparm_Prt ;AN007; + push cs ;AN007; + pop ds ;AN007; + mov dx, offset CRLFM ;AN007; + invoke PRINT ;AN007; + call Error_Line ;AN007; + pop si ;AN007; + pop dx ;AN007; + pop ds ;AN007; +BadParmp_Ret: ;AN030; + ret ;AN007; +Badparm_p endp + +NOPROB: ;GET FILE SIZE (NOTE < 64K!!) + MOV BX,AX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + INT 21H + MOV [COUNT],AX + XOR DX,DX + MOV AX,LSEEK SHL 8 ;Reset pointer to beginning of file + INT 21H +; MOV DX,CS + mov dx, [ConfBot] ;AN022;Use current CONFBOT value + MOV AX,[COUNT] + mov [config_size], ax ;save the size of config.sys file. + call ParaRound + SUB DX,AX + SUB DX,11H ;ROOM FOR HEADER + MOV [CONFBOT],DX ; Config starts here. New CONBOT value. + CALL TEMPCDS ; Finally get CDS to "safe" location +ASSUME DS:NOTHING,ES:NOTHING + + MOV DX,[CONFBOT] + MOV DS,DX + MOV ES,DX + XOR DX,DX + MOV CX,[COUNT] + MOV AH,READ + STC ;IN CASE OF INT 24 + INT 21H ;Function request + PUSHF +; +; Find the EOF mark in the file. If present, then trim length. + + SaveReg + MOV AL,1Ah ; eof mark + MOV DI,DX ; point ro buffer + JCXZ PutEOL ; no chars + REPNZ SCASB ; find end + JNZ PutEOL ; none found and count exahusted +; +; We found a 1A. Back up +; + DEC DI ; backup past 1A +; +; Just for the halibut, stick in an extra EOL +; +PutEOL: + MOV AL,CR + STOSB ; CR + MOV AL,LF + STOSB ; LF + SUB DI,DX ; difference moved + MOV Count,DI ; new count +; +; Restore registers +; + RestoreReg + + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + PUSH AX + MOV AH,CLOSE + INT 21H + POP AX + POPF + JC CONFERR ;IF NOT WE'VE GOT A PROBLEM + CMP CX,AX + JZ GETCOM ;COULDN'T READ THE FILE +CONFERR: + MOV DX,OFFSET CONFIG ;WANT TO PRINT CONFIG ERROR + CALL BADFIL +ENDCONV:JMP ENDCONF + +Multi_Pass: ;AN018;AN026; called to execute IFS=, INSTALL= commands + push cs ;AN018; + pop ds ;AN018; + cmp Multi_Pass_id, 10 ;J.K. + jae Endconv ;J.K. Do nothing. Just return. + push Confbot ;AN018; + pop es ;AN018; ES -> Confbot + mov si, Org_Count ;AN018; + mov Count, si ;AN018; set Count + xor si,si ;AN018; + mov Chrptr, si ;AN018; reset Chrptr, LineCount + mov LineCount, si ;AN018; + call GetChr ;AN018; + jmp Conflp ;AN018; +GETCOM: + invoke ORGANIZE ;ORGANIZE THE FILE + CALL GETCHR + +CONFLP: JC ENDCONV + call Reset_DOS_Version ;AN024;AN026; Still need to reset version even IBMDOS handles this through + ; function 4Bh call, since IBMDOS does not know when Load/Overlay call finishes. + +IF NOT BUFFERFLAG + call EMS_Stub_handler ;AN030; +ENDIF + + inc LineCount ;AN000; Increase LineCount. + mov Buffer_Pre_Scan, 0 ;AN030; Reset Buffer_Pre_Scan. + mov MultDeviceFlag,0 ;AN001; Reset MultDeviceFlag. + mov SetDevMarkFlag,0 ;AN004; Reset SetDevMarkFlag. + cmp al, LF ;AN000; LineFeed? + je Blank_Line ;AN000; then ignore this line. + MOV AH,AL + CALL GETCHR + jnc TryI ;AN000; + cmp Multi_Pass_ID, 2 ;AN026; + jae Endconv ;AN026;Do not show Badop again for multi_pass. + JMP BADOP + +COFF: PUSH CS + POP DS + invoke NEWLINE + JMP CONFLP +Blank_Line: ;AN000; + call Getchr ;AN000; + jmp CONFLP ;AN000; + +COFF_P: + push cs + pop ds + + +;J.K. 1/27/88 ;;;;;;;;;;;;;;;;;; +;To handle INSTALL= commands, we are going to use multi-pass. +;The first pass handles the other commands and only set Install_Flag when +;it finds any INSTALL command. The second pass will only handle the +;INSTALL= command. + +;------------------------------------------------------------------------------ +;INSTALL command +;------------------------------------------------------------------------------ +TRYI: + cmp Multi_Pass_Id, 0 ;AN029; the initial pass for XMAEM.SYS + je Multi_Try_XMAEM ;AN029; and BUFFERS= ... /X pre scan. + cmp Multi_Pass_Id, 2 ;AN026; the second pass for IFS= ? + je Multi_Try_J ;AN026; + cmp Multi_Pass_Id, 3 ;AN026; the third pass for INSTALL= ? + je Multi_Try_I ;AN026; + cmp ah, 'I' ;AN018; INSTALL= command? + jne TryB ;AN018; the first pass is for normal operation. + or Install_Flag, HAVE_INSTALL_CMD ;AN018; Set the flag + jmp coff ;AN018; and handles the next command + +Multi_Try_XMAEM: ;AN029; + cmp ah, 'D' ;AN029; device= command? + jne Multi_Try_Buff ;AN029; no skip it. + call Chk_XMAEM ;AN029; is it for XMAEM.SYS? + jnz Multi_Pass_FIlter ;AN029; no skip it. + mov byte ptr es:[si-1], 0FFh ;AN029; mark this command as a Null command for the next pass. + jmp TryDJ ;AN029; execute this command. +Multi_Try_Buff: ;AN030; + cmp ah, 'B' ;AN030; Buffers= command? + jne Multi_Pass_Filter ;AN030; + mov Buffer_Pre_Scan, 1 ;AN030; Set Buffer_Pre_Scan + jmp TryB ;AN030; TryB will set P_Buffer_Slash_X to non-zero value. + +Multi_Try_J: ;AN026; + cmp ah, 'J' ;AN026; IFS= command? + jne Multi_Pass_Filter ;AN026; No. Ignore this. + jmp GotJ ;AN026; Handles IFS= command. + +Multi_Try_I: ;AN026; + cmp ah, 'I' ;AN026; INSTALL= command? + jne Multi_Pass_Filter ;AN026; No. Ignore this. + call Do_Install_Exec ;Install it. + jmp Coff ;to handle next Install= command. + +Multi_Pass_Filter: ;AN023;AN026; + cmp ah, 'Y' ;AN023; Comment? + je Multi_Pass_Adjust ;AN023; + cmp ah, 'Z' ;AN023; Bad command? + je Multi_Pass_Adjust ;AN023; + cmp ah, '0' ;AN023; REM? + jne Multi_Pass_Coff ;AN023; ignore the rest of the commands. +Multi_Pass_Adjust: ;AN023; These commands need to + dec Chrptr ;AN023; adjust chrptr, count + inc Count ;AN023; for NEWLINE proc. +Multi_Pass_Coff: ;AN023; + jmp Coff ;AN018; To handle next INSTALL= commands. + +;------------------------------------------------------------------------------ + +Sysinit_Parse proc +;Set up registers for SysParse +;In) ES:SI -> command line in CONFBOT +; DI -> offset of the parse control defintion. +; +;Out) Calls SYSPARSE. +; Carry will set if Parse error. +; *** The caller should check the EOL condition by looking at AX +; *** after each call. +; *** If no parameters are found, then AX will contain a error code. +; *** If the caller needs to look at the SYNOMYM@ of the result, +; *** the caller should use CS:@ instead of ES:@. +; CX register should be set to 0 at the first time the caller calls this +; procedure. +; AX - exit code +; BL - TErminated delimeter code +; CX - new positional ordinal +; SI - set to pase scanned operand +; DX - selected result buffer + + push es ;save es,ds + push ds + + push es + pop ds ;now DS:SI -> command line + push cs + pop es ;now ES:DI -> control definition + + mov cs:Badparm_Seg,ds ;AN007;Save the pointer to the parm + mov cs:Badparm_Off,si ;AN007; we are about to parse for Badparm msg. + mov dx, 0 + call SysParse + cmp ax, $P_NO_ERROR ;no error +; $IF E,OR + JE $$LL1 + cmp ax, $P_RC_EOL ;or the end of line? +; $IF E + JNE $$IF1 +$$LL1: + clc +; $ELSE + JMP SHORT $$EN1 +$$IF1: + stc +; $ENDIF +$$EN1: + pop ds + pop es ;restore es,ds + ret +Sysinit_Parse endp + +;------------------------------------------------------------------------------ +; Buffer command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of buffers= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Buffers set * +; Buffer_Slash_X flag set if /X option chosen. * +; H_Buffers set if secondary buffer cache specified. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to Buf_Parms; /*Parse control definition*/ * +; Set DX,CX to 0; * +; Reset Buffer_Slash_X; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; if (Result_Val.$P_SYNONYM_ptr == Slash_E) then /*Not a switch * +; Buffer_Slash_X = 1 * +; else if (CX == 1) then /* first positional */ * +; Buffers = Result_Val.$P_Picked_Val; * +; else H_Buffers = Result_Val.$P_Picked_Val; * +; else {Show Error message;Error Exit} * +; }; * +; If (Buffer_Slash_X is off & Buffers > 99) then Show_Error; * +; }; * +; * +;******************************************************************************* +;TryB: CMP AH,'B' ;BUFFER COMMAND? +; JNZ TRYC +; invoke GETNUM +; JZ TryBBad ; Gotta have at least one +; CMP AX,100 ; check for max number +; JB SaveBuf +;TryBBad:JMP BadOp +;SaveBuf: +; MOV [BUFFERS],AX +;CoffJ1: JMP COFF + +TryB: + CMP AH,'B' + JNZ TryC + mov P_Buffer_Slash_X, 0 ;AN000;AN025; + mov di, offset Buf_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO4: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF4 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR4 +$$IF4: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then jmp to $Endloop for semantic check. + JE $$EN4 + cmp Result_Val.$P_SYNONYM_PTR, offset Switch_X ;AN000;AN025; +; $IF E ;AN000; + JNE $$IF8 + mov P_Buffer_Slash_X, 1 ;AN000;AN025; set the flag +; $ELSE ;AN000; + JMP SHORT $$EN8 +$$IF8: + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF10 + mov P_Buffers, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN10 +$$IF10: + mov P_H_Buffers, ax ;AN000; +; $ENDIF ;AN000; +$$EN10: +; $ENDIF ;AN000; +$$EN8: +; $ENDLOOP ;AN000; + JMP SHORT $$DO4 +$$EN4: + cmp P_Buffers, 99 ;AN000; +; $IF A,AND ;AN000; + JNA $$IF15 + cmp P_Buffer_Slash_X, 0 ;AN000;AN025; +; $IF E ;AN000; + JNE $$IF15 + call Badparm_p ;AN000; + mov P_H_Buffers, 0 ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN15 +$$IF15: + mov ax, P_Buffers ;AN000; We don't have any problem. + mov Buffers, ax ;AN000; Now, let's set it really. + mov ax, P_H_Buffers ;AN000; + mov H_Buffers, ax ;AN000; + mov al, P_Buffer_Slash_X ;AN000;AN025; + mov Buffer_Slash_X, al ;AN000;AN025; + mov ax, LineCount ;AN000; + mov Buffer_LineNum, ax ;AN000; Save the line number for the future use. +; $ENDIF ;AN000; +$$EN15: +; $ENDSRCH ;AN000; +$$SR4: + jmp Coff + +;------------------------------------------------------------------------------ +; Break command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of Break = command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn the Control-C check on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to Brk_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_Ctrl_Break, on; * +; else /*OFF */ * +; Set P_Ctrl_Break, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set Ctrl_Break check according to * +; }; * +; * +;******************************************************************************** +;TryC: CMP AH,'C' +; JZ GOTC +; JMP TRYDJ +;GOTC: +; CMP AL,'O' ;FIRST LETTER OF "ON" or "OFF" +; JNZ TryCBad +; CALL GETCHR +; JC TryCBad +; CMP AL,'N' ;SECOND LETTER OF "ON" +; JNZ TryCoff +; MOV AH,SET_CTRL_C_TRAPPING ;TURN ON CONTROL-C CHECK +; MOV AL,1 +; MOV DL,AL +; INT 21H +;CoffJ2: JMP Coff +;TryCOff:CMP AL,'F' +; JNZ TryCBad ; Check for "OFF" +; CALL GetChr +; JC TryCBad +; CMP AL,'F' +; JZ COffJ2 +;TryCBad:JMP BadOp +; +TryC: + CMP AH,'C' + JNZ TRYM + mov di, offset Brk_Parms ;AN000; + xor cx,cx ;AN000; + mov dx,cx ;AN000; +; $SEARCH ;AN000; +$$DO19: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse error + JNC $$IF19 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN000; + JMP SHORT $$SR19 +$$IF19: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN19 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF23 + mov P_Ctrl_Break, 1 ;AN000; Turn it on +; $ELSE ;AN000; + JMP SHORT $$EN23 +$$IF23: + mov P_Ctrl_Break, 0 ;AN000; Turn it off +; $ENDIF ;AN000; +$$EN23: +; $ENDLOOP ;AN000; we actually set the ctrl break + JMP SHORT $$DO19 +$$EN19: + mov ah, SET_CTRL_C_TRAPPING ;AN000; if we don't have any parse error. + mov al, 1 ;AN000; + mov dl, P_Ctrl_Break ;AN000; + Int 21h ;AN000; +; $ENDSRCH ;AN000; +$$SR19: + jmp Coff + +;------------------------------------------------------------------------------ +; MultiTrack command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of MultiTrack= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn MulTrk_Flag on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to Brk_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_Mtrk, on; * +; else /*OFF */ * +; Set P_Mtrk, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set MulTrk_Flag according to P_Mtrk. * +; * +; }; * +; * +;******************************************************************************** +TryM: ;AN002; + CMP AH,'M' ;AN002; + JNZ TRYW ;AN002; + mov di, offset Mtrk_Parms ;AN002; + xor cx,cx ;AN002; + mov dx,cx ;AN002; +; $SEARCH ;AN002; +$$DO28: + call Sysinit_Parse ;AN002; +; $EXITIF C ;AN002; Parse error + JNC $$IF28 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN002; + JMP SHORT $$SR28 +$$IF28: + cmp ax, $P_RC_EOL ;AN002; End of Line? +; $LEAVE E ;AN002; then end the $ENDLOOP + JE $$EN28 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; +; $IF E ;AN002; + JNE $$IF32 + mov P_Mtrk, 1 ;AN002; Turn it on temporarily. +; $ELSE ;AN002; + JMP SHORT $$EN32 +$$IF32: + mov P_Mtrk, 0 ;AN002; Turn it off temporarily. +; $ENDIF ;AN002; +$$EN32: +; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. + JMP SHORT $$DO28 +$$EN28: + push ds ;AN002; + mov ax, Code ;AN002; + mov ds, ax ;AN002; + assume ds:Code + cmp P_Mtrk, 0 ;AN002; +; $IF E ;AN002; + JNE $$IF36 + mov MulTrk_Flag, MULTRK_OFF2 ;AN002; 0001h +; $ELSE ;AN002; + JMP SHORT $$EN36 +$$IF36: + mov MulTrk_Flag, MULTRK_ON ;AN002; 8000h +; $ENDIF ;AN002; +$$EN36: + pop ds ;AN002; + assume ds:SYSINITSEG +; $ENDSRCH ;AN002; +$$SR28: + jmp Coff ;AN002; + +;------------------------------------------------------------------------------ +; CPSW command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the parameters of CPSW= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Turn CPSW on or off. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI to CPSW_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; if (Result_Val.$P_Item_Tag == 1) then /*ON */ * +; Set P_CPSW, on; * +; else /*OFF */ * +; Set P_CPSW, off; * +; else {Show message;Error_Exit}; * +; }; * +; If (no error) then * +; DOS function call to set CPSW according to P_CPSW. * +; }; * +; * +;******************************************************************************** +TryW: ;AN002; + CMP AH,'W' ;AN002; + JNZ TRYDJ ;AN002; + mov di, offset CPSW_Parms ;AN002; + xor cx,cx ;AN002; + mov dx,cx ;AN002; +; $SEARCH ;AN002; +$$DO40: + call Sysinit_Parse ;AN002; +; $EXITIF C ;AN002; Parse error + JNC $$IF40 + call Badparm_p ;AN007; Show message and end the serach loop. +; $ORELSE ;AN002; + JMP SHORT $$SR40 +$$IF40: + cmp ax, $P_RC_EOL ;AN002; End of Line? +; $LEAVE E ;AN002; then end the $ENDLOOP + JE $$EN40 + cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; +; $IF E ;AN002; + JNE $$IF44 + mov P_CPSW, 1 ;AN002; Turn it on temporarily. +; $ELSE ;AN002; + JMP SHORT $$EN44 +$$IF44: + mov P_CPSW, 0 ;AN002; Turn it off temporarily. +; $ENDIF ;AN002; +$$EN44: +; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. + JMP SHORT $$DO40 +$$EN40: + mov ah, SET_CTRL_C_TRAPPING ;AN000; The same function number as Ctrl_Break + mov al, 4 ;AN000; Set CPSW state function + mov dl, P_CPSW ;AN000; 0=off, 1=on + Int 21h ;AN000; +; $ENDSRCH ;AN002; +$$SR40: + jmp Coff ;AN002; + +;------------------------------------------------------------------------------ +; Device command +;------------------------------------------------------------------------------ +TRYDJ: + and cs:IFS_Flag, NOT_IFS ;AN000; Reset the flag + CMP AH,'D' + JZ GOTDJ + CMP AH,'J' + jz GOTJ + JMP TRYQ +GOTJ: ;AN000; IFS= command. + or cs:[IFS_Flag], IS_IFS ;AN000; set the flag. + cmp Multi_Pass_Id, 2 ;second pass? + je GOTDJ ;then proceed + jmp Coff ;else ignore this until the second pass. + +; jmp GOTDJ_Cont +;GOTD: +; test cs:[IFS_Flag], HAD_IFS ;AN000; Cannot have DEVICE= command after IFS= command. +; jz GOTDJ_Cont ;AN000; +; call Incorrect_Order ;AN000; Display "Incorrect order ..." msg. +; jmp COFF ;AN000; + +GOTDJ: + MOV BX,CS ;DEVICE= or IFS= command. + MOV DS,BX + + MOV WORD PTR [BPB_ADDR],SI + MOV WORD PTR [BPB_ADDR+2],ES + +;J.K. In case it is for IFS=, then set the parameter pointer. + mov word ptr [ifs_rh.IFSR_PARMS@], SI ;AN000; for IFS + mov word ptr [ifs_rh.IFSR_PARMS@+2], ES ;AN000; + + CALL ROUND +;J.K. Set up the DEVMARK entries here for MEM command. +;J.K. Only the DEVMARK_ID and DEVMARK_FILENAME will be set. +;J.K. DEVMARK_SIZE should be set after a successful process of this file. + call Set_DevMark ;AN004; + inc [MEMHI] ;AN004;Size of DEVMARK is a paragraph!! + ;Don't forget decrease MEMHI + ; with an unsuccessful process of this file!!. + XOR AX,AX + MOV WORD PTR [ENTRY_POINT],AX + MOV AX,[MEMHI] + MOV WORD PTR [ENTRY_POINT+2],AX ;SET ENTRY POINT + + IF NOT NOEXEC + MOV [LDOFF],AX ;SET LOAD OFFSET + ENDIF + + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV DX,SI ;DS:DX POINTS TO FILE NAME + + IF NOEXEC + LES BX,DWORD PTR CS:[MEMLO] + CALL LDFIL ;LOAD IN THE DEVICE DRIVER + ELSE +; We are going to open the cdevice driver and size it as is done +; in LDFIL. The reason we must do this is that EXEC does NO checking +; for us. We must make sure there is room to load the device without +; trashing SYSINIT. This code is not +; perfect (for instance .EXE device drivers are possible) because +; it does its sizing based on the assumption that the file being loaded +; is a .COM file. It is close enough to correctness to be usable. + MOV ES,AX ;ES:0 is LOAD addr + MOV AX,OPEN SHL 8 ;OPEN THE FILE + STC ;IN CASE OF INT 24 + INT 21H + JC BADLDRESET + MOV BX,AX ;Handle in BX +;AN016; UNDO THE EXTENDED ATTRIBUTE HANDLING +; call Get_Ext_Attribute ;AN009; +; jc BadLdReset ;AN009; +; test cs:[IFS_Flag], IS_IFS ;AN009; +; jnz Chk_Ext_Attr_IFS ;AN009; +; cmp al, EA_UNSPECIFIED ;AN009;Check the extended attr. for device driver +; je Ext_Attr_Ok ;AN009; Allow 0 and EA_DEVICE_DRIVER +; cmp al, EA_DEVICE_DRIVER ;AN009; +; je Ext_Attr_Ok ;AN009; +; stc ;AN012;BadLdReset depends on the carry bit. +; jmp BadLdReset ;AN009; +;Chk_Ext_Attr_IFS: ;AN009; +; cmp al, EA_IFS_DRIVER ;AN009; +; je Ext_Attr_Ok ;AN012; +; stc ;AN012; +; jmp BadLdReset ;AN012; +;Ext_Attr_Ok: ;AN009; + PUSH DX ; Save pointer to name + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JNC GO_AHEAD_LOAD + MOV AH,CLOSE ; Close file + INT 21H + POP DX ; Clean stack + STC ; Close may clear carry + JMP SHORT BADLDRESET + +GO_AHEAD_LOAD: + ; Convert size in DX:AX to para in AX + ADD AX,15 ; Round up size for conversion to para + ADC DX,0 + MOV CL,4 + SHR AX,CL + MOV CL,12 + SHL DX,CL ; Low nibble of DX to high nibble + OR AX,DX ; AX is now # of para for file + + MOV CX,ES ; CX:0 is xaddr + ADD CX,AX ; New device will take up to here + JC MEM_ERRJY ; WOW!!!! + CMP CX,CS:[ALLOCLIM] + JB OKLDX +MEM_ERRJY: + JMP MEM_ERR + +OKLDX: + POP DX ; Recover name pointer + MOV AH,CLOSE ; Close file + INT 21H + MOV BX,CS + MOV ES,BX + MOV BX,OFFSET PRMBLK ;ES:BX POINTS TO PARAMETERS + MOV AL,3 + MOV AH,EXEC + STC ;IN CASE OF INT 24 + INT 21H ;LOAD IN THE DEVICE DRIVER + ENDIF + +BADLDRESET: + PUSH DS + POP ES ;ES:SI BACK TO CONFIG.SYS + PUSH CS + POP DS ;DS BACK TO SYSINIT +ASSUME DS:SYSINITSEG + JNC GOODLD +BADBRK: + test cs:[SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip0_ResetMEMHI ;AN004; then do not + dec cs:[MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip0_ResetMEMHI: + cmp byte ptr es:[si], CR ;file name is CR? (Somebody entered "device=" without filename) + jne BADBRK_1 + jmp BADOP ;show "Unrecognized command in CONFIG.SYS" +BADBRK_1: + invoke BADLOAD + JMP COFF + +GOODLD: +;J.K. If it is IFS=, then we should set IFS_DOSCALL@ field in IFSHEADER. + test cs:[IFS_Flag], IS_IFS ;AN000; + jz Skip_IFSHEADER_Set ;AN000; + push es ;AN000; + push di ;AN000; + push ds ;AN000; + mov bx, word ptr cs:[ENTRY_POINT+2] ;AN000; + mov ds, bx ;AN000; DS:0 will be the header + les di, cs:[DosInfo] ;AN000; + mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@] ;AN000; + mov word ptr ds:[IFS_DOSCALL@], bx ;AN000; + mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@]+2 ;AN000; + mov word ptr ds:[IFS_DOSCALL@]+2, bx ;AN000; + pop ds ;AN000; + pop di ;AN000; + pop es ;AN000; +Skip_IFSHEADER_Set: ;AN000; + SaveReg ;INITIALIZE THE DEVICE +; call Chk_IBMCACHE ;AN024 IBMCACHE.SYS problem.;AN026;IBMDOS will handles this thru 4Bh call. +Restore:MOV BL,ES:[SI] ; while ((c=*p) != 0) + OR BL,BL + JZ Got + INC SI ; p++; + JMP Restore +Got: MOV BYTE PTR ES:[SI],' ' ; *p = ' '; + SaveReg + PUSH CS + POP ES + + test cs:[IFS_Flag], IS_IFS ;AN000; + jz Got_Device_Com ;AN000; + mov bx, IFS_CALL@ ;AN000; offset from the start of IFSHEADER + call CallIFS ;AN000; + jmp short End_Init_Call +Got_Device_Com: + push ds ;AN017; + push si ;AN017; + lds si, cs:[ENTRY_POINT] ;AN017; Peeks the header attribute + test word ptr ds:[si.SDEVATT], DEVTYP ;AN017;Block device driver? + jnz Got_Device_Com_Cont ;AN017;No. + lds si, cs:[DOSINFO] ;AN017; DS:SI -> SYS_VAR + cmp ds:[si.SYSI_NUMIO], 26 ;AN017; No more than 26 drive number + jb Got_Device_Com_Cont ;AN017; + pop si ;AN017; + pop ds ;AN017; + pop si ;AN017;clear the stack + pop es ;AN017; + jmp BadNumBlock ;AN017; +Got_Device_Com_Cont: ;AN017; + pop si ;AN017; + pop ds ;AN017; + MOV BX,SDEVSTRAT + invoke CALLDEV ; CallDev (SDevStrat); + MOV BX,SDEVINT + invoke CALLDEV ; CallDev (SDevInt); +End_Init_Call: + RestoreReg + MOV BYTE PTR [SI],0 ; *p = 0; + + PUSH CS + POP DS + + test [IFS_Flag], IS_IFS ;AN000; + jz Was_Device_Com ;AN000; + cmp [ifs_rh.IFSR_RETCODE], 0 ;AN000; Was a success ? + jne Erase_Dev_do ;AN000; + pop si ;AN000; restore es:si to clean up the + pop es ;AN000; stack for Set_Break call. + mov ax, word ptr [Entry_Point+2] ;AN000; Get the loaded segment + add ax, word ptr [ifs_rh.IFSR_RESSIZE] ;AN000; + mov word ptr [Break_addr], 0 ;AN000; + mov word ptr [Break_addr+2], ax ;AN000; + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004; + invoke Set_Break ;AN000; Will also check the memory size too. + push es ;AN000; Save it again, in case, for Erase_Dev_Do. + push si ;AN000; + jc Erase_Dev_do ;AN000; +Link_IFS: ;AN000; + les di, cs:[dosinfo] ;AN000; + mov cx, word ptr es:[di.SYSI_IFS] ;AN000; save old pointer + mov dx, word ptr es:[di.SYSI_IFS+2] ;AN000; + lds si, cs:[Entry_Point] ;AN000; + mov word ptr es:[di.SYSI_IFS],si ;AN000; + mov word ptr es:[di.SYSI_IFS+2], ds ;AN000; + mov word ptr ds:[si], cx ;AN000; We don't permit multiple IFSs. + mov word ptr ds:[si+2], dx ;AN000; + pop si ;AN000; Restore es:si for the next command. + pop es ;AN000; +; mov cs:[IFS_Flag], HAD_IFS ;AN014; Set the flag. + jmp COFF ;AN000; + +ERASE_DEV_do: ;AC000;; Modified to show message "Error in CONFIG.SYS..." + pop si + pop es + push cs + pop ds + test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip1_ResetMEMHI ;AN004; then do not + dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip1_ResetMEMHI: + cmp ConfigMsgFlag, 0 ;AN015; + je No_Error_Line_Msg ;AN015; + call Error_Line ;AN021; No "Error in CONFIG.SYS" msg for device driver. DCR D493 + mov ConfigMsgFlag, 0 ;AN015;AN021;Set the default value again. +No_Error_Line_Msg: ;AN015; + JMP Coff + +Was_Device_Com: ;AN000; + MOV AX,WORD PTR [BREAK_ADDR+2] + CMP AX,[MEMORY_SIZE] + JB BREAKOK + POP SI + POP ES + JMP BADBRK + +BREAKOK: + LDS DX,[ENTRY_POINT] ;SET DS:DX TO HEADER + MOV SI,DX + ADD SI,SDEVATT ;DS:SI POINTS TO ATTRIBUTES + LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO + MOV AX,DS:[SI] ;GET ATTRIBUTES + TEST AX,DEVTYP ;TEST IF BLOCK DEV + JZ ISBLOCK + or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; + invoke Set_Break ; Go ahead and alloc mem for device + jc Erase_Dev_do ;device driver's Init routien failed. + TEST AX,ISCIN ;IS IT A CONSOLE IN? + JZ TRYCLK + MOV WORD PTR ES:[DI.SYSI_CON],DX + MOV WORD PTR ES:[DI.SYSI_CON+2],DS + +TRYCLK: TEST AX,ISCLOCK ;IS IT A CLOCK DEVICE? + JZ GOLINK + MOV WORD PTR ES:[DI+SYSI_CLOCK],DX + MOV WORD PTR ES:[DI+SYSI_CLOCK+2],DS +GOLINK: JMP LINKIT + +ISBLOCK: + MOV AL,CS:[UNITCOUNT] ;IF NO UNITS FOUND, erase the device + OR AL,AL + jz Erase_Dev_do +; JNZ PERDRV +; MOV AX, -1 +; JMP ENDDEV + +PERDRV: + CBW ; WARNING NO DEVICE > 127 UNITS + MOV CX,AX + MOV DH,AH + MOV DL,ES:[DI.SYSI_NUMIO] ;GET NUMBER OF DEVICES + MOV AH,DL + ADD AH,AL ; Check for too many devices + CMP AH,26 ; 'A' - 'Z' is 26 devices + JBE OK_BLOCK +BadNumBlock: ;AN017; + PUSH CS + POP DS + MOV DX,OFFSET BADBLOCK + invoke PRINT + JMP ERASE_DEV_do + +OK_BLOCK: + or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; + invoke SET_BREAK ; Alloc the device + ADD ES:[DI.SYSI_NUMIO],AL ;UPDATE THE AMOUNT + ADD CS:DriveNumber,AL ; remember amount for next device + LDS BX,CS:[BPB_ADDR] ;POINT TO BPB ARRAY +PERUNIT: + LES BP,CS:[DOSINFO] + LES BP,DWORD PTR ES:[BP.SYSI_DPB] ;GET FIRST DPB + +SCANDPB:CMP WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + JZ FOUNDPB + LES BP,ES:[BP.DPB_NEXT_DPB] + JMP SCANDPB +FOUNDPB: + MOV AX,CS:[MEMLO] + MOV WORD PTR ES:[BP.DPB_NEXT_DPB],AX + MOV AX,CS:[MEMHI] + MOV WORD PTR ES:[BP.DPB_NEXT_DPB+2],AX + LES BP,DWORD PTR CS:[MEMLO] + ADD WORD PTR CS:[MEMLO],DPBSIZ + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004;Add DPB area for this unit + CALL ROUND ;Check for alloc error + MOV WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + MOV ES:[BP.DPB_FIRST_ACCESS],-1 + + MOV SI,[BX] ;DS:SI POINTS TO BPB + INC BX + INC BX ;POINT TO NEXT GUY + MOV WORD PTR ES:[BP.DPB_DRIVE],DX + MOV AH,SETDPB ;HIDDEN SYSTEM CALL + INT 21H + MOV AX,ES:[BP.DPB_SECTOR_SIZE] + PUSH ES + LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO + CMP AX,ES:[DI.SYSI_MAXSEC] + POP ES + ja Bad_BPB_Size_Sector + PUSH DS + PUSH DX + LDS DX,CS:[ENTRY_POINT] + MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR],DX + MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR+2],DS + POP DX + POP DS + INC DX + INC DH + LOOP PERUNIT + PUSH CS + POP DS + CALL TEMPCDS ; Set CDS for new drives + +LINKIT: + LES DI,CS:[DOSINFO] ;ES:DI = DOS TABLE + MOV CX,WORD PTR ES:[DI.SYSI_DEV] ;DX:CX = HEAD OF LIST + MOV DX,WORD PTR ES:[DI.SYSI_DEV+2] + + LDS SI,CS:[ENTRY_POINT] ;DS:SI = DEVICE LOCATION + MOV WORD PTR ES:[DI.SYSI_DEV],SI ;SET HEAD OF LIST IN DOS + MOV WORD PTR ES:[DI.SYSI_DEV+2],DS + MOV AX,DS:[SI] ;GET POINTER TO NEXT DEVICE + MOV WORD PTR CS:[ENTRY_POINT],AX ;AND SAVE IT + + MOV WORD PTR DS:[SI],CX ;LINK IN THE DRIVER + MOV WORD PTR DS:[SI+2],DX +ENDDEV: + POP SI + POP ES + INC AX ;AX = FFFF (no more devs if YES)? + JZ COFFJ3 + inc cs:MultDeviceFlag ;AN001; Possibly multiple device driver. + JMP GOODLD ;OTHERWISE PRETEND WE LOADED IT IN +COFFJ3: mov cs:MultDeviceFlag, 0 ;AN001; Reset the flag + JMP COFF + +Bad_BPB_Size_Sector: + POP SI + POP ES + MOV DX,OFFSET BADSIZ_PRE +; MOV BX,OFFSET BADSIZ_POST + mov bx, offset CRLFM ;AN???; + invoke PRNERR + test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, + jnz Skip2_ResetMEMHI ;AN004; then do not + dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. +Skip2_ResetMEMHI: + JMP COFF + + +;------------------------------------------------------------------------------ +; Country command +; J.K. The syntax is: +; COUNTRY=country id {,codepage {,path}} +; COUNTRY=country id {,,path} :Default CODEPAGE ID in DOS +;------------------------------------------------------------------------------ +TRYQ: + CMP AH,'Q' + JZ TRYQ_CONT + JMP TRYF +TRYQ_CONT: + +; invoke GETNUM +; JZ TryQBad ; 0 is never a valid code, or number is +; ; bad +; MOV BX,AX ; Country code in BX +; +; ;J.K. 5/26/86 +; MOV DX,0 ; assume no code page id +; +; invoke skip_delim ;skip the delimeters after the first num +; jc TryQ_Def_File ;no more characters left? then use default file +; cmp al, CR ; +; je TryQ_Def_File +; cmp al, LF +; jne TRYQ_YES_EXTENDED +; inc [COUNT] ;This is for NEWLINE routine in COFF. +; dec [CHRPTR] +;COFFJ41: +; JMP TryQ_Def_File ;O.K. no code page, no path specified. Use default path. +; +;TRYQ_YES_EXTENDED: +; cmp al, ',' ;was the second comma? +; jne TryQ_GETNUM +; invoke skip_delim ;Yes, skip ',' and other possible delim +; jmp short TRYQ_PATH ;and No code page id entered. +;TRYQ_GETNUM: +; invoke GETNUM +; jc TryQBadCOM ;"Country=xxx,path" will not be accepted. +;; jc TRYQ_PATH ;Codepage is not specified. No code page. +;; ;At this point, AL already contain the +;; ;first char of the PATH. +; jz TryQBad ;codepage=0 entered. Error +; mov DX, AX ;save code page in DX +; invoke skip_delim ;move CHRPTR to the path string +; jc TryQ_Def_File ;no more char? then use default filename +; cmp al, CR +; je TryQ_Def_File +; cmp al, LF +; jne TryQ_PATH ;path entered. +; inc [COUNT] +; dec [CHRPTR] +;TryQ_Def_File: +; push dx ;save code page +; mov cs:CNTRY_DRV, 0 ;flag that the default path has been used!!! +; mov dx, offset CNTRY_ROOT ;the default path +; jmp TRYQ_OPEN +; +;TryQBad: ;"Invalid country code or code page" +; STC +; MOV DX,OFFSET BADCOUNTRY +; jmp TryQChkErr +; +;TryQBadCOM: ;Error in COUNTRY command +; STC +; MOV DX,OFFSET BADCOUNTRYCOM +; jmp TryQChkErr +; +;TRYQ_PATH: ;DS - sysinitseg, ES - CONFBOT, +; mov CX, [COUNT] ;AL - the first char of path +; inc CX ;BX - country id, DX - codepage id, 0 = No code page +; mov DI, SI +;TRYQ_PATH_LOOP: ;find the end of path to put 0 after that. +; mov AL, byte ptr ES:[DI] +; call delim +; jz TRYQ_PATH_END +; cmp al, 13 +; jz TRYQ_PATH_END +; inc DI +; jmp short TRYQ_PATH_LOOP +;TryQBad_Brg:jmp short TryQBad +;TRYQ_PATH_END: +; mov es:byte ptr [di], 0 ;make it a ASCIIZ string. (Organize did not handle this string) +; push ds ;switch ds,es +; push es +; pop ds +; pop es +; +; mov di, offset CNTRY_DRV ;move the user specified path to CNTRY_DRV +; call Move_ASCIIZ +; +; push ds ;restore ds,es +; push es +; pop ds +; pop es +; +;; call Set_Country_Path ;set CNTRY_DRV +; +; push dx ;save DX +; mov dx, offset CNTRY_DRV ;Now DS:DX -> CNTRY_DRV + + mov Cntry_Drv, 0 ;AN000; Reset the drive,path to default value. + mov P_Code_Page,0 ;AN000; + mov di, offset Cntry_Parms ;AN000; + xor cx,cx ;AN000; + mov dx,cx ;AN000; +; $SEARCH ;AN000; +$$DO49: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse error, check the error code and + JNC $$IF49 + call Cntry_Error ;AN000; Show message and end the serach loop. + mov P_Cntry_Code, -1 ;AN000; Signals that parse error. +; $ORELSE ;AN000; + JMP SHORT $$SR49 +$$IF49: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $SEARCH LOOP + JE $$EN49 + cmp Result_Val.$P_TYPE, $P_NUMBER ;AN000; Numeric? +; $IF E ;AN000; + JNE $$IF53 + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF54 + mov P_Cntry_Code, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN54 +$$IF54: + mov P_Code_Page, ax ;AN000; +; $ENDIF ;AN000; +$$EN54: +; $ELSE ;AN000; Path entered. + JMP SHORT $$EN53 +$$IF53: + push ds ;AN000; + push es ;AN000; + push si ;AN000; + push di ;AN000; + push cs ;AN000; + pop es ;AN000; + lds si, RV_Dword ;AN000; Move the path to known place. + mov di, offset CNTRY_Drv ;AN000; + call Move_ASCIIZ ;AN000; + pop di ;AN000; + pop si ;AN000; + pop es ;AN000; + pop ds ;AN000; +; $ENDIF ;AN000; +$$EN53: +; $ENDLOOP + JMP SHORT $$DO49 +$$EN49: +; $ENDSRCH ;AN000; +$$SR49: + cmp P_Cntry_Code, -1 ;AN000; Had a parse error? + jne TRYQ_OPEN ;AN000; + jmp Coff ;AN000; + +TryQBad: ;"Invalid country code or code page" + STC + MOV DX,OFFSET BADCOUNTRY + jmp TryQChkErr + +TRYQ_OPEN: + cmp CNTRY_Drv, 0 ;AC000; + je TRYQ_Def ;AC000; + mov dx, offset CNTRY_Drv ;AC000; + jmp TryQ_Openit ;AC000; +TRYQ_Def: ;AC000; + mov dx, offset CNTRY_Root ;AC000; +TryQ_Openit: + mov ax, 3d00h ;open a file + stc + int 21h + jc TryQFileBad ;open failure + + mov cs:CntryFileHandle, ax ;save file handle + mov bx, ax + mov ax, cs:P_Cntry_Code ;AN000; + mov dx, cs:P_Code_Page ;AN000; Now, AX=country id, bx=filehandle +; xchg ax, bx ;now, AX = country id, BX = file handle + mov cx, cs:[MEMHI] + add cx, 128 ;I need 2K buffer to handle COUNTRY.SYS + cmp cx, cs:[ALLOCLIM] + ja TryQMemory ;cannot allocate the buffer for country.sys + + mov si, offset CNTRY_DRV ;DS:SI -> CNTRY_DRV + cmp byte ptr [si],0 ;default path? + jne TRYQ_Set_for_DOS + inc si + inc si ;DS:SI -> CNTRY_ROOT +TRYQ_Set_for_DOS: + les di, cs:SYSI_Country ;ES:DI -> country info tab in DOS + push di ;save di + add di, ccPath_CountrySys + call MOVE_ASCIIZ ;Set the path to COUNTRY.SYS in DOS. + pop di ;ES:DI -> country info tab again. + mov cx, cs:[MEMHI] + mov ds, cx + xor si, si ;DS:SI -> 2K buffer to be used. + call SetDOSCountryInfo ;now do the job!!! + jnc TryQchkERR ;read error or could not find country,code page combination + cmp cx, -1 ;Could not find matching country_id,code page? + je TryQBad ;then "Invalid country code or code page" +TryQFileBad: + push cs ;AN000; + pop es ;AN000; + cmp cs:CNTRY_DRV,0 ;Is the default file used? + je TryQDefBad +; mov si, cs:[CONFBOT] +; mov es, si +; mov si, cs:[CHRPTR] +; dec si ;ES:SI -> path in CONFBOT + mov si, offset CNTRY_Drv + jmp short TryQBADLOAD +TryQDefBad: ;Default file has been used. +; push cs +; pop es + mov si, offset CNTRY_ROOT ;ES:SI -> \COUNTRY.SYS in SYSINIT_SEG +TryQBADLOAD: + call BADLOAD ;DS will be restored to SYSINIT_SEG + mov cx, cs:[CONFBOT] + mov es, cx ;Restore ES -> CONFBOT. + jmp short CoffJ4 +TryQMemory: + MOV DX,OFFSET INSUFMEMORY +TryQChkErr: + mov cx, cs:[CONFBOT] + mov es, cx ;restore ES -> CONFBOT seg + push cs + pop ds ;retore DS to SYSINIT_SEG + jnc CoffJ4 ;if no error, then exit + invoke PRINT ;else show error message + call Error_Line ;AN000; +CoffJ4: + mov bx, CntryFileHandle + mov ah, 3eh + int 21h ;close a file. Don't care even if it fails. + JMP COFF + +Cntry_Error proc near +;Function: Show "Invalid country code or code page" messages, or +; "Error in COUNTRY command" depending on the error code +; in AX returned by SYSPARSE; +;In: AX - error code +; DS - Sysinitseg +; ES - CONFBOT +;Out: Show message. DX destroyed. + + cmp ax, $P_OUT_OF_RANGE +; $IF E + JNE $$IF61 + mov dx, offset BadCountry ;"Invalid country code or code page" +; $ELSE + JMP SHORT $$EN61 +$$IF61: + mov dx, offset BadCountryCom ;"Error in CONTRY command" +; $ENDIF +$$EN61: + invoke Print + call Error_Line + ret +Cntry_Error endp + +;------------------------------------------------------------------------------ +; Files command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of FILES= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Variable FILES set. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to FILES_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; Files = Result_Val.$P_Picked_Val * +; else * +; Error Exit; * +; }; * +; }; * +; * +;******************************************************************************* +TRYF: + CMP AH,'F' + JNZ TRYL + +; invoke GETNUM +; CMP AX,5 ;j.k. change it to 8!!!!!!!! +; JB TryFBad ; Gotta have at least 5 +; CMP AX,256 +; JAE TryFBad ; Has to be a byte +; MOV [FILES],AL +;CoffJ5: JMP COFF +;TryFBad:JMP BadOp + + mov di, offset Files_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO64: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF64 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR64 +$$IF64: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN64 + mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; + mov P_Files, al ;AN000; Save it temporarily +; $ENDLOOP ;AN000; + JMP SHORT $$DO64 +$$EN64: + mov al, P_Files ;AN000; + mov Files, al ;AN000; No error. Really set the value now. +; $ENDSRCH ;AN000; +$$SR64: + jmp Coff + +;------------------------------------------------------------------------------ +; LastDrive command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of LASTDRIVE= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variable NUM_CDS. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to LDRV_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; Set NUM_CDS to the returned value; * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; }; * +; * +;******************************************************************************* +TRYL: + CMP AH,'L' + JNZ TRYP + +; OR AL,020h +; SUB AL,'a' +; JB TryLBad +; INC AL +; CMP AL,26 ; a-z are allowed +; JA TryLBad +; MOV [NUM_CDS],AL +;CoffJ6: JMP COFF +;TryLBad:JMP BadOp + + mov di, offset LDRV_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO70: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF70 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR70 +$$IF70: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN70 + mov al, RV_Byte ;AN000; Pick up the drive number + mov P_Ldrv, al ;AN000; Save it temporarily +; $ENDLOOP ;AN000; + JMP SHORT $$DO70 +$$EN70: + mov al, P_Ldrv ;AN000; +; sub al, 'A' ;AN000; Convert it to drive number +; inc al ;AN000; make it to be a number of drives. + mov Num_CDS, al ;AN000; No error. Really set the value now. +; $ENDSRCH ;AN000; +$$SR70: + jmp Coff + + +;------------------------------------------------------------------------------- +; Setting Drive Parameters +;------------------------------------------------------------------------------- +TRYP: + CMP AH,'P' + JNZ TRYK + invoke PARSELINE + JC TryPBad + invoke SETPARMS + INVOKE DIDDLEBACK + jc TryPBad + JMP COFF +TryPBad:jmp Badop +;------------------------------------------------------------------------------- +; Setting Internal Stack Parameters +; STACKS=M,N where +; M is the number of stacks (range 8 to 64, default 9) +; N is the stack size (range 32 to 512 bytes, default 128) +; J.K. 5/5/86: STACKS=0,0 implies no stack installation. +; Any combinations that are not within the specified limits will +; result in "Unrecognized command" error. +;------------------------------------------------------------------------------- +;******************************************************************************* +; * +; Function: Parse the parameters of STACKS= command. * +; The minimum value for "number of stacks" and "stack size" is * +; 8 and 32 each. In the definition of SYSPARSE value list, they * +; are set to 0. This is for accepting the exceptional case of * +; STACKS=0,0 case (,which means do not install the stack.) * +; So, after SYSPARSE is done, we have to check if the entered * +; values (STACK_COUNT, STACK_SIZE) are within the actual range, * +; (or if "0,0" pair has been entered.) * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variables STACK_COUNT, STACK_SIZE. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to STKS_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_Parse; * +; if (no error) then * +; { if (CX == 1) then /* first positional = stack count */ * +; P_Stack_Count = Result_Val.$P_Picked_Val; * +; if (CX == 2) then /* second positional = stack size */ * +; P_Stack_Size = Result_Val.$P_Picked_Val; * +; } * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; Here check P_STACK_COUNT,P_STACK_SIZE if it meets the condition; * +; If O.K., then set Stack_Count, Stack_Size; * +; else Error_Exit; * +; }; * +;******************************************************************************* +TRYK: + CMP AH,'K' + JE Do_TryK + jmp TRYS + + IF STACKSW + +; MOV SepChr,',' +; INVOKE GetNum ; Get number of stacks +; MOV SepChr,0 +; cmp ax, 0 ;J.K. 5/5/86 +; je TRYK_0 ;J.K. Let's accept 0. +; CMP AX, MinCount ; 8 <= Number of Stacks <= 64 +; JB TryKBad +; CMP AX, MaxCount +; JA TryKBad +;TRYK_0: +; MOV [STACK_COUNT], AX +; +; Skip delimiters after the first number. +; +; invoke Skip_delim ;J.K. +; JC TryKBad +; +; INVOKE GetNum ; Get size of individual stack +; JC TryKBad ; Number bad +; +; cmp ax, 0 ;J.K. 5/5/86 +; je TRYK_SIZE0 ;J.K. 5/5/86. Accept 0 +; +; CMP AX, MinSize ; 32 <= Stack Size <= 512 +; JB TryKBad +; CMP AX, MaxSize +; JA TryKBad +;TRYK_SIZE0: +; MOV [STACK_SIZE], AX +; cmp ax,0 +; je TRYK_BOTH0 +;TRYK_OK: +; mov word ptr [stack_addr], -1 ;set the flag that the user entered stacks= command. +; JMP COFF +;TRYK_BOTH0: +; cmp [STACK_COUNT],0 ;stack_size = 0. Stack_Count = 0 too? +; je TRYK_OK ;yes. accepted. +;TryKBad: +; MOV DX, OFFSET BADSTACK ;J.K. 5/26/86 "Invalid stack parameter" +; invoke PRINT +; JMP COFF + +Do_TryK: + mov di, offset STKS_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO76: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF76 + mov dx, offset BadStack ;AN000; "Invalid stack parameter" + call Print ;AN000; and Show messages and end the search loop. + call Error_Line ;AN006; +; $ORELSE ;AN000; + JMP SHORT $$SR76 +$$IF76: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN76 + mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; +; $IF E ;AN000; + JNE $$IF80 + mov P_Stack_Count, ax ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN80 +$$IF80: + mov P_Stack_Size, ax ;AN000; +; $ENDIF ;AN000; +$$EN80: +; $ENDLOOP ;AN000; + JMP SHORT $$DO76 +$$EN76: + cmp P_Stack_Count, 0 ;AN000; +; $IF NE ;AN000; + JE $$IF84 + cmp P_Stack_Count, MINCOUNT ;AN000; +; $IF B,OR ;AN000; + JB $$LL85 + cmp P_Stack_Size, MINSIZE ;AN000; +; $IF B ;AN000; + JNB $$IF85 +$$LL85: + mov P_Stack_Count, -1 ;AN000; Invalid +; $ENDIF ;AN000; +$$IF85: +; $ELSE ;AN000; + JMP SHORT $$EN84 +$$IF84: + cmp P_Stack_Size, 0 ;AN000; +; $IF NE ;AN000; + JE $$IF88 + mov P_Stack_Count, -1 ;AN000; Invalid +; $ENDIF ;AN000; +$$IF88: +; $ENDIF ;AN000; +$$EN84: + cmp P_Stack_Count, -1 ;AN000; Invalid? +; $IF E ;AN000; + JNE $$IF91 + mov Stack_Count, DEFAULTCOUNT ;AN000;Reset to default value. + mov Stack_Size, DEFAULTSIZE ;AN000; + mov word ptr STACK_ADDR, 0 ;AN000; + mov dx, offset BadStack ;AN000; + call Print ;AN000; + call Error_Line ;AN006; +; $ELSE ;AN000; + JMP SHORT $$EN91 +$$IF91: + mov ax, P_Stack_Count ;AN000; + mov Stack_Count, ax ;AN000; + mov ax, P_Stack_Size ;AN000; + mov Stack_Size, ax ;AN000; + mov word ptr Stack_Addr, -1 ;AN000;STACKS= been accepted. +; $ENDIF ;AN000; +$$EN91: +; $ENDSRCH ;AN000; +$$SR76: + jmp Coff + ENDIF +;------------------------------------------------------------------------------ +; Switch command ;No longer supported. +;------------------------------------------------------------------------------ +;TRYW: +; CMP AH,'W' +; JNZ TRYA +; JMP BadOp ; no longer implemented +; MOV DL,AL +; MOV AX,(CHAR_OPER SHL 8) OR 1 ;SET SWITCH CHARACTER +; MOV [COMMAND_LINE+1],DL +; INT 21H +; JMP COFF +;------------------------------------------------------------------------------ +; Availdev command ;No longer supported. +;------------------------------------------------------------------------------ +;TRYA: +; CMP AH,'A' +; JNZ TRYS +; JMP BadOp ; NO LONGER IMPLEMENTED +; CMP AL,'F' ;FIRST LETTER OF "FALSE" +; JNZ COFFJ7 +; MOV AX,(CHAR_OPER SHL 8) OR 3 ;TURN ON "/DEV" PREFIX +; XOR DL,DL +; INT 21H +;COFFJ7: JMP COFF + +;------------------------------------------------------------------------------ +; shell command +;------------------------------------------------------------------------------ +TRYS: + CMP AH,'S' + JNZ TRYX + MOV [COMMAND_LINE+1],0 + MOV DI,OFFSET COMMND + 1 + MOV [DI-1],AL +STORESHELL: + CALL GETCHR + OR AL,AL + JZ GETSHPARMS + CMP AL," " + JB ENDSH + MOV [DI],AL + INC DI + JMP STORESHELL + +ENDSH: + MOV BYTE PTR [DI],0 + CALL GETCHR + CMP AL,LF + JNZ CONV + CALL GETCHR +CONV: JMP CONFLP + +GETSHPARMS: + MOV BYTE PTR [DI],0 + MOV DI,OFFSET COMMAND_LINE+1 +PARMLOOP: + CALL GETCHR + CMP AL," " + JB ENDSH + MOV [DI],AL + INC DI + JMP PARMLOOP + +;------------------------------------------------------------------------------ +; FCBS Command +;------------------------------------------------------------------------------ +;******************************************************************************* +; Function: Parse the parameters of FCBS= command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; Set the variables FCBS, KEEP. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to FCBS_Parms; * +; Set DX,CX to 0; * +; While (End of command line) * +; { SYSPARSE; * +; if (no error) then * +; { if (CX == 1) then /* first positional = FCBS */ * +; FCBS = Result_Val.$P_Picked_Val; * +; if (CX == 2) then /* second positional = KEEP */ * +; KEEP = Result_Val.$P_Picked_Val; * +; } * +; else /*Error exit*/ * +; Error Exit; * +; }; * +; }; * +;******************************************************************************* +TRYX: + CMP AH,'X' + JNZ TRYY +; invoke GETNUM +; JZ TryXBad ; gotta have at least one +; CMP AX,256 +; JAE TryXBad ; Can't be more than 8 bits worth +; MOV [FCBS],AL +; +; Skip delimiters after the first number including "," +; +; invoke Skip_delim ;J.K. +; jc tryxbad +; invoke GetNum +; JC TryXBad ; Number bad (Zero is OK here) +; CMP AX,256 +; JAE TryXBad +; CMP AL,FCBS +; JA TryXBad +; MOV Keep,AL +; JMP COFF +;TryXBad:JMP BadOp + + mov di, offset FCBS_Parms ;AN000; + xor cx, cx ;AN000; + mov dx, cx ;AN000; + +; $SEARCH ;AN000; +$$DO95: + call Sysinit_Parse ;AN000; +; $EXITIF C ;AN000; Parse Error, + JNC $$IF95 + call Badparm_p ;AN007; and Show messages and end the search loop. +; $ORELSE ;AN000; + JMP SHORT $$SR95 +$$IF95: + cmp ax, $P_RC_EOL ;AN000; End of Line? +; $LEAVE E ;AN000; then end the $ENDLOOP + JE $$EN95 + mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; + cmp cx, 1 ;AN000; The first positional? +; $IF E ;AN000; + JNE $$IF99 + mov P_Fcbs, al ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN99 +$$IF99: + mov P_Keep, al ;AN000; +; $ENDIF ;AN000; +$$EN99: +; $ENDLOOP ;AN000; + JMP SHORT $$DO95 +$$EN95: + mov al, P_Fcbs ;AN005;make sure P_Fcbs >= P_Keep + cmp al, P_Keep ;AN005; +; $IF B ;AN005; + JNB $$IF103 +; call Badop_p ;AN005; + call Badparm_p ;AN011;show "Bad parameter -" msg. + mov P_Keep, 0 ;AN005; +; $ELSE ;AN005; + JMP SHORT $$EN103 +$$IF103: + mov Fcbs, al ;AN000; No error. Really set the value now. + mov al, P_Keep ;AN000; + mov Keep, al ;AN000; +; $ENDIF ;AN005; +$$EN103: +; $ENDSRCH ;AN000; +$$SR95: + jmp Coff + +;------------------------------------------------------------------------------ +; Comment= Do nothing. Just decrese CHRPTR, and increase COUNT for correct +; line number +;------------------------------------------------------------------------------ +TRYY: ;AN000; + cmp ah, 'Y' ;AN000; + jne Try0 ;AN000; +DoNothing: + dec CHRPTR ;AN000; + inc COUNT ;AN000; + jmp COFF ;AN000; + +;------------------------------------------------------------------------------ +; REM command +;------------------------------------------------------------------------------ +Try0: ;AN003;do nothing with this line. + cmp ah, '0' ;AN003; + je DoNothing ;AN003; + +;------------------------------------------------------------------------------ +; SWITCHES command +;------------------------------------------------------------------------------ +;******************************************************************************* +; * +; Function: Parse the option switches specified. * +; Note - This command is intended for the future use also. When we need to * +; to set system data flag, use this command. * +; * +; Input : * +; ES:SI -> parameters in command line. * +; Output: * +; P_Swit_K set if /K option chosen. * +; * +; Subroutines to be called: * +; Sysinit_Parse * +; Logic: * +; { * +; Set DI points to Swit_Parms; /*Parse control definition*/ * +; Set DX,CX to 0; * +; While (End of command line) * +; { Sysinit_parse; * +; if (no error) then * +; if (Result_Val.$P_SYNONYM_ptr == Swit_K) then * +; P_Swit_K = 1 * +; endif * +; else {Show Error message;Error Exit} * +; }; * +; }; * +; * +;******************************************************************************* + + cmp ah, '1' ;AN019;Switches= command entered? + jne Tryz ;AN019; + + mov di, offset Swit_Parms ;AN019; + xor cx, cx ;AN019; + mov dx, cx ;AN019; + +; $SEARCH ;AN019; +$$DO107: + call Sysinit_Parse ;AN019; +; $EXITIF C ;AN019; Parse Error, + JNC $$IF107 + call Badparm_p ;AN019; and Show messages and end the search loop. +; $ORELSE ;AN019; + JMP SHORT $$SR107 +$$IF107: + cmp ax, $P_RC_EOL ;AN019; End of Line? +; $LEAVE E ;AN019; then jmp to $Endloop for semantic check. + JE $$EN107 + cmp Result_Val.$P_SYNONYM_PTR, offset Swit_K ;AN019; +; $IF E ;AN019; + JNE $$IF111 + mov P_Swit_K, 1 ;AN019; set the flag +; $ENDIF ;AN019; +$$IF111: +; $ENDLOOP ;AN019; + JMP SHORT $$DO107 +$$EN107: + cmp P_Swit_K, 1 ;AN019;If /K entered, + push ds ;AN019; + mov ax, Code ;AN019; + mov ds, ax ;AN019; + assume ds:Code ;AN019; +; $IF E ;AN019; + JNE $$IF114 + mov KEYRD_Func, 0 ;AN019;Use the conventional keyboard functions + mov KEYSTS_Func, 1 ;AN019; +; $ENDIF ;AN019; +$$IF114: + pop ds ;AN019; + assume ds:SYSINITSEG ;AN019; +; $ENDSRCH ;AN019; +$$SR107: + jmp Coff ;AN019; + +;------------------------------------------------------------------------------ +; Bogus command +;------------------------------------------------------------------------------ +TRYZ: + cmp ah, 0FFh ;AN029; + je TryFF ;AN029; + dec CHRPTR + inc COUNT + JMP BADOP + +;------------------------------------------------------------------------------ +; Null command +;------------------------------------------------------------------------------ +TryFF: ;AN029;Skip this command. + jmp DoNothing ;AN029; + +GETCHR: + PUSH CX + MOV CX,COUNT + JCXZ NOCHAR + MOV SI,CHRPTR + MOV AL,ES:[SI] + DEC COUNT + INC CHRPTR + CLC +GET_RET: + POP CX + return +NOCHAR: STC + JMP SHORT GET_RET + +Incorrect_Order proc near ;AN000; +;Show "Incorrect order in CONFIG.SYS ..." message. + mov dx, offset BADORDER ;AN000; + call print ;AN000; + call ShowLineNum ;AN000; + ret ;AN000; +Incorrect_Order endp ;AN000; +; + public Error_Line +Error_Line proc near ;AN000; +;Show "Error in CONFIG.SYS ..." message. + push cs ;AN000; + pop ds ;AN000; + mov dx, offset ErrorCmd ;AN000; + call print ;AN000; + call ShowLineNum ;AN000; + ret ;AN000; +Error_Line endp ;AN000; +; +ShowLineNum proc near ;AN000; +;J.K. Convert the binary LineCount to Decimal ASCII string in ShowCount +;and Display Showcount at the current curser position. +;In.) LineCount +; +;Out) the number is printed. + push es ;AN000; + push ds ;AN000; + push di ;AN000; + + push cs ;AN000; + pop es ;AN000; es=cs + push cs ;AN000; + pop ds ;AN000; + +; mov ax, ' ' +; mov di, offset ShowCount ;clean it up. +; stosw +; stosw +; stosb ;lenght of ShowCount is 5. +; dec di ;let DI points to the least significant ASCII field. + + mov di, offset ShowCount+4 ;AN000; DI -> the least significant decimal field. + mov cx, 10 ;AN000; decimal devide factor + mov ax, cs:LineCount ;AN000; +SLN_Loop: ;AN000; + cmp ax, 10 ;AN000; < 10? + jb SLN_Last ;AN000; + xor dx,dx ;AN000; + div cx ;AN000; + or dl, 30h ;AN000; add "0" (= 30h) to make it an ascii. + mov [di],dl ;AN000; + dec di ;AN000; + jmp SLN_Loop ;AN000; +SLN_Last: ;AN000; + or al, 30h ;AN000; + mov [di],al ;AN000; + mov dx, di ;AN000; + call print ;AN000; show it. + pop di ;AN000; + pop ds ;AN000; + pop es ;AN000; + ret ;AN000; +ShowLineNum endp ;AN000; + + +CallIFS proc near ;AN000; +;******************************************************************************* +; Function: Interface to IFS call. This procedure will call IFS_CALL@ * +; * +; Input : * +; Entry_Point - Segment:Offset of loaded IFS. * +; BX = IFS_CALL@ (offset of IFS_CALL@ from the IFS header) * +; ES = Segment of IFS request header * +; IFS_Packet - IFS Request packet * +; * +; Output: Nothing * +;******************************************************************************* + push ax ;AN000; + mov ds, word ptr cs:[Entry_Point+2] ;AN000; + add bx, word ptr cs:[Entry_Point] ;AN000; DS:[BX] = Real IFS_CALL@ addr. + mov ax, ds:[bx] ;AN000; save it + push word ptr cs:[Entry_Point] ;AN000; save Entry point offset + mov word ptr cs:[Entry_Point], ax ;AN000; set for the call + mov bx, offset IFS_RH ;AN000; Now, ES:BX -> Request packet + call cs:[Entry_Point] ;AN000; Far call + pop word ptr cs:[Entry_Point] ;AN000; Restore Entry point offset + pop ax ;AN000; + ret ;AN000; +CallIFS endp ;AN000; + + +Set_DevMark proc near ;AN004; +;******************************************************************************* +; Function: Set a paragraph of informations infront of a Device file or * +; an IFS file to be loaded for MEM command. * +; The structure is: * +; DEVMARK_ID byte "D" for device, "I" for IFS * +; DEVMARK_SIZE size in para for the device loaded * +; DEVMARK_FILENAME 11 bytes. Filename * +; * +; Input : * +; [MEMHI] = address to set up DEVMARK. * +; [MEMLO] = 0 * +; ES:SI -> pointer to [drive][path]filename,0 * +; [IFS_Flag] = IS_IFS bit set if IFS= command. * +; * +; Output: DEVMARK_ID, DEVMARK_FILENAME set * +; cs:[DevMark_addr] set. * +; AX, CX register destroyed. * +;******************************************************************************* + push ds ;AN004; + push si ;AN004; + push es ;AN004; + push di ;AN004; + + mov di, cs:[MEMHI] ;AN004; + mov ds, di ;AN004; + assume ds:nothing ;AN004; + mov [DevMark_Addr], di ;AN004; save the DEVMARK address for the future. + test [IFS_Flag], IS_IFS ;AN004; + jnz SDVMK_IFS ;AN004; + mov al, DEVMARK_DEVICE ;AN004; ='D' + jmp short SDVMK_ID ;AN004; +SDVMK_IFS: + mov al, DEVMARK_IFS ;AN004; ='I' +SDVMK_ID: ;AN004; + mov ds:[DEVMARK_ID], al ;AN004; + inc di ;AN008; + mov ds:[DEVMARK_SEG], di ;AN008; + xor al,al ;AN004; + push si ;AN004; + pop di ;AN004; now es:si = es:di = [path]filename,0 + mov cx, 128 ;AN004; Maximum 128 char + repnz scasb ;AN004; find 0 + dec di ;AN020; Now es:di-> 0 +SDVMK_Backward: ;AN004; find the pointer to the start of the filename. + mov al, byte ptr es:[di] ;AN004;;AN020;We do this by check es:di backward until + cmp al, '\' ;AN004;;AN020; DI = SI or DI -> '\' or DI -> ':'. + je SDVMK_GotFile ;AN004;;AN020; + cmp al, ':' ;AN004; + je SDVMK_GotFile ;AN004; + cmp di, si ;AN004; + je SDVMK_FilePtr ;AN004; + dec di ;AN004; + jmp SDVMK_BackWard ;AN004; +SDVMK_GotFile: ;AN004; + inc di ;AN004; +SDVMK_FilePtr: ;AN004; now es:di -> start of file name + push di ;AN004; + pop si ;AN004; save di to si. + push ds ;AN004; switch es, ds + push es ;AN004; + pop ds ;AN004; + pop es ;AN004; now, ds:si -> start of filename + mov di, DEVMARK_FILENAME ;AN004; + push di ;AN004; + mov al, ' ' ;AN004; + mov cx, 8 ;AN004; + rep stosb ;AN004; Clean up Memory. + pop di ;AN004; + mov cx, 8 ;AN004; Max 8 char. only +SDVMK_Loop: ;AN004; + lodsb ;AN004; + cmp al, '.' ;AN004; + je SDVMK_Done ;AN004; + cmp al, 0 ;AN004; + je SDVMK_Done ;AN004; + stosb ;AN004; + loop SDVMK_Loop ;AN004; +SDVMK_Done: ;AN004; + pop di ;AN004; + pop es ;AN004; + pop si ;AN004; + pop ds ;AN004; + ret ;AN004; +Set_DevMark endp ;AN004; + +Chk_XMAEM proc near ;AN029; +;Function: Check XMAEM.SYS file name. +;In: ES:SI -> path, filename, 0 +;out: if XMAEM.SYS, then zero flag set. + + push es ;AN029; + push si ;AN029; + push ds ;AN029; + push di ;AN029; + push cx ;AN029; + mov di, si ;AN029;save current starting pointer +CX_Cmp: ;AN029; + cmp byte ptr es:[si], 0 ;AN029; + je CX_Endfile ;AN029; + inc si ;AN029; + jmp CX_Cmp ;AN029; +CX_Endfile: ;AN029; + dec si ;AN029; + cmp byte ptr es:[si], '\' ;AN029; + je CX_Got_Tail ;AN029; + cmp byte ptr es:[si], ':' ;AN029; + je CX_Got_Tail ;AN029; + cmp di, si ;AN029; + je CX_Got_Tail0 ;AN029; + jmp CX_Endfile ;AN029; +CX_Got_Tail: ;AN029; + inc si ;AN029; +CX_Got_Tail0: ;AN029; + push cs ;AN029; + pop ds ;AN029; + push si ;AN029; + pop di ;AN029;now es:di -> filename,0 + mov cx, 9 ;AN029; + mov si, offset XMAEM_File ;AN029;ds:si -> XMAEM.SYS,0 + repe cmpsb ;AN029; +CX_Ret: ;AN029; + pop cx ;AN029; + pop di ;AN029; + pop ds ;AN029; + pop si ;AN029; + pop es ;AN029; + ret ;AN029; +Chk_XMAEM endp + +;Chk_IBMCACHE proc near ;AN024;AN026; Don't need this any more. + ; IBMDOS is going to handle this through 4Bh call. +;Function: IBMCACHE.SYS does not handle a DOS version 4.0 or above. +; So, this procedure will check if the device driver is IBMCACHE.SYS. +; If it is, through new INT 2fh interface "Set/Restore DOS version" +; AX=122Fh +; DX= 0 ; reset +; otherwise ; DH = minor version, DL = major version +; INT 2fh +;In: ES:SI -> path, filename, 0 +;out: if IBMCACHE.SYS, then DOS version changed to 4.00 temporarily. +; Reset_Dos_Version proc will later reset it back to current DOS version 4.0. + +; push es ;AN024; +; push si ;AN024; +; push ds ;AN024; +; push di ;AN024; +; push cx ;AN024; +; mov di, si ;AN024;save current starting pointer +;CIC_Cmp: ;AN024; +; cmp byte ptr es:[si], 0 ;AN024; +; je CIC_Endfile ;AN024; +; inc si ;AN024; +; jmp CIC_Cmp ;AN024; +;CIC_Endfile: ;AN024; +; dec si ;AN024; +; cmp byte ptr es:[si], '\' ;AN024; +; je CIC_Got_Tail ;AN024; +; cmp byte ptr es:[si], ':' ;AN024; +; je CIC_Got_Tail ;AN024; +; cmp di, si ;AN024; +; je CIC_Got_Tail0 ;AN024; +; jmp CIC_Endfile ;AN024; +;CIC_Got_Tail: ;AN024; +; inc si ;AN024; +;CIC_Got_Tail0: ;AN024; +; push cs ;AN024; +; pop ds ;AN024; +; push si ;AN024; +; pop di ;AN024;now es:di -> filename,0 +; mov cx, 12 ;AN024; +; mov si, offset IBMCACHE_File ;AN024;ds:si -> IBMCACHE.SYS,0 +; repe cmpsb ;AN024; +; jnz CIC_ret ;AN024; +; mov ax, 122Fh ;AN024;Change DOS version to +; mov dx, 2803h ;AN024; DOS 3.4 temporarily. +; int 2fh ;AN024; +;CIC_Ret: ;AN024; +; pop cx ;AN024; +; pop di ;AN024; +; pop ds ;AN024; +; pop si ;AN024; +; pop es ;AN024; +; ret ;AN024; +;Chk_IBMCACHE endp +; + +Reset_DOS_Version proc near ;AN024; +;Function: issue AX=122Fh, DX=0, INT 2fh to restore the DOS version. + push ax ;AN024; + push dx ;AN024; + mov ax, 122Fh ;AN024; + mov dx, 0 ;AN024; + int 2fh ;AN024; + pop dx ;AN024; + pop ax ;AN024; + ret ;AN024; +Reset_DOS_Version endp + + +;Int 2F EMS handler + Int 67h handler for EMS +;========================================================================= +; Int_2F_EMS - This routine provides support for VDISK, +; FASTOPEN, and BUFFERS to determine the physical +; EMS pages available for their usage. +; +; Inputs : AH - Function code (18h) to return available phys. page +; DI - FEh (Signals to return useable page for VDISK & FASTOPEN) +; FFh (Signals to return useable page for BUFFERS) +; +; AL = 0 is for installation check. - J.K. +; +; Outputs : ES - Segment value for physical page +; DI - Physical Page number +; AH - Non-zero (physical page not available) +; Zero (valid physical page data returned) +; +; For installation check, AL = 0FFh for being present. - J.K. +; For the other functions, AX = 0 for successful op. +; AX = -1 for an error. +; +; Date : 5/5/88 +; Release : DOS 4.0 +;========================================================================= + +;Int_2F_Handler proc ;traps Int_2f and checks for EMS ;an000; dms; + +EMS_STUB_START label byte ;AN030;J.K. +;Dummy DEVICE HEADER for other dummy ;AN031; Symphony assumes int 67h handler seg as a device driver! + DD -1 ;AN031;becomes pointer to next device header + DW 0C040H ;AN031;attribute (character device) + DW 0000 ;AN031;pointer to harzard area. System will hang. + DW 0000 ;AN031;pointer to harzard area. System will hang. + DB 'EMMXXXX0' ;AN031;device name + +INTV2F equ $-EMS_STUB_START ;AN030;J.K.pointer to old 2Fh handler ;an000; dms; +IntV2FO DW ? ;AN030;;offset ;an000; dms; +IntV2FS DW ? ;AN030;;segment ;an000; dms; + +OLDINT67_VECTOR equ $-EMS_STUB_START ;AN030;J.K. +OldInt67 dd ? ;AN030;; save pointer to old INT 67 handler here + +IF BUFFERFLAG + +LOCKFLAG equ $-EMS_STUB_START +LOCK_FLAG db ? + +ELSE + +EMSPAGE_CNT equ $-EMS_STUB_START ;AN030;J.K. +EMSPageCount dw ? ;AN030;; save count of EMS mappable pages here + +EMSReservedArray_X label word ;AN030;;J.K. For initialization routine +EMSRESERVEDARRAY equ $-EMS_STUB_START ;AN030;;J.K. + dw 0ffffh,0ffffh ;AN030;; array of reserved pages + dw 0ffffh,0ffffh ;AN030;; phys_page_segment, phys_page_number * 2 entries +MappableArray_X label word ;AN030;;J.K. for initialization routine +MAPPABLEARRAY equ $-EMS_STUB_START ;AN030;;J.K. + dw 64 dup (0,0) ;AN030;; table to get addresses from old INT 67 handler + +ENDIF + ; 64 entries * 2 words +NEWEMS2F_OFF equ $-EMS_STUB_START;AN030; +Int_2F_EMS: ;AN030;;J.K. Name changed. + cmp ah,1Bh ;AN030;;AN032;2Fh trap for Mappable Phys. Add. Array ;an000; dms; + je Int_2F_EMS_MINE ;AN030;;This one we want ;an000; dms; + + jmp dword ptr cs:IntV2F ;AN030;;go to old interrupt handler ;an000; dms; + +Int_2F_EMS_MINE: ;AN030; + or al, al ;AN030;;J.K. Installation check? + jnz Int_2F_5800_Func ;AN030;;J.K. + mov al, 0FFh ;AN030;;J.K. Yes, I am here! + iret ;AN030;;J.K. + +Int_2F_5800_Func: ;AN030; + +IF BUFFERFLAG +; int 3 + cmp di, 80h + jne st_flag + mov byte ptr cs:LOCKFLAG, 0 + jmp Int_2f_5800_Good_Exit +st_flag: + cmp di, 81h + jne Int_2f_5800_Err_Exit + mov byte ptr cs:LOCKFLAG, 1 + jmp Int_2f_5800_Good_Exit +ELSE + + push si ;AN030;; ;an000; dms; + +; mov si,offset EMSReservedArray ;point to array containing pages ;an000; dms; + mov si, EMSRESERVEDARRAY ;AN030;;J.K. + + cmp di,0feh ;AN030;;VDISK or FASTOPEN request? ;an000; dms; + jne Int_2F_5800_Buff_Ck ;AN030;;no - check for buffers ;an000; dms; + + cmp word ptr cs:[si],0ffffh ;AN030;;valid entry? ;an000; dms; + je Int_2F_5800_Err_Exit ;AN030;;no - exit ;an000; dms; + + mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; + mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; + jmp Int_2F_5800_Good_Exit ;AN030;;exit routine ;an000; dms; + +Int_2F_5800_Buff_Ck: ;AN030; + + cmp di,0ffh ;AN030;;BUFFERS request? ;an000; dms; + jne Int_2F_5800_Err_Exit ;AN030;;no - exit with error ;an000; dms; + + add si,4 ;AN030;;point to second element in array ;an000; dms; + + cmp word ptr cs:[si],0ffffh ;AN034;;valid entry? ;an000; dms; + je Int_2F_5800_Err_Exit ;AN034;;no - exit ;an000; dms; + + mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; + mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; + +ENDIF + +Int_2F_5800_Good_Exit: ;AN030; + + xor ax,ax ;AN030;;signal good return ;an000; dms; + jmp Int_2F_Exit ;AN030;;exit routine ;an000; dms; + +Int_2F_5800_Err_Exit: ;AN030; + + mov ax,0ffffh ;AN030;;signal error ;an000; dms; + +Int_2F_Exit: ;AN030; + + +IF NOT BUFFERFLAG + pop si ;AN030;;restore regs ;an000; dms; +ENDIF + iret ;AN030;;return to caller ;an000; dms; + + + +;------------------------------------------------------------------- +; +; INT 67h Filter +; +; This routine filters INT 67's looking for AH=58h. When initialized, +; the original INT 67 handler is called and the mappable address array +; is changed to "reserve" two pages for DOS use. This new array is +; then returned to the calling program when INT 67 AH=58h is found. +; +; Information about the two pages "reserved" for DOS is returned +; via an unpublished INT 2Fh interface. +; +; 5/10/88 for DOS 4.0. +;------------------------------------------------------------------- + +IF NOT BUFFERFLAG + +GetMappableArray equ 58h ; INT 67 function code for Get Mappable Array +GetPageFrame equ 41h ; function code for getting the page frame address +null equ 0 ; zero value +I67Error8F equ 8fh ;AN031;; invalid sub-function error + +ENDIF + +;------------------------------------------------------------------- +NEW67_OFFSET equ $-EMS_STUB_START ;J.K. +Int67Filter: ;AN030; + +IF BUFFERFLAG +; int 3 + cmp byte ptr cs:LOCKFLAG, 1 + jne PassThru + mov ah, 80h + stc + iret +ELSE + cmp ah,GETMAPPABLEARRAY ;AN030;; is this the INT 67 call we are interested in? + jne PassThru ;AN030;; no, pass it to old INT 67 handler + ;AN030;; yes ... + cmp al,0 ;AN031;; AL=0 return count and table + je I67Fcn0 + + cmp al,1 ;AN031;; AL=1 return count only + jne I67Error ;AN031;; otherwise, error + + +; return count of mappable pages + + sti ;AN031;; turn interrupts on + + mov cx,word ptr cs:EMSPAGE_CNT ;AN031;J.K. get number of mappable pages in fake table + xor ah,ah ;AN031;; good return code + iret + +; return invalid sub-function code + +I67Error: + sti ;AN031;; turn interrupts on + mov ah,I67Error8F ;AN031;; invalid sub-function error + iret + + +I67Fcn0: ;AN031 + +; copy the fake table to user's buffer + + sti ;AN030;; turn interrupts on + + push ds ;AN030; save some regs + push di ;AN030; + push si ;AN030; + + mov cx,word ptr cs:EMSPAGE_CNT ;AN030;J.K. get number of mappable pages in fake table + shl cx,1 ;AN030;; count * 2 = number of words to copy + + push cs ;AN030;; point DS:SI to fake table + pop ds ;AN030; +; lea si,MappableArray + mov si, MAPPABLEARRAY ;AN030;;J.K. + + rep movsw ;AN030;; copy CX words from DS:SI to ES:DI + + xor ah,ah ;AN030;; good return code + mov cx,word ptr cs:EMSPAGE_CNT ;AN030;; page count returned to user in CX + + + pop si ;AN030;; restore some regs + pop di ;AN030; + pop ds ;AN030; + + iret ;AN030;; end of INT 67 filter routine + +ENDIF + +;------------------------------------------------------------------- +; +; PassThru - send request to old INT 67 handler +; +;------------------------------------------------------------------- + +PassThru: + jmp dword ptr cs:OldINT67_VECTOR ;AN030;;J.K. jump to old INT 67 handler + ; (IRET will return to calling program) + + +EMS_STUB_END label byte ;AN030; +;------------------------------------------------------------------- + +IF NOT BUFFERFLAG +;------------------------------------------------------------------- +; +; Int67FilterInit - This routine is called to initialize the INT 67 +; filter. It should be called as soon as possible after installation. +; +;------------------------------------------------------------------- + +Int67FilterInit: ;AN030; + push es ;AN030;; save caller's ES:DI + push di ;AN030; + + push cs ;AN030;; make ES:DI point to our array + pop es ;AN030; + mov di,offset MappableArray_X ;AN030; + +; call dword ptr cs:OldInt67 ; get mappable array from EMS DD + + mov ah, GetMappableArray ;AN030; + xor al,al ;AN030; + int 67h ;AN030;;J.K. + + +;------------------------ +; scan table looking for highest phys_page_number + + xor ax,ax ;AN030;; + + cmp cx,0 ;AN033;; are the any pages left? + je NoMoreEMSPages ;AN033;; no, don't bother looking any more + + call GetHighestPage ;AN030;; get highest entry from table + + mov EMSReservedArray_X+4,bx ;AN030;; phys_page_segment + mov EMSReservedArray_X+6,ax ;AN030;; phys_page_number + + cmp cx,0 ;AN033;; are the any pages left? + je NoMoreEMSPages ;AN033;; no, don't bother looking any more + + call GetHighestPage ;AN030;; get next highest entry from table + + mov EMSReservedArray_X+0,bx ;AN030;; phys_page_segment + mov EMSReservedArray_X+2,ax ;AN030;; phys_page_number + +NoMoreEMSPages: ;AN033;; + mov EMSPageCount,cx ;AN030;; save new page count for INT 67 filter + + pop di + pop es + ret ;AN030;; return to calling program + + + page +;------------------------------------------------------------------- +; +; GetHighestPage - returns highest physical page number in AX +; and segment for it in BX. A -1 means no valid page found. +; +;------------------------------------------------------------------- +GetHighestPage: + + xor ax,ax ;AN030;; zero candidate register + mov bx,ax ;AN030;; zero pointer to candidate page + + push cx ;AN030;; save count + push dx ;AN030; + push di ;AN030;; save pointer + +PageScanLoop: ;AN030; + cmp ax,ES:[di+2] ;AN030;; get phys_page_number + ja LookAtNextPage ;AN030;; this one is lower than the one we are holding + + cmp es:[di], 0a000h ; Only reserve pages in memory above 640K.. + jb LookAtNextPage ; fix for ps2emm and m20emm with motherboard + ; disabled. 7/25/88. HKN. + + mov ax,ES:[di+2] ;AN030;; this one is higher, make it new candidate + mov bx,di ;AN030;; pointer to new candidate page, used to zero + ; it later so we don't get the same one again + mov dx,cx ;AN030;; save count where we found candidate + +LookAtNextPage: ;AN030; + add di,4 ;AN030;; point to next entry in mappable table + + loop PageScanLoop ;AN030;; look at next entry + + cmp bx,null ;AN030;; did we find any pages? + jne FoundOne ;AN030;; yes, exit + + jmp ReturnError ;AN030; + +;------------------------ +FoundOne: ;AN030; + cmp ax,3 ;AN030;; could the one we found be part of a page frame + ja NotFrame ;AN030;; no, carry on + +; yes, find out if it is part of frame + + push ax ;AN030;; save physical page number + push bx ;an030;; dms; bx destroyed by call + mov ah,GetPageFrame ;AN030;; function code to get page frame ... +; call dword ptr cs:OldInt67 ; ... from the EMS DD + int 67h ;AN030;;J.K. + or ah,ah ;an030;;dms; error? + pop bx ;an030;;dms; restore bx + pop ax ;AN030;; restore phys page number + jnz NotFrame ;AN030;; no frame available, carry on + +; there is a frame, this page is part of frame, so return -1's + +ReturnError: ;AN030; + mov ax,0ffffh ;AN030;; indicate failure + mov bx,ax ;AN030;; ax and bx = -1 + + pop di ;AN030;; restore pointer + pop dx + pop cx ;AN030;; restore count + + jmp GHPExit ;AN030; + + + + +;------------------------ +; Found a page, and it is not part of a page frame, so re-pack table +; and return info. The entry we "reserve" for DOS must be removed +; from the table and the other entries moved up to repack the table. +; The count must be reduced by 1 to reflect this change. + +Notframe: ;AN030; + + mov di,bx ;AN030;; make ES:DI point to highest page table entry + + mov bx,ES:[di] ;AN030;; get segment address of page + + mov cx,dx ;AN030;; get count from candidate page + + push ax ;AN030; +PackLoop: ;AN030; + mov ax, es:[di+4] ;AN030; + mov es:[di+0], ax ;AN030; + mov ax, es:[di+6] ;AN030; + mov es:[di+2], ax ;AN030; + add di, 4 ;AN030; + loop PackLoop ;AN030;; do it until done + pop ax ;AN030; + + pop di ;AN030;; restore pointer + pop dx ;AN030; + pop cx ;AN030;; restore count + + sub cx,1 ;AN030;; reduce count by one, one less page in table now + +GHPExit: ;AN030; + + ret ;AN030;; return to caller + +ENDIF + +;========================================================================= +; EMS_Install_Check : THIS MODULE DETERMINES WHETHER OR NOT EMS IS +; INSTALLED FOR THIS SESSION. +; +; INPUTS : NONE +; +; OUTPUTS : ES:BX - FRAME ARRAY +; CY - EMS NOT AVAILABLE +; NC - EMS AVAILABLE +; +; Date : 5/6/88 +;========================================================================= + +EMS_Install_Check proc near ;AN030;; check if EMS is installed ;an000; dms; + + push ax ;AN030;; save regs ;an000; dms; + + push ds ;AN030;; save ds ;an000; dms; + xor ax,ax ;AN030;; set ax to 0 ;an000; dms; + mov ds,ax ;AN030;; set ds to 0 ;an000; dms; + cmp ds:word ptr[067h*4+0],0 ;AN030;; see if int 67h is there ;an000; dms; + pop ds ;AN030;; restore ds ;an000; dms; + je EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; + + mov ah,40h ;AN030;; Get Status function ;an000; dms; + xor al,al ;AN030;; clear al ;an000; dms; + int 67h ;AN030;; ;an000; dms; + or ah,ah ;AN030;; EMS installed? ;an000; dms; + jnz EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; + + mov ah,46h ;AN030;; Get Version number ;an000; dms; + xor al,al ;AN030;; clear al ;an000; dms; + int 67h ;AN030;; ;an000; dms; + cmp al,40h ;AN030;; Version 4.0? ;an000; dms; + jb EMS_Install_Ck_Err_Exit ;AN030;; exit routine - wrong EMS loaded ;an000; dms; + + clc ;AN030;; signal EMS loaded ;an000; dms; + jmp EMS_Install_Ck_Exit ;AN030;; exit routine ;an000; dms; + +EMS_Install_Ck_Err_Exit: ;AN030; + + stc ;AN030;; signal EMS not loaded ;an000; dms; + +EMS_Install_Ck_Exit: ;AN030; + + pop ax ;AN030;; restore regs ;an000; dms; + + ret ;AN030;; return to caller ;an000; dms; + +EMS_Install_Check endp ; ;an000; dms; + +EMS_Stub_Handler proc near ;AN030; +;At the request of Architecture Group, this logic is implemented. +;Function: If (Buffer_Slash_X <> 0 and EMS_Stub_Installed == 0), +; then { call Chk_EMS; +; if EMS is there, then install EMS_Stub dynamically +; and initialize it.} +; Note: EMS_Stub consists of INT 2fh EMS handler and INT 67h handler. +; When EMS_Stub is installed, EMS_Stub_Installed will be set to 1. + + push es ;AN030; + push si ;AN030; + push ds ;AN030; + push di ;AN030; + push ax ;AN030; + push cx ;AN030; + cmp EMS_Stub_Installed, 0 ;AN030; + je EMS_Stub_X ;AN030; + jmp EMS_SH_Ret ;AN030; +EMS_Stub_X: ;AN030; + cmp Buffer_Slash_X, 0 ;AN030; + je EMS_SH_Ret ;AN030; + call EMS_Install_Check ;AN030; + jc EMS_SH_Ret ;AN030; +;Install EMS_Stub. ;AN030; +EMS_Stub_Do: + push es ;AN030; + xor ax,ax ;AN030;save current Int 2fh, 67h vectors. + mov es, ax ;AN030; + mov ax, word ptr es:[2fh*4] ;AN030; + mov IntV2FO, ax ;AN030; + mov ax, word ptr es:[2fh*4+2] ;AN030; + mov IntV2FS, ax ;AN030; + mov ax, word ptr es:[67h*4] ;AN030; + mov word ptr cs:[OldInt67], ax ;AN030; + mov ax, word ptr es:[67h*4+2] ;AN030; + mov word ptr cs:[OldInt67+2], ax ;AN030; + pop es ;AN030; + +IF NOT BUFFERFLAG +;initalize tables in INT 67h handler + call Int67FilterInit ;AN030; + cmp ax, 0ffffh ; if the page found was part of a lim 4.0 page frame + je EMS_SH_ret ; do not install stub. 7/24/88. HKN +ENDIF + call Round ;AN030; + mov ax, DEVMARK_EMS_STUB ;AN030; + call SetDevMark ;AN030; + mov ax, [memhi] ;AN030; + mov es, ax ;AN030; + assume es:nothing ;AN030; + xor di, di ;AN030; + push cs ;AN030; + pop ds ;AN030; + mov cx, offset EMS_STUB_END ;AN030; + mov si, offset EMS_STUB_START ;AN030; + sub cx, si ;AN030;cx = size in byte + mov [memlo], cx ;AN030; + rep movsb ;AN030; + or [SetDevMarkFlag], FOR_DEVMARK ;AN030;set the devmark_size for MEM command. + call Round ;AN030;and get the next [memhi] avaiable. + mov EMS_Stub_Installed, 1 ;AN030; + + xor ax, ax ;AN030; + mov ds, ax ;AN030; + cli ;AN030; + mov word ptr ds:[2Fh*4],NEWEMS2F_OFF;AN030;set the new int 2fh, 67h vectors. + mov word ptr ds:[2Fh*4+2], es ;AN030; + mov word ptr ds:[67h*4],NEW67_OFFSET;AN030; + mov word ptr ds:[67h*4+2], es ;AN030; + sti ;AN030; +EMS_SH_Ret: ;AN030; + pop cx ;AN030; + pop ax ;AN030; + pop di ;AN030; + pop ds ;AN030; + pop si ;AN030; + pop es ;AN030; + ret ;AN030; + +EMS_Stub_Handler endp ;AN030; + + +SYSINITSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/SYSIMES.ASM b/v4.0/src/BIOS/SYSIMES.ASM new file mode 100644 index 0000000..0640282 --- /dev/null +++ b/v4.0/src/BIOS/SYSIMES.ASM @@ -0,0 +1,38 @@ + ;SCCSID = @(#)sysimes.asm 1.2 85/07/25 +%OUT ...SYSIMES + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001 D246, P976 Show "Bad command or parameters - ..." msg 9/22/87 J.K. +;AN002 P1820 New Message SKL file 10/20/87 J.K. +;AN003 D486 Share installation for large media 02/24/88 J.K. +;============================================================================== + +iTEST = 0 +include MSequ.INC +include MSmacro.INC + +SYSINITSEG SEGMENT PUBLIC BYTE 'SYSTEM_INIT' + + PUBLIC BADOPM,CRLFM,BADSIZ_PRE,BADLD_PRE,BADCOM,SYSSIZE,BADCOUNTRY +; PUBLIC BADLD_POST,BADSIZ_POST,BADMEM,BADBLOCK,BADSTACK + PUBLIC BADMEM,BADBLOCK,BADSTACK + PUBLIC INSUFMEMORY,BADCOUNTRYCOM + public BadOrder,Errorcmd ;AN000; + public BadParm ;AN001; + public SHAREWARNMSG ;AN003; + + +;include sysimes.inc +include MSbio.cl3 ;AN002; + +SYSSIZE LABEL BYTE + +PATHEND 001,SYSMES + +SYSINITSEG ENDS + END diff --git a/v4.0/src/BIOS/SYSINIT1.ASM b/v4.0/src/BIOS/SYSINIT1.ASM new file mode 100644 index 0000000..7869b76 --- /dev/null +++ b/v4.0/src/BIOS/SYSINIT1.ASM @@ -0,0 +1,2668 @@ + PAGE ,132 ; +; SCCSID = @(#)sysinit1.asm 1.7 85/10/24 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSINIT1 +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; p40 Boot from the system with no floppy diskette drives 6/26/87 J.K. +;AN002; d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; d9 Double word mov for 386 machine 7/15/87 J.K. +;AN004; p447 BUFFERS = 50 /E without EMS installed hangs 8/25/87 J.K. +;AN005; d184 Set DEVMARK for MEM command 8/25/87 J.K. +;AN006; p851 Installable files not recognized corretly. 9/08/87 J.K. +;AN007; p1299 Set the second entry of DEVMARK for MEM command 9/25/87 J.K. +;AN008; p1361 New Extended Attribute 9/28/87 J.K. +;AN009; p1326 Buffers = 50 /e hangs 9/28/87 J.K. +;AN010; New EMS Interface +;AN011; New Message SKL file 10/20/87 J.K. +;AN012; P2211 Setting EA=7 for ANSI.SYS hangs the system 11/02/87 J.K. +;AN013; p2343 Set the name for SYSINIT_BASE for MEM command 11/11/87 J.K. +;AN014; D358 New device driver INIT function package 12/03/87 J.K. +;AN015; For Installed module with no parameter 12/11/87 J.K. +;AN016; D285 Undo the Extended Attribute handling 12/17/87 J.K. +;AN017; P2806 Show "Error in CONFIG.SYS ..." for INSTALL= command 12/17/87 J.K. +;AN018; P2914 Add Extended Memory Size in SYSVAR 01/05/88 J.K. +;AN019; P3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN020; P3497 Performace fix for new buffer scheme 02/15/88 J.K. +;AN021; D486 SHARE installation for big media 02/23/88 J.K. +;AN022; D493 Undo D358 & do not show error message for device driv02/24/88 J.K. +;AN023; D474 Change BUFFERS= /E option to /X for expanded memory 03/16/88 J.K. +;AN024; D506 Take out the order dependency of the IFS= 03/28/88 J.K. +;AN025; P4086 Memory allocation error when loading SHARE.EXE 03/31/88 J.K. +;AN026; D517 New Balanced Real memory buffer set up scheme 04/18/88 J.K. +;AN027; D528 Install XMAEM.SYS first before everything else 04/29/88 J.K. +;AN028; P4669 SHARE /NC causes an error 05/03/88 J.K. +;AN029; P4759 Install EMS INT2fh, INT 67h handler 05/12/88 J.K. +;AN030; P4934 P4759 INT 2Fh handler number be changed to 1Bh 05/20/88 J.K. +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +CR equ 13 +LF equ 10 +TAB equ 9 + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE +MYCDS_SIZE equ 88 ;J.K. Size of Curdir_List. If it is not + ;the same, then will generate compile error. + +; + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H +;dossize equ 0C000H ;J.K. for the debugging version of IBMDOS. + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include BIOSTRUC.INC + include smifssym.inc ;AN000; + include defems.inc ;AN010; + include DEVMARK.inc ;AN005; + include cputype.inc + + include version.inc + +.list + +;AN000 J.K. If MYCDS_SIZE <> CURDIRLEN, then force a compilatiaon error. + if MYCDS_SIZE NE CURDIRLEN + %OUT  !!! SYSINIT1 COMPILATION FAILED. DIFFERENT CDS SIZE !!! + .ERRE MYCDS_SIZE EQ CURDIRLEN + endif + + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + +;--------------------------------------- +;Equates for Main stack and stack Initialization program + IF STACKSW + +EntrySize equ 8 + +MinCount equ 8 +DefaultCount equ 9 +MaxCount equ 64 + +MinSize equ 32 +DefaultSize equ 128 +MaxSize equ 512 + +AllocByte equ es:byte ptr [bp+0] +IntLevel equ es:byte ptr [bp+1] +SavedSP equ es:word ptr [bp+2] +SavedSS equ es:word ptr [bp+4] +NewSP equ es:word ptr [bp+6] +Free equ 0 +allocated equ 1 +overflowed equ 2 +clobbered equ 3 + + +;External variables in IBMBIO for INT19h handling rouitne. J.K. 10/23/86 +CODE segment public 'code' + EXTRN Int19sem:byte + + IRP AA,<02,08,09,0A,0B,0C,0D,0E,70,72,73,74,76,77> + EXTRN Int19OLD&AA:dword + ENDM +CODE ends + ENDIF +;--------------------------------------- +;J.K. 6/29/87 External variable defined in IBMBIO module for Multi-track +MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns + ; it on after handling CONFIG.SYS file as a + ; default value, if MulTrk_flag = MULTRK_OFF1. +MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered. +MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off. + +CODE segment public 'code' + EXTRN MulTrk_flag:word ;AN002; +CODE ends +;J.K. 6/29/87 End of Multi-track definition. + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADCOM:BYTE + EXTRN SYSSIZE:BYTE + EXTRN CONDEV:BYTE,AUXDEV:BYTE,PRNDEV:BYTE,COMMND:BYTE + extrn DeviceParameters:byte + extrn DevMark_Addr:word + extrn SetDevMarkFlag:byte + extrn PathString:byte ;AN021; + extrn LShare:byte ;AN021; + extrn ShareWarnMsg:byte ;AN021; + + EXTRN INT24:NEAR,MEM_ERR:NEAR + EXTRN DOCONF:NEAR + extrn Multi_Pass:NEAR ;AN024; + extrn BadLoad:near + extrn Error_Line:near + + PUBLIC CURRENT_DOS_LOCATION + PUBLIC FINAL_DOS_LOCATION + PUBLIC DEVICE_LIST + PUBLIC SYSI_COUNTRY + PUBLIC MEMORY_SIZE + PUBLIC DEFAULT_DRIVE + PUBLIC BUFFERS + PUBLIC FILES + PUBLIC NUM_CDS + PUBLIC SYSINIT + PUBLIC CNTRYFILEHANDLE + PUBLIC COMMAND_LINE + public Big_Media_Flag ;AN021;Set by IBMINIT + + IF STACKSW + ;Internal Stack Information + PUBLIC STACK_COUNT + PUBLIC STACK_SIZE + PUBLIC STACK_ADDR + ENDIF + + PUBLIC dosinfo,entry_point + PUBLIC fcbs,keep + PUBLIC confbot,alloclim + PUBLIC zero,sepchr,STALL + PUBLIC count,chrptr,org_count + PUBLIC bufptr,memlo,prmblk,memhi + PUBLIC ldoff,area,PACKET,UNITCOUNT + PUBLIC BREAK_ADDR,BPB_ADDR,drivenumber + public Config_Size + public Install_Flag + public COM_Level + public CMMT + public CMMT1 + public CMMT2 + public Cmd_Indicator + public LineCount + public ShowCount + public Buffer_LineNum + public DoNotShowNum + public IFS_Flag + public IFS_RH + public H_Buffers + public Buffer_Slash_X ;AN023; + public ConfigMsgFlag ;AN014; + public Do_Install_Exec ;AN019; + public Multi_Pass_Id ;AN024; + + +; +SYSINIT$: + IF STACKSW +.SALL + include MSSTACK.INC ;Main stack program and data definitions +; include STKMES.INC ;Fatal stack error message + include MSBIO.CL5 ;Fatal stack error message +.XALL + public Endstackcode +Endstackcode label byte + ENDIF + +; +SYSINIT: + JMP GOINIT +DOSINFO LABEL DWORD + DW 0000 +CURRENT_DOS_LOCATION DW 0000 + +MSDOS LABEL DWORD +ENTRY_POINT LABEL DWORD + DW 0000 +FINAL_DOS_LOCATION DW 0000 +DEVICE_LIST DD 00000000 + +SYSI_Country LABEL DWORD ;J.K. 5/29/86 Pointer to + DW 0000 ;country table in DOS + DW 0000 + +Fake_Floppy_Drv db 0 ;AN001;Set to 1 if this machine + ;does not have any floppies!!! +Big_Media_Flag db 0 ;AN021;Set by IBMINIT if > 32 MB fixed media exist. +; +;Variables for Stack Initialization Program. + IF STACKSW +STACK_COUNT DW DefaultCount +STACK_SIZE DW DefaultSize +STACK_ADDR DD 00000000 + ENDIF +; various default values + +MEMORY_SIZE DW 0001 +DEFAULT_DRIVE DB 00 ;initialized by IBMINIT. +BUFFERS DW -1 ; initialized during buffer allocation +H_Buffers dw 0 ;AN000; # of the Heuristic buffers. Initially 0. +Buffer_Pages dw 0 ;AN000; # of extended memory pages for the buffer. +BufferBuckets dw 0 ;AN000; +Buffer_odds dw 0 ;AN000; +SingleBufferSize dw ? ;AN000; Maximum sector size + buffer header +MaxNumBuf1 db 15 ;AN026;Num of buffers in a bucket group 1. +MaxNumBuf2 db 15 ;AN026;Num of buffers in a possible bucket group 2. +NthBuck db 0 ;AN026; 1st bucket group = 1st bucket through Nth Bucket. The rest = second group + +IF BUFFERFLAG + +FIRST_PAGE DW 0, 0 +LAST_PAGE DW 0, 0 +NPA640 DW 0 +EMS_SAVE_BUF DB 0,0,0,0,0,0,0,0,0,0,0,0 + +ENDIF + +FILES DB 8 ; enough files for pipe +FCBS DB 4 ; performance for recycling +Keep DB 0 ; keep original set +NUM_CDS DB 5 ; 5 net drives +CONFBOT DW ? +ALLOCLIM DW ? +FOOSTRNG DB "A:\",0 +COMMAND_LINE DB 2,0,"P" ;Default Command.com Args + DB 29 DUP (0) +ZERO DB 0 +SepChr DB 0 +LineCount dw 0 ;AN000; Line count in config.sys +ShowCount db ' ',CR,LF,'$' ;AN000; Used to convert Linecount to ASCII. +Buffer_LineNum dw 0 ;AN000; Line count for "BUFFERS=" command if entered. + +Sys_Model_Byte db 0FFh ;model byte used in SYSINIT +Sys_Scnd_Model_Byte db 0 ;secondary model byte used in SYSINIT +; +Buffer_Slash_X db 0 ;AN000;AN023; BUFFERS= ... /X option entered. +Real_IBM_Page_Id dw 0 ;AN029; +IBM_Frame_Seg dw 0 ;AN000; segment value for physical IBM page frame. +Frame_Info_Buffer dw (MAX_NUM_PAGEFRAME * 4) dup (0) ;AN010; For EMS. as per spec. 2 words per entry +EMSHandleName db 'BUFFERS ' ;AN010; 8 char. EMS handle name +EMS_Ctrl_Tab dd 0 ;AN010; +EMS_State_Buf dd 0 ;AN010; +BUF_PREV_OFF dw 0 ;AN020; +EMS_Buf_First dw 0 ;AN020; + + IF NOT NOEXEC +COMEXE EXEC0 <0,COMMAND_LINE,DEFAULT_DRIVE,ZERO> + ENDIF + +;------------------------------------------------------------------ +;J.K. 2/23/87 ;variables for INSTALL= command. + +Multi_Pass_Id db 0 ;AN024;AN027; +Install_Flag dw 0 ;AN000; + HAVE_INSTALL_CMD equ 00000001b ;AN019; CONFIG.SYS has INSTALL= commands + HAS_INSTALLED equ 00000010b ;AN019; SYSINIT_BASE installed. + SHARE_INSTALL equ 00000100b ;AN021; Used to install SHARE.EXE + +Config_Size dw 0 ;AN000; size of config.sys file. Set by SYSCONF.ASM +Sysinit_Base_Ptr dd 0 ;AN000; pointer to SYSINIT_BASE +Sysinit_Ptr dd 0 ;AN000; returning addr. from SYSINIT_BASE +CheckSum dw 0 ;AN000; Used by Sum_up + +Ldexec_FCB db 20 dup (' ') ;AN000;big enough +Ldexec_Line db 0 ;AN000;# of parm characters +Ldexec_start db ' ' ;AN000; +Ldexec_parm db 80 dup (0) ;AN000; + +INSTEXE EXEC0 <0,Ldexec_Line,Ldexec_FCB,Ldexec_FCB> ;AN000; + +;AN016; Undo the extended attribute handling +;EA_QueryList label byte +; dw 1 ;AN008; I need just one EA info. +; db 02h ;AN008; Type is BINARY +; dw 8000h ;AN008; Flag is SYSTEM DEFINED. +; db 8 ;AN008; Length of name is 8 bytes +; db 'FILETYPE' ;AN008; Name is FILETYPE +;Ext_Attr_List dw 1 ;AN008; Just 1 Extended attribute List +; db 2 ;AN008;EA_TYPE +; dw 8000h ;AN008;FLAG +; db 0 ;AN008;Failure reason +; db 8 ;AN008;Length of NAME +; dw 1 ;AN008;Length of VALUE +; db 'FILETYPE' ;AN008;Name +;Ext_Attr_Value db 0 ;AN008;Value +;SIZE_EXT_ATTR_LIST equ $-Ext_Attr_List ;AN008; +; +;;Extended attribute value +;EA_INSTALLABLE equ 4 ;AN008;Value for Installable file + +;------------------------------------------------------------------ +;J.K. 5/15/87 ;Request header, variables for IFS= command. + +IFS_Flag dw 0 ;AN000; Set to 1 if it is an IFS. + IS_IFS equ 00000001b ;IFS command? + NOT_IFS equ 11111110b + +IFS_RH IFSRH ;AN000; IFS initialization request packet + +;------------------------------------------------------------------ +;Variables for Comment= +COM_Level db 0 ;AN000;level of " " in command line +CMMT db 0 ;AN000;length of COMMENT string token +CMMT1 db 0 ;AN000;token +CMMT2 db 0 ;AN000;token +Cmd_Indicator db ? ;AN000; +DoNotShowNum db 0 ;AN000; + +;------------------------------------------------------------------ +COUNT DW 0000 +Org_Count dw 0000 ;AN019; +CHRPTR DW 0000 +CntryFilehandle DW 0000 +Old_Area dw 0 ;AN013; +Impossible_Owner_Size dw 0 ;AN013; Paragraph +;------------------------------------------------------------------ +BucketPTR LABEL dword ;AN000; +BUFPTR LABEL DWORD ;LEAVE THIS STUFF IN ORDER! +MEMLO DW 0 +PRMBLK LABEL WORD +MEMHI DW 0 +LDOFF DW 0 +AREA DW 0 + +PACKET DB 24 ;AN014; Was 22 + DB 0 + DB 0 ;INITIALIZE CODE + DW 0 + DB 8 DUP (?) +UNITCOUNT DB 0 +BREAK_ADDR DD 0 +BPB_ADDR DD 0 +DriveNumber DB 0 +ConfigMsgFlag dw 0 ;AN014;AN022; Used to control "Error in CONFIG.SYS line #" message + +TempStack DB 80h DUP (?) + +GOINIT: +;J.K. before doing anything else, let's set the model byte +;SB33043***************************************************************** + mov ah,0c0h ;get system configuration ;SB ;3.30* + int 15h ; * ;SB ;3.30* +;SB33043***************************************************************** + jc No_ROM_Config + cmp ah, 0 ; double check + jne No_ROM_Config + mov al, ES:[BX.bios_SD_modelbyte] + mov cs:[Sys_Model_Byte], al + mov al, ES:[BX.bios_SD_scnd_modelbyte] + mov cs:[Sys_Scnd_Model_Byte], al + jmp short Move_Myself +No_ROM_Config: ; Old ROM + mov ax, 0f000h + mov ds, ax + mov al, byte ptr ds:[0fffeh] + mov cs:[Sys_Model_Byte], al ;set the model byte. +;J.K.6/24/87 Set Fake_Floppy_Drv if there is no diskette drives in this machine. +;SB34SYSINIT1001******************************************************** +;SB execute the equipment determination interrupt and then +;SB check the returned value to see if we have any floppy drives +;SB if we have no floppy drive we set cs:Fake_Floppy_Drv to 1 +;SB See the AT Tech Ref BIOS listings for help on the equipment +;SB flag interrupt (11h) + + int 11h + test ax,1 ; has floppy ? + jnz Move_Myself + mov cs:Fake_Floppy_Drv,1 ; no floppy, fake. + +;SB34SYSINIT1001******************************************************** +Move_Myself: + CLD ; Set up move + XOR SI,SI + MOV DI,SI + + IF MSVER + MOV CX,cs:[MEMORY_SIZE] + CMP CX,1 ; 1 means do scan + JNZ NOSCAN + MOV CX,2048 ;START SCANNING AT 32K BOUNDARY + XOR BX,BX + +MEMSCAN:INC CX + JZ SETEND + MOV DS,CX + MOV AL,[BX] + NOT AL + MOV [BX],AL + CMP AL,[BX] + NOT AL + MOV [BX],AL + JZ MEMSCAN +SETEND: + MOV cs:[MEMORY_SIZE],CX + ENDIF + + IF IBMVER OR IBMJAPVER + MOV CX,cs:[MEMORY_SIZE] + ENDIF + +NOSCAN: ; CX is mem size in para + MOV AX,CS + MOV DS,AX +ASSUME DS:SYSINITSEG + + MOV AX,OFFSET SYSSIZE + Call ParaRound + SUB CX,AX ;Compute new sysinit location + MOV ES,CX + MOV CX,OFFSET SYSSIZE + 1 + SHR CX,1 ;Divide by 2 to get words + REP MOVSW ;RELOCATE SYSINIT + + ASSUME ES:SYSINITSEG + + PUSH ES + MOV AX,OFFSET SYSIN + PUSH AX + +AAA_DUMMY PROC FAR + RET +AAA_DUMMY ENDP +; +; MOVE THE DOS TO ITS PROPER LOCATION +; +SYSIN: + + ASSUME DS:NOTHING,ES:SYSINITSEG,SS:NOTHING + + MOV AX,[CURRENT_DOS_LOCATION] ; Where it is (set by BIOS) + MOV DS,AX + MOV AX,[FINAL_DOS_LOCATION] ; Where it is going (set by BIOS) + MOV ES,AX + + ASSUME ES:NOTHING + + XOR SI,SI + MOV DI,SI + + MOV CX,DOSSIZE/2 + REP MOVSW + + LDS SI,[DEVICE_LIST] ; Set for call to DOSINIT + MOV DX,[MEMORY_SIZE] ; Set for call to DOSINIT + + CLI + MOV AX,CS + MOV SS,AX + MOV SP,OFFSET LOCSTACK ; Set stack + + ASSUME SS:SYSINITSEG + + IF NOT ALTVECT + STI ; Leave INTs disabled for ALTVECT + ENDIF +LOCSTACK LABEL BYTE + + CALL MSDOS ; Call DOSINIT + ;ES:DI -> SysInitVars_Ext + mov ax, word ptr es:[di.SYSI_InitVars] ;J.K. 5/29/86 + mov word ptr [dosinfo], ax + mov ax, word ptr es:[di.SYSI_InitVars+2] + mov word ptr [dosinfo+2],ax ;set the sysvar pointer + + mov ax, word ptr es:[di.SYSI_Country_Tab] + mov word ptr [SYSI_Country],ax + mov ax, word ptr es:[di.SYSI_Country_Tab+2] + mov word ptr [SYSI_Country+2],ax ;set the SYSI_Country pointer J.K. + + les di, dosinfo ;es:di -> dosinfo + + clc ;AN018;Get the extended memory size +;SB34SYSINIT1002************************************************************** +;SB execute the get extended memory size subfunction in the BIOS INT 15h +;SB if the function reports an error do nothing else store the extended +;SB memory size reported at the appropriate location in the dosinfo buffer +;SB currently pointed to by es:di. Use the offsets specified in the +;SB definition of the sysinitvars struct in inc\sysvar.inc +;SB 5 LOCS + + mov ah,88h + int 15h ;check extended memory size + jc No_Ext_Memory + mov es:[di].SYSI_EXT_MEM,ax ;save extended memory size +No_Ext_Memory: + +;SB34SYSINIT1002************************************************************** + mov word ptr es:[di.SYSI_IFS], -1 ;AN000; Initialize SYSI_IFS chain. + mov word ptr es:[di.SYSI_IFS+2], -1 ;AN000; + + mov ax, es:[di.SYSI_MAXSEC] ;AN020; Get the sector size + add ax, BUFINSIZ ;AN020; size of buffer header + mov [SingleBufferSize], ax ;AN020; total size for a buffer + + mov al, Default_Drive ;AN000;Get the 1 based boot drive number set by IBMINIT + mov es:[di.SYSI_BOOT_DRIVE], al ;AN000; set SYSI_BOOT_DRIVE + +; Determine if 386 system... + Get_CPU_Type ; macro to determine cpu type + cmp ax, 2 ; is it a 386? + jne Not_386_System ; no: don't mess with flag + mov es:[di.SYSI_DWMOVE], 1 ;AN003; +Not_386_System: ;AN003; + MOV AL,ES:[DI.SYSI_NUMIO] + MOV DriveNumber,AL ; Save start of installable block drvs + + MOV AX,CS + SUB AX,11H ; room for header we will copy shortly + mov cx, [SingleBufferSize] ;AN020;Temporary Single buffer area + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; + shr cx, 1 ;AN020; Paragraphs + inc cx ;AN020; + sub ax, cx ;AN020; + MOV [CONFBOT],AX ; Temp "unsafe" location + + push es ;AN020; + push di ;AN020; + les di, es:[di.SYSI_BUF] ;AN020;get the buffer hash entry pointer + les di, es:[di.HASH_PTR] ;AN020; + mov word ptr es:[di.BUFFER_BUCKET],0 ;AN020; + mov word ptr es:[di.BUFFER_BUCKET+2], ax ;AN020; + mov es, ax ;AN020; + xor ax, ax ;AN020; + mov di, ax ;AN020;es:di -> Single buffer + mov es:[di.BUF_NEXT], ax ;AN020;points to itself + mov es:[di.BUF_PREV], ax ;AN020;points to itself + mov word ptr es:[di.BUF_ID],00FFh ;AN020;free buffer, clear flag + mov word ptr es:[di.BUF_SECTOR], 0 ;AN020; + mov word ptr es:[di.BUF_SECTOR+2], 0 ;AN020; + pop di ;AN020; + pop es ;AN020; + + PUSH DS ; Save as input to RE_INIT + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + CALL TEMPCDS ; Set up CDSs so RE_INIT and SYSINIT + ; can make DISK system calls + + POP DS ; Recover DS input to RE_INIT +ASSUME DS:NOTHING + + IF NOT IBMJAPVER + CALL RE_INIT ; Re-call the BIOS + ENDIF + + STI ; INTs OK + CLD ; MAKE SURE +; DOSINIT has set up a default "process" (PHP) at DS:0. We will move it out +; of the way by putting it just below SYSINIT at end of memory. + MOV BX,CS + SUB BX,10H + MOV ES,BX + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP MOVSW + MOV WORD PTR ES:[PDB_JFN_Pointer + 2],ES ; Relocate + MOV AH,SET_CURRENT_PDB + INT 21H ; Tell DOS we moved it + PUSH DS + PUSH CS + POP DS +ASSUME DS:SYSINITSEG + MOV DX,OFFSET INT24 ;SET UP INT 24 HANDLER + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H + INT 21H + + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H ;FIRST TIME FAILS + MOV AH,ALLOC + INT 21H ;SECOND TIME GETS IT + MOV [AREA],AX + MOV [MEMHI],AX ; MEMHI:MEMLO now points to + ; start of free memory + IF ALTVECT + MOV DX,OFFSET BOOTMES + invoke PRINT ;Print message DOSINIT couldn't + ENDIF + + POP DS +ASSUME DS:NOTHING + + MOV DL,[DEFAULT_DRIVE] + OR DL,DL + JZ NODRVSET ; BIOS didn't say + DEC DL ;A = 0 + MOV AH,SET_DEFAULT_DRIVE + INT 21H ;SELECT THE DISK +;J.K. 2/23/87 Modified to handle INSTALL= command. +NODRVSET: + CALL DOCONF ;DO THE CONFIG STUFF + inc cs:Multi_Pass_Id ;AN027; + call Multi_Pass ;AN027; + inc cs:Multi_Pass_Id ;AN024; + call Multi_Pass ;AN024; + call EndFile + test Install_Flag, HAVE_INSTALL_CMD ;AN019; + jz DoLast ;AN019; + inc cs:Multi_Pass_Id ;AN024; + call Multi_Pass ;AN019;AN024; Execute INSTALL= commands + +;J.K. [AREA] has the segment address for the allocated memory of SYSINIT,CONFBOT. +;Free the CONFBOT area used for CONFIG.SYS and SYSINIT itself. +DoLast: + call LoadShare ;AN021; Try to load share.exe, if needed. + mov cs:[DoNotShowNum], 1 ;AN000; Done with CONFIG.SYS. Do not show line number message. + mov cx, [area] ;AN000; + mov es, cx ;AN000; + mov ah, 49h ;AN000; Free allocated memory for command.com + int 21h ;AN000; + + test cs:[Install_flag], HAS_INSTALLED ;AN013; SYSINIT_BASE installed? + jz Skip_Free_SYSINITBASE ;AN013; No. +;Set Block from the Old_Area with Impossible_Owner_size. +;This will free the unnecessary SYSINIT_BASE that had been put in memory to +;handle INSTALL= command. + push es ;AN013; + push bx ;AN013; + mov ax, cs:[Old_Area] ;AN013; + mov es, ax ;AN013; + mov bx, cs:[Impossible_Owner_Size] ;AN013; + mov ah, SETBLOCK ;AN013; + int 21h ;AN013; + MOV AX,ES ;AN013; + DEC AX ;AN013; + MOV ES,AX ;Point to arena + MOV ES:[arena_owner],8 ;Set impossible owner + pop bx ;AN013; + pop es ;AN013; +Skip_Free_SYSINITBASE: ;AN013; + IF NOEXEC + MOV BP,DS ;SAVE COMMAND.COM SEGMENT + PUSH DS + POP ES + MOV BX,CS + SUB BX,10H ; Point to current PHP + MOV DS,BX + XOR SI,SI + MOV DI,SI + MOV CX,80H + REP MOVSW ; Copy it to new location for shell + MOV WORD PTR ES:[PDB_JFN_Pointer + 2],ES ; Relocate + MOV BX,ES + MOV AH,SET_CURRENT_PDB + INT 21H ; Tell DOS we moved it + MOV ES:[PDB_PARENT_PID],ES ;WE ARE THE ROOT + ENDIF + + PUSH CS + POP DS +ASSUME DS:SYSINITSEG +; +; SET UP THE PARAMETERS FOR COMMAND +; + + MOV SI,OFFSET COMMAND_LINE+1 + + IF NOEXEC + MOV DI,81H + ELSE + PUSH DS + POP ES + MOV DI,SI + ENDIF + + MOV CL,-1 +COMTRANLP: ;FIND LENGTH OF COMMAND LINE + INC CL + LODSB + STOSB ;COPY COMMAND LINE IN + OR AL,AL + JNZ COMTRANLP + DEC DI + MOV AL,CR ; CR terminate + STOSB + + IF NOEXEC + MOV ES:[80H],CL ; Set up header + MOV AL,[DEFAULT_DRIVE] + MOV ES:[5CH],AL + ELSE + MOV [COMMAND_LINE],CL ;Count + ENDIF + + MOV DX,OFFSET COMMND ;NOW POINTING TO FILE DESCRIPTION + + IF NOEXEC + MOV ES,BP ;SET LOAD ADDRESS + MOV BX,100H + CALL LDFIL ;READ IN COMMAND + JC COMERR + MOV DS,BP + MOV DX,80H + MOV AH,SET_DMA ;SET DISK TRANFER ADDRESS + INT 21H + CLI + MOV SS,BP + MOV SP,DX + STI + XOR AX,AX ;PUSH A WORD OF ZEROS + PUSH AX + PUSH BP ;SET HIGH PART OF JUMP ADDRESS + MOV AX,100H + PUSH AX ;SET LOW PART OF JUMP ADDRESS +CCC PROC FAR + RET ;CRANK UP COMMAND! +CCC ENDP + + ELSE +; We are going to open the command interpreter and size it as is done in +; LDFIL. The reason we must do this is that SYSINIT is in free memory. If +; there is not enough room for the command interpreter, EXEC will probably +; overlay our stack and code so when it returns with an error SYSINIT won't be +; here to catch it. This code is not perfect (for instance .EXE command +; interpreters are possible) because it does its sizing based on the +; assumption that the file being loaded is a .COM file. It is close enough to +; correctness to be usable. + + PUSH DX ; Save pointer to name + +; First, find out where the command interpreter is going to go. + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H ;Get biggest piece + MOV AH,ALLOC + INT 21H ;SECOND TIME GETS IT + JC MEMERRJX ; Oooops + MOV ES,AX + MOV AH,DEALLOC + INT 21H ; Give it right back + MOV BP,BX +; ES:0 points to Block, and BP is the size of the block +; in para. + +; We will now adjust the size in BP DOWN by the size of SYSINIT. We +; need to do this because EXEC might get upset if some of the EXEC +; data in SYSINIT is overlayed during the EXEC. + MOV BX,[MEMORY_SIZE] + MOV AX,CS + SUB BX,AX ; BX is size of SYSINIT in Para + ADD BX,11H ; Add the SYSINIT PHP + SUB BP,BX ; BAIS down + JC MEMERRJX ; No Way. + + MOV AX,(OPEN SHL 8) ;OPEN THE FILE being EXECED + STC ;IN CASE OF INT 24 + INT 21H + JC COMERR ; Ooops + MOV BX,AX ;Handle in BX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JC COMERR + ; Convert size in DX:AX to para in AX + ADD AX,15 ; Round up size for conversion to para + ADC DX,0 + MOV CL,4 + SHR AX,CL + MOV CL,12 + SHL DX,CL ; Low nibble of DX to high nibble + OR AX,DX ; AX is now # of para for file + ADD AX,10H ; 100H byte PHP + CMP AX,BP ; Will it fit? + JB OKLD ; Jump if yes. +MEMERRJX: + JMP MEM_ERR + +OKLD: + MOV AH,CLOSE + INT 21H ; Close file + POP DX ; Recover pointer to name + PUSH CS + POP ES + ASSUME ES:SYSINITSEG + MOV BX,OFFSET COMEXE ; Point to EXEC block + MOV WORD PTR [BX.EXEC0_COM_LINE+2],CS ; Set segments + MOV WORD PTR [BX.EXEC0_5C_FCB+2],CS + MOV WORD PTR [BX.EXEC0_6C_FCB+2],CS + XOR AX,AX ;Load and go + MOV AH,EXEC + STC ;IN CASE OF INT 24 + INT 21H ;GO START UP COMMAND + ENDIF +; NOTE FALL THROUGH IF EXEC RETURNS (an error) + +COMERR: + MOV DX,OFFSET BADCOM ;WANT TO PRINT COMMAND ERROR + INVOKE BADFIL +STALL: JMP STALL + + PUBLIC TEMPCDS +TEMPCDS: +ASSUME DS:SYSINITSEG + LES DI,[DOSINFO] + + MOV CL,BYTE PTR ES:[DI.SYSI_NUMIO] + XOR CH,CH + MOV ES:[DI.SYSI_NCDS],CL + MOV AL,CL + MOV AH,SIZE curdir_list + MUL AH + call ParaRound + MOV SI,[CONFBOT] + SUB SI,AX + MOV [ALLOCLIM],SI ; Can't alloc past here! + MOV WORD PTR ES:[DI.SYSI_CDS + 2],SI + MOV AX,SI + MOV WORD PTR ES:[DI.SYSI_CDS],0 + LDS SI,ES:[DI.SYSI_DPB] +ASSUME DS:NOTHING + MOV ES,AX + XOR DI,DI + +FOOSET: ; Init CDSs + MOV AX,WORD PTR [FOOSTRNG] + STOSW + MOV AX,WORD PTR [FOOSTRNG + 2] + STOSW + INC BYTE PTR [FOOSTRNG] + XOR AX,AX + PUSH CX + MOV CX,curdir_flags - 4 + REP STOSB + CMP SI,-1 +; JNZ NORMCDS +;J.K. 6/24/87 Should handle the system that does not have any floppies. +;J.K. In this case, we are going to pretended there are two dummy floppies +;J.K. in the system. Still they have DPB and CDS, but we are going to +;J.K. 0 out Curdir_Flags, Curdir_devptr of CDS so IBMDOS can issue +;J.K. "Invalid drive specification" message when the user try to +;J.K. access them. + je Fooset_Zero ;AN001;Don't have any physical drive. +;SB34SYSINIT1003************************************************************* +;SB Check to see if we are faking floppy drives. If not go to NORMCDS. +;SB If we are faking floppy drives then see if this CDS being initialised +;SB is for drive a: or b: by checking the appropriate field in the DPB +;SB pointed to by ds:si. If not for a: or b: then go to NORMCDS. If +;Sb for a: or b: then execute the code given below starting at Fooset_Zero. +;SB For dpb offsets look at inc\dpb.inc. +;SB 5 LOCS + + cmp cs:Fake_Floppy_Drv,1 ;fake drive ? + jnz NORMCDS + cmp ds:[si].dpb_drive,02 ;check for a: or b: + jae NORMCDS + +;SB34SYSINIT1003************************************************************* +Fooset_Zero: ;AN001; + XOR AX,AX + MOV CL,3 + REP STOSW + POP CX + JMP SHORT FINCDS +NORMCDS: + POP CX +;J.K. If a non-fat based media is detected (by DPB.NumberOfFat == 0), then +; set curdir_flags to 0. This is for signaling IBMDOS and IFSfunc that +; this media is a non-fat based one. + cmp [SI.dpb_FAT_count], 0 ;AN000; Non fat system? + je SetNormCDS ;AN000; Yes. Set curdir_Flags to 0. AX = 0 now. + MOV AX,CURDIR_INUSE ;AN000; else, FAT system. set the flag to CURDIR_INUSE. +SetNormCDS: ;AN000; + STOSW ; curdir_flags + MOV AX,SI + STOSW ; curdir_devptr + MOV AX,DS + STOSW + LDS SI,[SI.dpb_next_dpb] +FINCDS: + MOV AX,-1 + STOSW ; curdir_ID + STOSW ; curdir_ID + STOSW ; curdir_user_word + mov ax,2 + stosw ; curdir_end + mov ax, 0 ;AN000;Clear out 7 bytes (curdir_type, + stosw ;AN000; curdir_ifs_hdr, curdir_fsda) + stosw ;AN000; + stosw ;AN000; + stosb ;AN000; + LOOP FOOSET + MOV BYTE PTR [FOOSTRNG],"A" + return + +;------------------------------------------------------------------------------ +; Allocate FILEs +;------------------------------------------------------------------------------ +ENDFILE: +; WE ARE NOW SETTING UP FINAL CDSs, BUFFERS, FILES, FCSs STRINGs etc. We no +; longer need the space taken by The TEMP stuff below CONFBOT, so set ALLOCLIM +; to CONFBOT. + +;J.K. 2/23/87 If this procedure has been called to take care of INSTALL= command, +;then we have to save ES,SI registers. + +; test [Install_Flag],IS_INSTALL ;AN000; Called to handle INSTALL=? +; jz ENDFILE_Cont ;AN000; +; push es ;AN000; Save es,si for CONFIG.SYS +; push si ;AN000; +; test [Install_Flag],HAS_INSTALLED ;AN000; Sysinit_base already installed? +; jz ENDFILE_Cont ;AN000; No. Install it. +; jmp DO_Install_EXEC ;AN000; Just handle "INSTALL=" cmd only. +;ENDFILE_Cont: ;AN000; + + push ds ;AN002; + mov ax, Code ;AN002; + mov ds, ax ;AN002; + assume ds:Code + cmp MulTrk_flag, MULTRK_OFF1 ;AN002;=0, MULTRACK= command entered? + jne MulTrk_Flag_Done ;AN002; + or MulTrk_flag, MULTRK_ON ;AN002; Default will be ON. +MulTrk_Flag_Done: ;AN002; + pop ds ;AN002; + assume ds:nothing + + MOV AX,[CONFBOT] + MOV [ALLOCLIM],AX + + PUSH CS + POP DS + INVOKE ROUND + MOV AL,[FILES] + SUB AL,5 + JBE DOFCBS + push ax ;AN005; + mov al, DEVMARK_FILES ;AN005; + call SetDevMark ;AN005; Set DEVMARK for SFTS (FILES) + pop ax ;AN005; + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV BX,[MEMLO] + MOV DX,[MEMHI] + LDS DI,[DOSINFO] ;GET POINTER TO DOS DATA + LDS DI,[DI+SYSI_SFT] ;DS:BP POINTS TO SFT + MOV WORD PTR [DI+SFLINK],BX + MOV WORD PTR [DI+SFLINK+2],DX ;SET POINTER TO NEW SFT + PUSH CS + POP DS + LES DI,DWORD PTR [MEMLO] ;POINT TO NEW SFT + MOV WORD PTR ES:[DI+SFLINK],-1 + MOV ES:[DI+SFCOUNT],AX + MOV BL,SIZE SF_ENTRY + MUL BL ;AX = NUMBER OF BYTES TO CLEAR + MOV CX,AX + ADD [MEMLO],AX ;ALLOCATE MEMORY + MOV AX,6 + ADD [MEMLO],AX ;REMEMBER THE HEADER TOO + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before the STOSB + ADD DI,AX + XOR AX,AX + REP STOSB ;CLEAN OUT THE STUFF + +;------------------------------------------------------------------------------ +; Allocate FCBs +;------------------------------------------------------------------------------ +DOFCBS: + PUSH CS + POP DS + INVOKE ROUND + mov al, DEVMARK_FCBS ;AN005;='X' + call SetDevMark ;AN005; + MOV AL,[FCBS] + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV BX,[MEMLO] + MOV DX,[MEMHI] + LDS DI,[DOSINFO] ;GET POINTER TO DOS DATA + ASSUME DS:NOTHING + MOV WORD PTR [DI+SYSI_FCB],BX + MOV WORD PTR [DI+SYSI_FCB+2],DX ;SET POINTER TO NEW Table + MOV BL,CS:Keep + XOR BH,BH + MOV [DI+SYSI_keep],BX + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + LES DI,DWORD PTR [MEMLO] ;POINT TO NEW Table + MOV WORD PTR ES:[DI+SFLINK],-1 + MOV ES:[DI+SFCOUNT],AX + MOV BL,SIZE SF_ENTRY + MOV CX,AX + MUL BL ;AX = NUMBER OF BYTES TO CLEAR + ADD [MEMLO],AX ;ALLOCATE MEMORY + MOV AX,size sf-2 + ADD [MEMLO],AX ;REMEMBER THE HEADER TOO + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before the STOSB + ADD DI,AX ;Skip over header + MOV AL,"A" +FillLoop: + PUSH CX ; save count + MOV CX,SIZE sf_entry ; number of bytes to fill + cld + REP STOSB ; filled + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_ref_count],0 + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_position],0 + MOV WORD PTR ES:[DI-(SIZE sf_entry)+sf_position+2],0 + POP CX + LOOP FillLoop + +;------------------------------------------------------------------------------ +; Allocate Buffers +;------------------------------------------------------------------------------ + +; Search through the list of media supported and allocate 3 buffers if the +; capacity of the drive is > 360KB + + CMP [BUFFERS], -1 ; Has buffers been already set? + je DoDefaultBuff + cmp Buffer_Slash_X, 1 ;AN000; + jne DO_Buffer ;AN000; + call DoEMS ;AN000; Carry set if (enough) EMS is not available + jc DoDefaultBuff ;AN000; Error. Just use default buffer. +DO_Buffer: + jmp DOBUFF ; the user entered the buffers=. + +DoDefaultBuff: + mov [H_Buffers], 0 ;AN000; Default is no heuristic buffers. + MOV [BUFFERS], 2 ; Default to 2 buffers + PUSH AX + PUSH DS + LES BP,CS:[DOSINFO] ; Search through the DPB's + LES BP,DWORD PTR ES:[BP.SYSI_DPB] ; Get first DPB + +ASSUME DS:SYSINITSEG + PUSH CS + POP DS + +NEXTDPB: + ; Test if the drive supports removeable media + MOV BL, BYTE PTR ES:[BP.DPB_DRIVE] + INC BL + MOV AX, (IOCTL SHL 8) OR 8 + INT 21H + +; Ignore fixed disks + OR AX, AX ; AX is nonzero if disk is nonremoveable + JNZ NOSETBUF + +; Get parameters of drive + XOR BX, BX + MOV BL, BYTE PTR ES:[BP.DPB_DRIVE] + INC BL + MOV DX, OFFSET DeviceParameters + MOV AX, (IOCTL SHL 8) OR GENERIC_IOCTL + MOV CX, (RAWIO SHL 8) OR GET_DEVICE_PARAMETERS + INT 21H + JC NOSETBUF ; Get next DPB if driver doesn't support + ; Generic IOCTL + +; Determine capacity of drive +; Media Capacity = #Sectors * Bytes/Sector + MOV BX, WORD PTR DeviceParameters.DP_BPB.BPB_TotalSectors + +; To keep the magnitude of the media capacity within a word, +; scale the sector size +; (ie. 1 -> 512 bytes, 2 -> 1024 bytes, ...) + MOV AX, WORD PTR DeviceParameters.DP_BPB.BPB_BytesPerSector + XOR DX, DX + MOV CX, 512 + DIV CX ; Scale sector size in factor of + ; 512 bytes + + MUL BX ; AX = #sectors * size factor + OR DX, DX ; Just in case of LARGE floppies + JNZ SETBUF + CMP AX, 720 ; 720 Sectors * size factor of 1 + JBE NOSETBUF +SETBUF: + MOV [BUFFERS], 3 + jmp Chk_Memsize_for_Buffers ; Now check the memory size for default buffer count +; JMP BUFSET ; Jump out of search loop +NOSETBUF: + CMP WORD PTR ES:[BP.DPB_NEXT_DPB],-1 + jz Chk_Memsize_for_Buffers +; JZ BUFSET + LES BP,ES:[BP.DPB_NEXT_DPB] + JMP NEXTDPB + +;J.K. 10/15/86 DCR00014. +;From DOS 3.3, the default number of buffers will be changed according to the +;memory size too. +; Default buffers = 2 +; If diskette Media > 360 kb, then default buffers = 3 +; If memory size > 128 kb (2000H para), then default buffers = 5 +; If memory size > 256 kb (4000H para), then default buffers = 10 +; If memory size > 512 kb (8000H para), then default buffers = 15. + +Chk_Memsize_for_Buffers: + cmp [memory_size], 2000h + jbe BufSet + mov [buffers], 5 + cmp [memory_size], 4000h + jbe BufSet + mov [buffers], 10 + cmp [memory_size], 8000h + jbe BufSet + mov [buffers], 15 + +BUFSET: +ASSUME DS:NOTHING + POP DS + POP AX + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;J.K. Here we should put extended stuff and new allocation scheme!!! +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;******************************************************************************* +; * +; Function: Actually allocate BUFFERS into the (extended) memory and initialize* +; it. * +; If it is installed in real memory, the number of buffers in each * +; bucket will be balanced out as far as possible for perfermance. * +; Also, if the user specified the secondary buffer cache, it will * +; be installed in the real memory. * +; * +; Input : * +; BuffINFO.EMS_MODE - 0=IBM mode, -1 = do not use extended memory. * +; BuffINFO.Frame_Page - Page frame 0 segment address * +; MEMHI:MEMLO - Start of the next available memory * +; Buffer_Pages = Number of extended memory pages for buffer * +; BUFFERS = Number of buffers * +; H_Buffers = Number of secondary buffers * +; * +; Output: * +; BuffINFO.Cache_Count - # of caches to be installed. * +; Hash table set. * +; BuffINFO set. * +; BufferBuckets set. * +; MaxNumBuf1, MaxNumBuf2, and NthBuck set. * +; * +; Subroutines to be called: * +; * +; Logic: * +; { * +; IF (BuffINFO.EMS_MODE == -1) THEN * +; { * +; IF BUFFERS < 30 THEN * +; {# of Bucket = 1; MaxNumBuf1 = BUFFERS; NthBuck = 1} * +; ELSE { * +; # of Bucket = BUFFERS/15; * +; r = BUFFERS mod 15; * +; IF r == 0 THEN NthBuck = # of Bucket * +; ELSE * +; { * +; AddBuff = r / # of Bucket; * +; NthBuck = r mod # of Bucket; * +; MaxNumBuf1 = 15 + AddBuff; /* 1st Bucket - Nth Bucket* +; MaxNumBuf2 = 15 + AddBuff +1;/*(N+1)th Bucket to last* +; } * +; } * +; } * +; ELSE * +; { * +; # of Bucket = Buffer_Pages * 2; /* 2 buckets per page * +; }; * +; * +; /*Now allocate memory for Hash table */ * +; Hash Table Size = (size Buffer_Hash_Entry) * # of Bucket; * +; Set BuffINFO.Hash_ptr to MEMHI:MEMLO; * +; Adjust MEMHI:MEMLO according to Hash table size; * +; * +; /*Set buffers*/ * +; IF (EMS_MODE <> -1) THEN * +; Set_EMS_Buffer * +; ELSE /*Do not use the extended memory */ * +; Set_Buffer; * +;/*Now set the caches if specified.*/ * +; IF (BuffINFO.Cache_count > 0) THEN * +; {Set BuffINFO.Cache_ptr to MEMHI:MEMLO; * +; MEMHI:MEMLO = MEMHI:MEMLO + 512 * BuffINFO.Cache_count; * +; }; * +; }; * +; * +;******************************************************************************* +DOBUFF: ;AN000; + lds bx, cs:[DosInfo] ;AN000; ds:bx -> SYSINITVAR + + mov ax, [Buffers] ;AN000;Set SYSI_BUFFERS + mov word ptr ds:[bx.SYSI_BUFFERS], ax ;AN000; + mov ax, [H_Buffers] ;AN000; + mov word ptr ds:[bx.SYSI_BUFFERS+2], ax ;AN000; + + lds bx, ds:[bx.SYSI_BUF] ;AN000; now, ds:bx -> BuffInfo + cmp ds:[bx.EMS_MODE], -1 ;AN000; +; $IF E, LONG ;AN000; + JE $$XL1 + JMP $$IF1 +$$XL1: + xor dx, dx ;AN000; + mov ax, [Buffers] ;AN000; < 99 + cmp al, 30 ;AN026; if less than 30, +; $IF B ;AN026; + JNB $$IF2 + mov [BufferBuckets], 1 ;AN026; then put every buffer + mov ds:[bx.HASH_COUNT], 1 ;AN026; into one bucket + mov [MaxNumBuf1], al ;AN026; + mov [NthBuck], 1 ;AN026; +; $ELSE ;AN026; else... + JMP SHORT $$EN2 +$$IF2: + mov cl, 15 ;AN026; Magic number 15. + div cl ;AN026; al=# of buckets, ah=remainders + push ax ;AN026; save the result + xor ah, ah ;AN026; + mov [BufferBuckets], ax ;AN026; + mov ds:[bx.HASH_COUNT], ax ;AN026; + pop ax ;AN026; + or ah, ah ;AN026; +; $IF Z ;AN026;if no remainders + JNZ $$IF4 + mov [NthBuck], al ;AN026;then set NthBuck=# of bucket for Set_Buffer proc. +; $ELSE ;AN026;else + JMP SHORT $$EN4 +$$IF4: + mov cl, al ;AN026; + mov al, ah ;AN026;remainder/# of buckets + xor ah, ah ;AN026; = + div cl ;AN026;al=additional num of buffers + or ah, ah ;AN026;ah=Nth bucket +; $IF Z ;AN026; + JNZ $$IF6 + add [MaxNumBuf1], al ;AN026; + mov ax, [BufferBuckets] ;AN026; + mov [NthBuck], al ;AN026; +; $ELSE ;AN026; + JMP SHORT $$EN6 +$$IF6: + mov [NthBuck], ah ;AN026; + add [MaxNumBuf1], al ;AN026;MaxNumNuf are initially set to 15. + add [MaxNumBuf2], al ;AN026; + inc [MaxNumBuf1] ;AN026;Additional 1 more buffer for group 1 buckets. +; $ENDIF ;AN026; +$$EN6: +; $ENDIF ;AN026; +$$EN4: +; $ENDIF ;AN026; +$$EN2: +; $ELSE ;AN000; Use the extended memory. + JMP SHORT $$EN1 +$$IF1: + mov ax, [Buffer_Pages] ;AN000; + mov cx, MAXBUCKETINPAGE ;AN000; + mul cx ;AN000; gauranteed to be word boundary. + mov [BufferBuckets], ax ;AN000; + mov ds:[bx.HASH_COUNT], ax ;AN000; +; $ENDIF ;AN000; +$$EN1: + invoke Round ;AN000; get [MEMHI]:[MEMLO] + mov al, DEVMARK_BUF ;AN005; ='B' + call SetDevMark ;AN005; +;Now, allocate Hash table at [memhi]:[memlo]. AX = Hash_Count. + mov ax, [BufferBuckets] ;AN026; # of buckets==Hash_Count + mov cx, size BUFFER_HASH_ENTRY ;AN000; + mul cx ;AN000; now AX = Size of hash table. + les di, ds:[bx.HASH_PTR] ;AN000; save Single buffer address. + mov cx, [MemLo] ;AN000; + mov word ptr ds:[bx.HASH_PTR], cx ;AN000; set BuffINFO.HASH_PTR + mov cx, [MemHi] ;AN000; + mov word ptr ds:[bx.HASH_PTR+2], cx ;AN000; + mov [Memlo], ax ;AN000; + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + call Round ;AN000; get new [memhi]:[memlo] +;Allocate buffers + push ds ;AN000; Save Buffer info. ptr. + push bx ;AN000; + cmp ds:[bx.EMS_MODE], -1 ;AN000; +; $IF NE ;AN000; + JE $$IF13 + call Set_EMS_Buffer ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN13 +$$IF13: + call Set_Buffer ;AN000; +; $ENDIF ;AN000; +$$EN13: + pop bx ;AN000; + pop ds ;AN000; +;Now set the secondary buffer if specified. + cmp [H_Buffers], 0 ;AN000; +; $IF NE ;AN000; + JE $$IF16 + call Round ;AN000; + mov cx, [MemLo] ;AN000; + mov word ptr ds:[bx.CACHE_PTR], cx ;AN000; + mov cx, [MemHi] ;AN000; + mov word ptr ds:[bx.CACHE_PTR+2], cx ;AN000; + mov cx, [H_Buffers] ;AN000; + mov ds:[bx.CACHE_COUNT], cx ;AN000; + mov ax, 512 ;AN000; 512 byte + mul cx ;AN000; + mov [Memlo], ax ;AN000; + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + call Round ;AN000; +; $ENDIF ;AN000; +$$IF16: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;J.K. END OF NEW BUFFER SCHEME. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;DOBUFF: +; INVOKE ROUND +; DEC [BUFFERS] ; FIRST DEC acounts for buffer already +; ; in system. +; JZ BUF1 ; All done +; PUSH DS +; LES DI,BUFPTR +; LDS BX,DOSINFO +; MOV AX,WORD PTR [BX.SYSI_BUF] ; Link in new buffer +; MOV WORD PTR ES:[DI.buf_link],AX +; MOV AX,WORD PTR [BX.SYSI_BUF+2] +; MOV WORD PTR ES:[DI.buf_link+2],AX +; MOV WORD PTR [BX.SYSI_BUF],DI +; MOV WORD PTR [BX.SYSI_BUF+2],ES +; MOV WORD PTR ES:[DI.buf_ID],00FFH ;NEW BUFFER FREE +; mov word ptr es:[di.buf_Sector],0 ;AN000; +; mov word ptr es:[di.buf_Sector+2],0 ;AN000; +; MOV BX,[BX.SYSI_MAXSEC] +; POP DS +; ADD BX,BUFINSIZ +; ADD [MEMLO],BX +; JMP DOBUFF + +;------------------------------------------------------------------------------ +; Allocate CDSs +;------------------------------------------------------------------------------ +BUF1: + INVOKE ROUND + push ax ;AN005; + mov ax, DEVMARK_CDS ;AN005;='L' + call SetDevMark ;AN005; + pop ax ;AN005; + LES DI,[DOSINFO] + MOV CL,BYTE PTR ES:[DI.SYSI_NUMIO] + CMP CL,[NUM_CDS] + JAE GOTNCDS ; User setting must be at least NUMIO + MOV CL,[NUM_CDS] +GOTNCDS: + XOR CH,CH + MOV ES:[DI.SYSI_NCDS],CL + MOV AX,[MEMHI] + MOV WORD PTR ES:[DI.SYSI_CDS + 2],AX + MOV AX,[MEMLO] + MOV WORD PTR ES:[DI.SYSI_CDS],AX + MOV AL,CL + MOV AH,SIZE curdir_list + MUL AH + call ParaRound + ADD [MEMHI],AX + or [SetDevMarkFlag], FOR_DEVMARK ;AN005; + INVOKE ROUND ; Check for mem error before initializing + LDS SI,ES:[DI.SYSI_DPB] +ASSUME DS:NOTHING + LES DI,ES:[DI.SYSI_CDS] + CALL FOOSET + +;------------------------------------------------------------------------------ +; Allocate Space for Internal Stack +;------------------------------------------------------------------------------ + + IF STACKSW + + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + IF IBM +;Don't install the system stack on the PCjr. Ignore STACKS=command too. + CMP [Sys_Model_Byte], 0FDh ; PCjr = 0FDh + JE SkipStack_brdg + ENDIF + +;J.K. 10/15/86 DCR00013 +;If the use does not entered STACKS= command, as a default, do not install +;sytem stacks for PC1, PC XT, PC Portable cases. +;Otherwise, install it to the user specified value or to the default +;value of 9, 128 for the rest of the system. + + cmp word ptr [stack_addr], -1 ;Has the user entered "stacks=" command? + je DoInstallStack ;Then install as specified by the user + cmp [Sys_Scnd_Model_Byte], 0 ;PC1, XT has the secondary model byte = 0 + jne DoInstallStack ;Other model should have default stack of 9, 128 + cmp [Sys_Model_Byte], 0FFh ;PC1 ? + je SkipStack_brdg + cmp [Sys_Model_Byte], 0FEh ;PC/XT or PC Portable ? + jne DoInstallStack +SkipStack_Brdg: + jmp SkipStack +DoInstallStack: + mov ax, [stack_count] ;J.K. Stack_count = 0? + cmp ax, 0 ;then, stack size must be 0 too. + jz SkipStack_brdg ;Don't install stack. +;J.K. 10/21/86 Dynamic Relocation of Stack code. + call Round ;[memhi] = Seg. for stack code + ;[memlo] = 0 +;J.K. Set DEVMARK block into memory for MEM command +;J.K. DEVMARK_ID = 'S' for stack + mov al, DEVMARK_STK ;AN005;='S' + call SetDevMark + + mov ax, [memhi] + mov es, ax ;ES -> Seg. the stack code is going to move. + assume es:nothing + push cs + pop ds + xor si,si ;!!We know that Stack code is at the beginning of SYSINIT. + xor di,di + mov cx, offset Endstackcode + mov [memlo],cx + call Round ;Have enough space for relocation? + rep movsb + + mov ax, [memlo] + mov word ptr [stack_addr],ax ;set for stack area initialization + mov ax, [memhi] ;This will be used by Stack_Init routine. + mov word ptr [stack_addr+2],ax + +; Space for Internal Stack area = STACK_COUNT(ENTRYSIZE + STACK_SIZE) + MOV AX, EntrySize + ADD AX, [STACK_SIZE] + MOV CX, [STACK_COUNT] + MUL CX + call ParaRound ; Convert size to pargraphs + ADD [MEMHI], AX + or [SetDevMarkFlag], FOR_DEVMARK ;AN005;To set the DEVMARK_SIZE for Stack by ROUND routine. + INVOKE ROUND ; Check for memory error before + ; continuing + CALL StackInit ; Initialize hardware stack. CS=DS=sysinitseg, ES=Relocated stack code & data + +SkipStack: + ENDIF + + PUSH CS + POP DS + ASSUME DS:SYSINITSEG + + MOV AL,[FILES] + XOR AH,AH ; DO NOT USE CBW INSTRUCTION!!!!! + ; IT DOES SIGN EXTEND. + MOV CX,AX + XOR BX,BX ;Close standard input + MOV AH,CLOSE + INT 21H + MOV BX,2 +RCCLLOOP: ;Close everybody but standard output + MOV AH,CLOSE ; Need output so we can print message + INT 21H ; in case we can't get new one open. + INC BX + LOOP RCCLLOOP + + MOV DX,OFFSET CONDEV + MOV AL,2 + MOV AH,OPEN ;OPEN CON FOR READ/WRITE + STC ; Set for possible INT 24 + INT 21H + JNC GOAUX + INVOKE BADFIL + JMP SHORT GOAUX2 + +GOAUX: PUSH AX + MOV BX,1 ;close standard output + MOV AH,CLOSE + INT 21H + POP AX + + MOV BX,AX ;New device handle + MOV AH,XDUP + INT 21H ;Dup to 1, STDOUT + MOV AH,XDUP + INT 21H ;Dup to 2, STDERR + +GOAUX2: MOV DX,OFFSET AUXDEV + MOV AL,2 ;READ/WRITE ACCESS + INVOKE OPEN_DEV + + MOV DX,OFFSET PRNDEV + MOV AL,1 ;WRITE ONLY + INVOKE OPEN_DEV + +;J.K.9/29/86 ******************* +;Global Rearm command for Shared Interrupt devices attached in the system; +;Shared interrupt attachment has some problem when it issues interrupt +;during a warm reboot. Once the interrupt is presented by the attachment, +;no further interrupts on that level will be presented until a global rearm +;is issued. By the request of the system architecture group, IBMBIO will +;issue a global rearm after every device driver is loaded. +;To issue a global rearm: ;For PC1, XT, Palace +; OUT 02F2h, XX ; Interrupt level 2 +; OUT 02F3h, XX ; Interrupt level 3 +; OUT 02F4h, XX ; Interrupt level 4 +; OUT 02F5h, XX ; Interrupt level 5 +; OUT 02F6h, XX ; Interrupt level 6 +; OUT 02F7h, XX ; Interrupt level 7 +; +; ;For PC AT, in addition to the above commands, +; ;need to handle the secondary interrupt handler +; OUT 06F2h, XX ; Interrupt level 10 +; OUT 06F3h, XX ; Interrupt level 11 +; OUT 06F4h, XX ; Interrupt level 12 +; OUT 06F6h, XX ; Interrupt level 14 +; OUT 06F7h, XX ; Interrupt level 15 +; +; ;For Round-Up machine +; None. +; where XX stands for any value. +; For your information, after Naples level machine, the system service bios +; call (INT 15h), function AH=0C0h returns the system configuration parameters +; + + cmp [sys_model_byte], 0FDh ;PCjr? +; je GoCheckInstall + je Set_Sysinit_Base +;SB33045******************************************************************* + push ax ;Save Regs ;SB ;3.30* + push bx ; * ;SB ;3.30* + push dx ; * ;SB ;3.30* + push es ; * ;SB ;3.30* + mov al,0ffh ;Reset h/w by writing to port ;SB ;3.30* + mov dx,2f2h ;Get starting address ;SB ;3.30* + out dx,al ; out 02f2h,0ffh + inc dx + out dx,al ; out 02f3h,0ffh + inc dx + out dx,al ; out 02f4h,0ffh + inc dx + out dx,al ; out 02f5h,0ffh + inc dx + out dx,al ; out 02f6h,0ffh + inc dx + out dx,al ; out 02f7h,0ffh +;SB33045******************************************************************* + +;SB33046******************************************************************* +;SB Secondary global rearm ;3.30 + mov ax,0f000h ;Get machine type ;SB ;3.30* + mov es,ax ; * ;SB ;3.30* + cmp byte ptr es:[0fffeh],0fch ;Q:Is it a AT type machine ;SB ;3.30* + je startrearm ; *if AT no need to check + mov ah,0c0h ;Get system configuration ;SB ;3.30* + int 15h ; * ;SB ;3.30* + jc finishrearm ; *jmp if old rom ;SB ;3.30* +; ;SB ;3.30* +; Test feature byte for secondary interrupt controller ;SB ;3.30* +; ;SB ;3.30* + test es:[bx.bios_SD_featurebyte1],ScndIntController ; ;SB ;3.30* + je finishrearm ;Jmp if it is there ;SB ;3.30* +startrearm: + mov al,0ffh ;Write any pattern to port ;SB ;3.30* + mov dx,6f2h ;Get starting address ;SB ;3.30* + out dx,al ;out 06f2h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f3h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f4h,0ffh + inc dx ;Bump address ;SB ;3.30* + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f6h,0ffh + inc dx ;Bump address ;SB ;3.30* + out dx,al ;out 06f7h,0ffh +finishrearm: ; ;SB ;3.30* + pop es ;Restore regs ;SB ;3.30* + pop dx ; * ;SB ;3.30* + pop bx ; * ;SB ;3.30* + pop ax ; * ;SB ;3.30* +;SB33046******************************************************************* + +;J.K. 9/29/86 Global Rearm end ******************* + +;------------------------------------------------------------------------------ +; Allocate SYSINIT_BASE for INSTALL= command +;------------------------------------------------------------------------------ +;J.K. SYSINIT_BASE allocation. +;Check if ENDFILE has been called to handle INSTALL= command. + +Set_Sysinit_Base: +;GoCheckInstall: +; test [Install_Flag], HAVE_INSTALL_CMD ;AN019;;AN021;install sysinit base all the time. +; jz Skip_SYSINIT_BASE ;AN019; + +;J.K.-------------------------------------------------------------------------- +;SYSINIT_BASE will be established in the secure area of +;lower memory when it handles the first INSTALL= command. +;SYSINIT_BASE is the place where the actual EXEC function will be called and +;will check SYSINIT module in high memory if it is damaged by the application +;program. If SYSINIT module has been broken, then "Memory error..." message +;is displayed by SYSINIT_BASE. +;------------------------------------------------------------------------------ + push ax ;AN013; Set DEVMARK for MEM command + mov ax, [memhi] ;AN013; + sub ax, [area] ;AN013; + mov [Impossible_owner_size], ax ;AN013;Remember the size in case. + mov al, DEVMARK_INST ;AN013; + call SetDevMark ;AN013; + pop ax ;AN013; + + mov di, [memhi] ;AN000; + mov es, di ;AN000; + assume es:nothing ;AN000; + mov word ptr [sysinit_base_ptr+2],di ;AN000; save this entry for the next use. + xor di, di ;AN000; + mov word ptr [sysinit_base_ptr], di ;AN000; es:di -> destination. + mov si, offset SYSINIT_BASE ;AN000; ds:si -> source code to be relocated. + mov cx, Size_SYSINIT_BASE ;AN000; + add [memlo],cx ;AN000; + or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN013; + call round ;AN000; check mem error. Also, readjust MEMHI for the next use. + rep movsb ;AN000; reallocate it. + + mov word ptr [Sysinit_Ptr], offset SYSINITPTR ;AN000; Returing address from + mov word ptr [Sysinit_Ptr+2], cs ;AN000; SYSINIT_BASE back to SYSINIT. + or [Install_Flag],HAS_INSTALLED ;AN000; Set the flag. + +;------------------------------------------------------------------------------ +; Free the rest of the memory from MEMHI to CONFBOT. Still from CONFBOT to +; the top of the memory will be allocated for SYSINIT and CONFIG.SYS if +; HAVE_INSTALL_CMD. +;------------------------------------------------------------------------------ +;Skip_SYSINIT_BASE: ;AN021; + + INVOKE ROUND + MOV BX,[MEMHI] + MOV AX,[AREA] + mov [Old_Area], ax ;AN013; Save [AREA] + MOV ES,AX ;CALC WHAT WE NEEDED + SUB BX,AX + MOV AH,SETBLOCK + INT 21H ;GIVE THE REST BACK + PUSH ES + MOV AX,ES + DEC AX + MOV ES,AX ;Point to arena + MOV ES:[arena_owner],8 ;Set impossible owner + POP ES + + mov bx,0ffffh ;AN000; + mov ah,Alloc ;AN000; + int 21h ;AN000; + mov ah,Alloc ;AN000; + int 21h ;AN000; Allocate the rest of the memory + + mov [memhi],ax ;AN000; Start of the allocated memory + mov [memlo],0 ;AN000; to be used next. + + ;;;; At this moment, memory from [MEMHI]:0 to Top-of-the memory is + ;;;; allocated. + ;;;; To protect sysinit, confbot module (From CONFBOT (or =ALLOCLIM at + ;;;; this time) to the Top-of-the memory), here we are going to + ;;;; 1). "SETBLOCK" from MEMHI to CONFBOT. + ;;;; 2). "ALLOC" from CONFBOT to the top of the memory. + ;;;; 3). "Free Alloc Memory" from MEMHI to CONFBOT. +;Memory allocation for SYSINIT, CONFBOT module. + mov es, ax ;AN000; + mov bx, [confbot] ;AN000; + sub bx, ax ;AN000; CONFBOT - MEMHI + dec bx ;AN000; Make a room for the memory block id. + dec bx ;AN000; make sure!!!. + mov ah, SETBLOCK ;AN000; + int 21h ;AN000; this will free (CONFBOT to top of memory) + mov bx, 0ffffh ;AN000; + mov ah, ALLOC ;AN000; + int 21h ;AN000; + mov ah, ALLOC ;AN000; + int 21h ;AN000; allocate (CONFBOT to top of memory) + mov [area],ax ;AN000; Save Allocated memory segment. + ;AN000; Need this to free this area for COMMAND.COM. + mov es, [memhi] ;AN000; + mov ah, 49h ;AN000; Free Allocated Memory. + int 21h ;AN000; Free (Memhi to CONFBOT(=AREA)) + +; IF NOEXEC +; MOV BX,0FFFFH ;ALLOCATE THE REST OF MEM FOR COMMAND +; MOV AH,ALLOC +; INT 21H +; MOV AH,ALLOC +; INT 21H +; MOV DS,AX +; ENDIF + +; test cs:[Install_Flag],IS_INSTALL ;AN000; +; jnz DO_Install_Exec ;AN000; + +ENDFILE_Ret: + return + + +Do_Install_Exec proc near ;AN000; Now, handles INSTALL= command. + + push si ;AN000; save SI for config.sys again. + + ;;;; We are going to call LOAD/EXEC function. + ;;;;;Set ES:BX to the parameter block here;;;;;;; + ;;;;;Set DS:DX to the ASCIIZ string. Remember that we already has 0 + ;;;;;after the filename. So parameter starts after that. If next + ;;;;;character is a line feed (i.e. 10), then assume that the 0 + ;;;;;we already encountered used to be a carrage return. In this + ;;;;;case, let's set the length to 0 which will be followed by + ;;;;;carridge return. +;J.K. ES:SI -> command line in CONFIG.SYS. Points to the first non blank +;character after =. + push es ;AN000; + push ds ;AN000; + pop es ;AN000; + pop ds ;AN000; es->sysinitseg, ds->confbot seg + assume ds:nothing ;AN000; + mov dx, si ;AN000; ds:dx->file name,0 in CONFIG.SYS image. +;AN016; UNDO THE EXTENDED ATTRIBUTES HANDLING +; mov ax, OPEN SHL 8 ;AN008; +; int 21h ;AN008; +; jc SysInitPtr ;AN008; +; mov bx, ax ;AN008;handle +; call Get_Ext_Attribute ;AN008;Get the extended attribute. +; cmp al, EA_INSTALLABLE ;AN008; +; je EA_Installable_OK ;AN012; +; stc ;AN012; +; jmp SysInitPtr ;AN012; +;EA_Installable_OK: ;AN012; + xor cx,cx ;AN000; + cld ;AN000; + mov cs:Ldexec_start, ' ' ;AN015; Clear out the parm area + mov di, offset Ldexec_parm ;AN000; +InstallFilename: ;AN000; skip the file name + lodsb ;AN000; al = ds:si; si++ + cmp al, 0 ;AN000; + je Got_InstallParm ;AN000; + jmp InstallFilename ;AN000; +Got_InstallParm: ;AN000; copy the parameters to Ldexec_parm + lodsb ;AN000; + mov es:[di], al ;AN000; + cmp al, LF ;AN000;AN028; line feed? + je Done_InstallParm ;AN000;AN028; + inc cl ;AN000; # of char. in the parm. + inc di ;AN000; + jmp Got_Installparm ;AN000; +Done_Installparm: ;AN000; + mov byte ptr cs:[Ldexec_line], cl ;AN000; length of the parm. + cmp cl, 0 ;AN015;If no parm, then + jne Install_Seg_Set ;AN015; let the parm area + mov byte ptr cs:[Ldexec_Start],CR ;AN015; starts with CR. +Install_Seg_Set: ;AN015; + mov word ptr cs:0, 0 ;AN000; Make a null environment segment + mov ax, cs ;AN000; by overlap JMP instruction of SYSINITSEG. + mov cs:[INSTEXE.EXEC0_ENVIRON],ax ;AN000; Set the environment seg. + mov word ptr cs:[INSTEXE.EXEC0_COM_LINE+2],ax ;AN000; Set the seg. + mov word ptr cs:[INSTEXE.EXEC0_5C_FCB+2],ax ;AN000; + mov word ptr cs:[INSTEXE.EXEC0_6C_FCB+2],ax ;AN000; + call Sum_up ;AN000; + mov es:CheckSum, ax ;AN000; save the value of the sum + xor ax,ax ;AN000; + mov ah, EXEC ;AN000; Load/Exec + mov bx, offset INSTEXE ;AN000; ES:BX -> parm block. + push es ;AN000; Save es,ds for Load/Exec + push ds ;AN000; these registers will be restored in SYSINIT_BASE. + jmp cs:dword ptr SYSINIT_BASE_PTR ;AN000; jmp to SYSINIT_BASE to execute + ; LOAD/EXEC function and check sum. + +;J.K. This is the returning address from SYSINIT_BASE. +SYSINITPTR: ;AN000; returning far address from SYSINIT_BASE + pop si ;AN000; restore SI for CONFIG.SYS file. + push es ;AN000; + push ds ;AN000; + pop es ;AN000; + pop ds ;AN000; now ds - sysinitseg, es - confbot + jnc Exec_Exit_Code + test cs:Install_Flag, SHARE_INSTALL ;AN021; Called by LoadShare proc? + jnz Install_Error_Exit ;AN021; Just exit with carry set. + push si ;AN000; Error in loading the file for INSTALL=. + call BadLoad ;AN000; ES:SI-> path,filename,0. + pop si ;AN000; + jmp Install_Exit_Ret +Exec_Exit_Code: + test cs:Install_Flag, SHARE_INSTALL ;AN021; Called by LoadShare proc? + jnz Install_Exit_Ret ;AN021; Just exit. + mov ah, 4dh ;AN017; + int 21h ;AN017; + cmp ah, 3 ;AN017;Only accept "Stay Resident" prog. + je Install_Exit_Ret ;AN017; + call Error_Line ;AN017;Inform the user +Install_Error_Exit: ;AN021; + stc ;AN021; +Install_Exit_Ret: + ret +Do_Install_Exec endp + +Public ParaRound +ParaRound: + ADD AX,15 + RCR AX,1 + SHR AX,1 + SHR AX,1 + SHR AX,1 + return + +;------------------------------------------------------------------------------ +;J.K. SYSINIT_BASE module. +;In: After relocation, +; AX = 4B00h - Load and execute the program DOS function. +; DS = CONFBOT. Segment of CONFIG.SYS file image +; ES = Sysinitseg. Segment of SYSINIT module itself. +; DS:DX = pointer to ASCIIZ string of the path,filename to be executed. +; ES:BX = pointer to a parameter block for load. +; SYSSIZE (Byte) - offset vaule of End of SYSINIT module label +; BIGSIZE (word) - # of word from CONFBOT to SYSSIZE. +; CHKSUM (word) - Sum of every byte from CONFBOT to SYSSIZE in a +; word boundary moduler form. +; SYSINIT_PTR (dword ptr) - Return address to SYSINIT module. +;Note: SYSINIT should save necessary registers and when the control is back + + + public Sysinit_Base +Sysinit_Base: ;AN000; + mov word ptr cs:SYSINIT_BASE_SS, SS ;AN000; save stack + mov word ptr cs:SYSINIT_BASE_SP, SP ;AN000; + int 21h ;AN000; LOAD/EXEC DOS call. + mov SS, word ptr cs:SYSINIT_BASE_SS ;AN000; restore stack + mov SP, word ptr cs:SYSINIT_BASE_SP ;AN000; + pop ds ;AN000; restore CONFBOT seg + pop es ;AN000; restore SYSINITSEG + jc SysInit_Base_End ;AN000; LOAD/EXEC function failed. + ;At this time, I don't have to worry about + ;that SYSINIT module has been broken or not. + call Sum_up ;AN000; Otherwise, check if it is good. + cmp es:CheckSum, AX ;AN000; + je SysInit_Base_End ;AN000; +;Memory broken. Show "Memory allocation error" message and stall. + mov ah, 09h ;AN000; + push cs ;AN000; + pop ds ;AN000; + mov dx, Mem_alloc_err_msg ;AN000; + int 21h ;AN000; +Stall_now: jmp Stall_now ;AN000; + +SysInit_Base_End: jmp es:Sysinit_Ptr ;AN000; return back to sysinit module + +Sum_up: ;AN000; +;In: +; ES - SYSINITSEG. +;OUT: AX - Result +;Remark: Since this routine will only check starting from "LocStack" to the end of +; Sysinit segment, the data area, and the current stack area are not +; coverd. In this sense, this check sum routine only gives a minimal +; gaurantee to be safe. +;First sum up CONFBOT seg. + push ds ;AN021; + mov ax,es:ConfBot ;AN021; + mov ds,ax ;AN021; + xor si,si ;AN000; + xor ax,ax ;AN000; + mov cx,es:Config_Size ;AN000; If CONFIG_SIZE has been broken, then this + ;whole test better fail. + shr cx, 1 ;AN000; make it a word count + jz Sum_Sys_Code ;AN025; When CONFIG.SYS file not exist. +Sum1: ;AN000; + add ax, ds:word ptr [si] ;AN000; + inc si ;AN000; + inc si ;AN000; + loop Sum1 ;AN000; +;Now, sum up SYSINIT module. +Sum_Sys_Code: ;AN025; + mov si, offset LocStack ;AN000; Starting after the stack. + ;AN000; This does not cover the possible STACK code!!! + mov cx, offset SYSSIZE ;AN000; SYSSIZE is the label at the end of SYSINIT + sub cx, si ;AN000; From After_Checksum to SYSSIZE + shr cx, 1 ;AN000; +Sum2: ;AN000; + add ax, es:word ptr [si] ;AN000; + inc si ;AN000; + inc si ;AN000; + loop Sum2 ;AN000; + pop ds ;AN021; + ret ;AN000; + +Sysinit_Base_SS equ $-Sysinit_Base ;AN000; + dw ? ;AN000; +Sysinit_Base_SP equ $-Sysinit_Base ;AN000; + dw ? ;AN000; +Mem_Alloc_Err_msg equ $-Sysinit_Base ;AN000; +;include BASEMES.INC ;AN000; Memory allocation error message +include MSBIO.CL4 ;AN011; Memory allocation error message +End_Sysinit_Base label byte ;AN000; +SIZE_SYSINIT_BASE equ $-Sysinit_Base ;AN000; + +; +;AN016; Undo the extended attribute handling +; public Get_Ext_Attribute +;Get_Ext_Attribute proc near ;AN008; +;;In: BX - file handle +;;Out: AL = The extended attribute got from the handle. +;; AX destroyed. +;; Carry set when DOS function call fails. +; +; push ds ;AN008; +; push si ;AN008; +; push es ;AN008; +; push di ;AN008; +; push cx ;AN008; +; +; push cs ;AN008; +; pop ds ;AN008; +; push cs ;AN008; +; pop es ;AN008; +; +; mov Ext_Attr_Value, 0ffh ;AN008; Initialize to unrealistic value +; mov ax, 5702h ;AN008;Get extended attribute by handle thru LIST +; mov si, offset EA_QueryList ;AN008; +; mov di, offset Ext_Attr_List ;AN008; +; mov cx, SIZE_EXT_ATTR_LIST ;AN008; +; int 21h ;AN008; +; mov al, Ext_Attr_Value ;AN008; +; pop cx ;AN008; +; pop di ;AN008; +; pop es ;AN008; +; pop si ;AN008; +; pop ds ;AN008; +; ret ;AN008; +;Get_Ext_Attribute endp ;AN008; + + +;------------------------------------------------------------------------------ + +DoEMS proc near +;******************************************************************************* +; Function: Called prior to DOBUFF subroutine. Only called when /E option * +; for the buffers= command has been specified. * +; This routine will check if the extended memory is avaiable, * +; and determine what is the page number. We only use physical page * +; 254. if it is there, then this routine will calculate the number * +; of pages needed for buffers and will allocate logical pages in the * +; extended memory and get the page handle of them. * +; * +; Input : * +; Buffers - Number of buffers * +; Buffer_LineNum - Saved line number to be used in case of Error case * +; * +; Output: * +; BuffINFO.EMS_Handle * +; Buffer_Pages = Number of pages for buffer in the extended memory. * +; BuffINFO.EMS_MODE = -1 No extended memory or Non-IBM compatible mode. * +; Buffers = the number will be changed to be a multiple of 30. * +; Carry set if no extended memory exist or if it is not big enough. * +; AX, BX, CX, DX destroyed. * +; * +; Logic: * +; { * +; Get EMS Version (AH=46h); * +; If (EMS not installed or it is not IBM compatible or * +; (Available_pages * 30 < Buffers) then * +; {Show error message "Error in CONFIG.SYS line #"; * +; Set carry; Exit }; * +; else * +; Buffer_Pages = Roundup(BUFFERS/30); /* Round up 30 buffers per page*/ * +; Buffers = Buffer_Pages * 30; /* Set the new number of Buffers*/* +; Allocate Buffer_Pages (AH=43h) and set EMS_Handle; * +; }; * +; * +;******************************************************************************* + + push es ;AN000; + push di ;AN000; save es, di + push si ;AN010; + push bx ;AN010; + xor di,di ;AN004; if vector pointer of + mov es, di ;AN004; EMS (INT 67h) is 0,0 + mov di, word ptr es:[EMS_INT * 4] ;AN004; then error. + mov ax, word ptr es:[EMS_INT * 4 +2] ;AN009; + or ax,di ;AN009; +; $IF NZ,AND,LONG ;AN004; + JNZ $$XL2 + JMP $$IF18 +$$XL2: + les di, cs:[DosInfo] ;AN000; es:di -> SYSINITVAR + les di, es:[di.SYSI_BUF] ;AN000; now, es:di -> BuffInfo + + mov ah, EMS_STATUS ;AN000; get the status of EMS = 40h + int EMS_INT ;AN000; + or ah, ah ;AN000; EMS installed? +; $IF Z,AND,LONG ;AN000; + JZ $$XL3 + JMP $$IF18 +$$XL3: + mov ah, EMS_VERSION ;AN010;=46h + int EMS_INT ;AN010; + cmp AL, EMSVERSION ;AN010;40h = 4.0 +; $IF AE,AND,LONG ;AN010; + JAE $$XL4 + JMP $$IF18 +$$XL4: + call Check_IBM_PageID ;AN000; IBM (compatible) mode? + +IF BUFFERFLAG + mov ax, cs:[LAST_PAGE] + mov es:[di.EMS_LAST_PAGE], ax + mov ax, cs:[LAST_PAGE+2] + mov es:[di.EMS_LAST_PAGE+2], ax + mov ax, cs:[FIRST_PAGE] + mov es:[di.EMS_FIRST_PAGE], ax + mov ax, cs:[FIRST_PAGE+2] + mov es:[di.EMS_FIRST_PAGE+2], ax + mov ax, cs:[NPA640] + mov es:[di.EMS_NPA640], ax + mov es:[di.EMS_SAFE_FLAG], 1 +ENDIF + +; $IF NC,AND,LONG ;AN000; + JNC $$XL5 + JMP $$IF18 +$$XL5: + mov ah, EMAP_STATE ;AN010; Check if the size of + mov al, GET_MAP_SIZE ;AN010; the MAP state table + mov bx, 1 ;AN010; # of pages + int EMS_INT ;AN010; is acceptable. + or ah, ah ;AN010; +; $IF Z,AND ;AN010; + JNZ $$IF18 + cmp al, EMS_MAP_BUFF_SIZE ;AN010; Curretly=12 bytes +; $IF BE,AND ;AN010; + JNBE $$IF18 + mov ah, EQ_PAGES ;AN000; Get number of unallocated & total pages = 42h + int EMS_INT ;AN000; result in BX + xor dx, dx ;AN000; + mov ax, cs:[Buffers] ;AN000; + mov cx, MAXBUFFINBUCKET*MAXBUCKETINPAGE ;AN000; + call Roundup ;AN000; find out how many pages are needed. + cmp bx, ax ;AN000; AX is the number of pages for [buffers] +; $IF AE,AND ;AN000; + JNAE $$IF18 + mov cs:[Buffer_Pages], ax ;AN000; + mov bx, ax ;AN000; prepare for Get handle call. + mul cx ;AN000; + mov cs:[Buffers], ax ;AN000; set new [Buffers] for the extended memory. + mov ah, E_GET_HANDLE ;AN000; allocate pages = 43h + int EMS_INT ;AN000; page handle in DX. + or ah, ah ;AN000; +; $IF Z ;AN000; pages allocated. + JNZ $$IF18 + mov ah, EMS_HANDLE_NAME ;AN010; + mov al, SET_HANDLE_NAME ;AN010; + push es ;AN010; + push di ;AN010; + push ds ;AN010; + push cs ;AN010; + pop ds ;AN010; + mov si, offset EMSHandleName ;AN010; + int EMS_INT ;AN010; Set the handle name + pop ds ;AN010; + pop di ;AN010; + pop es ;AN010; + xor ah,ah ;AN010; + mov es:[di.EMS_MODE], ah ;AN000; put 0 in EMS_mode. + mov es:[di.EMS_HANDLE], dx ;AN000; save EMS handle + mov ax, cs:[IBM_Frame_Seg] ;AN010; + mov es:[di.EMS_PAGE_FRAME],ax ;AN010; + mov ax, cs:[Real_IBM_Page_Id] ;AN029; + mov es:[di.EMS_PAGEFRAME_NUMBER], ax;AN029; + mov ax, es ;AN010; + mov word ptr cs:[EMS_Ctrl_tab+2],ax ;AN010; + mov word ptr cs:[EMS_state_buf+2],ax;AN010; + push di ;AN010;save di-> Buffinfo + add di, EMS_SEG_CNT ;AN010; + mov word ptr cs:[EMS_Ctrl_tab], di ;AN010; + pop di ;AN010; + add di, EMS_MAP_BUFF ;AN010; + mov word ptr cs:[EMS_state_Buf],di ;AN010; + clc ;AN000; +; $ELSE ;AN000; + JMP SHORT $$EN18 +$$IF18: + mov ax, cs:[Buffer_LineNum] ;AN000; Show error message. + push cs:[LineCount] ;AN017; Save current line count + mov cs:[LineCount], ax ;AN000; Now, we can change Linecount + call Error_Line ;AN000; since we are through with CONFIG.SYS file. + pop cs:[LineCount] ;AN017; Restore line count + stc ;AN000; +; $ENDIF +$$EN18: + pop bx ;AN010; + pop si ;AN010; + pop di ;AN000; + pop es ;AN000; + ret ;AN000; +DoEMS endp + +; +Set_Buffer proc near +;******************************************************************************* +;Function: Set buffers in the real memory. * +; For each hash table entry, set the pointer to the * +; corresponding hash bucket. * +; Lastly set the memhi, memlo for the next available free address. * +; ** At the request of IBMDOS, each hash bucket will start at the * +; ** new segment. * +; * +;Input: ds:bx -> BuffInfo. * +; [Memhi]:[MemLo = 0] = available space for the hash bucket. * +; BufferInfo.Hash_Ptr -> Hash table. * +; BufferBuckets = # of buckets to install. * +; SingleBufferSize = Buffer header size + Sector size * +; MaxNumBuff1 = Number of buffers in the first group of buckets * +; MaxNumBuff2 = Number of buffers in the second group of buckets * +; NthBuck = 1st thru Nth bucket are the first group * +; * +;Output: Buffers, hash buckets and Hash table entries established. * +; [Memhi]:[Memlo] = address of the next available free space. * +; * +; { For (every bucket) * +; { Set Hash table entry; * +; Next buffer ptr = buffer size; * +; For (every buffer in the bucket) * +; { Calll Set_Buffer_Info; /*Set link, id... */ * +; IF (last buffer in a bucket) THEN * +; {last buffer's next_ptr -> first buffer; * +; first buffer's prev_ptr -> last buffer; * +; }; * +; Next buffer ptr += buffer size; * +; }; * +; }; * +; MEMHI:MEMLO = Current Buffer_Bucket add + (# of odd * buffer size)* +; }; * +;******************************************************************************* + + assume ds:nothing ;AN000;to make sure. + lds bx, ds:[bx.HASH_PTR] ;AN000;now, ds:bx -> hash table + xor dx, dx ;AN026;To be used to count buckets +; $DO ;AN000;For each bucket +$$DO21: + inc dl ;AN026; Current bucket number + mov word ptr ds:[bx.BUFFER_BUCKET],0 ;AN000;Memlo is 0 after ROUND. + mov di, [MemHi] ;AN000; + mov word ptr ds:[bx.BUFFER_BUCKET+2], di ;AN000;Hash entry set. + mov word ptr ds:[bx.DIRTY_COUNT], 0 ;AN020;set DIRTY_COUNT, BUFFER_RESERVED to 0. + mov es, di ;AN000; + xor di, di ;AN000;es:di -> hash bucket + xor cx, cx ;AN000 + xor ax, ax ;AN000 +; $DO ;AN000;For each buffer in the bucket +$$DO22: + call Set_Buffer_Info ;AN000;Set buf_link, buf_id... + inc cx ;AN000;buffer number + cmp dl, [NthBuck] ;AN026;Current bucket number > NthBuck? +; $IF BE ;AN026; + JNBE $$IF23 + cmp cl, [MaxNumBuf1] ;AN026; last buffer of the 1st group? +; $ELSE ;AN026; + JMP SHORT $$EN23 +$$IF23: + cmp cl, [MaxNumBuf2] ;AN026; last buffer of the 2nd group? +; $ENDIF ;AN026; +$$EN23: + +; $IF E ;AN020;Yes, last buffer + JNE $$IF26 + mov word ptr es:[di.BUF_NEXT], 0 ;AN020;the last buffer's next -> the first buffer in bucket (Circular chain) + mov word ptr es:[BUF_PREV], di ;AN020;the first buffer's prev -> the last buffer +; $ENDIF ;AN020; +$$IF26: + mov di, ax ;AN000;adjust next buffer position +; $ENDDO E ;AN000;flag set already for testing last buffer. + JNE $$DO22 + add [Memlo], ax ;AN000;AX is the size of this bucket. + or [SetDevMarkFlag], FOR_DEVMARK ;AN005;Update DEVMARK_SIZE + call Round ;AN000;memhi:memlo adjusted for the next bucket. + add bx, size BUFFER_HASH_ENTRY ;AN000;ds:bx -> next hash entry. + dec [BufferBuckets] ;AN000; +; $ENDDO Z ;AN000; + JNZ $$DO21 + ret ;AN000; +Set_Buffer endp + +; +Set_EMS_Buffer proc near +;******************************************************************************* +;Function: Set buffers in the extended memory. * +; For each hash table entry, set the pointer to the corresponding * +; hash bucket. * +; * +;Input: ds:bx -> BuffInfo. * +; BuffINFO.Hash_Ptr -> Hash table. * +; BuffINFO.EMS_Handle = EMS handle * +; Buffers = tatal # of buffers to install. * +; Multiple of MAXBUFFINBUCKET*MAXBUCKETINPAGE. * +; Buffer_Pages = # of extended memory pages for buffers. * +; BufferBuckets = # of buckets to install. * +; SingleBufferSize = Buffer header size + Sector size. * +; * +;Output: Buffers, hash buckets and Hash table entries established. * +; * +; { For (each page) * +; { Map the page; /*Map the page into Page frame * +; For (each bucket) /*Each page has two buckets */ * +; { * +; Set EMS_Page; * +; Set Buffer_Bucket; * +; Next buffer ptr = buffer size; * +; For (every buffer) /*A bucket has 15 buffers */ * +; { Set Buf_link to Next buffer ptr; * +; Set Buffer_ID to free; * +; If (last buffer in this bucket) THEN * +; {Buf_link = -1; * +; Next buffer ptr = 0; * +; }; * +; Next buffer ptr += buffer size; * +; }; * +; }; * +; }; * +; }; * +;******************************************************************************* + + assume ds:nothing ;AN000;to make sure. + +IF BUFFERFLAG + + push ax + mov ax, offset ems_save_buf + mov word ptr cs:[ems_state_buf], ax + push cs + pop word ptr cs:[ems_state_buf+2] + pop ax + +ENDIF + + call Save_MAP_State ;AN010; + mov dx, es:[bx.EMS_Handle] ;AN000;save EMS_Handle + lds si, ds:[bx.HASH_PTR] ;AN000;now ds:si -> Hash table + xor bx, bx ;AN000;starting logical page number. +; $DO ;AN000;For each page, +$$DO30: + call Map_Page ;AN000;map it to IBM physical page 254. + mov di, cs:IBM_Frame_Seg ;AN000; + mov es, di ;AN000 + xor di, di ;AN000;es:di -> bucket + xor ax, ax ;AN000 + xor cx, cx ;AN000 +; $DO ;AN000;For each bucket, +$$DO31: + mov ds:[si.EMS_PAGE_NUM], bx ;AN000;set the logical page number in Hash table. + mov word ptr ds:[si.BUFFER_BUCKET], di ;AN000;set the offset in hash table for this bucket. + mov word ptr ds:[si.BUFFER_BUCKET+2], es ;AN000;set the segment value in hash table. + mov word ptr ds:[si.DIRTY_COUNT], 0 ;AN020;set DIRTY_COUNT, BUFFER_RESERVED to 0. + push cx ;AN000;save bucket number + xor cx, cx ;AN000; +; $DO ;AN000;For each buffer in a bucket, +$$DO32: + call Set_Buffer_Info ;AN000;AX adjusted for the next buffer. + inc cx ;AN000;inc number of buffers in this bucket. + cmp cx, 1 ;AN020;The first buffer in the bucket? +; $IF E ;AN020; + JNE $$IF33 + mov cs:[EMS_Buf_First], di ;AN020;then save the offset value +; $ENDIF ;AN020; +$$IF33: + cmp cx, MAXBUFFINBUCKET ;AN000; +; $IF E ;AN000 + JNE $$IF35 + push word ptr cs:[EMS_Buf_First] ;AN020; + pop word ptr es:[di.BUF_NEXT] ;AN020;the last buffer's next -> the first buffer in bucket (Circular chain) + push di ;AN020;save di + push di ;AN020;di-> last buffer + mov di, cs:[EMS_Buf_First] ;AN020;es:di-> first buffer + pop word ptr es:[di.BUF_PREV] ;AN020;the first buffer's prev -> the last buffer + pop di ;AN020;restore di +; $ENDIF ;AN000; +$$IF35: + mov di, ax ;AN000;advance di to the next buffer position. +; $ENDDO E ;AN000; + JNE $$DO32 + add si, size BUFFER_HASH_ENTRY ;AN000;ds:si -> next hash table entry + pop cx ;AN000;restore bucket number + inc cx ;AN000;next bucket + cmp cx, MAXBUCKETINPAGE ;AN000;2 buckets per page +; $ENDDO E ;AN000; + JNE $$DO31 + inc bx ;AN000;increse logical page number + cmp bx, cs:[Buffer_Pages] ;AN000;reached the maximum page number? +; $ENDDO E ;AN000; + JNE $$DO30 + call Restore_MAP_State ;AN010; + ret ;AN000; +Set_EMS_Buffer endp + + +Set_Buffer_Info proc +;Function: Set buf_link, buf_id, Buf_Sector +;In: ES:DI -> Buffer header to be set. +; AX = DI +;Out: +; Above entries set. + + + push [Buf_Prev_Off] ;AN020; + pop es:[di.BUF_PREV] ;AN020; + mov Buf_Prev_Off, ax ;AN020; + add ax, [SingleBufferSize] ;AN000;adjust ax + mov word ptr es:[di.BUF_NEXT], ax ;AN020; + mov word ptr es:[di.BUF_ID], 00FFh ;AN000;new buffer free + mov word ptr es:[di.BUF_SECTOR], 0 ;AN000;To compensate the MASM 3 bug + mov word ptr es:[di.BUF_SECTOR+2],0 ;AN000;To compensate the MASM 3 bug + ret ;AN000; +Set_Buffer_Info endp + +Check_IBM_PageID proc near +;Function: check if the physical page 255 exists. (Physical page 255 is only +; one we are intereseted in, and this will be used for BUFFER +; manipulation by IBMBIO, IBMDOS) +;In: nothing +;Out: Carry clear and IBM_Frame_Seg set if it exist. All registers saved. + push es ;AN000; + push ax ;AN000; + push bx ;AN000; + push cx ;AN000; + push dx ;AN000; + push di ;AN010; + +IF NOT BUFFERFLAG + + mov ax, 1B00h ;AN029;AN030;AN0 Check EMS int 2fh installed. + int 2fh ;AN029; + cmp al, 0ffh ;AN029; + jne Cp_IBM_Err ;AN029;If not installed, then no IBM page. + mov ax, 1B01h ;AN029;AN030;Then ask if IBM page exists. + mov di, IBM_PAGE_ID ;AN029;=255 + int 2fh ;AN029; + or ah, ah ;AN029; + jnz Cp_IBM_Err ;AN029;;No IBM Page + mov cs:IBM_Frame_Seg, es ;AN029;;Save Physical IBM page frame addr. + mov cs:Real_IBM_Page_Id, di ;AN029;;Real page number for it. + clc ;AN029; + jmp short Cp_ID_Ret ;AN029; + +ELSE + push cs ;AN000; + pop es ;AN000; + mov ah, GET_PAGE_FRAME ;AN010;=58h + mov al, GET_NUM_PAGEFRAME ;AN010;=01h How many page frames? + int EMS_INT ;AN010; + or ah, ah ;AN010; + jnz hkn_err ;AN010; + cmp cx, MAX_NUM_PAGEFRAME ;AN010; + ja hkn_err ;AN010; cannot handle this big number + push cx ;AN010; + mov ah, GET_PAGE_FRAME ;AN010; + mov al, GET_PAGEFRAME_TAB ;AN010; + mov di, offset Frame_info_Buffer ;AN010; + int EMS_INT ;AN010; + pop cx ;AN010; + or ah, ah ;AN010; + jnz cp_IBM_Err ;AN010; +Cp_IBM_ID: ;AN010; + +; mov dx, es:[di] +; mov cs:[FIRST_PAGE], dx +; mov dx, es:[di+2] +; mov cs:[FIRST_PAGE+2], dx + + xor dx, dx + +; int 3 +find_page: + cmp es:[di], 0a000h ; is current page above 640K + jb next ; NO - goto check_last + + inc dx ; count the no. of pages above 640K + + cmp dx, 1 + jne first_ok + + mov ax, es:[di] + mov cs:[FIRST_PAGE], ax + mov ax, es:[di+2] + mov cs:[FIRST_PAGE+2], ax + +first_ok: + mov ax, cs:[FIRST_PAGE] + cmp ax, es:[di] ; is this page less than the one we have in + ; FIRST_PAGE + jbe check_last ; NO - goto check_last + mov ax, es:[di] ; update FIRST_PAGE with this page segment + mov cs:[FIRST_PAGE], ax + mov ax, es:[di+2] + mov cs:[FIRST_PAGE+2], ax + jmp next + +hkn_err: jmp cp_ibm_err + +check_last: + mov ax, cs:[LAST_PAGE] ; + cmp ax, es:[di] ; is this page greater than the one we have in + ; LAST_PAGE? + ja next ; NO - goto next + mov ax, es:[di] ; update LAST_PAGE with this value. + mov cs:[LAST_PAGE], ax + mov ax, es:[di+2] + mov cs:[LAST_PAGE+2], ax + +next: + add di, 4 + loop find_page + + cmp dx, 3 ; there should be at least 3 pages + ; above 640K for the buffers to be + ; installed. + jb Cp_IBM_Err + + mov ax, cs:[LAST_PAGE] + mov cs:IBM_Frame_Seg, ax + mov ax, cs:[LAST_PAGE+2] + mov cs:Real_IBM_Page_Id, ax + mov cs:[NPA640], dx + clc + jmp short Cp_Id_Ret + +ENDIF + + +; cmp word ptr es:[di+2], IBM_PAGE_ID ;AN010; the second word is the id +; je Got_IBM_ID ;AN010; +; add di, 4 ;AN010; advance to the next row (4 bytes) +; loop Cp_IBM_ID ;AN010; + +Cp_IBM_Err: ;AN010;;AN029; + stc ;AN000;;AN029; + jmp short Cp_ID_Ret ;AN000;;AN029; + +;Got_IBM_ID: ;AN000; +; mov ax, word ptr es:[di] ;AN010;Physical seg. addr. +; mov cs:IBM_Frame_Seg, ax ;AN000; +; clc ;AN000; +Cp_ID_Ret: ;AN000; + pop di ;AN010; + pop dx ;AN000; + pop cx ;AN000; + pop bx ;AN000; + pop ax ;AN000; + pop es ;AN000; + ret ;AN000; +Check_IBM_PageID endp + +; +Save_Map_State proc ;AN010; +;Function: Save the map state. +;In) +; EMS_Ctrl_Tab = double word pointer to EMS_state control table address +; EMS_state_Buf = double word pointer to EMS_MAP_BUFF address +;Out) Map state saved + push ax ;AN010; + push ds ;AN010; + push si ;AN010; + push es ;AN010; + push di ;AN010; + lds si, cs:EMS_Ctrl_Tab ;AN010; + les di, cs:EMS_state_Buf ;AN010; + mov ah, EMAP_STATE ;AN010; =4Fh + mov al, GET_MAP_STATE ;AN010; =00h + int EMS_INT ;AN010; + pop di ;AN010; + pop es ;AN010; + pop si ;AN010; + pop ds ;AN010; + pop ax ;AN010; + ret ;AN010; +Save_Map_State endp +; +Restore_Map_State proc ;AN010; + push ax ;AN010; + push ds ;AN010; + push si ;AN010; + lds si, cs:EMS_state_Buf ;AN010; + mov ah, EMAP_STATE ;AN010; + mov al, SET_MAP_STATE ;AN010; + int EMS_INT ;AN010; + pop si ;AN010; + pop ds ;AN010; + pop ax ;AN010; + ret ;AN010; +Restore_Map_State endp +; +Map_Page proc near ;AN000; +;Function: Map the logical page in BX of handle in DX to the physical page 255 +;In) +; BX = logical page number +; DX = EMS handle +; EMS_Ctrl_Tab = double word pointer to EMS_state control table address +; EMS_state_Buf = double word pointer to EMS_MAP_BUFF address +;Out) Logical page mapped into first phsical page frame. +; AX saved. + + push ax ;AN000; + mov ah, EMAP_L_TO_P ;AN000; + mov al, byte ptr cs:Real_IBM_PAGE_ID ;AN029;= 255 + int EMS_INT ;AN000; + pop ax ;AN000; + ret ;AN000; +Map_Page endp ;AN000; +; + +Roundup proc +;In: DX;AX - operand +; CX - divisor +; Important: DX should be less than CX. +;out: AX - Quotient (Rounded up) + + div cx ;AN000; + or dx, dx ;AN000; + jz RU_ret ;AN000; + inc AX ;AN000; +RU_ret: ;AN000; + ret ;AN000; +Roundup endp +;------------------------------------------------------------------------------ +;J.K. 5/6/86. IBMSTACK initialization routine. + IF STACKSW +.SALL + +INCLUDE STKINIT.INC + +.XALL + ENDIF +;------------------------------------------------------------------------------ + public SetDevMark +SetDevMark proc +;Set the DEVMARK for MEM command. +;In: [MEMHI] - the address to place DEVMARK +; [MEMLO] = 0 +; AL = ID for DEVMARK_ID +;OUT: DEVMARK established. +; the address saved in cs:[DevMark_Addr] +; [MEMHI] increase by 1. + + push es ;AN005; + push cx ;AN005; + + mov cx, cs:[memhi] ;AN005; + mov cs:[DevMark_Addr],cx ;AN005; + mov es, cx ;AN005; + mov es:[DEVMARK_ID], al ;AN005; + inc cx ;AN007; + mov es:[DEVMARK_SEG], cx ;AN007; + + pop cx ;AN005; + pop es ;AN005; + inc cs:[memhi] ;AN005; + ret ;AN005; +SetDevMark endp + +;******************************************************************************* +;Function: Load SHARE.EXE, if Big_Media_Flag = 1 and SHARE.EXE has not been * +; loaded yet. * +; This routine will use the same path for SHELL= command. * +; If SHELL= command has not been entered, then default to the root * +; directory. * +; If load fails, then issue message "Warning: SHARE.EXE not loaded" * +; * +;Input: Big_Media_Flag, COMMND * +;Output: Share.exe loaded if necessary. * +; * +;******************************************************************************* +LoadShare proc near ;AN021; + cmp Big_Media_Flag, 1 ;AN021; + jne LShare_Ret ;AN021; +;Check if SHARE is already loaded. + mov ax, 1000h ;AN021;multShare installation check + int 2fh ;AN021; + cmp al, 0ffh ;AN021; + jz LShare_Ret ;AN021;Share already loaded! +;SHARE not loaded. + push cs ;AN021; + pop ds ;AN021; + push cs ;AN021; + pop es ;AN021; + mov si, offset COMMND ;AN021; + mov di, offset PathString ;AN021; +LShare_String: ;AN021; + movsb ;AN021; + cmp byte ptr [di-1], 0 ;AN021;reached to the end? + jne LShare_string ;AN021; + mov si, offset PathString ;AN021;SI= start of PathString +LShare_Tail: ;AN021; + dec di ;AN021; + cmp byte ptr [di], "\" ;AN021; + je LShare_Got_Tail ;AN021; + cmp byte ptr [di], ":" ;AN021; + je LShare_Got_Tail ;AN021; + cmp di, si ;AN021;No path case (e.g. SHELL=command.com) + je LShare_Got_Tail_0 ;AN021; + jmp LShare_Tail ;AN021; +LShare_Got_Tail: ;AN021;di -> "\" or ":" + inc di ;AN021; +LShare_Got_Tail_0: ;AN021; + mov si, offset LShare ;AN021; +LShare_Set_Filename: ;AN021; + movsb ;AN021;Tag "SHARE.EXE",0,0Ah to the path. + cmp byte ptr [di-1], 0Ah ;AN021;Line feed? + jne LShare_Set_Filename ;AN021; +;Now, we got a path,filename with no parameters for SHARE.EXE + mov si, offset PathString ;AN021; + or Install_Flag, SHARE_INSTALL ;AN021;Signals Do_Install_Exec that this is for SHARE.EXE. + call Do_Install_Exec ;AN021;execute it. + jnc LShare_Ret ;AN021;No problem +;Load/Exec failed. Show "Warning: SHARE should be loaded for large media" + push cs ;AN021; + pop ds ;AN021; + mov dx, offset ShareWarnMsg ;AN021;WARNING! SHARE should be loaded... + invoke Print ;AN021; +LShare_Ret: ;AN021; + ret ;AN021; +LoadShare endp ;AN021; + +SYSINITSEG ENDS + END + \ No newline at end of file diff --git a/v4.0/src/BIOS/SYSINIT2.ASM b/v4.0/src/BIOS/SYSINIT2.ASM new file mode 100644 index 0000000..ff8b8ae --- /dev/null +++ b/v4.0/src/BIOS/SYSINIT2.ASM @@ -0,0 +1,1624 @@ + PAGE ,132 ; +; SCCSID = @(#)sysinit2.asm 1.13 85/10/15 +TITLE BIOS SYSTEM INITIALIZATION +%OUT ...SYSINIT2 + +;============================================================================== +;REVISION HISTORY: +;AN000 - New for DOS Version 4.00 - J.K. +;AC000 - Changed for DOS Version 4.00 - J.K. +;AN00x - PTM number for DOS Version 4.00 - J.K. +;============================================================================== +;AN001; p132 Multiple character device installation problem. 6/27/87 J.K. +;AN002; d24 MultiTrack= command added. 6/29/87 J.K. +;AN003; p29 Extra space character in parameters passed. +; (Modification on ORGANIZE routine for COMMENT= fixed this +; problem too) 6/29/87 J.K. +;AN004; d41 REM command in CONFIG.SYS 7/7/87 J.K. +;AN005; d184 Set DEVMARK for MEM command 8/25/87 J.K. +;AN006; p1820 New Message SKL file 10/20/87 J.K. +;AN007; p1821 Include the COPYRIGH.INC file 10/22/87 J.K. +;AN008; p2210 IBMDOS returns incorrect DBCS vector table length 11/02/87 J.K. +;AN009; p2667 ccMono_Ptr problem 11/30/87 J.K. +;AN010; p2792 Device?driver.sys /d:2 command should not work 12/09/87 J.K. +;AN011; p3120 REM followed by CR, LF causes problem 01/13/88 J.K. +;AN012; p3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. +;AN013; d479 New option to disable extended INT 16h function call 02/12/88 J.K. +;AN014; D486 SHARE installation for big media 02/23/88 J.K. +;AN015; D526 Add /NC parameter when installing SHARE.EXE 04/28/88 J.K. +;============================================================================== + +TRUE EQU 0FFFFh +FALSE EQU 0 +LF equ 10 +CR equ 13 +TAB equ 9 + +IBMVER EQU TRUE +IBM EQU IBMVER +STACKSW EQU TRUE ;Include Switchable Hardware Stacks +IBMJAPVER EQU FALSE ;If TRUE set KANJI true also +MSVER EQU FALSE +ALTVECT EQU FALSE ;Switch to build ALTVECT version +KANJI EQU FALSE + + IF IBMJAPVER +NOEXEC EQU TRUE + ELSE +NOEXEC EQU FALSE + ENDIF + +DOSSIZE EQU 0A000H + +.xlist +; INCLUDE dossym.INC + include smdossym.inc ;J.K. Reduced version of DOSSYM.INC + INCLUDE devsym.INC + include ioctl.INC + include DEVMARK.inc +.list + + IF NOT IBM + IF NOT IBMJAPVER + EXTRN RE_INIT:FAR + ENDIF + ENDIF + +code segment public 'code' + extrn EC35_Flag: byte +code ends + +SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' BYTE + +ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE + EXTRN BADSIZ_PRE:BYTE,BADLD_PRE:BYTE +; EXTRN BADSIZ_POST:BYTE,BADLD_POST:BYTE + EXTRN SYSSIZE:BYTE,BADCOUNTRY:BYTE + + EXTRN dosinfo:dword,entry_point:dword, + EXTRN MEMORY_SIZE:WORD,fcbs:byte,keep:byte + EXTRN DEFAULT_DRIVE:BYTE,confbot:word,alloclim:word + EXTRN BUFFERS:WORD,zero:byte,sepchr:byte + EXTRN FILES:BYTE + EXTRN count:word,chrptr:word + EXTRN bufptr:byte,memlo:word,prmblk:byte,memhi:word + EXTRN ldoff:word,area:word,PACKET:BYTE,UNITCOUNT:BYTE, + EXTRN BREAK_ADDR:DWORD,BPB_ADDR:DWORD,drivenumber:byte + extrn COM_Level:byte, CMMT:byte, CMMT1:byte, CMMT2:byte + extrn Cmd_Indicator:byte + extrn DoNotShowNum:byte + extrn MultDeviceFlag:byte + extrn DevMark_Addr:word ;AN005; + extrn SetDevMarkFlag:byte ;AN005; + extrn Org_Count:word ;AN012; + + EXTRN Stall:near + EXTRN Error_Line:near + + PUBLIC Int24,Open_Dev,Organize,Mem_Err,Newline,CallDev,Badload + PUBLIC PrnDev,AuxDev,Config,Commnd,Condev,GetNum,BadFil,PrnErr + PUBLIC Round,Delim,Print,Set_Break + PUBLIC SetParms, ParseLine, DiddleBack + PUBLIC Skip_delim,SetDOSCountryInfo,Set_Country_Path,Move_Asciiz + PUBLIC Cntry_Drv,Cntry_Root,Cntry_Path + PUBLIC Delim + public PathString ;AN014; + public LShare ;AN014; + +; +; The following set of routines is used to parse the DRIVPARM = command in +; the CONFIG.SYS file to change the default drive parameters. +; +SetParms: + push ds + push ax + push bx + push cx + push dx + push cs + pop ds + ASSUME DS:SYSINITSEG + xor bx,bx + mov bl,byte ptr drive + inc bl ; get it correct for IOCTL call (1=A,2=B...) + mov dx,offset DeviceParameters + mov ah, IOCTL + mov al, GENERIC_IOCTL + mov ch, RAWIO + mov cl, SET_DEVICE_PARAMETERS + int 21H + test word ptr Switches, flagec35 + jz Not_EC35 + + mov cl, byte ptr drive ; which drive was this for? + mov ax, Code ; get Code segment + mov ds, ax ; set code segment + assume ds:code + mov al, 1 ; assume drive 0 + shl al, cl ; set proper bit depending on drive + or ds:EC35_Flag, al ; set the bit in the permanent flags + +Not_EC35: + pop dx ; fix up all the registers + pop cx + pop bx + pop ax + pop ds + assume ds:nothing + ret + +; +; Replace default values for further DRIVPARM commands +; +DiddleBack: + push ds + push cs + pop ds + assume ds:sysinitseg + mov word ptr DeviceParameters.DP_Cylinders,80 + mov byte ptr DeviceParameters.DP_DeviceType, DEV_3INCH720KB + mov word ptr DeviceParameters.DP_DeviceAttributes,0 + mov word ptr switches,0 ; zero all switches + pop ds + assume ds:nothing + ret + +; +; Entry point is ParseLine. AL contains the first character in command line. +; +ParseLine: ; don't get character first time + push ds + push cs + pop ds + ASSUME DS:SYSINITSEG +NextSwtch: + cmp al,CR ; carriage return? + jz done_line + cmp al,LF ; linefeed? + jz put_back ; put it back and done +; Anything less or equal to a space is ignored. + cmp al,' ' ; space? + jbe get_next ; skip over space + cmp al,'/' + jz getparm + stc ; mark error invalid-character-in-input + jmp short exitpl + +getparm: + call Check_Switch + mov word ptr Switches,BX ; save switches read so far + jc swterr +get_next: + invoke getchr + jc done_line + jmp NextSwtch +swterr: + jmp exitpl ; exit if error + +done_line: + test word ptr Switches,flagdrive ; see if drive specified + jnz okay + stc ; mark error no-drive-specified + jmp short exitpl + +okay: + mov ax,word ptr switches + and ax,0003H ; get flag bits for changeline and non-rem + mov word ptr DeviceParameters.DP_DeviceAttributes,ax + mov word ptr DeviceParameters.DP_TrackTableEntries, 0 + clc ; everything is fine + call SetDeviceParameters +exitpl: + pop ds + ret + +put_back: + inc count ; one more char to scan + dec chrptr ; back up over linefeed + jmp short done_line +; +; Processes a switch in the input. It ensures that the switch is valid, and +; gets the number, if any required, following the switch. The switch and the +; number *must* be separated by a colon. Carry is set if there is any kind of +; error. +; +Check_Switch: + invoke getchr + jc err_check + and al,0DFH ; convert it to upper case + cmp al,'A' + jb err_check + cmp al,'Z' + ja err_check + push es + push cs + pop es + mov cl,byte ptr switchlist ; get number of valid switches + mov ch,0 + mov di,1+offset switchlist ; point to string of valid switches + repne scasb + pop es + jnz err_check + mov ax,1 + shl ax,cl ; set bit to indicate switch + mov bx,word ptr switches ; get switches so far + or bx,ax ; save this with other switches + mov cx,ax + test ax, switchnum ; test against switches that require number to follow + jz done_swtch + invoke getchr + jc err_Swtch + cmp al,':' + jnz err_swtch + invoke getchr + push bx ; preserve switches + mov byte ptr cs:sepchr,' ' ; allow space separators + call GetNum + mov byte ptr cs:sepchr,0 + pop bx ; restore switches +; Because GetNum does not consider carriage-return or line-feed as OK, we do +; not check for carry set here. If there is an error, it will be detected +; further on (hopefully). + call Process_Num + +done_swtch: + clc + ret + +err_swtch: + xor bx,cx ; remove this switch from the records +err_check: + stc + ret + +; +; This routine takes the switch just input, and the number following (if any), +; and sets the value in the appropriate variable. If the number input is zero +; then it does nothing - it assumes the default value that is present in the +; variable at the beginning. Zero is OK for form factor and drive, however. +; +Process_Num: + test word ptr Switches,cx ; if this switch has been done before, + jnz done_ret ; ignore this one. + test cx,flagdrive + jz try_f + mov byte ptr drive,al + jmp short done_ret + +try_f: + test cx,flagff + jz try_t +; Ensure that we do not get bogus form factors that are not supported + ;cmp al,Max_Dev_Type + ;ja done_ret + mov byte ptr DeviceParameters.DP_DeviceType,al + jmp short done_ret + +try_t: + or ax,ax + jz done_ret ; if number entered was 0, assume default value + test cx,flagcyln + jz try_s + mov word ptr DeviceParameters.DP_Cylinders,ax + jmp short done_ret + +try_s: + test cx,flagseclim + jz try_h + mov word ptr slim,ax + jmp short done_ret +; +; Must be for number of heads +try_h: + mov word ptr hlim,ax + +done_ret: + clc + ret + +; +; SetDeviceParameters sets up the recommended BPB in each BDS in the +; system based on the form factor. It is assumed that the BPBs for the +; various form factors are present in the BPBTable. For hard files, +; the Recommended BPB is the same as the BPB on the drive. +; No attempt is made to preserve registers since we are going to jump to +; SYSINIT straight after this routine. +; +SetDeviceParameters: + push es + push cs + pop es +ASSUME ES:SYSINITSEG + xor bx,bx + mov bl,byte ptr DeviceParameters.DP_DeviceType + cmp bl,DEV_5INCH + jnz Got_80 + mov cx,40 ; 48tpi has 40 cylinders + mov word ptr DeviceParameters.DP_Cylinders,cx +Got_80: + shl bx,1 ; get index into BPB table + mov si,offset BPBTable + mov si,word ptr [si+bx] ; get address of BPB +Set_RecBPB: + mov di,offset DeviceParameters.DP_BPB ; es:di -> BPB + mov cx,size a_BPB + cld + repe movsb + pop es +ASSUME ES:NOTHING + test word ptr switches,flagseclim + jz see_heads + mov ax,word ptr slim + mov word ptr DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax +see_heads: + test word ptr switches,flagheads + jz Set_All_Done + mov ax,word ptr hlim + mov word ptr DeviceParameters.DP_BPB.BPB_Heads,ax +; +; We need to set the media byte and the total number of sectors to reflect the +; number of heads. We do this by multiplying the number of heads by the number +; of 'sectors per head'. This is not a fool-proof scheme!! +; + mov cx,ax ; cx has number of heads + dec cl ; get it 0-based + mov ax,DeviceParameters.DP_BPB.BPB_TotalSectors ; this is OK for two heads + sar ax,1 ; ax contains # of sectors/head + sal ax,cl + jc Set_All_Done ; We have too many sectors - overflow!! + mov DeviceParameters.DP_BPB.BPB_TotalSectors,ax +; Set up correct Media Descriptor Byte + cmp cl,1 + mov bl,0F0H + mov al,2 ; AL contains sectors/cluster + ja Got_Correct_Mediad + mov bl,byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor + je Got_Correct_Mediad +; We have one head - OK for 48tpi medium + mov al,1 ; AL contains sectors/cluster + mov ch,DeviceParameters.DP_DeviceType + cmp ch,DEV_5INCH + jz Dec_Mediad + mov bl,0F0H + jmp short Got_Correct_Mediad +Dec_Mediad: + dec bl ; adjust for one head +Got_Correct_Mediad: + mov byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor,bl + mov byte ptr DeviceParameters.DP_BPB.BPB_SectorsPerCluster,al + clc +Set_All_Done: + RET + +ASSUME DS:NOTHING, ES:NOTHING + +NOCHAR1: STC + return + +ORGANIZE: + MOV CX,[COUNT] + JCXZ NOCHAR1 + CALL MAPCASE + XOR SI,SI + MOV DI,SI + xor ax,ax + mov COM_Level, 0 + +;ORG1: CALL GET ;SKIP LEADING CONTROL CHARACTERS +; CMP AL,' ' +; JB ORG1 +Org1: + call Skip_Comment ;AN000; + jz End_Commd_Line ;AN000; found a comment string and skipped. + call Get2 ;AN000; Not a comment string. Then get a char. + cmp al, LF ;AN000; + je End_Commd_Line ;AN000; starts with a blank line. + cmp al, ' ' ;AN000; + jbe Org1 ;AN000; skip leading control characters + jmp Findit ;AN000; +End_Commd_Line: ;AN000; + stosb ;AN000; store line feed char in buffer for the LineCount. + mov COM_Level, 0 ;AN000; reset the command level. + jmp Org1 ;AN000; +Findit: ;AN000; + PUSH CX + PUSH SI + PUSH DI + MOV BP,SI + DEC BP + MOV SI,OFFSET COMTAB ;Prepare to search command table + MOV CH,0 +FINDCOM: + MOV DI,BP + MOV CL,[SI] + INC SI + JCXZ NOCOM + REPE CMPSB + LAHF + ADD SI,CX ;Bump to next position without affecting flags + SAHF + LODSB ;Get indicator letter + JNZ FINDCOM + cmp byte ptr es:[di], CR ;AN011;The next char might be CR,LF + je GotCom0 ;AN011; such as in "REM",CR,LF case. + cmp byte ptr es:[di], LF ;AN011; + je GotCom0 ;AN011; + push ax ;AN010; + mov al, byte ptr es:[di] ;AN010;Now the next char. should be a delim. + call delim ;AN010; + pop ax ;AN010; + jnz findcom ;AN010; +GotCom0: + POP DI + POP SI + POP CX + JMP SHORT GOTCOM + +NOCOM: + POP DI + POP SI + POP CX + MOV AL,'Z' + stosb ;AN000; save indicator char. +Skip_Line: ;AN000; + call Get2 ;AN000; + cmp al, LF ;AN000; skip this bad command line + jne Skip_Line ;AN000; + jmp End_Commd_Line ;AN000; handle next command line + +GOTCOM: STOSB ;SAVE INDICATOR CHAR IN BUFFER + mov Cmd_Indicator, al ;AN000; save it for the future use. + +ORG2: CALL GET2 ;SKIP the commad name UNTIL DELIMITER + cmp al, LF ;AN011; + je Org21 ;AN011; + cmp al, CR ;AN011; + je Org21 ;AN011; + CALL DELIM ; + JNZ ORG2 + jmp short Org3 ;AN011; +Org21: ;AN011;if CR or LF then + dec si ;AN011; undo SI, CX register + inc cx ;AN011; and continue + +;ORG4: CALL GET2 +; call Delim ;J.K. 5/30/86. To permit "device=filename/p..." stuff. +; jz ORG_EXT ;J.K. 5/30/86 +;Org4_Cont: +; STOSB +; CMP AL,' ' +; JA ORG4 +; CMP AL,10 +; JZ ORG1 +; +; MOV BYTE PTR ES:[DI-1],0 + +Org3: + cmp Cmd_Indicator, 'Y' ;AN000; Comment= command? + je Get_Cmt_Token ;AN000; + cmp Cmd_Indicator, 'I' ;AN000; Install= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'D' ;AN000; Device= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'J' ;AN000; IFS= command? + je Org_file ;AN000; + cmp Cmd_Indicator, 'S' ;AN000; Shell= is a special one!!! + je Org_file ;AN000; + cmp Cmd_Indicator, '1' ;AN013; SWITCHES= command? + je Org_Switch ;AN013; + jmp Org4 ;AN000; +Org_Switch: + call Skip_Comment ;AN013; + jz End_Commd_Line_Brdg ;AN013; + call Get2 ;AN013; + call Org_Delim ;AN013; + jz Org_Switch ;AN013; + stosb ;AN013; + jmp Org5 ;AN013; +Org_file: ;AN000; Get the filename and put 0 at end, + call Skip_Comment ;AN000; + jz Org_Put_Zero ;AN000; + call Get2 ;AN000; Not a comment + call Delim ;AN000; + jz Org_file ;AN000; Skip the possible delimeters + stosb ;AN000; copy the first non delim char found in buffer +Org_Copy_File: ;AN000; + call Skip_Comment ;AN000; comment char in the filename? + jz Org_Put_Zero ;AN000; then stop copying filename at that point + call Get2 ;AN000; + cmp al, '/' ;AN000; a switch char? (device=filename/xxx) + je End_File_slash ;AN000; this will be the special case. + stosb ;AN000; save the char. in buffer + call Delim ;AN000; + jz End_Copy_File ;AN000; + cmp al, ' ' ;AN000; + ja Org_Copy_File ;AN000; keep copying + jmp End_Copy_File ;AN000; otherwise, assume end of the filename. +Get_Cmt_token: ;AN000; get the token. Just max. 2 char. + call Get2 ;AN000; + cmp al, ' ' ;AN000; skip white spaces or "=" char. + je Get_Cmt_Token ;AN000; (we are allowing the other special + cmp al, TAB ;AN000; charaters can used for comment id. + je Get_Cmt_Token ;AN000; character.) + cmp al, '=' ;AN000; = is special in this case. + je Get_Cmt_Token ;AN000; + cmp al, CR ;AN000; + je Get_Cmt_End ;AN000; cannot accept the carridge return + cmp al, LF ;AN000; + je Get_Cmt_End ;AN000; + mov CMMT1, al ;AN000; store it + mov CMMT, 1 ;AN000; 1 char. so far. + call Get2 ;AN000; + cmp al, ' ' ;AN000; + je Get_Cmt_End ;AN000; + cmp al, TAB ;AN000; + je Get_Cmt_End ;AN000; + cmp al, CR ;AN000; + je Get_Cmt_End ;AN000; + cmp al, LF ;AN000; + je End_Commd_Line_Brdg ;AN000; + mov CMMT2, al ;AN000; + inc CMMT ;AN000; +Get_Cmt_End: ;AN000; + call Get2 ;AN000; + cmp al, LF ;AN000; + jne Get_Cmt_End ;AN000; skip it. +End_Commd_Line_Brdg: jmp End_Commd_Line ;AN000; else jmp to End_Commd_Line + +Org_Put_Zero: ;AN000; Make the filename in front of + mov byte ptr es:[di], 0 ;AN000; the comment string to be an asciiz. + inc di ;AN000; + jmp End_Commd_Line ;AN000; (Maybe null if device=/*) +End_file_slash: ;AN000; AL = "/" option char. + mov byte ptr es:[di],0 ;AN000; make a filename an asciiz + inc di ;AN000; and + stosb ;AN000; store "/" after that. + jmp Org5 ;AN000; continue with the rest of the line + +End_Copy_File: ;AN000; + mov byte ptr es:[di-1], 0 ;AN000; make it an asciiz and handle the next char. + cmp al, LF ;AN000; + je End_Commd_Line_brdg ;AN000; + jmp Org5 ;AN000; + +Org4: ;AN000; Org4 skips all delimiters after the command name except for '/' + call Skip_Comment ;AN000; + jz End_Commd_Line_brdg ;AN000; + call Get2 ;AN000; + call Org_Delim ;AN000; skip delimiters EXCEPT '/' (mrw 4/88) + jz Org4 ;AN000; + jmp Org51 ;AN000; +Org5: ;AN000; rest of the line + call Skip_Comment ;AN000; Comment? + jz End_Commd_Line_brdg ;AN000; + call Get2 ;AN000; Not a comment. +Org51: ;AN000; + stosb ;AN000; copy the character + cmp al, '"' ;AN000; a quote ? + je At_Quote ;AN000; + cmp al, ' ' ;AN000; + ja Org5 ;AN000; + cmp al, LF ;AN000; line feed? + je Org1_brdg ;AN000; handles the next command line. + jmp Org5 ;AN000; handles next char in this line. +Org1_brdg: jmp Org1 ;AN000; +At_Quote: ;AN000; + cmp COM_Level, 0 ;AN000; + je Up_Level ;AN000; + mov COM_Level, 0 ;AN000; reset it. + jmp Org5 ;AN000; +Up_Level: ;AN000; + inc COM_level ;AN000; set it. + jmp Org5 ;AN000; + + +;ORG5: CALL GET2 +; STOSB +; CMP AL,10 +; JNZ ORG5 +; JMP ORG1 +; +;ORG_EXT: +; cmp al,' ' ;space? +; je Org4_Cont ;then do not make an exception. Go back. +; cmp al,9 ;Tab? +; je Org4_Cont +; mov byte ptr es:[di], 0 ;put 0 at the current DI to make it an ASCIIZ +; inc DI ; +; stosb ;and copy the delimeter char. +; jmp short ORG5 ;and continue as usual. + + +GET2: + JCXZ NOGET + MOV AL,ES:[SI] + INC SI + DEC CX + return + +;GET: JCXZ NOGET +; MOV AL,ES:[SI] +; INC SI +; DEC CX +; CALL Org_DELIM +; JZ GET +; return + +Skip_Comment: +;J.K.Skip the commented string until LF, if current es:si-> a comment string. +;J.K.In) ES:SI-> sting +;J.K. CX -> length. +;J.K.Out) Zero flag not set if not found a comment string. +;J.K. Zero flag set if found a comment string and skipped it. AL will contain +;J.K. the line feed charater at this moment when return. +;J.K. AX register destroyed. +;J.K. If found, SI, CX register adjusted accordingly. + + jcxz NoGet ;AN000; Get out of the Organize routine. + cmp COM_Level, 0 ;AN000; only check it if parameter level is 0. + jne No_Commt ;AN000; (Not inside quotations) + + cmp CMMT, 1 ;AN000; + jb No_Commt ;AN000; + mov al, es:[si] ;AN000; + cmp CMMT1, al ;AN000; + jne No_Commt ;AN000; + cmp CMMT, 2 ;AN000; + jne Skip_Cmmt ;AN000; + mov al, es:[si+1] ;AN000; + cmp CMMT2, al ;AN000; + jne No_Commt ;AN000; +Skip_Cmmt: ;AN000; + jcxz NoGet ;AN000; get out of Organize routine. + mov al, es:[si] ;AN000; + inc si ;AN000; + dec cx ;AN000; + cmp al, LF ;AN000; line feed? + jne Skip_Cmmt ;AN000; +No_Commt: ;AN000; + ret ;AN000; + + +DELIM: + CMP AL,'/' ;J.K. 5/30/86. IBM will assume "/" as an delimeter. + retz + cmp al, 0 ;J.K. 5/23/86 Special case for sysinit!!! + retz +Org_Delim: ;AN000; Used by Organize routine except for getting + CMP AL,' ' ;the filename. + retz + CMP AL,9 + retz + CMP AL,'=' + retz + CMP AL,',' + retz + CMP AL,';' + return + + +NOGET: POP CX + MOV COUNT,DI + mov Org_Count, DI ;AN012; + XOR SI,SI + MOV CHRPTR,SI + return + +;Get3: jcxz NOGET ;J.K.do not consider '/',',' as a delim. +; mov al, es:[si] +; inc si +; dec cx +; call DELIM +; jnz Get3_ret +; cmp al,'/' +; je Get3_ret +; cmp al,',' +; jne Get3 +;Get3_ret: +; ret + + + +; +; NEWLINE RETURNS WITH FIRST CHARACTER OF NEXT LINE +; +NEWLINE:invoke GETCHR ;SKIP NON-CONTROL CHARACTERS + retc + CMP AL,LF ;LOOK FOR LINE FEED + JNZ NEWLINE + invoke GETCHR + return + +MAPCASE: + PUSH CX + PUSH SI + PUSH DS + PUSH ES + POP DS + XOR SI,SI +CONVLOOP: + LODSB + + IF KANJI + CALL TESTKANJ + JZ NORMCONV + INC SI ;Skip next char + DEC CX + JCXZ CONVDONE ;Just ignore 1/2 kanji error +;Fall through, know AL is not in 'a'-'z' range +NORMCONV: + ENDIF + + CMP AL,'a' + JB NOCONV + CMP AL,'z' + JA NOCONV + SUB AL,20H + MOV [SI-1],AL +NOCONV: + LOOP CONVLOOP +CONVDONE: + POP DS + POP SI + POP CX + return + + IF KANJI +TESTKANJ: + CMP AL,81H + JB NOTLEAD + CMP AL,9FH + JBE ISLEAD + CMP AL,0E0H + JB NOTLEAD + CMP AL,0FCH + JBE ISLEAD +NOTLEAD: + PUSH AX + XOR AX,AX ;Set zero + POP AX + return + +ISLEAD: + PUSH AX + XOR AX,AX ;Set zero + INC AX ;Reset zero + POP AX + return + ENDIF + +ASSUME DS:NOTHING + +Yes_Break_Failed: ;device driver Init failed and aborted. + stc + pop ax + return + +SET_BREAK: +;J.K. 8/14/86 For DOS 3.3, this routine is modified to take care of the +;Device driver's initialization error and abort. +;If [break_addr+2] == [memhi] && [break_addr] = 0 then assume +;that the device driver's initialization has an error and wanted to +;abort the device driver. In this case, this routine will set carry +;and return to the caller. +;J.K. 6/26/87 If MultDeviceFlag <> 0, then do not perform the check. +;This is to allow the multiple character device driver which uses +;the same ending address segment with the offset value 0 for each +;of the drives. + + PUSH AX + MOV AX,WORD PTR [BREAK_ADDR+2] ;REMOVE THE INIT CODE + cmp MultDeviceFlag, 0 ;AN001; + jne Set_Break_Continue ;AN001;Do not check it. + cmp ax, [MEMHI] + jne Set_Break_Continue ;if not same, then O.K. + + cmp word ptr [BREAK_ADDR],0 + je Yes_Break_failed ;[Break_addr+2]=[MEMHI] & [Break_addr]=0 + +Set_Break_Continue: + MOV [MEMHI],AX + MOV AX,WORD PTR [BREAK_ADDR] + MOV [MEMLO],AX + POP AX ; NOTE FALL THROUGH + or [SetDevMarkFlag], SETBRKDONE ;AN005; Signal the successful Set_break + +; +; Round the values in MEMLO and MEMHI to paragraph boundary. +; Perform bounds check. +; +ROUND: + PUSH AX + MOV AX,[MEMLO] + + invoke ParaRound ; para round up + + ADD [MEMHI],AX + MOV [MEMLO],0 + mov ax,memhi ; ax = new memhi + CMP AX,[ALLOCLIM] ; if new memhi >= alloclim, error + JAE MEM_ERR + test cs:[SetDevMarkFlag], FOR_DEVMARK ;AN005; + jz Skip_Set_DEVMARKSIZE ;AN005; + push es ;AN005; + push si ;AN005; + mov si, cs:[DevMark_Addr] ;AN005; + mov es, si ;AN005; + sub ax, si ;AN005; + dec ax ;AN005; + mov es:[DEVMARK_SIZE], ax ;AN005; Paragraph + and cs:[SetDevMarkFlag], NOT_FOR_DEVMARK ;AN005; + pop si ;AN005; + pop es ;AN005; +Skip_Set_DEVMARKSIZE: ;AN005; + POP AX + clc ;clear carry + return + +MEM_ERR: + MOV DX,OFFSET BADMEM + PUSH CS + POP DS + CALL PRINT + JMP STALL + +CALLDEV:MOV DS,WORD PTR CS:[ENTRY_POINT+2] + ADD BX,WORD PTR CS:[ENTRY_POINT] ;Do a little relocation + MOV AX,DS:[BX] + PUSH WORD PTR CS:[ENTRY_POINT] + MOV WORD PTR CS:[ENTRY_POINT],AX + MOV BX,OFFSET PACKET + CALL [ENTRY_POINT] + POP WORD PTR CS:[ENTRY_POINT] + return + +BADNUM: + MOV sepchr,0 + XOR AX,AX ; Set Zero flag, and AX = 0 + pop bx ; J.K. + stc ; AND carry set + return + +ToDigit: + SUB AL,'0' + JB NotDig + CMP AL,9 + JA NotDig + CLC + return +NotDig: STC + return + +; GetNum parses a decimal number. +; Returns it in AX, sets zero flag if AX = 0 (MAY BE considered an +; error), if number is BAD carry is set, zero is set, AX=0. +GETNUM: push bx ; J.K. + XOR BX,BX ; running count is zero +B2: CALL ToDigit ; do we have a digit + JC BadNum ; no, bomb + XCHG AX,BX ; put total in AX + PUSH BX ; save digit + MOV BX,10 ; base of arithmetic + MUL BX ; shift by one decimal di... + POP BX ; get back digit + ADD AL,BL ; get total + ADC AH,0 ; make that 16 bits + JC BADNUM ; too big a number + XCHG AX,BX ; stash total + + invoke GETCHR ;GET NEXT DIGIT + JC B1 ; no more characters + cmp al, ' ' ;J.K. 5/23/86 space? + jz B15 ;J.K. 5/23/86 then end of digits + cmp al, ',' ;J.K. 5/23/86 ',' is a seperator!!! + jz B15 ;J.K. 5/23/86 then end of digits. + cmp al, TAB ;J.K. 5/23/86 TAB + jz B15 ;J.K. + CMP AL,SepChr ; allow 0 or special separators + JZ b15 + cmp al,SWTCHR ; See if another switch follows + JZ b15 + cmp al,LF ; Line-feed? + jz b15 + cmp al,CR ; Carriage return? + jz b15 + OR AL,AL ; end of line separator? + JNZ B2 ; no, try as a valid char... +b15: INC COUNT ; one more character to s... + DEC CHRPTR ; back up over separator +B1: MOV AX,BX ; get proper count + OR AX,AX ; Clears carry, sets Zero accordingly + pop bx + return + +SKIP_DELIM proc near ;J.K. +;Skip the delimeters pointed by CHRPTR. AL will contain the first non delimeter +;character encountered and CHRPTR will point to the next character. +;This rouitne will assume the second "," found as a non delimiter character. So +;in case if the string is " , , ", this routine will stop at the second ",". At +;this time, Zero flag is set. +;If COUNT is exhausted, then carry will be set. +Skip_delim_char: + call getchr + jc Skip_delim_exit + cmp al, ',' ;the first comma? + je Skip_delim_next + call delim ;check the charater in AL. + jz Skip_delim_char + jmp short Skip_delim_exit ;found a non delim char +Skip_delim_next: + call getchr + jc Skip_delim_exit + cmp al, ',' ;the second comma? + je Skip_delim_exit ;done + call delim + jz Skip_delim_next +Skip_delim_exit: + return +SKIP_DELIM endp + +;J.K. 5/26/86 ***************************************************************** +SetDOSCountryInfo proc near +;Input: ES:DI -> pointer to DOS_COUNTRY_CDPG_INFO +; DS:0 -> buffer. +; SI = 0 +; AX = country id +; DX = code page id. (If 0, then use ccSysCodePage as a default.) +; BX = file handle +; This routine can handle maxium 72 COUNTRY_DATA entries. +;Output: DOS_country_cdpg_info set. +; Carry set if any file read failure or wrong information in the file. +; Carry set and CX = -1 if cannot find the matching COUNTRY_id, CODEPAGE +; _id in the file. + + push di + push ax + push dx + + xor cx,cx + xor dx,dx + mov ax, 512 ;read 512 bytes + call ReadInControlBuffer ;Read the file header + jc SetDOSData_fail + push es + push si + push cs + pop es + mov di, offset COUNTRY_FILE_SIGNATURE + mov cx, 8 ;length of the signature + repz cmpsb + pop si + pop es + jnz SetDOSData_fail ;signature mismatch + + add si, 18 ;SI -> county info type + cmp byte ptr ds:[si], 1 ;Only accept type 1 (Currently only 1 header type) + jne SetDOSData_fail ;cannot proceed. error return + inc si ;SI -> file offset + mov dx, word ptr ds:[si] ;Get the INFO file offset. + mov cx, word ptr ds:[si+2] + mov ax, 1024 ;read 1024 bytes. + call ReadInControlBuffer ;Read INFO + jc SetDOSData_fail + mov cx, word ptr ds:[si] ;get the # of country, codepage combination entries + cmp cx, 72 ;cannot handle more than 72 entries. + ja SetDOSData_fail + inc si + inc si ;SI -> entry information packet + pop dx ;restore code page id + pop ax ;restore country id + pop di + +SetDOSCntry_find: ;Search for desired country_id,codepage_id. + cmp ax, word ptr ds:[si+2] ;compare country_id + jne SetDOSCntry_next + cmp dx, 0 ;No user specified code page ? + je SetDOSCntry_any_codepage;then no need to match code page id. + cmp dx, word ptr ds:[si+4] ;compare code page id + je SetDOSCntry_got_it +SetDOSCntry_next: + add si, word ptr ds:[si] ;next entry + inc si + inc si ;take a word for size of entry itself + loop SetDOSCntry_find + mov cx, -1 ;signals that bad country id entered. +SetDOSCntry_fail: + stc + ret + +SetDOSData_fail: + pop si + pop cx + pop di + jmp short SetDOSCntry_fail + +SetDOSCntry_any_CodePage: ;use the code_page_id of the country_id found. + mov dx, word ptr ds:[si+4] +SetDOSCntry_got_it: ;found the matching entry + mov cs:CntryCodePage_Id, dx ;save code page ID for this country. + mov dx, word ptr ds:[si+10] ;get the file offset of country data + mov cx, word ptr ds:[si+12] + mov ax, 512 ;read 512 bytes + call ReadInControlBuffer + jc SetDOSCntry_fail + mov cx, word ptr ds:[si] ;get the number of entries to handle. + inc si + inc si ;SI -> first entry + +SetDOSCntry_data: + push di ;ES:DI -> DOS_COUNTRY_CDPG_INFO + push cx ;save # of entry left + push si ;si -> current entry in Control buffer + + mov al, byte ptr ds:[si+2] ;get data entry id + call GetCountryDestination ;get the address of destination in ES:DI + jc SetDOSCntry_data_next ;No matching data entry id in DOS + + + mov dx, word ptr ds:[si+4] ;get offset of data + mov cx, word ptr ds:[si+6] + mov ax, 4200h + stc + int 21h ;move pointer + jc SetDOSData_fail + mov dx, 512 ;start of data buffer +; mov cx, word ptr es:[di] ;length of the corresponding data in DOS. +; add cx, 10 ;Signature + A word for the length itself + mov cx, 20 ;read 20 bytes only. We only need to + mov ah, 3fh ;look at the length of the data in the file. + stc + int 21h ;read the country.sys data + jc SetDOSData_fail ;read failure + cmp ax, cx + jne SetDOSData_fail + + mov dx, word ptr ds:[si+4] ;AN008;get offset of data again. + mov cx, word ptr ds:[si+6] ;AN008; + mov ax, 4200h ;AN008; + stc ;AN008; + int 21h ;AN008;move pointer back again + jc SetDOSData_fail ;AN008; + + push si ;AN008; + mov si, (512+8) ;AN008;get length of the data from the file + mov cx, word ptr ds:[si] ;AN008; + pop si ;AN008; + mov dx, 512 ;AN008;start of data buffer + add cx, 10 ;AN008;Signature + A word for the length itself + mov ah, 3fh ;AN008;Read the data from the file. + stc ;AN008; + int 21h ;AN008; + jc SetDOSData_fail ;AN008; + cmp ax, cx ;AN008; + jne SetDOSData_fail ;AN008; + + mov al, byte ptr ds:[si+2] ;save Data id for future use. + mov si, (512+8) ;SI-> data buffer + id tag field + mov cx, word ptr ds:[si] ;get the length of the file + inc cx ;Take care of a word for lenght of tab + inc cx ;itself. + cmp cx, (2048 - 512 - 8) ;Fit into the buffer? + ja SetDOSData_fail + cmp al, SetCountryInfo ;is the data for SetCountryInfo table? + jne SetDOSCntry_Mov ;no, don't worry + push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009;Cannot destroy ccMono_ptr address. Save them. + push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;At this time DI -> ccCountryInfoLen + push di ;save DI + + push ax + mov ax,cs:CntryCodePage_Id ;Do not use the Code Page info in Country_Info + mov ds:[si+4], ax ;Use the saved one for this !!!! + pop ax + +SetDOSCntry_Mov: + rep movsb ;copy the table into DOS + cmp al, SetCountryInfo ;was the ccMono_ptr saved? + jne SetDOSCntry_data_next + pop di ;restore DI + pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;restore + pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009; + +SetDOSCntry_data_next: + pop si ;restore control buffer pointer + pop cx ;restore # of entries left + pop di ;restore pointer to DSO_COUNTRY_CDPG + add si, word ptr ds:[si] ;try to get the next entry + inc si + inc si ;take a word of entry length itself +; loop SetDOSCntry_data + dec cx ;AN008; + cmp cx,0 ;AN008; + je SetDOSCntry_OK ;AN008; + jmp SetDOSCntry_data ;AN008; +SetDOSCntry_OK: ;AN008; + ret +SetDOSCountryInfo endp +; + +GetCountryDestination proc near +;Get the destination address in the DOS country info table. +;Input: AL - Data ID +; ES:DI -> DOS_COUNTRY_CDPG_INFO +;On return: +; ES:DI -> Destination address of the matching data id +; carry set if no matching data id found in DOS. + + push cx + add di, ccNumber_of_entries ;skip the reserved area, syscodepage etc. + mov cx, word ptr es:[di] ;get the number of entries + inc di + inc di ;SI -> the first start entry id +GetCntryDest: + cmp byte ptr es:[di], al + je GetCntryDest_OK + cmp byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry? + je GetCntryDest_1 + add di, 5 ;next data id + jmp short GetCntryDest_loop +GetCntryDest_1: + add di, NEW_COUNTRY_SIZE + 3 ;next data id +GetCntryDest_loop: + loop GetCntryDest + stc + jmp short GetCntryDest_exit +GetCntryDest_OK: + cmp al, SetCountryInfo ;select country info? + jne GetCntryDest_OK1 + inc di ;now DI -> ccCountryInfoLen + jmp short GetCntryDest_exit +GetCntryDest_OK1: + les di, dword ptr es:[di+1] ;get the destination in ES:DI +GetCntryDest_Exit: + pop cx + ret +GetCountryDestination endp + +; +ReadInControlBuffer proc near +;Move file pointer to CX:DX +;Read AX bytes into the control buffer. (Should be less than 2 Kb) +;SI will be set to 0 hence DS:SI points to the control buffer. +;Entry: CX,DX offset from the start of the file where the read/write pointer +; be moved. +; AX - # of bytes to read +; BX - file handle +; DS - buffer seg. +;Return: The control data information is read into DS:0 - DS:0200. +; CX,DX value destroyed. +; Carry set if error in Reading file. +; + push ax ;# of bytes to read + mov ax, 4200h + stc + int 21h ;move pointer + pop cx ;# of bytes to read + jc RICB_exit + xor dx,dx ;ds:dx -> control buffer + xor si,si + mov ah,3fh ;read into the buffer + stc + int 21h ;should be less than 1024 bytes. +RICB_exit: + ret +ReadInControlBuffer endp + +; +SET_COUNTRY_PATH proc near +;In: DS - SYSINITSEG, ES - CONFBOT, SI -> start of the asciiz path string +; DOSINFO_EXT, CNTRY_DRV, CNTRY_ROOT, CNTRY_PATH +; Assumes current directory is the ROOT directory. +;Out: DS:DI -> full path (CNTRY_DRV). +; Set the CNTRY_DRV string from the COUNTRY=,,path command. +; DS, ES, SI value saved. + + push si + push ds ;switch ds, es + push es + pop ds + pop es ;now DS -> CONFBOT, ES -> SYSINITSEG + + call chk_drive_letter ;current DS:[SI] is a drive letter? + jc SCP_Default_drv ;no, use current default drive. + mov al, byte ptr DS:[SI] + inc si + inc si ;SI -> next char after ":" + jmp short SCP_SetDrv +SCP_Default_drv: + mov ah, 19h + int 21h + add al, "A" ;convert it to a character. +SCP_SetDrv: + mov cs:CNTRY_DRV, al ;set the drive letter. + mov di, offset CNTRY_PATH + mov al, byte ptr DS:[SI] + cmp al, "\" + je SCP_Root_Dir + cmp al, cs:SWTCHR ;let's accept "/" as an directory delim + je SCP_Root_Dir + jmp short SCP_Path +SCP_Root_Dir: + dec di ;DI -> CNTRY_ROOT +SCP_Path: + call MOVE_ASCIIZ ;copy it + mov di, offset CNTRY_DRV +SCPath_Exit: + push ds ;switch ds, es + push es + pop ds + pop es ;DS, ES value restored + pop si + RET +SET_COUNTRY_PATH endp + +; +CHK_DRIVE_LETTER proc near +;Check if DS:[SI] is a drive letter followed by ":". +;Assume that every alpha charater is already converted to UPPER CASE. +;Carry set if not. +; + push ax + cmp byte ptr ds:[si], "A" + jb CDLetter_NO + cmp byte ptr ds:[si], "Z" + ja CDLetter_NO + cmp byte ptr ds:[si+1], ":" + jne CDLetter_NO + jmp short CDLetter_exit +CDLetter_NO: + stc +CDLetter_exit: + pop ax + ret +CHK_DRIVE_LETTER endp + +; +MOVE_ASCIIZ proc near +;In: DS:SI -> source ES:DI -> target +;Out: copy the string until 0. +;Assumes there exists a 0. +MASCIIZ_loop: + movsb + cmp byte ptr DS:[SI-1], 0 ;Was it 0? + jne MASCIIZ_loop + ret +MOVE_ASCIIZ endp + +; +; DS:DX POINTS TO STRING TO OUTPUT (ASCIZ) +; +; PRINTS +; +; +; +BADFIL: + PUSH CS + POP ES + MOV SI,DX +BADLOAD: + MOV DX,OFFSET BADLD_PRE ;WANT TO PRINT CONFIG ERROR +; MOV BX,OFFSET BADLD_POST + mov bx, offset CRLFM ;AN006; +PRNERR: + PUSH CS + POP DS + call Print +PRN1: MOV DL,ES:[SI] + OR DL,DL + JZ PRN2 + MOV AH,STD_CON_OUTPUT + INT 21H + INC SI + JMP PRN1 +PRN2: MOV DX,BX + call Print + cmp DoNotShowNum, 1 ;AN000; suppress line number when handling COMMAND.COM + je Prnexit + call Error_Line +PRNEXIT: + return + +PRINT: MOV AH,STD_CON_STRING_OUTPUT + INT 21H + return + + + IF NOEXEC +; +; LOAD NON EXE FILE CALLED [DS:DX] AT MEMORY LOCATION ES:BX +; +LDFIL: + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DS + PUSH BX + XOR AX,AX ;OPEN THE FILE + MOV AH,OPEN + STC ;IN CASE OF INT 24 + INT 21H + POP DX ;Clean stack in case jump + JC LDRET + PUSH DX + MOV BX,AX ;Handle in BX + XOR CX,CX + XOR DX,DX + MOV AX,(LSEEK SHL 8) OR 2 + STC ;IN CASE OF INT 24 + INT 21H ; Get file size in DX:AX + JC LDCLSP + OR DX,DX + JNZ LDERRP ; File >64K + POP DX + PUSH DX + MOV CX,ES ; CX:DX is xaddr + ADD DX,AX ; Add file size to Xaddr + JNC DOSIZE + ADD CX,1000H ; ripple carry +DOSIZE: + mov ax,dx + call ParaRound + mov dx,ax + + ADD CX,DX + CMP CX,[ALLOCLIM] + JB OKLD + JMP MEM_ERR + +OKLD: + XOR CX,CX + XOR DX,DX + MOV AX,LSEEK SHL 8 ;Reset pointer to beginning of file + STC ;IN CASE OF INT 24 + INT 21H + JC LDCLSP + POP DX + PUSH ES ;READ THE FILE IN + POP DS ;Trans addr is DS:DX + MOV CX,0FF00H ; .COM files arn't any bigger than + ; 64k-100H + MOV AH,READ + STC ;IN CASE OF INT 24 + INT 21H + JC LDCLS + MOV SI,DX ;CHECK FOR EXE FILE + CMP WORD PTR [SI],"ZM" + CLC ; Assume OK + JNZ LDCLS ; Only know how to do .COM files + STC + JMP SHORT LDCLS + +LDERRP: + STC +LDCLSP: + POP DX ;Clean stack +LDCLS: + PUSHF + MOV AH,CLOSE ;CLOSE THE FILE + STC + INT 21H + POPF + +LDRET: POP DS + POP SI + POP DX + POP CX + POP BX + POP AX + return + ENDIF + +; +; OPEN DEVICE POINTED TO BY DX, AL HAS ACCESS CODE +; IF UNABLE TO OPEN DO A DEVICE OPEN NULL DEVICE INSTEAD +; +OPEN_DEV: + CALL OPEN_FILE + JNC OPEN_DEV3 +OPEN_DEV1: + MOV DX,OFFSET NULDEV + CALL OPEN_FILE + return + +OPEN_DEV3: + MOV BX,AX ; Handle from open to BX + XOR AX,AX ; GET DEVICE INFO + MOV AH,IOCTL + INT 21H + TEST DL,10000000B + retnz + MOV AH,CLOSE + INT 21H + JMP OPEN_DEV1 + +OPEN_FILE: + MOV AH,OPEN + STC + INT 21H + return + +;J.K. TEST INT24. Return back to DOS with the fake user response of "FAIL" +INT24: + mov al, 3 ;AN000; Fail the system call + iret ;AN000; Return back to DOS. + + +;INT24: ADD SP,6 ;RESTORE MACHINE STATE +; POP AX +; POP BX +; POP CX +; POP DX +; POP SI +; POP DI +; POP BP +; POP DS +; POP ES +; PUSH AX +; MOV AH,GET_DEFAULT_DRIVE ;INITIALIZE DOS +; INT 21H +; POP AX +; IRET ;BACK TO USER + + IF ALTVECT +BOOTMES DB 13,10,"MS-DOS version " + DB MAJOR_VERSION + "0" + DB "." + DB (MINOR_VERSION / 10) + "0" + DB (MINOR_VERSION MOD 10) + "0" + DB 13,10 + DB "Copyright 1981,88 Microsoft Corp.",13,10,"$" + ENDIF + +include copyrigh.inc ;P1821; Copyright statement + +NULDEV DB "NUL",0 +CONDEV DB "CON",0 +AUXDEV DB "AUX",0 +PRNDEV DB "PRN",0 + +CONFIG DB "\CONFIG.SYS",0 + +CNTRY_DRV DB "A:" +CNTRY_ROOT DB "\" +CNTRY_PATH DB "COUNTRY.SYS",0 + DB 52 DUP (0) + +COUNTRY_FILE_SIGNATURE db 0FFh,'COUNTRY' + +CntryCodePage_Id DW ? + +COMMND DB "\COMMAND.COM",0 + DB 51 dup (0) + +PathString db 64 dup (0) ;AN014; +LShare db "SHARE.EXE",0,"/NC",0Dh,0Ah ;AN014;AN015;To be used by Load/exec. + ;/NC parm will disable file sharing check. + +COMTAB LABEL BYTE +;;;; DB 8,"AVAILDEV",'A' ; NO LONGER SUPPORTED + DB 7,"BUFFERS", 'B' + DB 5,"BREAK", 'C' + DB 6,"DEVICE", 'D' + DB 5,"FILES", 'F' + DB 4,"FCBS", 'X' + DB 9,"LASTDRIVE",'L' + db 10,"MULTITRACK", 'M' ;AN002; + DB 8,"DRIVPARM", 'P' ; RS for DOS 3.2 + IF STACKSW + DB 6,"STACKS", 'K' ; BAS for DOS 3.2 + ENDIF + DB 7,"COUNTRY", 'Q' + DB 5,"SHELL", 'S' + db 7,"INSTALL", 'I' ;AN000; + db 3,"IFS", 'J' ;AN000; + db 4,"CPSW", 'W' ;AN000; +;;;; DB 8,"SWITCHAR",'W' ; NO LONGER SUPPORTED + db 7,"COMMENT", 'Y' ;AN000; + db 3,"REM", '0' ;AN004; + db 8,"SWITCHES", '1' ;AN013; + DB 0 + +public DeviceParameters +DeviceParameters a_DeviceParameters <0,DEV_3INCH720KB,0,80> + +hlim dw 2 +slim dw 9 + +public drive +drive db ? + +public switches +Switches dw 0 + +; +; The following are the recommended BPBs for the media that we know of so +; far. + +; 48 tpi diskettes + +BPB48T DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 2*9*40 + DB 0FDH + DW 2 + DW 9 + DW 2 + DD 0 + DD 0 + +; 96tpi diskettes + +BPB96T DW 512 + DB 1 + DW 1 + DB 2 + DW 224 + DW 2*15*80 + DB 0F9H + DW 7 + DW 15 + DW 2 + DD 0 + DD 0 + +; 3 1/2 inch diskette BPB + +BPB35 DW 512 + DB 2 + DW 1 + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DD 0 + DD 0 + +BPB35H DW 0200H + DB 01H + DW 0001H + DB 02H + DW 0E0h + DW 0B40H + DB 0F0H + DW 0009H + DW 0012H + DW 0002H + DD 0 + DD 0 + +BPBTable dw BPB48T ; 48tpi drives + dw BPB96T ; 96tpi drives + dw BPB35 ; 3.5" drives +; The following are not supported, so default to 3.5" media layout + dw BPB35 ; Not used - 8" drives + dw BPB35 ; Not Used - 8" drives + dw BPB35 ; Not Used - hard files + dw BPB35 ; Not Used - tape drives + dw BPB35H ; 3-1/2" 1.44MB drive + +switchlist db 8,"FHSTDICN" ; Preserve the positions of N and C. + +; The following depend on the positions of the various letters in SwitchList + +switchnum equ 11111000B ; which switches require number + +flagec35 equ 00000100B ; electrically compatible 3.5 inch disk drive +flagdrive equ 00001000B +flagcyln equ 00010000B +flagseclim equ 00100000B +flagheads equ 01000000B +flagff equ 10000000B + +SWTCHR EQU "/" ; switch follows this character + +SYSINITSEG ENDS + END -- cgit v1.2.3