; modification history ; ; 3.21 sp added pushf-popf fix around NoParms to fix bug ;;Rev 3.30 Modification ----------------------------------------------- test = 0 include msgroup.inc ;define code segment include dskprm.inc include msequ.inc include msmacro.inc include msextrn.inc include biostruc.inc include cmosequ.inc EXTRN OLD13:DWORD ; THE FOLLOWING LABEL DEFINES THE END OF THE AT ROM PATCH. THIS IS USED ; AT CONFIGURATION TIME. ; Warning!!! 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. ;Warning!!! This code will be dynamically relocated by MSINIT. EXTRN base_century:byte EXTRN base_year:byte EXTRN month_tab:byte public Daycnt_to_day ;for real time clock support Daycnt_to_day proc near ;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)) ;# 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 add base_year, al ;So, ah = 0. Adjust year inc daycnt ;set daycnt to 1 base cmp daycnt, 366 ;daycnt=remainder of leap year bk jbe Leapyear ;within 366+355+355+355 days. inc base_year ;if daycnt <= 366, then leap year sub daycnt, 366 ;else daycnt--, base_year++; ;And next three years are normal 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 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] ;cmp daycnt for each month til fit 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 ;al=day,dl=month,dh=year,cl=cntry call word ptr BinToBCD ;To save 15 bytes, Bin_To_BCD proc ;was rel 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 ; real time clock sup ;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 bcd, ah=low digit 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 routines for CMOS clock 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 add EVENB ; ; THE K09 REQUIRES 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. ; Warning!!! 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 MOV AH, 01h ; COMMAND TO SET THE TIME INT 1Ah ; CALL ROM-BIOS TIME ROUTINE STI JMP INT6C_RET_ADDR ; LONG JUMP INT6C ENDP INCLUDE READCLOCK.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 ;;End of Modification ----------------------------------------------- ;------------------------------------------------------------------------ ; : ; System initiailzation : ; : ; 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. : ; : ;------------------------------------------------------------------------ ; DRVFAT must be the first location of freeable space! EVENB DRVFAT DW 0000 ; Drive and FAT ID of DOS BIOS$ DW 0000 ; First sector of data DOSCNT DW 0000 ; How many sectors to read fBigFAT DB 0 ; Flags for drive FatLen DW ? ; number of sectors in FAT. FatLoc DW ? ; seg addr of fat sector ;;Rev 3.30 Modification ----------------------------------------------- ; THE FOLLOWING TWO BYTES ARE USED TO SAVE 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 RET BY ROM public Model_Byte MODEL_BYTE DB 0FFH ; MODEL BYTE. SET UP AT INIT TIME. ; FF - PC-1, EXPANSION, OLD PC-2 ; FE - NEWER PC-2 (64/256K PLANAR) ; FD - ; FC - public Secondary_Model_Byte Secondary_Model_Byte db 0 ;;End of Modification ----------------------------------------------- BOOTBIAS = 200H EVENB DiskTable DW 512, 0100h, 64, 0 DW 2048, 0201h, 112, 0 DW 8192, 0402h, 256, 0 DW 32680, 0803h, 512, 0 DW 65535, 1004h, 1024, 0 DiskTable2 DW 32680, 0803h, 512, 0 DW 65535, 0402h, 512, fBIG ;;Rev 3.30 Modification ----------------------------------------------- ;************************************************************************* ;Variables for Mini disk initialization ;************************************************************************* End_Of_BDSM dw ? ;offset value of the ending add ;of BDSM table. Needed to figure ;the Final_DOS_Location. numh db 0 ;number of hard files mininum db 0 ;logical drive num for mini disk 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 ;Mini Disk BPB pt add in DskDrvs. ;;End of Modification ----------------------------------------------- Bios_Date DB '01/10/84',0 ; ; 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 DD 0 ;hidden sectors - sp DD 0 ;big total sectors - sp DB 6 DUP(?) ;reserved ; 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 DD 0 ;hidden sectors - sp DD 0 ;big total sectors - sp DB 6 DUP(?) ;reserved 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 DD 0 ;hidden sectors - sp DD 0 ;big total sectors - sp DB 6 DUP(?) ;reserved 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 (0-based) ; Public INIT INIT PROC NEAR MESSAGE FTESTINIT,<"MSBIO",CR,LF> ;3.30 CLI XOR AX,AX MOV DS,AX ; ; 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 ; rom-bios equipment determination 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 ; save number of diskette drives in CL test DL, 80h ; booted from hard disk ? jnz GotHrd ; yes, jump down xor AX, AX ; no - indicate boot from drive A GotHrd: ; At this point the registers contain these values: ; AX = 0-based drive we booted from ; BX = the logical number of the first data sector on the disk ; CL = number of floppies including logical one ; CH = media byte ; Message fTestINIT,<"Init",CR,LF> ; ; set up local stack ; xor DX,DX cli ; turn interrupts off while manupulating stack mov SS,DX ; set stack segment register mov SP,700h ; set stack pointer sti ; turn interrupts on ASSUME SS:NOTHING ; preserve some of the values in registers push CX ; save number of floppies and media byte mov BIOS$,BX ; save first data sector mov AH,CH ; FAT ID to AH too push AX ; save boot drive number, and media byte ;;Rev 3.30 Modification ----------------------------------------------- ; Let Model_byte, Secondary_Model_Byte be set here!!! mov ah,0c0h ; return system environment int 15h ; call ROM-Bios routine 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 ;;End of Modification ----------------------------------------------- Turn_Timer_On: mov AL,EOI out AKPORT,AL ; turn on the timer Message fTestINIT,<"COM devices",CR,LF> ;;Rev 3.30 Modification ----------------------------------------------- mov si,offset COM4DEV call AUX_INIT mov si,offset COM3DEV call AUX_INIT ;;End of Modification ----------------------------------------------- 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 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 ;----------------------------------------------- ; ; THE FOLLOWING DEPEND ON THE TYPE OF MACHINE. ; 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 ; call rom-bios for memory size mov CL, 6 ; get ready for shift shl AX, CL ; change from K to 16 byte blocks pop CX ; restore CX mov DRVFAT, CX push AX mov dx,ds:(7C00h + 16h) ; number of sectors/fat from boot sec xor dh,dh mov FatLen,DX ; ; Convert sector count to paragraph count:512 bytes / sec / 16 bytes / para ; = 32 para /sector ; ;;Rev 3.30 Modification ----------------------------------------------- SHL DX,1 SHL DX,1 SHL DX,1 SHL DX,1 SHL DX,1 ;;End of Modification ----------------------------------------------- SUB AX,dx ; room for FAT MOV FatLoc,AX ; location to read fat 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 ; Allocation of buffers has moved to SYSINIT - Aug 19/85 BAS ;DEF_BUFF: MOV MEMORY_SIZE,AX INC CL MOV DEFAULT_DRIVE,CL ;SAVE DEFAULT DRIVE SPEC ;DOSSEG = ((((OFFSET END$)-(OFFSET START$))+15)/16)+BIOSEG+SYSIZE ; BAS DEBUG ;MOV CURRENT_DOS_LOCATION,((((OFFSET END$)-(OFFSET 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 mov ds,ax mov ax,word ptr ds:(0fH*4+2) ; segment for Int 15 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 ; ;************************************************************** ; 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 anything if CMOS clock, ;then set the system time accordingly. ;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> mov DL, 80h ; tell rom bios to look at hard drives mov AH, 8h ; set command to get drive parameter int 13h ; call ROM-BIOS to get number of drives jc ENDDRV ; old, rom therefore no hard disks mov HNUM, DL ; save number of hard drives in HNUM 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 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 MOV AH, 8h ;GET DRIVE PARAMETERS INT 13h ;CALL ROM-BIOS JNC PARMSFROMROM JMP NOPARMSFROMROM ; GOT AN OLD ROM PARMSFROMROM: ;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 IO.SYS,MSDOS to boot up before it sets CMOS. ;This should only happen with drive B. ;;Rev 3.30 Modification ----------------------------------------------- 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 NUM 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 presence of changeline ; mov AH, 15h ; set command to get DASD type int 13h ; call ROM-BIOS JC CHANGELINE_DONE CMP AH,02 ; CHECK FOR PRESENCE OF CHANGELINE JNE CHANGELINE_DONE ;;End of Modification ----------------------------------------------- ; ; 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 ; ;3.30 ; WE NOW TRY TO SET UP THE FORM FACTOR FOR THE TYPES OF MEDIA THAT WE KNOW;3.30 ; AND CAN RECOGNISE. FOR THE REST, WE SET THE FORM FACTOR AS "OTHER". ;3.30 ; ;3.30 CHANGELINE_DONE: ;3.30 ; 40 CYLINDERS AND 9 OR LESS SEC/TRK, TREAT AS 48 TPI MEDIUM. ;3.30 CMP NUM_CYLN,40 ;3.30 JNZ TRY_80 ;3.30 CMP SEC_TRK,9 ;3.30 JBE GOT_FF ;3.30 GOTOTHER: ;3.30 MOV DH,FFOTHER ; WE HAVE A "STRANGE" MEDIUM ;3.30 JMP SHORT GOT_FF ;3.30 ;3.30 ; ;3.30 ; 80 CYLINDERS AND 9 SECTORS/TRACK => 720 KB DEVICE ;3.30 ; 80 CYLINDERS AND 15 SEC/TRK => 96 TPI MEDIUM ;3.30 ; ;3.30 TRY_80: ;3.30 CMP NUM_CYLN,80 ;3.30 JNZ GOTOTHER ;3.30 CMP SEC_TRK,15 ;3.30 JZ GOT96 ;3.30 CMP SEC_TRK,9 ;3.30 JNZ GOTOTHER ;3.30 MOV DH,FFSMALL ;3.30 JMP SHORT GOT_FF ;3.30 ;3.30 GOT96: ;3.30 MOV DH,FF96TPI ;3.30 ;3.30 GOT_FF: ;3.30 JMP SHORT NEXTDRIVE ;3.30 ;3.30 ; AN OLD ROM, SO WE EITHER HAVE A 48TPI OR 96TPI DRIVE. IF THE DRIVE ;3.30 ; HAS CHANGELINE, WE ASSUME IT IS A 96TPI, OTHERWISE IT IS A 48TPI. ;3.30 ;3.30 NOPARMSFROMROM: ;3.30 POP ES ;3.30 POP CX ;3.30 POP DX ;3.30 POP DI ;3.30 POP DS ;3.30 ;3.30 MOV AH, 15h ; SET COMMAND TO GET DASD TYPE ;3.30 INT 13h ; CALL ROM-BIOS ;3.30 JC NEXTDRIVE ;3.30 CMP AH,2 ; IS THERE CHANGELINE? ;3.30 JNZ NEXTDRIVE ;3.30 OR CL,FCHANGELINE ;3.30 MOV FHAVE96,1 ; REMEMBER WE HAVE 96TPI DRIVES ;3.30 MOV NUM_CYLN,80 ;3.30 MOV DH,FF96TPI ;3.30 MOV AL,15 ; SET EOT IF NECESSARY ;3.30 CMP AL, EOT ;3.30 JBE EOT_OK2 ;3.30 MOV EOT,AL ;3.30 EOT_OK2: ;3.30 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 ; fill BDS for drive 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 ;3.30 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> ; Don't forget we have mov single,2 ; single drive system or cx,fI_Am_Mult ; set that this is one of ; several drives or word ptr [di].flags,cx ; save flags mov di,word ptr [di].link ; move to next BDS in list inc dl ; add a number jmp short NextDrive ; Use same info for BDS as previous No_Single: inc dl jmp loop_drive Done_Drives: mov ax,-1 ; Signify end of list by mov word ptr [di].link,ax ; setting pointer to -1 ; ; 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 ;3.30 mov DL, 80h ; set first hard file number mov di,offset BDSH ; Set up first hard file. mov bl,HARDNUM call SETHARD 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 ;3.30 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 ; set second hard file number call SETHARD jnc HardFile2_OK dec HNUM jmp short SetIt HardFile2_OK: Call Install_BDS SETIT: mov al,HNUM or al,al JZ STATIC_CONFIGURE ;3.30 add al,HARDNUM mov DRVMAX,al ; End of physical drive initialization. ;3.30 ; *** Do not change the position of the following statement. ; *** DoMini routine will use [DRVMAX] value for the start of the logical ;3.30 ; *** drive number of Mini disk(s). ;3.30 ;3.30 call DoMini ;For setting up mini disks, if found -;3.30 ; End of drive initialization. ;9/24/86 We now decide, based on the configurations available so far,;3.30 ;what code or data we need to keep as a stay resident code. The following;3.30 ;table shows the configurations under consideration. They are listed in ;3.30 ;the order of their current position memory. ;3.30 ;Configuration will be done in two ways: ;3.30 ;First, we are going to set "Static configuration". Static configuration ;3.30 ;will consider from basic configuration to ENDOF96TPI configuration. ;3.30 ;The result of static configuration will be the address the Dynamic ;3.30 ;configuration will use to start with. ;3.30 ;Secondly, "Dynamic cofiguration" will be performed. Dynamic configuration;3.30 ;involves possible relocation of CODE/DATA. Dynamic configuration routine ;3.30 ;will take care of BDSM tables and AT ROM Fix module thru K09 suspend/res ;3.30 ;code individually. After these operation, FINAL_DOS_LOCATION will be set.;3.30 ;This will be the place SYSINIT routine will relocate MSDOS module. ;3.30 ; ;3.30 ; 1. BASIC CONFIGURATION FOR MSBIO (EndFloppy, EndSwap) ;3.30 ; 2. ENDONEHARD ;3.30 ; 3. ENDTWOHARD ;3.30 ; 4. END96TPI ;a system that supports "Change Line Error" ;3.30 ; 5. End of BDSM ;BDSM tables for mini disks. ;3.30 ; 6. ENDATROM ;Some of AT ROM fix module. ;3.30 ; 7. ENDCMOSCLOCKSET;Supporting program for CMOS clock write. ;3.30 ; 8. ENDK09 ;K09 CMOS Clock module to handle SUSPEND/RESUME ;3.30 ; ;3.30 ;9/24/86. ;3.30 ;3.30 ; *** For mini disk configuration. 4/7/86 ;3.30 ; *** END_OF_BDSM will contain the ending address(off) of BDSM table for ;3.30 ; *** mini disks which is located right after the label END96TPI. ;3.30 ; *** The variable NUM_MINI_DSK will indicate the existance. 4/7/86 ;3.30 ;3.30 ;3.30 STATIC_CONFIGURE: ;3.30 ;3.30 ;3.30 PUSH AX ;3.30 mov ax, offset END96TPI ;let's start with the biggest one.;3.30 cmp fHave96, 0 ;Is change line support there? ;3.30 jnz Config96 ;Yes. ;3.30 ;3.30 mov ax, offset ENDTWOHARD ;3.30 cmp HNUM, 1 ;1 hard file? ;3.30 jbe No_Two_HRD ;3.30 jmp ConfigTwoHard ;3.30 No_Two_HRD: ;3.30 mov ax, offset ENDONEHARD ;3.30 jnz Basic_Floppy ;3.30 jmp ConfigOneHard ;3.30 Basic_Floppy: ;3.30 mov ax, offset ENDFLOPPY ;3.30 jmp Dynamic_Configure ;static configuration is done! ;3.30 ; ; Keep the 96tpi code ; Config96: ; ; Save old INT 13 vector ; PUSH AX PUSH DS XOR AX,AX MOV DS,AX ASSUME DS:NOTHING ;3.30 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 ;3.30 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 ;4/7/86 for mini disks installed ;3.30 ;if not installed, then num_mini_dsk = 0. ;3.30 MOV DrvMax,AL POP AX DYNAMIC_CONFIGURE: ;3.30 call Get_Para_Offset ;For dynamic allocation, we are ;3.30 ;going to use offset address that ;3.30 ;is in paragraph boundary. ;3.30 push cs ;3.30 pop es ;es -> code ;3.30 assume es:code ;3.30 cld ;clear direction ;3.30 ;3.30 cmp [num_mini_dsk], 0 ;Mini disk(s) installed ? ;3.30 jz CheckATROM ;No. ;3.30 mov ax, End_Of_BDSM ;set the new ending address ;3.30 call Get_Para_Offset ;3.30 CheckATROM: ;3.30 cmp Model_Byte, 0FCh ;AT ? ;3.30 jnz CheckCMOSClock ;3.30 cmp HNUM, 0 ;No hard file? ;3.30 jz CheckCMOSClock ;3.30 mov si, 0F000h ;3.30 mov es, si ;ES -> BIOS segment ;3.30 assume es:nothing ;3.30 mov si, offset BIOS_DATE ;3.30 mov di, 0FFF5H ;ROM BIOS string is at F000:FFF5 ;3.30 Cmpbyte: ;Only patch ROM for bios 01/10/84 ;3.30 cmpsb ;3.30 jnz CheckCMOSClock ;3.30 cmp byte ptr [si-1],0 ;3.30 jnz Cmpbyte ;3.30 ;3.30 SetRomCode: ;Now we have to install ROM fix ;3.30 ;AX is the address to move. ;3.30 push cs ;3.30 pop es ;set ES to CODE seg ;3.30 assume es:code ;3.30 mov word ptr ORIG13, ax ;3.30 mov word ptr ORIG13+2, cs ;set new ROM bios int 13 vector ;3.30 mov cx, offset ENDATROM ;3.30 mov si, offset IBM_DISK_IO ;3.30 sub cx, si ;size of AT ROM FIX module ;3.30 mov di, ax ;destination ;3.30 rep movsb ;relocate it ;3.30 mov ax, di ;new ending address ;3.30 call Get_Para_Offset ;in AX ;3.30 ;3.30 CheckCMOSClock: ;3.30 push cs ;3.30 pop es ;set ES to CODE seg ;3.30 assume es:code ;3.30 cmp HaveCMOSClock, 1 ;CMOS Clock exists? ;3.30 jne CheckK09 ;3.30 mov DaycntToDay, ax ;set the address for MSCLOCK ;3.30 mov cx, offset EndDaycntToDay ;3.30 mov si, offset Daycnt_To_Day ;3.30 sub cx, si ;size of CMOS clock sup routine ;3.30 mov di, ax ;3.30 rep movsb ;3.30 mov ax, di ;3.30 call Get_Para_Offset ;3.30 mov BinToBCD, ax ;set the address for MSCLOCK ;3.30 mov cx, offset EndCMOSClockSet ;3.30 mov si, offset Bin_To_BCD ;3.30 sub cx, si ;3.30 mov di, ax ;3.30 rep movsb ;3.30 mov ax, di ;3.30 call Get_Para_Offset ;3.30 ;3.30 CheckK09: ;3.30 push ax ;save ax ;3.30* mov ax,4100h ;Q: is it a K09 ;3.30* mov bl,0 ; ;3.30* int 15h ; ;3.30* pop ax ;3.30 jc CONFIGDONE ;3.30 ;3.30 mov si, offset INT6C ;3.30 mov cx, offset ENDK09 ;3.30 sub cx, si ;size of K09 routine ;3.30 mov di, ax ;3.30 push di ;save destination ;3.30 rep movsb ;3.30 mov ax, di ; ;3.30 call Get_Para_Offset ;AX = new ending address ;3.30 pop di ;3.30 ;3.30 push ax ;3.30 push ds ;3.30 mov fHaveK09, 1 ;remember we have a K09 type ;3.30 xor ax,ax ;3.30 mov ds, ax ;3.30 assume ds:nothing ;3.30 ;3.30 mov word ptr ds:[4 * 6Ch], di ;new INT 6Ch handler ;3.30 mov ds:[4 * 6Ch +2], cs ;3.30 ;3.30 pop ds ;3.30 assume ds:code ;3.30 pop ax ;restore the ending address ;3.30 ; ; Set up config stuff for SYSINIT ; ConfigDone: MOV DX,SYSINITSEG MOV DS,DX ASSUME DS:SYSINITSEG SUB AX,OFFSET START$ ;3.30 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 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 BL,[DI].FatSiz ; get size of fat on media mov fBigFat,BL mov CL,[DI].SecPerClus ; get sectors/cluster mov AX,[DI].HIDSEC ; get number of hidden sectors sub BIOS$,AX ; subtract hidden sector offset 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,((((OFFSET END$)-(OFFSET START$))+15)/16)+SYSIZE LOADIT: MOV AX, OFFSET END$ ;3.30 SUB AX, OFFSET START$ ;3.30 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 ;3.30 EOFBig: Message fTestINIT, CMP BX,0FFF7h ; else ISEOFX: ;3.30 JB LOADIT ; } WHILE (!ISEOF (CLUS)); ;3.30 ;3.30 CALL SETDRVPARMS ;3.30 ;3.30 MESSAGE FTESTINIT,<"SYSINIT",CR,LF> ;3.30 ZWAIT ;3.30 MESSAGE FTESTINIT,<"ON TO SYSINIT...",CR,LF> ;3.30 JMP SYSINIT ;3.30 ;3.30 INIT ENDP ;3.30 ;3.30 ;**************************** ;3.30 ;3.30 Get_Para_Offset proc near ;3.30 ;in: AX - offset value ;3.30 ;out: AX - offset value adjusted for the next paragraph boundary. ;3.30 add ax, 15 ;make a paragraph ;3.30 rcr ax, 1 ;3.30 shr ax, 1 ;3.30 shr ax, 1 ;3.30 shr ax, 1 ;3.30 shl ax, 1 ;now, make it back to offset value ;3.30 shl ax, 1 ;3.30 shl ax, 1 ;3.30 shl ax, 1 ;3.30 ret ;3.30 Get_Para_Offset endp ;3.30 ; ; READ A FAT SECTOR INTO fat location ; GETFAT PROC NEAR ;3.30 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 ;3.30 ; ; READ A BOOT RECORD INTO 7C0:BootBias ; GetBoot reads the boot record into 7C0:BootBias ; On Entry: ; DL contains ROM drive number (80 or 81) ; On Exit: ; if carry set error ; if carry clear: ; ES:BX piont to boot sector ; AX and CX are not preserved ; BX and ES are used to return values ; GETBOOT PROC NEAR mov AX, 07C0h ; prepare to load ES mov ES, AX ; load ES segment register mov BX, BootBias ; load BX, ES:BX is where sector goes mov AX, 0201h ; command to read & num sec. to 1 xor DH, DH ; head number zero mov CX, 0001h ; cylinder zero and sector one int 13h ; call rom bios jc ERRET cmp WORD PTR ES:[BootBias+1FEH],0AA55H ; DAVE LITTON 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 ;3.30 ; ; 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 ;3.30 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 mov AH, 8 ; set command to get drive parameters int 13h ; call rom-bios disk routine ; 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 ()) 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 ADD BX,16 ; p += sizeof Partition; CMP BX,202H+BootBias ; if (p == &boot[0x202h]) JNZ SET1 ; return -1; SETRET: STC ; } jmp Ret_Hard SET2: PUSH DX MOV AX,WORD PTR ES:[BX+4] MOV DX,WORD PTR ES:[BX+6] ;Decrement the sector count by 1 to make it zero based. Exactly 64k ;3.30 ;sectors should be allowed ;3.30 ; ;3.30 SUB AX,1 ; PTM 901 12/12/86 MT ;3.30 SBB DX,0 ; PTM 901 12/12/86 MT ;3.30 ADD AX,WORD PTR ES:[BX+8] ADC DX,WORD PTR ES:[BX+10] JZ OKDrive Message fTestHard,<"Partition invalid",CR,LF> OR fBigFat,fTOOBIG OKDrive: POP DX MOV AX,WORD PTR ES:[BX+4] MOV [DI].HIDSEC,AX ; BPB->HidSecCt = p->PartitionBegin; MOV AX,WORD PTR ES:[BX+8] CMP AX,64 ; if (p->PartitionLength < 64) JB SETRET ; return -1; MOV WORD PTR [DI].DRVLIM,AX ; BPB->MaxSec = p->PartitionLength; PUSH AX PUSH DX MOV AX,[DI].HidSec ; boot sector number XOR DX,DX MOV BH,DH MOV BL,byte ptr [DI].SecLim DIV BX MOV CL,DL ; CL is sector number INC CL ; sectors are 1 based CWD MOV BL,byte ptr [DI].HdLim DIV BX ; DL is head, AX is cylinder ; ; DL is head. ; AX is cylinder ; CL is sector number ; TOS is drive ; ;*** For Mini Disks *** 4/7/86 ;3.30 cmp word ptr [di].IsMini, 1 ;check for mini disk - 4/7/86 ;3.30 jnz OKnotMini ;not mini disk. - 4/7/86 ;3.30 add ax, [di].hidden_trks ;set phy track num - 4/7/86 ;3.30 OKnotMini: ; 4/7/86 ;3.30 ;*** End of added logic for mini disk ;3.30 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 ; TOS is drive ; POP AX ; AL is drive MOV DH,DL ; DH is head MOV DL,AL ; DL is drive ; ; CL is sector + 2 high bits of cylinder ; CH is low 8 bits of cylinder ; DH is head ; DL is drive ; xor BX, BX ; clear BX -- ES:BX points to buffer mov ax, 0201h ; set command to read one sector int 13h ; call rom-bios to read sector pop AX ; ; ES:[0] points to the boot sector. In theory, (ha ha) the BPB in this thing ; is correct. We can, therefore, pull out all the relevant statistics on the ; media if we recognize the version number. ; CMP WORD PTR ES:[3], "B" SHL 8 + "I" JNZ Unknownj CMP WORD PTR ES:[5], " " SHL 8 + "M" JNZ Unknownj CMP WORD PTR ES:[8], "." SHL 8 + "2" JNZ Try5 CMP BYTE PTR ES:[10], "0" JNZ Try5 Message fTestHard,<"Version 2.0 media",CR,LF> JMP SHORT CopyBPB unknownj: jmp unknown Try5: CMP WORD PTR ES:[8],"." SHL 8 + "3" JNZ Unknownj cmp byte ptr es:[10],"1" ;do not trust 3.0 boot record. 4/15/86;3.30 jb unknownj ;if version >= 3.1, then O.K. 4/15/86 ;3.30 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. MOV AX,WORD PTR ES:[11+DRVLIM-BytePerSec] ; Total sectors MNUM fTestHard,AX Message fTestHard,<" Sec "> DEC AX ; Subtract # reserved (always 1) MOV DX,WORD PTR ES:[11+cSecFAT-BytePerSec] ; Sectors for 1 fat MNUM fTestHard,DX Message fTestHard,<" Sec/Fat "> MOV [DI+cSecFAT],DX ; Set in BIOS BPB SHL DX,1 ; Always 2 FATs SUB AX,DX ; Sub # FAT sectors MOV DX,WORD PTR ES:[11+cDIR-BytePerSec] ; # root entries MOV [DI+cDIR],DX ; Set in BIOS BPB MNUM fTestHard,DX Message fTestHard,<" directory entries "> MOV CL,4 SHR DX,CL ; Div by 16 ents/sector SUB AX,DX ; Sub # dir sectors ; AX now contains the # of data sectors. MOV CL,BYTE PTR ES:[11+SecPerClus-BytePerSec] ; 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> DIV CX ; AX now contains the # clusters. CMP AX,4096-10 ; is this 16-bit fat? JB GoodRetj ; No OR fBigFat,fBIG ; 16 bit FAT GoodRetj: JMP GoodRet Unknown: Message fTestHard,<"Unknown hard media. Assuming 3.0.",CR,LF> MOV SI,OFFSET DiskTable2 Scan: CMP AX,[SI] JBE GotParm ADD SI,4 * 2 JMP Scan GotParm: MOV CL,BYTE PTR [SI+6] OR fBigFat,CL MOV CX,[SI+2] MOV DX,[SI+4] ; ; AX = number of sectors on disk drive ; 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 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> XOR BX,BX MOV BL,CH DEC BX ADD BX,AX 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 GOODRET ;3.30 DoBig: Message fTestHard,<" Big fat",CR,LF> MOV CL,4 ; 16 (2^4) directory entries per sector SHR DX,CL ; cSecDir = cDir / 16; SUB AX,DX ; AX -= cSecDir; AX -= cSecReserved; DEC AX ; ax = t - r - d MOV BL,2 MOV BH,SecPerClus[DI] ; bx = 256 * secperclus + 2 XOR DX,DX 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 DIV BX ; cSecFat = ceil((total-dir-res)/ ; (256*secperclus+2)); MOV WORD PTR [DI].cSecFat,AX ; number of fat sectors GoodRet: 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 ;3.30 ; ; 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 ;3.30 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 mov ax,es:[di].DrvLim push ax mov ax,word ptr es:[di].hdlim mul word ptr es:[di].seclim mov cx,ax ; cx has # sectors per cylinder pop ax xor dx,dx ; set up for div 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: push cs pop ds cmp bl,ffOther ; Special case "other" type of medium JNZ NOT_PROCESS_OTHER ;3.30 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 ; New logic to get the sectors/fat area. ;3.30 ;Fat entry assumed to be 1.5 bytes;3.30 mov bx, 3 ;3.30 mul bx ;3.30 mov bx,2 ;3.30 div bx ;3.30 xor dx, dx ;3.30 mov bx, 512 ;3.30 div bx ;3.30 inc ax ;3.30 No_Round_Up: mov [di].RcSecFat,ax jmp short Go_To_Next_BDS NOT_PROCESS_OTHER: ;3.30 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 ;3.30 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 ;3.30 ; ; READ CLUSTER SPECIFIED IN BX ; CX = SECTORS PER CLUSTER ; DI = LOAD LOCATION ; GETCLUS PROC NEAR ;3.30 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 ADD AX,BIOS$ ;ADD IN FIRST DATA SECTOR 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, WHEN FINISHED SI=ENTRY BX ; UNPACK: PUSH DS PUSH BX MOV SI,FatLoc TEST fBigFat,fBIG ; if (!fBigFat) { JNZ Unpack16 MOV DS,SI MOV SI,BX SHR SI,1 MOV BX,[SI+BX] ; p = fat[clus+clus/2]; JNC HAVCLUS ; if (clus&1) SHR BX,1 ; p >>= 4; SHR BX,1 SHR BX,1 SHR BX,1 HAVCLUS: AND BX,0FFFH ; oldclus=clus; clus = p & 0xFFF; JMP SHORT UNPACKX ;3.30 Unpack16: ; else { MOV DS,SI SHL BX,1 ; oldclus = clus; MOV BX,[BX] ; clus = fat[2*clus]; UNPACKX: ;3.30 POP SI ; return; POP DS ; } MNUM fTestINIT Message fTestINIT,<" "> SUB SI,BX CMP SI,-1 ;one apart? JNZ GETCL2 ADD DOSCNT,CX JMP GETCL1 GETCL2: PUSH BX MOV AX,DRVFAT ;GET DRIVE AND FAT SPEC MOV CX,DOSCNT 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; ;3.30 ; ; SI POINTS TO DEVICE HEADER ; ; 4/22/86 - print_init, aux_init is modified to eliminate the ;3.30 ; self-modifying code. ;3.30 ;3.30 PRINT_INIT: ;3.30 call Get_device_number ;3.30 mov ah,1 ;initalize printer port ;3.30 int 17h ;call ROM-Bios routine ;3.30 ret ;3.30 ;3.30 AUX_INIT: ;3.30 call Get_device_number ;3.30 mov al,RSINIT ;2400,N,1,8 (MSEQU.INC) ;3.30* mov ah,0 ;initalize AUX port ;3.30* int 14h ;call ROM-Bios routine ;3.30* ret ;3.30 ;3.30 GET_DEVICE_NUMBER: ;3.30 ;SI -> device header ;3.30 MOV AL,CS:[SI+13] ;GET DEVICE NUMBER FROM THE NAME ;3.30 SUB AL,"1" ;3.30 CBW ;3.30 MOV DX,AX ;3.30 RET ;3.30 ; ; purge_96tpi NOP's calls to 96tpi support. ; PURGE_96TPI PROC NEAR ;MJB001 ;3.30 PUSH DS PUSH ES push cs ;mjb001 pop es ;mjb001 push cs ;mjb001 pop ds ;mjb001 ASSUME DS:CODE,ES:CODE ;3.30 MOV SI,OFFSET PatchTable PatchLoop: LODSW MOV CX,AX JCXZ PatchDone LODSW MOV DI,AX MOV AL,90h REP STOSB JMP PatchLoop PatchDone: mov di,offset TABLE_PATCH ; ARR 2.42 MOV AX,OFFSET EXIT STOSW STOSW POP ES POP DS ret ;mjb001 PURGE_96TPI ENDP ;3.30 ;Mini disk initialization routine. Called right after DoHard - 4/7/86;3.30 ; DoMini **************************************************************** ;3.30 ; **CS=DS=ES=code ;3.30 ; **DoMini will search for every extended partition in the system, and ;3.30 ; initialize it. ;3.30 ; **BDSM stands for BDS table for Mini disk and located right after the ;3.30 ; label End96Tpi. End_Of_BDSM will have the offset value of the ending ;3.30 ; address of BDSM table. ;3.30 ; **BDSM is the same as usual BDS except that TIM_LO, TIM_HI entries are ;3.30 ; overlapped and used to id mini disk and the number of Hidden_trks. ;3.30 ; Right now, they are called as IsMini, Hidden_Trks respectively. ;3.30 ; **DoMini will use the same routine in SETHARD routine after label SET1 ;3.30 ; to save coding. ;3.30 ; **DRVMAX determined in DoHard routine will be used for the next ;3.30 ; available logical mini disk drive number. ;3.30 ; ;3.30 ; Input: DRVMAX, DSKDRVS ;3.30 ; ;3.30 ; Output: MiniDisk installed. BDSM table established and installed to BDS.;3.30 ; num_mini_dsk - number of mini disks installed in the system. ;3.30 ; End_Of_BDSM - ending offset address of BDSM. ;3.30 ; ;3.30 ; ;3.30 ; Called modules: ;3.30 ; GetBoot, WRMSG, int 13h (AH=8, Rom) ;3.30 ; FIND_MINI_PARTITION (new), Install_BDSM (new), ;3.30 ; SetMini (new, it will use SET1 routine) ;3.30 ; Variables used: End_Of_BDSM, numh, mininum, num_mini_dsk, ;3.30 ; Rom_Minidsk_num, Mini_HDLIM, Mini_SECLIM ;3.30 ; BDSMs, BDSM_type (struc), Start_BDS ;3.30 ;************************************************************************ ;3.30 ; ;3.30 ;3.30 DoMini: ;3.30 Message fTestHard,<"Start of DoMini...",cr,lf> ;3.30 ;3.30 push ax ;Do I need to do this? ;3.30 ;3.30 mov di, offset BDSMs ;from now on, DI points to BDSM ;3.30 mov dl, 80h ;look at first hard drive ;3.30* mov ah, 8h ;get drive parameters ;3.30* int 13h ;call ROM-Bios ;3.30* cmp dl, 0 ;3.30 jz DoMiniRet ;no hard file? Then exit. ;3.30 mov numh, dl ;save the number of hard files. ;3.30 xor ax,ax ;3.30 mov al, drvmax ;3.30 mov mininum, al ;this will be logical drive letter;3.30 ;for mini disk to start with. ;3.30 ;3.30 shl ax, 1 ;ax=number of devices. word bndry ;3.30 push bx ;3.30 mov bx, offset DSKDRVS ;3.30 add bx, ax ;3.30 mov Mini_BPB_ptr, BX ;Mini_BPB_ptr points to first avlb;3.30 ;spot in DskDrvs for Mini disk ;3.30 ;which points to BPB area of BDSM.;3.30 pop bx ;3.30 ;3.30 mov Rom_Minidsk_num, 80h ;3.30 DoMiniBegin: ;3.30 inc dh ;Get # of heads (conv to 1 based) ;3.30 xor ax, ax ;3.30 mov al, dh ;3.30 mov Mini_HDLIM, ax ;save it. ;3.30 xor ax, ax ;3.30 and cl, 3fh ;Get # of sectors/track ;3.30 mov al, cl ;3.30 mov Mini_SECLIM, ax ;and save it. ;3.30 ;3.30 mov dl, Rom_Minidsk_num ;drive number
;3.30 call GETBOOT ;rd master boot rec 7c0:BootBias ;3.30 jc DoMiniNext ;3.30 call FIND_MINI_PARTITION ;3.30 DoMiniNext: ;3.30 dec numh ;3.30 jz DoMiniRet ;3.30 inc Rom_MiniDsk_Num ;Next hard file ;3.30 mov dl, Rom_MiniDsk_Num ;look at next hard drive ;3.30* mov ah, 8h ;get drive parameters ;3.30* int 13h ;call ROM-Bios ;3.30* jmp DoMiniBegin ;3.30 ;3.30 DoMiniRet: ;3.30 pop ax ;3.30 ret ;3.30 ;3.30 ;3.30 ;Find_Mini_Partition tries to find every Extended partition on a disk. ;3.30 ;At entry: DI -> BDSM entry ;3.30 ; ES:BX -> 07c0:BootBias - Master Boot Record ;3.30 ; Rom_MiniDsk_Num - ROM drive number ;3.30 ; MiniNum - Logical drive number ;3.30 ; Mini_HDLIM, Mini_SECLIM ;3.30 ; ;3.30 ;Called routine: SETMINI which uses SET1 (in SETHARD routine) ;3.30 ;Variables & equates used from orig BIOS - flags, fNon_Removable, fBigfat ;3.30 ; ;3.30 ; ;3.30 FIND_MINI_PARTITION: ;3.30 ;3.30 add bx, 1C2h ;BX -> system id. ;3.30 ;3.30 FmpNext: ;3.30 cmp byte ptr ES:[BX], 5 ; 5 = extended partition ID. ;3.30 jz FmpGot ;3.30 add bx, 16 ; for next entry ;3.30 cmp bx, 202h+BootBias ;3.30 jnz FmpNext ;3.30 jmp FmpRet ;not found extended partition ;3.30 ;3.30 FmpGot: ;found my partition. ;3.30 Message ftestHard,<"Found my partition...",cr,lf> ;3.30 xor ax,ax ;3.30 or al, fNon_Removable ;3.30 or word ptr [DI].Flags, ax ;3.30 mov byte ptr [DI].FormFactor, ffHardFile ;3.30 mov fBigFat, 0 ;assume 12 bit Fat. ;3.30 mov ax, Mini_HDLIM ;3.30 mov [DI].HDLIM, ax ;3.30 mov ax, Mini_SECLIM ;3.30 mov [DI].SECLIM, ax ;3.30 mov al, Rom_MiniDsk_Num ;3.30 mov [DI].DriveNum, al ;set physical number ;3.30 mov al, Mininum ;3.30 mov [DI].DriveLet, al ;set logical number ;3.30 ;3.30 cmp word ptr ES:[BX+8], 64 ;**With current BPB, only lower word ;3.30 ; is meaningful. ;3.30 je FmpRet ;should be bigger than 64 sectors at least ;3.30 sub bx, 4 ;let BX point to the start of the entry ;3.30 mov dh, byte ptr ES:[BX+2] ;3.30 and dh, 11000000b ;get higher bits of cyl ;3.30 rol dh, 1 ;3.30 rol dh, 1 ;3.30 mov dl, byte ptr ES:[BX+3] ;cyl byte ;3.30 mov [DI].Hidden_Trks, dx ;set hidden trks ;3.30 ;** Now, read the volume boot record into BootBias. ;3.30 mov cx,ES:[BX+2] ;cylinder,cylinder/sector ;3.30* mov dh,ES:[BX+1] ;head ;3.30* mov dl,Rom_MiniDsk_Num ;drive ;3.30* mov ax,7c0h ; ;3.30* mov es,ax ;buffer segment ;3.30* mov bx,BOOTBIAS ;buffer offset ;3.30* mov ax,0201h ;read,1 sector ;3.30* int 13h ;call ROM-Bios routine ;3.30* jc FmpRet ;cannot continue. ;3.30 mov bx, 1c2h+BootBias ;3.30 ;3.30 call SetMini ;install a mini disk. BX value saved. ;3.30 jc FmpnextChain ;3.30 ;3.30 call Install_BDSM ;install the BDSM into the BDS table ;3.30 ; call Show_Installed_Mini ;show the installed message. 3/35/86 - Don't show messages. ;3.30 inc mininum ;increase the logical drive number for next ;3.30 inc num_mini_dsk ;increase the number of mini disk installed. ;3.30 ;3.30 push bx ;now, set the DskDrvs pointer to BPB info. ;3.30 mov bx, Mini_BPB_ptr ;3.30 lea si, [di].BytePerSec ;points to BPB of BDSM ;3.30 mov [bx], si ;3.30 inc Mini_BPB_ptr ;advance to the next address ;3.30 inc Mini_BPB_ptr ;3.30 pop bx ;3.30 ;3.30 add DI, type BDSM_type ;adjust to the next BDSM table entry. ;3.30 mov End_OF_BDSM, DI ;set the ending address of BDSM table to this. ;3.30 ; Message fTestHard,<"Mini disk installed.",cr,lf> ;3.30 FmpnextChain: jmp FmpNext ;let's find out if we have any chained partition ;3.30 FmpRet: ;3.30 ret ;3.30 ;3.30 SetMini: ;3.30 push di ;3.30 push bx ;3.30 push ds ;3.30 jmp SET1 ;will be returned to Find mini partition routine. ;3.30 ;Some logic has been added to SET1 to ;3.30 ;deal with Mini disks. ;3.30 ;3.30 ; ;3.30 ;Install BDSM installs a BDSM (pointed by DS:DI) into the end of the current ;3.30 ;linked list of BDS. ;3.30 ;Also, set the current BDSM pointer segment to DS. ;3.30 ;At entry: DS:DI -> BDSM ;3.30 ; ;3.30 Install_BDSM: ;3.30 ;3.30 push ax ;3.30 push si ;3.30 push es ;3.30 ;3.30 les si, dword ptr cs:Start_BDS ;start of the beginning of list ;3.30 I_BDSM_Next: ;3.30 cmp word ptr es:[si], -1 ;end of the list? ;3.30 jz I_BDSM_New ;3.30 mov si, word ptr es:[si].link ;3.30 mov ax, word ptr es:[si].link+2 ;next pointer ;3.30 mov es, ax ;3.30 jmp short I_BDSM_Next ;3.30 I_BDSM_New: ;3.30 mov ax, ds ;3.30 mov word ptr ds:[di].link+2, ax ;BDSM segment had not been initialized. ;3.30 mov word ptr es:[si].link+2, ax ;3.30 mov word ptr es:[si].link, di ;3.30 mov word ptr ds:[di].link, -1 ;make sure it is a null ptr. ;3.30 ;3.30 I_BDSM_ret: ;3.30 pop es ;3.30 pop si ;3.30 pop ax ;3.30 ret ;3.30 ;3.30 ;***The following code is not needed any more. Don't show any ;3.30 ;***messages to be compatible with the behavior of IO.SYS. ;3.30 ;;Show the message "Mini disk installed ..." ;3.30 ;;This routine uses WRMSG procedure which will call OUTCHR. ;3.30 ;Show_Installed_Mini: ;3.30 ; push ax ;3.30 ; push bx ;3.30 ; push ds ;3.30 ; ;3.30 ; mov al, Mininum ;logical drive number ;3.30 ; add al, Drv_Letter_Base ;='A' ;3.30 ; mov Mini_Drv_Let, al ;3.30 ; mov si, offset Installed_Mini ;3.30 ; call WRMSG ;3.30 ; ;3.30 ; pop ds ;3.30 ; pop bx ;3.30 ; pop ax ;3.30 ; ret ;3.30 ;**End of mini disk initialization** ; 4/7/86 ;3.30 ;3.30 ;3.30 CMOS_Clock_Read proc near ;3.30 ;3.30 ; IN ORDER TO DETERMINE IF THERE IS A CLOCK PRESENT IN THE SYSTEM, THE FOLLOWING ;3.30 ; NEEDS TO BE DONE. ;3.30 PUSH AX ;3.30 PUSH CX ;3.30 PUSH DX ;3.30 PUSH BP ;3.30 ;3.30 XOR BP,BP ;3.30 LOOP_CLOCK: ;3.30 XOR CX,CX ;3.30 XOR DX,DX ;3.30 MOV AH,2 ;READ REAL TIME CLOCK ;3.30 INT 1Ah ;CALL ROM-BIOS ROUTINE ;3.30 CMP CX,0 ;3.30 JNZ CLOCK_PRESENT ;3.30 ;3.30 CMP DX,0 ;3.30 JNZ CLOCK_PRESENT ;3.30 ;3.30 CMP BP,1 ; READ AGAIN AFTER A SLIGHT DELAY, IN CASE CLOCK ;3.30 JZ NO_READDATE ; WAS AT ZERO SETTING. ;3.30 ;3.30 INC BP ; ONLY PERFORM DELAY ONCE. ;3.30 MOV CX,4000H ;3.30 DELAY: ;3.30 LOOP DELAY ;3.30 JMP LOOP_CLOCK ;3.30 ;3.30 CLOCK_PRESENT: ;3.30 mov cs:HaveCMOSClock, 1 ; Set the flag for cmos clock ;3.30 ;3.30 call CMOSCK ; Reset CMOS clock rate that may be ;3.30 ;possibly destroyed by CP DOS and POST routine did not ;3.30 ;restore that. ;3.30 ;3.30 PUSH SI ;3.30 MESSAGE FTESTINIT,<"CLOCK DEVICE",CR,LF> ;3.30 CALL READ_REAL_DATE ;MJB002 READ REAL-TIME CLOCK FOR DATE ;3.30 ;3.30 CLI ;MJB002 ;3.30 MOV DAYCNT,SI ;MJB002 SET SYSTEM DATE ;3.30 STI ;MJB002 ;3.30 POP SI ;MJB002 ;3.30 NO_READDATE: ;3.30 POP BP ;3.30 POP DX ;3.30 POP CX ;3.30 POP AX ;3.30 RET ;3.30 ;3.30 CMOS_Clock_Read endp ;3.30 ; ;3.30 ; 10/28/86 ;3.30 ; THE FOLLOWING CODE IS WRITTEN BY JACK GULLEY IN ENGINEERING GROUP. ;3.30 ; CP DOS IS CHANGING CMOS CLOCK RATE FOR ITS OWN PURPOSES AND IF THE ;3.30 ; USE COLD BOOT THE SYSTEM TO USE PC DOS WHILE RUNNING CP DOS, THE CMOS ;3.30 ; CLOCK RATE ARE STILL SLOW WHICH SLOW DOWN DISK OPERATIONS OF PC DOS ;3.30 ; WHICH USES CMOS CLOCK. PC DOS IS PUT THIS CODE IN MSINIT TO FIX THIS ;3.30 ; PROBLEM AT THE REQUEST OF CP DOS. ;3.30 ; THE PROGRAM IS MODIFIED TO BE RUN ON MSINIT. Equates are defined in CMOSEQU.INC. ;3.30 ; This program will be called by CMOS_Clock_Read procedure. ;3.30 ; ;3.30 ; The following code CMOSCK is used to insure that the CMOS has not ;3.30 ; had its rate controls left in an invalid state on older AT's. ;3.30 ; ;3.30 ; It checks for an AT model byte "FC" with a submodel type of ;3.30 ; 00, 01, 02, 03 or 06 and resets the periodic interrupt rate ;3.30 ; bits incase POST has not done it. This initilization routine ;3.30 ; is only needed once when DOS loads. It should be ran as soon ;3.30 ; as possible to prevent slow diskette access. ;3.30 ; ;3.30 ; This code exposes one to DOS clearing CMOS setup done by a ;3.30 ; resident program that hides and re-boots the system. ;3.30 ; ;3.30 CMOSCK PROC NEAR ; CHECK AND RESET RTC RATE BITS ;3.30 ;3.30 ;Model byte and Submodel byte were already determined in MSINIT. ;3.30 push ax ;3.30 cmp cs:Model_byte, 0FCh ;check for PC-AT model byte ;3.30 ; EXIT IF NOT "FC" FOR A PC-AT ;3.30 JNE CMOSCK9 ; Exit if not an AT model ;3.30 ;3.30 CMP cs:Secondary_Model_Byte,06H ; Is it 06 for the industral AT ;3.30 JE CMOSCK4 ; Go reset CMOS periodic rate if 06 ;3.30 CMP cs:Secondary_Model_Byte,04H ; Is it 00, 01, 02, or 03 ;3.30 JNB CMOSCK9 ; EXIT if problem fixed by POST ;3.30 ; Also,Secondary_model_byte = 0 when AH=0c0h, int 15h failed. ;3.30 CMOSCK4: ; RESET THE CMOS PERIODIC RATE ;3.30 ; Model=FC submodel=00,01,02,03 or 06 ;3.30 mov al,CMOS_REG_A or NMI ;NMI disabled on return mov ah,00100110b ;Set divider & rate selection call CMOS_WRITE 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 CMOSCK9: ; EXIT ROUTINE ;3.30 pop ax ;3.30 RET ; RETurn to caller ;3.30 ; Flags modifyied ;3.30 CMOSCK ENDP ;3.30 PAGE ;3.30 ;--- CMOS_READ ----------------------------------------------------------------- ;3.30 ; READ BYTE FROM CMOS SYSTEM CLOCK CONFIGURATION TABLE : ;3.30 ; : ;3.30 ; INPUT: (AL)= CMOS TABLE ADDRESS TO BE READ : ;3.30 ; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : ;3.30 ; BITS 6-0 = ADDRESS OF TABLE LOCATION TO READ : ;3.30 ; : ;3.30 ; OUTPUT: (AL) VALUE AT LOCATION (AL) MOVED INTO (AL). IF BIT 7 OF (AL) WAS : ;3.30 ; ON THEN NMI LEFT DISABLED. DURING THE CMOS READ BOTH NMI AND : ;3.30 ; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : ;3.30 ; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : ;3.30 ; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : ;3.30 ; ONLY THE (AL) REGISTER AND THE NMI STATE IS CHANGED. : ;3.30 ;------------------------------------------------------------------------------- ;3.30 ;3.30 CMOS_READ PROC NEAR ; READ LOCATION (AL) INTO (AL) ;3.30 PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS ;3.30 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 PUSH CS ; *PLACE CODE SEGMENT IN STACK AND ;3.30 CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 ;3.30 RET ; RETURN WITH FLAGS RESTORED ;3.30 ;3.30 CMOS_READ ENDP ;3.30 ;3.30 CMOS_POPF PROC NEAR ; POPF FOR LEVEL B- PARTS ;3.30 IRET ; RETURN FAR AND RESTORE FLAGS ;3.30 ;3.30 CMOS_POPF ENDP ;3.30 ;3.30 ;--- CMOS_WRITE ---------------------------------------------------------------- ;3.30 ; WRITE BYTE TO CMOS SYSTEM CLOCK CONFIGURATION TABLE : ;3.30 ; : ;3.30 ; INPUT: (AL)= CMOS TABLE ADDRESS TO BE WRITTEN TO : ;3.30 ; BIT 7 = 0 FOR NMI ENABLED AND 1 FOR NMI DISABLED ON EXIT : ;3.30 ; BITS 6-0 = ADDRESS OF TABLE LOCATION TO WRITE : ;3.30 ; (AH)= NEW VALUE TO BE PLACED IN THE ADDRESSED TABLE LOCATION : ;3.30 ; : ;3.30 ; OUTPUT: VALUE IN (AH) PLACED IN LOCATION (AL) WITH NMI LEFT DISABLED : ;3.30 ; IF BIT 7 OF (AL) IS ON. DURING THE CMOS UPDATE BOTH NMI AND : ;3.30 ; NORMAL INTERRUPTS ARE DISABLED TO PROTECT CMOS DATA INTEGRITY. : ;3.30 ; THE CMOS ADDRESS REGISTER IS POINTED TO A DEFAULT VALUE AND : ;3.30 ; THE INTERRUPT FLAG RESTORED TO THE ENTRY STATE ON RETURN. : ;3.30 ; ONLY THE CMOS LOCATION AND THE NMI STATE IS CHANGED. : ;3.30 ;------------------------------------------------------------------------------- ;3.30 ;3.30 CMOS_WRITE PROC NEAR ; WRITE (AH) TO LOCATION (AL) ;3.30 PUSHF ; SAVE INTERRUPT ENABLE STATUS AND FLAGS ;3.30 PUSH AX ; SAVE WORK REGISTER VALUES ;3.30 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 POP AX ; RESTORE WORK REGISTERS ;3.30 PUSH CS ; *PLACE CODE SEGMENT IN STACK AND ;3.30 CALL CMOS_POPF ; *HANDLE POPF FOR B- LEVEL 80286 ;3.30 RET ;3.30 ;3.30 CMOS_WRITE ENDP ;3.30 ; ;3.30 END$: code ends end