$title(Bootstrap First Stage) $genonly ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; TITLE: bs1.inc ; Bootstrap first stage code and configuration macros ; ; DATE: 25 Sept 1985 ; ; ABSTRACT: Include file to generate bootstrap first stage. ; Generates code for setup and to call options, ; and generates device table. ; ; Set tabs = 8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; stacksize equ 256 extrn bserror: far ; bootstrap error routine NULL EQU 0 code segment public 'CODE' code ends boot segment public 'BOOT' second_stage label far boot ends stack segment stack 'STACK' db stacksize dup (?) stack ends data segment public 'DATA' dummy_file_name label byte second_stage_ptr label dword second_stage_o dw ? second_stage_s dw ? public inhibit_co inhibit_co db ? data ends assume cs:code, ss:stack, ds:data code segment ; %SET(is_cico, 0) %*DEFINE(cico) ( %SET(is_cico, -1) ) %SET(sdm_base,0F000H) %DEFINE(cpu_type) (8086) %DEFINE(delay) (0F00H) %*DEFINE(cpu(ctype)) ( %DEFINE(cpu_type) (%ctype) %IF (%EQS(%cpu_type,8086)) THEN (%DEFINE(delay) (0800H)) ELSE (%IF (%EQS(%cpu_type,8088)) THEN (%DEFINE(delay) (0600H)) ELSE (%IF (%EQS(%cpu_type,80186)) THEN (%DEFINE(delay) (0D00H)) ELSE (%IF (%EQS(%cpu_type,80188)) THEN (%DEFINE(delay) (0600H)) ELSE (%IF (%EQS(%cpu_type,80286)) THEN (%DEFINE(delay) (0F00H)) ELSE (%IF (%EQS(%cpu_type,80386)) THEN (%DEFINE(delay) (3C00H)) ELSE (%IF (%EQS(%cpu_type,80486)) THEN (%DEFINE(delay) (3F00H)) FI) FI )FI )FI )FI )FI )FI ) %SET(clear_ext, 0) ;set to false %*DEFINE(clear_sdm_extensions) ( %SET(clear_ext, -1) %'set to true' ) %' TRIM and ARG are utility macros %' %' TRIM(a) - returns the input parameter trimmed of leading and %' trailing blanks. %*DEFINE(TRIM(a)) LOCAL x y (%MATCH( x y)(%a)%x)%' %' %' ARG - gets the next comma-delimited arg from variable named TAIL, %' stripped and trimmed. Any macro that has a valid type of NONE %' uses this macro so that the other parameters are not needed. %*DEFINE(ARG) LOCAL a (%MATCH(a,tail)(%tail)%TRIM(%a))%' %' %' %DEFINE(extrn_list) () %' %*DEFINE(external(target,extrn_type)) LOCAL a b (%' %MATCH(a,b)(%extrn_list)%' %' %SET(result,-1)%' %WHILE(%LEN(%a) NE 0) (%' %' '%IF(%EQS(%target,%a)) THEN(%' %' '%SET(result,0)%' %' ')FI %' %' %' '%MATCH(a,b)(%b)%' )%' %' %IF(%result) THEN(%' %' '%DEFINE(extrn_list) (%target,%extrn_list) %' %' '%IF(%EQS(%extrn_type,far)) THEN(%' code ends extrn %target : %extrn_type code segment %' ') ELSE(%' extrn %target : %extrn_type %' ')FI %' )FI %' %' ) %' %' TITLE: system_120_init %' INPUTS: None %' OUTPUTS: System 120 initialization code. %' ABSTRACT: This macro sets up the initialization code for the System 120. %' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* %*DEFINE(system_120_INIT)(%' %SET(sdm_base, 0E000H) SDM_OFFSET equ 0FFF0H INIT_POLLTIMES equ 0FFFFH ENTER_SDM_FLAG equ 00H ENTER_FIRSTSTAGE_FLAG equ 01H RET_TO_BIOS_FLAG equ 02H %' code ends system_120_seg segment AT 0E000H dw 0AA55H db 0FFH ; at 0e000:0003 - entrypoint for 120 initialization code from ROM BIOS jmp far ptr boot_init_120 ; at 0e000:0008 - entrypoint for boot command from SDM jmp far ptr bootstrap_entry system_120_seg ends code segment public boot_init_120 boot_init_120 proc far ;int 3 pushf cli push ax ; save regs in case we must return to push bx ; ROM BIOS push cx push dx push si push di push bp push ds push es mov ax,data mov ds,ax ;set up BSL data segment mov polltimes, INIT_POLLTIMES sub sp, 4 %external(auto_device_select,near) call auto_device_select ; call auto procedure add sp, 4 or ax, ax ; device found? jz ret_to_BIOS cmp dl, RET_TO_BIOS_FLAG je ret_to_BIOS cmp dl, ENTER_SDM_FLAG jne enter_firststage mov ax, %sdm_base push ax mov ax, SDM_OFFSET push ax ;jmp firststage ret ret_to_BIOS: pop es ;restore all saved registers pop ds pop bp pop di pop si pop dx pop cx pop bx pop ax popf ret enter_firststage: lea bx, dummy_file_name mov byte ptr [bx], CR mov ax, bx mov dl, 0FFH ; load inhibit_co flag jmp s120_begin boot_init_120 endp )%' %' %' %' TITLE: iAPX_186_init %' INPUTS: RELO - a boolean for whether to put the 186 PIC into RMX mode %' and the register values for UMCS,LMCS,MPCS,MMCS,and PACS %' OUTPUTS: public variables for the chip select registers %' ABSTRACT: This macro sets up the public variables for programming %' the 5 iAPX_186 chip select registers. Assumes Relo Reg will %' not be moved. %' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* %*DEFINE(iAPX_186_INIT(parameters))(%DEFINE(tail)(%parameters)%' %' %IF ((%NES(%cpu_type,80186)) AND (%NES(%cpu_type,80188))) THEN (%' ERROR -- CPU type is not 80186 or 80188 ) ELSE (%' ; ; This procedure sets up the chip select registers for ; the 80186/8. It must be executed before the execution leaves ; the top 1K of memory. ; ; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* boot_186_init segment at 0fff0h assume cs:boot_186_init,ds:boot_186_init public firststage_186 firststage_186 proc far cli %IF (%is_bist) THEN (%'Initialize the 186 before and after the bist runs mov bx,boot_186_init mov es,bx ; the segment value is still in bx mov bx,offset init186_table ; point to the init table init_loop_1: mov dx,es:[bx] ; set up the port cmp dx,NULL ; a null port will terminate the loop. je init_finished_1 mov ax,es:[bx+2] ; get the programming value out dx,ax ; initialize the register add bx,4 ; point to the next table entry. jmp init_loop_1 ; do the next output init_finished_1: $include(:F1:bbist.inc) ) FI mov bx,boot_186_init mov es,bx ; the segment value is still in bx mov bx,offset init186_table ; point to the init table init_loop_2: mov dx,es:[bx] ; set up the port cmp dx,NULL ; a null port will terminate the loop. je init_finished_2 mov ax,es:[bx+2] ; get the programming value out dx,ax ; initialize the register add bx,4 ; point to the next table entry. jmp init_loop_2 ; do the next output init_finished_2: jmp far ptr continue_186 ; enter the firststage firststage_186 endp init186_table: %DEFINE(rmx_v)(%ARG)%' %IF ((%EQS(%rmx_v,Y)) OR (%EQS(%rmx_v,y)) OR (%EQS(%rmx_v,YES)) OR (%EQS(%rmx_v,yes)) ) THEN (%' DW 0fffeh DW 40ffh )FI%' %DEFINE(umcs_v)(%ARG)%' %IF ((%NES(%umcs_v,NONE)) AND (%NES(%umcs_v,none))) THEN (%' DW 0ffa0h DW %umcs_v )FI%' %DEFINE(lmcs_v)(%ARG)%' %IF ((%NES(%lmcs_v,NONE)) AND (%NES(%lmcs_v,none))) THEN (%' DW 0ffa2h DW %lmcs_v )FI%' %DEFINE(mpcs_v)(%ARG)%' %IF ((%EQS(%mpcs_v,NONE)) OR (%EQS(%mpcs_v,none))) THEN (%' %' '%SET(mpcs_v,0)%' )FI%' %DEFINE(mmcs_v)(%ARG)%' %IF ((%NES(%mmcs_v,NONE)) AND (%NES(%mmcs_v,none))) THEN (%' %' '%IF (%EQS(%mpcs_v,0)) THEN (%' ERROR -- MPCS register must be initialized to program the MMCS register %' ') ELSE (%' DW 0ffa8h DW %mpcs_v DW 0ffa6h DW %mmcs_v )FI )FI%' %DEFINE(pacs_v)(%ARG)%' %IF ((%NES(%pacs_v,NONE)) AND (%NES(%pacs_v,none))) THEN (%' %' '%IF (%EQS(%mpcs_v,0)) THEN (%' ERROR -- MPCS register must be initialized to program the PACS register %' ') ELSE (%' DW 0ffa8h DW %mpcs_v DW 0ffa4h DW %pacs_v )FI )FI )FI%' DW 0 DW 0 boot_186_init ends assume cs:code, ss:stack, ds:data %' )%' END OF THE iAPX_186_INIT MACRO. bootstrap_entry label far public bootstrap_entry ; entry for SDMs xor dl, dl ; clear inhibit_co flag pop ax ; return address pop ax pop di ; will change to BX later pop es jmp setup_reg ; get ptr to cmd line bootstrap_begin label far public bootstrap_begin ; entry for SCT xor dl, dl ; clear inhibit_co flag s120_begin label far ; entry for system 120 BSL mov di,ax ; will change to BX later mov ax,ds mov es,ax setup_reg: mov ss, cs: stackseg ; load stack segment mov sp, stacksize ; load stack pointer assume ss:stack, ds:data mov ds, cs: dataseg ; load data segment mov inhibit_co, dl ; load global flag used by monitor CO xface mov bx,di ; return name pointer to ES:BX jmp got_name firststage label far ; first stage starts here public firststage cli ; disable interrupts jmp setup db 43H,6FH,70H,79H,72H,69H,67H,68H,74H db ' 1980 - 1991 Intel Corporation ' db 'program_version_number=V8.3program_name=iRMX Bootstrap Loader',0 setup: %IF (%is_bist) THEN (%' $include(:f1:bbist.inc) ) FI continue_186: ; jumped to by 186 init- bypass bist cli ; disable interrupts cld ; clear the direction flag in case SDM ; is not around %IF (%is_auto_config_mem) THEN (%' mov al, 0F8H ; Set reset complete bits in the out 34H, al ; control/status register of the out 31H, al ; PSB control record. mov al, 0A4H ; Record type = 6; register = 29H. out 30H, al ; The values output must change if the xor ax, ax ; interconnect registers on the processor out 3CH, al ; board change. mov al, 0 ; The values output must change if the out 34H, al ; interconnect registers on the CSM out 31H, al ; board change. mov al, 0F0H ; Turn off error light on CSM board. out 30H, al ; Record type = FEH; register = 3CH mov al, 40H out 3CH, al mov ax, 080H mov ss, ax ; load stack segment for onboard mem mov sp, stacksize ; load stack pointer mov ds, ax ; load data segment for onboard mem ) ELSE (%' mov ss, cs: stackseg ; load stack segment mov sp, stacksize ; load stack pointer mov ds, cs: dataseg ; load data segment mov inhibit_co, 0 ; load global flag used by montior CO xface ) FI jmp startup %SET(is_loadfile, 0) %*DEFINE(loadfile) ( %SET(is_loadfile, -1) ) %SET(is_console, 0) %*DEFINE(console) ( %SET(is_console, -1) ) %SET(is_manual, 0) %*DEFINE(manual) ( %SET(is_manual, -1) %SET(is_console, -1) %SET(device_select, -1) ) %SET(is_auto, 0) %*DEFINE(auto) ( %SET(is_auto, -1) %SET(device_select, -1) ) %DEFINE(default_fn) ('/system/rmx86',0) %*DEFINE(defaultfile(fn)) ( %DEFINE(default_fn) (%fn, 0) ) %DEFINE(times) (0) %*DEFINE(retries(r)) ( %DEFINE(times) (%r+1) ) %SET(device_select, 0) %SET(first_device, -1) %*DEFINE(device(parameters))(%DEFINE(tail)(%parameters)%' %SET(uinfo_exists, -1) %DEFINE(name) (%ARG) %DEFINE(unit) (%ARG) %DEFINE(device_init) (%ARG) %DEFINE(device_read) (%ARG) %DEFINE(unit_info) (%ARG) %IF (%LEN (%unit_info) EQ 0) THEN ( %' '%DEFINE(unit_info)(0) )ELSE(%' %' '%external(%unit_info,far) ) FI %' %external(%device_init,far) ; %external(%device_read,far) ; $include(:f1:bs1dev.inc) ) %*DEFINE(end) ( %IF (%device_select) THEN ( db 0FFH ; terminate table ) FI default_file label byte public default_file db %default_fn %IF (%is_console) THEN ( bs_echo label byte ; Echo for Delete public bs_echo ; db bs_echo_end-bs_echo-1 ; db 08H, 020H, 08H ; bs_echo_end label byte ; ; can_echo label byte ; Echo for Cancel (CNTL/X) public can_echo ; db can_echo_end-can_echo-1 ; db '#', 0DH, 0AH ; can_echo_end label byte ; ; prompt label byte ; Prompt character public prompt ; db '*' ; ) FI public sdm_config_table sdm_config_table dw 0FF80H, %sdm_base public dmon_config_table dmon_config_table dw 0000H, 0040H code ends %IF (%is_copy) THEN (%' MODE equ 0000010000000001B ;specifies system wide params for adma ADMASTART equ 10010B ;start command word for GCR MEMXFER equ 1100000011011101B ;channel command for command blk GMR_PORT equ 0208H ;gmr port address GCR_PORT equ 0200H ;gcr port address GSR_PORT equ 0204H ;gsr port address CPRL0_PORT equ 0220H ;cprl0 port address CPRH0_PORT equ 0222H ;cprh0 port address STAT0 equ 03H ;status bits for channel 0 COPYSEG equ 0FFF9H ;hardwired physical segment for copycode ; NOTE: COPYSEGLO and COPYSEGHI must be consistent with COPYSEG COPYSEGLO equ 0FF90H ;low word of COPYSEG COPYSEGHI equ 00FFH ;high word of COPYSEG RNCIAR equ 0F8C0H ; reset not complete ic RNCLO_PORT equ 030H ; io address for low byte of ic RNCHI_PORT equ 034H ; io address for high byte of ic DATA_PORT equ 03CH ; io address for ic data RESETCOM equ 011111100B ; clears reset not complete admablk struc ;adma command block cmd dw MEMXFER ;adma command asrc_lo dw src_lo ;low word of source address asrc_hi dw src_hi ;high word of source address adest_lo dw dest_lo ;low word of destination address adest_hi dw dest_hi ;high word of destination address acount_lo dw count_lo ;low word of transfer count acount_hi dw count_hi ;high word of transfer count status dw ? ;status word stop_1 dw 0 ;stop word stop_2 dw 0 ; stop_3 dw 0 admablk ends copycode segment AT COPYSEG assume cs:copycode ORG 0H dmacmd admablk <> ;command block for dma promcopy label near public promcopy ; clear reset not complete bit in iPSB control/status register mov ax, RNCIAR ; ax <-- reset not complete ic address mov dx, RNCLO_PORT ; dx <-- port for low byte of RNCIAR out dx, al ; write low byte of reset not complete ic addr mov al, ah ; al <-- high byte of reset not complete ic addr mov dx, RNCHI_PORT ; dx <-- port for high byte of RNCIAR out dx, al ; write high byte of reset not complete ic addr mov dx, DATA_PORT ; dx <-- ic data port in al, dx ; get iPSB control/status register and al, RESETCOM ; clear reset not complete bit out dx, al ; write it back to ic record ;Now copy prom to ram mov dx, GMR_PORT ; write mode word to mov ax, MODE ; adma mode register out dx, ax ; ;convert command block pointer to 20 bit address mov ax, COPYSEGLO mov dx, CPRL0_PORT ; write low word of command pointer out dx, ax ; to pointer register on adma mov ax, COPYSEGHI mov dx, CPRH0_PORT ; write high word of command pointer out dx, ax ; address to pointer register ; start command mov ax, ADMASTART ;start mov dx, GCR_PORT ;command out dx, al dmawait: mov dx, GSR_PORT ;get status in al, dx ; and al, STAT0 ;and check if dma done cmp al, 0 ; jne dmawait ;loop til done jmp firststage ;transfer control to code in ram ORG 0FFF0H - COPYSEGLO penter label near public penter jmp promcopy copycode ends ) FI %' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* %' INPUTS: NONE %' OUTPUTS: BDEV_INIT_LEN - number of device initialization outputs %' BDEV_INIT_STRUC_LEN - the length of the device init structure %' ABSTRACT: %' This macro declares four publics needed for device and serial %' channel init. %' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* %IF (%is_cico) THEN ( $eject boot_dev_init segment bdev_init_len DW %dev_cnt bdev_init_struc_len DW size dev_init boot_dev_init ends ) FI end)