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/MSINIT.ASM | 2819 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2819 insertions(+) create mode 100644 v4.0/src/BIOS/MSINIT.ASM (limited to 'v4.0/src/BIOS/MSINIT.ASM') 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 -- cgit v1.2.3