; File : $Workfile$ ; ; Description : ; ; Original Author : DIGITAL RESEARCH ; ; Last Edited By : $CALDERA$ ; ;-----------------------------------------------------------------------; ; Copyright Work of Caldera, Inc. All Rights Reserved. ; ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND ; CIVIL LIABILITY. ;-----------------------------------------------------------------------; ; ; *** Current Edit History *** ; *** End of Current Edit History *** ; ; $Log$ ; INIT.ASM 1.25 93/12/07 15:51:27 ; Move int13pointer to offset 0B4h as some app expects it there ; INIT.ASM 1.24 93/11/18 18:57:20 ; Increase amount reserved for COMMAND.COM by 256 bytes ; INIT.ASM 1.23 93/11/17 19:29:26 ; Change default DEBLOCK seg to FFFF for performance reasons ; INIT.ASM 1.19 93/07/22 19:43:59 ; switch over to REQUEST.EQU ; ENDLOG include BIOSGRPS.EQU include DRMACROS.EQU include IBMROS.EQU include MSDOS.EQU include REQUEST.EQU ; request header equates include BPB.EQU include UDSC.EQU include DRIVER.EQU ; IBM AT Hardware equates COMPRESSED equ TRUE ; enables compressed changes. ; a little macro to help locate things ; it warns us when the ORG get trampled on orgabs MACRO address local was,is was = offset $ org address is = offset $ if was GT is if2 %OUT ERROR - absolute data overwritten !! moving it endif org was endif ENDM jmpfar MACRO address, fixup db 0EAh ; jmpf opcode dw CG:address ; offset of destination fixup dw 0EDCh ; segment of destination ENDM callfar MACRO address, fixup db 09Ah ; callf opcode dw CG:address ; offset of destination fixup dw 0EDCh ; segment of destination ENDM F5KEY equ 3F00h F8KEY equ 4200h IVECT segment at 0000h org 0000h*4 i0off dw ? i0seg dw ? org 0001h*4 i1off dw ? i1seg dw ? org 0003h*4 i3off dw ? i3seg dw ? org 0004h*4 i4off dw ? i4seg dw ? org 0015h*4 i15off dw ? i15seg dw ? org 0019h*4 i19off dw ? i19seg dw ? org 001Eh*4 i1Eptr label dword i1Eoff dw ? i1Eseg dw ? org 002Fh*4 i2Fptr label dword i2Foff dw ? i2Fseg dw ? org 006Ch*4 i6Cptr label dword i6Coff dw ? i6Cseg dw ? IVECT ends CGROUP group CODE, RCODE, ICODE CG equ offset CGROUP CODE segment 'CODE' Assume CS:CGROUP, DS:Nothing, ES:Nothing, SS:Nothing public strat extrn ConsoleTable:word extrn ClockTable:word extrn SerParCommonTable:word extrn DiskTable:near extrn Int13Deblock:near extrn Int13Unsure:near extrn Int2FHandler:near extrn ResumeHandler:near extrn biosinit_end:byte ; End of the BIOS Init Code and Data extrn biosinit:near extrn boot_options:word extrn rcode_fixups:word extrn rcode_seg:word extrn rcode_offset:word extrn rcode_len:word extrn icode_len:word extrn current_dos:word extrn device_root:dword extrn mem_size:word extrn ext_mem_size:word extrn init_buf:byte extrn init_drv:byte extrn init_runit:byte extrn comspec_drv:byte extrn init_flags:word include biosmsgs.def ; Include TFT Header File Public A20Enable A20Enable proc near ;======== ; This location is fixed up at run time to be a RET ; If the BIOS is relocated to the HMA then it is fixed up again to be ; CALLF IBMDOS:A20Enable; RET ; Calling this location at run time will ensure that the HMA is mapped ; in so we can access the HMA code. ; A20Enable endp init proc near ; this is at BIOSCODE:0000h ifndef COPYPROT jmp init0 ; jump to reusable init space else extrn protect:near ; Jump to Copy protection code jmp protect ; which will return control to endif ; INIT0 on completion init endp compflg label word ifdef COPYPROT dw ' ' ; stops any compression working else dw offset CGROUP:INITDATA ; compresses from INITDATA onwards endif ; this word set to 0 when compressed orgabs 06h db 'COMPAQCompatible' dw offset CGROUP:RCODE ; lets find offset of RCODE MemFixup dw 0 ; and its relocated segment Public cleanup cleanup PROC far ; BIOSINIT will call here later ret cleanup endp ; Local single character buffer for Ctrl-Break handling public serparFlag, serparChar serparFlag db 4 dup (FALSE) ; we haven't got any yet serparChar db 4 dup (?) ; will store one character ; Device driver headers for serial/parallel devices con_drvr dw CG:aux_drvr, 0 ; link to next device driver dw DA_CHARDEV+DA_SPECIAL+DA_ISCOT+DA_ISCIN+DA_IOCTL dw CG:strat, CG:IntCon db 'CON ' aux_drvr dw CG:prn_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntCOM1 db 'AUX ' prn_drvr dw CG:clock_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntLPT1 db 'PRN ' clock_drvr dw disk_drvr, 0 ; link to next device driver dw DA_CHARDEV+DA_ISCLK dw CG:strat, CG:IntClock db 'CLOCK$ ' com1_drvr dw CG:lpt1_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntCOM1 db 'COM1 ' com2_drvr dw CG:com3_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntCOM2 db 'COM2 ' com3_drvr dw CG:com4_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntCOM3 db 'COM3 ' IFDEF EMBEDDED extrn rdisk_drvr:near com4_drvr dw CG:rdisk_drvr, 0 ; link to next device driver ELSE com4_drvr dw -1, -1 ; link to next device driver ENDIF dw DA_CHARDEV dw CG:strat, CG:IntCOM4 db 'COM4 ' orgabs 0b4h ; save address at fixed location ; for dirty apps Public i13pointer, i13off_save, i13seg_save i13pointer label dword ; address of ROS Int 13h entry i13off_save dw ? i13seg_save dw ? orgabs 0b8h ; REQ_HDR public req_ptr, req_off, req_seg req_ptr label dword req_off dw 0 ;** fixed location ** req_seg dw 0 ;** fixed location ** strat proc far mov cs:req_off,bx mov cs:req_seg,es ret strat endp lpt1_drvr dw CG:lpt2_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntLPT1 db 'LPT1 ' lpt2_drvr dw CG:lpt3_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntLPT2 db 'LPT2 ' lpt3_drvr dw CG:com2_drvr, 0 ; link to next device driver dw DA_CHARDEV dw CG:strat, CG:IntLPT3 db 'LPT3 ' orgabs 100h ; save vectors at fixed location ; for dirty apps Public orgInt13 NUM_SAVED_VECS equ 5 vecSave db 10h dw 0,0 db 13h orgInt13 dw 0,0 db 15h dw 0,0 db 19h dw 0,0 db 1Bh dw 0,0 Int19Trap: cld cli ; be sure... push cs pop ds lea si,vecSave mov cx,NUM_SAVED_VECS ; restore this many vectors Int19Trap10: xor ax,ax ; zero AH for lodsb mov es,ax ; ES -> interrupt vectors lodsb ; AX = vector to restore shl ax,1 shl ax,1 ; point at address xchg ax,di ; ES:DI -> location to restore movsw movsw ; restore this vector loop Int19Trap10 ; go and do another int 19h ; and go to original int 19... orgabs 16ch ; PRN:/AUX: the device number devno db 0,0 ;** fixed location ** Public NumDiskUnits, DeblockSeg disk_drvr dw CG:com1_drvr, 0 ; link to next driver dw DA_NONIBM+DA_GETSET+DA_REMOVE+DA_BIGDRV dw CG:strat, CG:IntDisk NumDiskUnits db 5, 7 dup (?) dw 0EDCh ; checked by DRIVER.SYS dw 0 ; was allocate UDSC DeblockSeg dw 0A000h ; segment we start deblocking IntLPT1: ; LPT1 call DeviceDriver dw 0 IntLPT2: ; LPT2 call DeviceDriver dw 1 IntLPT3: ; LPT3 call DeviceDriver dw 2 IntCOM1: ; AUX = COM1 call DeviceDriver dw 3 IntCOM2: ; COM2 call DeviceDriver dw 4 IntCOM3: ; COM3 call DeviceDriver dw 5 IntCOM4: ; COM4 call DeviceDriver dw 6 IntCon: call DeviceDriver dw offset CGROUP:ConsoleTable IntClock: call DeviceDriver dw offset CGROUP:ClockTable Public IntDiskTable IntDisk: call DeviceDriver IntDiskTable: dw offset CGROUP:DiskTable DeviceDriver proc near call A20Enable ; make sure A20 is on jmpfar DriverFunction, DriverFunctionFixup DeviceDriver endp extrn i13_AX:word Public Int13Trap Int13Trap proc far ;-------- ; The Int 13 code is in low memory for speed, with unusual conditions ; having the overhead of A20Enable calls ; cmp ah,ROS_FORMAT ; ROS format function? je Int13TrapFormat Int13Trap10: mov cs:i13_AX,ax ; save Op/Count in case of error clc pushf ; fake an Int call cs:i13pointer ; call the ROM BIOS jc Int13Trap20 ; check for error ret 2 ; none, so return to caller Int13Trap20: cmp ah,9 ; it it a DMA error ? je Int13TrapDMA ; then deblock it call Int13TrapUnsure ; else declare floppy drive unsure stc ; restore error flag ret 2 ; return to user Int13TrapFormat: call Int13TrapUnsure ; mark media as unsure jmps Int13Trap10 ; and resume Int13TrapDMA: call A20Enable ; make sure A20 is on jmpfar Int13Deblock, Int13DeblockFixup Int13TrapUnsure proc near call A20Enable ; make sure A20 is on callfar Int13Unsure, Int13UnsureFixup ret Int13TrapUnsure endp Int13Trap endp Public Int2FTrap Int2FTrap proc far ;-------- jmpfar Int2FHandler, Int2FFixup Int2FTrap endp Resume proc far ;----- call A20Enable ; make sure A20 is on jmpfar ResumeHandler, ResumeFixup Resume endp Int0Trap proc far ;------- call A20Enable ; make sure A20 is on jmpfar Int0Handler, Int0Fixup Int0Trap endp Public FastConsole FastConsole proc far ;---------- ; RAM entry to ensure INT29 vector is below INT20 vector ; We keep the normal path low to maxmimise performance, but on backspace we ; take the A20Enable hit and call high for greater TPA. ; pushx ; old ROS corrupts these cmp al,8 ; back space character je Fastcon30 ; special case Fastcon10: mov ah,0Eh ; use ROS TTY-like output function mov bx,7 ; use the normal attribute int VIDEO_INT ; output the character in AL Fastcon20: popx iret Fastcon30: call A20Enable ; make sure A20 is on jmpfar OutputBS, OutputBSFixup ; call up to the HMA FastConsole endp Public ControlBreak ControlBreak proc far ;----------- mov cs:word ptr local_char,'C'-40h + (256*TRUE) ;; mov local_char,'C'-40h ; force ^C into local buffer ;; mov local_flag,TRUE ; indicate buffer not empty Int1Trap: Int3Trap: Int4Trap: iret ControlBreak endp public daycount daycount dw 0 ; More Disk Data public local_buffer,local_id,local_pt local_buffer db 512 dup (?) ; local deblocking buffer SECSIZE equ 512 IDOFF equ SECSIZE-2 ; last word in boot sector is ID PTOFF equ IDOFF-40h ; 4*16 bytes for partition def's local_id equ word ptr local_buffer + IDOFF local_pt equ word ptr local_buffer + PTOFF public bpbs,bpb160,bpb360,bpb720,NBPBS ; List of BPBs that we usually support bpb160 BPB <512,1,1,2, 64, 40*1*8,0FEh,1, 8,1,0,0> bpb180 BPB <512,1,1,2, 64, 40*1*9,0FCh,2, 9,1,0,0> bpb320 BPB <512,2,1,2,112, 40*2*8,0FFh,1, 8,2,0,0> bpb360 BPB <512,2,1,2,112, 40*2*9,0FDh,2, 9,2,0,0> bpb1200 BPB <512,1,1,2,224,80*2*15,0F9h,7,15,2,0,0> bpb720 BPB <512,2,1,2,112, 80*2*9,0F9h,3, 9,2,0,0> bpb1440 BPB <512,1,1,2,224,80*2*18,0F0h,9,18,2,0,0> bpb2880 BPB <512,2,1,2,240,80*2*36,0F0h,9,36,2,0,0> NBPBS equ 8 ; The following is a template, that gets overwritten ; with the real parameters and is used while formatting public local_parms,parms_spt,parms_gpl public layout_table,bpbtbl local_parms db 11011111b ; step rate db 2 ; DMA mode db 37 ; 2*18.2 = 2 second motor off db 2 ; 512 bytes per sector parms_spt db 18 ; sectors per track db 2Ah ; gap length for read/write db 0FFh ; data length (128 byte/sector only) parms_gpl db 50h ; data length for format db 0F6h ; fill byte for format db 15 ; head settle time in ms db 8 ; motor on delay in 1/8s ; The BPB table need not survive config time, so share with layout table bpbtbl label word MAX_SPT equ 40 layout_table label word ; current # of sectors/track S = 1 rept MAX_SPT ; C H S N ; - - - - db 0, 0, S, 2 S = S + 1 endm orgabs 600h ; CON: one character look-ahead buffer ; nb. it's at 61B in DOS 4.0 Public local_char, local_flag local_char db 0 ;** fixed location ** local_flag db 0 ;** fixed location ** public endbios endbios dw offset CGROUP:RESBIOS ; pointer to last resident byte CODE ends ICODE segment 'ICODE' ; reusable initialization code Assume CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:Nothing bpbs dw CG:bpb360 ; 0: 320/360 Kb 5.25" floppy dw CG:bpb1200 ; 1: 1.2 Mb 5.25" floppy dw CG:bpb720 ; 2: 720 Kb 3.5" floppy dw CG:bpb360 ; 3: (8" single density) dw CG:bpb360 ; 4: (8" double density) dw CG:bpb360 ; 5: hard disk dw CG:bpb360 ; 6: tape drive dw CG:bpb1440 ; 7: 1.44 Mb 3.5" floppy dw CG:bpb1440 ; 8: Other dw CG:bpb2880 ; 9: 2.88 Mb 3.5" floppy Public init0 init0 proc near ; ; We now uncompress to > (7C00h (ie. boot stack) - 700h (ie. base of code) ; This means our stack collides with our code, very bad news. ; To avoid this we switch stacks into a safer area ie. 0C000h ; The floppy parameters also live at 7C00, so we have to relocate these ; before we expand. mov cs:byte ptr A20Enable,0C3h ; fixup the RET mov sp, 0C000h ; switch to magic stack sti cld push cx ; save entry registers push di ; (important in ROM systems) xor si,si mov ds,si mov es,si Assume DS:IVECT, ES:IVECT mov di,522h ; ES:DI -> save area for parameters lds si,i1Eptr ; DS:SI -> FD parameters for ROS Assume DS:Nothing mov i1Eoff,di mov i1Eseg,es ; setup new location mov cx,11 rep movsb mov es:byte ptr 0-7[di],36 ; enable read/writing of 36 sectors/track pop di pop cx if COMPRESSED mov si, cs ; preserve entry registers mov ds, si ; other than si, ds and es mov es, si xor si, si mov si, compflg ; Get Compresed BIOS Flag or si, si ; Set to Zero if the BIOS has jnz not_compressed ; been compressed mov si, CG:INITDATA push di ; bios_seg push ax ; bdos_seg push bx ; initial drives push cx ; memory size push dx ; initial flags lea cx, biosinit_end sub cx, si inc cx ; length of compressed part plus one mov di, cx neg di ; furthest offset we can use and di, 0fff0h ; on the next para below push di push si shr cx, 1 rep movsw ; take a copy pop di ; di is now -> compressed dest pop si ; this is now -> compressed source bios_r20: lodsw ; get control word mov cx,ax ; as a count jcxz bios_r40 ; all done test cx,8000h ; negative ? jnz bios_r30 ; yes do zeros rep movsb ; else move in data bytes jmp short bios_r20 ; and to the next bios_r30: and cx,7fffh ; remove sign jcxz bios_r20 ; none to do xor ax,ax rep stosb ; fill with zeros jmp short bios_r20 bios_r40: pop dx pop cx pop bx pop ax pop di not_compressed: endif mov si,cs mov ds,si ; DS -> local data segment cmp dl,0ffh ; booting from ROM? jz rom_boot cmp si,1000h ; test if debugging jb disk_boot ; skip if not ; When the BIOS is loaded by the DOSLOAD or LOADER utilities under ; Concurrent for DEBUGGING or in a ROM system then on entry AX ; contains the current location of the BDOS and CX the memory Size. ; Bx is the current code segment mov rcode_seg,dx ; rom segment of bios mov current_dos,ax ; current location of the BDOS mov mem_size,cx ; total memory size mov init_drv,bl ; initial drive mov comspec_drv,bh ; mov init_buf,3 ; assume default # of buffers mov init_flags,3 jmp bios_exit rom_boot: ; BIOS is copied from ROM: ; DL = 0FFh ; AX = segment address of DRBDOS ; BH = COMSPEC drive ; BL = INIT_DRV mov rcode_seg,di ; DI = BIOS ROM SEG mov current_dos,ax ; current location of the BDOS mov init_drv,bl ; initial drive C: mov comspec_drv,bh ; commspec drive C: mov init_flags,3 ; it is a ROM system, use comspec drive jmps rom_boot10 ; common code disk_boot: mov rcode_seg,cs sub ax,ax mov current_dos,ax ; current BDOS location to disk load xchg ax,dx ; AL = boot drive mov init_runit,al ; save the ROS unit test al,al ; test the boot drive jz floppy_boot ; skip if floppy boot mov al,2 ; it's drive C: floppy_boot: mov init_drv,al ; set boot drive rom_boot10: pushx ; save registers sub bx,bx mov ds,bx ; DS:BX -> interrupt vectors Assume DS:IVECT push cs ; we want to save vectors some pop es ; locally lea di,vecSave mov cx,NUM_SAVED_VECS ; restore this many vectors SaveVectors: xor ax,ax ; zero AH mov al,es:[di] ; AX = vector to save inc di ; skip to save position shl ax,1 shl ax,1 ; point at address xchg ax,si ; DS:SI -> location to save movsw movsw ; save this vector loop SaveVectors ; go and do another mov i0off,CG:Int0Trap mov i0seg,cs ; now grab int0 vector mov i1off,CG:Int1Trap mov i1seg,cs ; now grab int1 vector mov i3off,CG:Int1Trap mov i3seg,cs ; now grab int3 vector mov i4off,CG:Int1Trap mov i4seg,cs ; now grab int4 vector mov i19off,CG:Int19Trap mov i19seg,cs ; now grab int19 vector popx Assume DS:CGROUP, ES:CGROUP call get_boot_options ; look for user keypress mov boot_options,ax ; return any options mov ah,EXT_MEMORY int SYSTEM_INT ; find out how much extended memory jnc bios_extmem xor ax,ax ; say we have no memory bios_extmem: mov ext_mem_size,ax ; we have and store for reference mov init_buf,3 ; assume default of 3 buffers int MEMORY_INT ; get amount of conventional memory cmp ax,128 jbe bios_mem mov init_buf,5 ; use 5 buffers if > 128K of memory bios_mem: ; get amount of conventional memory mov cl,6 ; in kilobytes (AX) shl ax,cl ; convert Kb's to paragraphs mov mem_size,ax ; set end of TPA bios_exit: ; The following code performs the fixups necessary for ROM executable ; internal device drivers. mov ax,cs ; check if we are on a rommed system cmp ax,rcode_seg jne keep_rcode ; if so no relocation required mov ax,CG:RCODE mov rcode_offset,ax ; fixup variable need mov bx,CG:IDATA sub bx,ax mov icode_len,bx ; during init we need RCODE and ICODE mov bx,CG:RESUMECODE sub bx,ax mov rcode_header,bx mov rcode_len,bx ; afterwards we just need RCODE keep_rcode: ; If the system ROM BIOS supports RESUME mode then it will call Int 6C ; when returning from sleep mode. We take this over and reset the clock ; based upon the RTC value. To save space we only relocate the code if ; required. ; mov ax,4100h ; does the BIOS support resume mode xor bx,bx int 15h ; lets ask it jc resume_exit push ds xor ax,ax mov ds,ax ; DS = vectors Assume DS:IVECT mov i6Coff,CG:Resume mov i6Cseg,cs ; point Int 6C at resume code Assume DS:CGROUP pop ds mov ax,cs ; check if we are on a rommed system cmp ax,rcode_seg jne resume_exit ; if so nothing extra to keep mov ax,CG:RESBIOS sub ax,CG:RCODE mov rcode_header,ax ; keep Resume code as well... mov rcode_len,ax ; afterwards we just need RCODE resume_exit: mov ax,CG:ENDCODE ; discard RCODE (we will relocate it) mov endbios,ax mov rcode_fixups,CG:bios_fixup_tbl mov bx,CG:con_drvr ; get first device driver in chain mov word ptr device_root+0,bx mov word ptr device_root+2,ds init1: cmp word ptr [bx],0FFFFh ; last driver in BIOS? je init3 mov 2[bx],ds ; fix up segments in driver chain mov bx,[bx] jmps init1 init3: jmp biosinit ; jump to BIOS code init0 endp get_boot_options: ;---------------- ; On Entry: ; None ; On Exit: ; AX = boot options mov si,offset CGROUP:starting_dos_msg lodsb ; get 1st character (never NULL) get_boot_options10: mov ah,0Eh mov bx,7 int VIDEO_INT ; TTY write of character lodsb ; fetch another character test al,al ; end of string ? jnz get_boot_options10 call option_key ; poll keyboard for a while jnz get_boot_options20 ; if key available return that mov ah,2 ; else ask ROS for shift state int 16h and ax,3 ; a SHIFT key is the same as F5KEY jz get_boot_options20 mov ax,F5KEY ; ie. bypass everything get_boot_options20: ret option_key: ;---------- ; On Entry: ; None ; On Exit: ; AX = keypress if interesting (F5/F8) ; ZF clear if we have an interesting key ; ; Poll keyboard looking for a key press. We do so for a maximum of 36 ticks ; (approx 2 seconds). ; xor ax,ax int 1Ah ; get ticks in DX mov cx,dx ; save in CX for later option_key10: push cx mov ah,1 int 16h ; check keyboard for key pop cx jnz option_key30 ; stop if key available push cx xor ax,ax int 1Ah ; get ticks in DX pop cx sub dx,cx ; work out elapsed time cmp dx,36 ; more than 2 secs ? jb option_key10 option_key20: xor ax,ax ; timeout, set ZF, no key pressed ret option_key30: cmp ax,F5KEY ; if it is a key we want then je option_key40 ; read it, else just leave cmp ax,F8KEY ; in the type-ahead buffer jne option_key20 option_key40: xor ax,ax int 16h ; read the key test ax,ax ; clear ZF to indicate we have a key ret ICODE ends INITDATA segment 'INITDATA' ; This is a zero terminated list of locations to be fixed up with the ; segment of the relocated BIOS RCODE bios_fixup_tbl dw CG:MemFixup dw CG:OutputBSFixup dw CG:DriverFunctionFixup dw CG:Int0Fixup dw CG:Int13DeblockFixup dw CG:Int13UnsureFixup dw CG:Int2FFixup dw CG:ResumeFixup IFDEF EMBEDDED dw CG:RdiskFixup endif dw 0 INITDATA ends CODE segment 'CODE' IFDEF EMBEDDED extrn RdiskFixup:word endif CODE ends RCODE_ALIGN segment public para 'RCODE' ifndef ROMSYS db 1100h dup(0) ; reserve space for command.com endif RCODE_ALIGN ends RCODE segment public word 'RCODE' rcode_header dw 0 Public DataSegment DataSegment dw 0070h ; segment address of low data/code ; Called to vector to appropriate sub-function in device driver ; The Function table address immediately follows the near call, so we can index ; into it using the return address. If the offset is in the range 0-6 it's ; actually a device number for the serial/parallel driver ; ; ; On Entry to subfunctions ES:BX -> req_hdr, DX = devno (serial/parallel) ; FunctionTable struc FunctionTableMax db ? FunctionTableEntry dw ? FunctionTable ends Public DriverFunction DriverFunction proc far cld sub sp,(size P_STRUC)-4 ; make space for stack variables push bp ; (BP and RET are included) mov bp,sp ; set up stack frame pushx pushx ; save all registers mov ds,cs:DataSegment mov si,(size P_STRUC)-2[bp] ; get return address = command table lodsw ; AX = following word xchg ax,dx ; DX = device number (0-6) mov si,offset CGROUP:SerParCommonTable cmp dx,6 ; if not a device number it's a table jbe DriverFunction10 mov si,dx ; DS:SI -> table DriverFunction10: les bx,req_ptr ; ES:BX -> request header mov REQUEST_OFF[bp],bx mov REQUEST_SEG[bp],es mov al,es:RH_CMD[bx] ; check if legal command cmp al,cs:FunctionTableMax[si] ja cmderr ; skip if out of range cbw ; convert to word add ax,ax ; make it a word offset add si,ax ; add index to function table call cs:FunctionTableEntry[si] les bx,REQUEST[bp] cmddone: or ax,RHS_DONE ; indicate request is "done" mov es:RH_STATUS[bx],ax ; update the status for BDOS popx ; restore all registers popx pop bp add sp,(size P_STRUC)-2 ; discard stack variables ret cmderr: mov ax,RHS_ERROR+3 ; "invalid command" error jmps cmddone ; return the error DriverFunction endp OutputBS proc far ;------- ; pushx ; these are on the stack pushx mov ah,3 ; get cursor address mov bh,0 ; on page zero int VIDEO_INT ; BH = page, DH/DL = cursor row/col test dx,dx ; row 0, col 0 jz OutputBS10 ; ignore if first line dec dl ; are we in column 0? jns OutputBS10 ; no, normal BS dec dh ; else move up one line push ds xor ax,ax mov ds,ax mov dl,ds:byte ptr [44ah] ; DL = # of columns dec dx ; DL = last column pop ds mov ah,2 ; set cursor, DH/DL = cursor, BH = page int VIDEO_INT ; set cursor address jmps OutputBS20 OutputBS10: mov ax,0E08h ; use ROS TTY-like output function mov bx,7 ; use the normal attribute int VIDEO_INT ; output the character in AL OutputBS20: popx popx iret OutputBS endp Int0Handler proc far ;---------- cld push cs pop ds mov si,CG:div_by_zero_msg ; DS:SI points at ASCIZ message mov bx,STDERR ; to STDERR - where else ? mov cx,1 ; write one at a time int0_loop: mov dx,si ; DS:DX points at a char lodsb ; lets look at it first test al,al ; end of string ? je int0_exit mov ah,MS_X_WRITE ; write out the error int DOS_INT jnc int0_loop ; if it went OK do another int0_exit: mov ax,MS_X_EXIT*256+1 ; time to leave - say we got an error int DOS_INT ; go for it! Int0Handler endp RCODE ends end init