%';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' TITLE: NUCLEUS DEVICE CONFIGURATION MACROS %' %' DATE: APRIL 24, 1981 %' %' ABSTRACT: This module contains the definitions of the %' MASTER_PIC, SLAVE_PIC, TIMER, CPU_TYPE and NDP_SUPPORT %' macros. These macros allow the device characteristics %' and device ports to be selectively configured. If any %' parameter which has a default value is not specified, %' that parameter assumes its default value. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' UTILITY MACROS USED BY MASTER_PIC, SLAVE_PIC AND TIMER MACROS %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' Define strings for strip. %' %define(cr) ( ) %define(lf) ( ) %define(tab) ( ) %define(space) ( ) %' %' Strip: %' strip all occurances of "char" string from "arg" string. %' %*define(strip(char,arg)) local str head tail (%' %' '%define(str) (%0)%' %' '%define(tail) (%arg)%' %' '%while(%nes(%tail,%0)) (%' %' '%match(head%(%char)tail) (%tail)%' %' '%define(str) (%str%head)%' %' ')%' %' '%str%' )%' %' %' Cleanup: %' strip spaces, tabs and CRLFs from string. %' %*define(cleanup(str)) (%strip(%space,%strip(%tab,%strip(%cr,%strip(%lf,%str))))) %' %' %*define(define_port(seg,port,entry))( %seg segment word public 'CODE' org 2*(%entry) dw %port org 18 ; force seg to 9 words in length %seg ends ) %' %' %*define(define_info(seg,info,entry))( %seg segment byte public 'CODE' org %entry db %info org 9 ; force seg to be 9 bytes in length %seg ends ) %' %' %*define(define_public_byte(name,info))( %' 'public %name %name db %info ) %' %' %*define(slave_bit(level))(%' %%level) %set(level00H,1) %set(level0,1) %set(level01H,2) %set(level1,2) %set(level02H,4) %set(level2,4) %set(level03H,8) %set(level3,8) %set(level04H,16) %set(level4,16) %set(level05H,32) %set(level5,32) %set(level06H,64) %set(level6,64) %set(level07H,128) %set(level7,128) %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' NAME: TIMER %' %' INPUT: type, base, level, count, selction, delta %' where: %' type is the type of timer (80130 or 8253). %' base is the base address of the device. %' level is the encoded level the interrupt %' occurs on . %' count is the programmed count (T*C). %' selection is timer to be used for the system clock. %' delta is the spacing (in bytes) between ports on the timer. %' %' OUTPUT: Definitions for clock_control_port, clock_x_port, %' clock_count, c_clock_level, clock_mode_word, %' c_clock_spec_eoi and c_clock_on used in initializing %' the iRMX 86 system clock. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %*define(timer(type_p,base_p,level_p,count_p,selection_p,timer_port_delta_p))( ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Timer Definition ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %define(type)(%cleanup(%type_p)) %define(base)(%cleanup(%base_p)) %define(level)(%cleanup(%level_p)) %define(count)(%cleanup(%count_p)) %define(selection)(%cleanup(%selection_p)) %define(timer_port_delta)(%cleanup(%timer_port_delta_p)) %' %IF (%EQS(%timer_port_delta,%0)) THEN (%' %define(timer_port_delta)(2))FI%' %' %IF (%EQS(%type,%0)) THEN (%' %define(type)(8253))FI%' %' %IF (%EQS(%base,%0)) THEN (%' %define(base)(0D0H))FI%' %' %IF(%EQS(%type,80130)) THEN(%' %DEFINE(base)(%EVAL(%base + (4 * %timer_port_delta))))FI%' %' %IF (%EQS(%level,%0)) THEN (%' %define(level)(02H)) ELSE (%set(level,((%level / 16) AND 07h)))FI%' %' %IF (%EQS(%count,%0)) THEN (%' %define(count)(12288))FI%' %' %IF (%EQS(%selection,%0)) THEN (%' %define(selection)(0))FI%' %' %IF ((%EQS(%type,80130) AND (%selection NE 0)) OR (%selection GT 2)) THEN (%OUT( ERROR ___ BAD COUNTER SELECTION %selection )%' ; ERROR ___ BAD COUNTER SELECTION %selection )FI%' %set(counter_x_port_sel,(%selection * %timer_port_delta))%' %set(control_word_sel,(%selection * 040h))%' %' %' The order of the definitions in the segment is critical. %' Do not arbitrarily reorder them. %' timer_cnf_seg segment byte public 'CODE' org 0 dw %base + (3 * %timer_port_delta) ; clock_control_port dw %base + %counter_x_port_sel ; clock_x_port dw %count ; clock_count db %level ; c_clock_level db 34H + %control_word_sel ; counter x, mode 2, binary count db %eval(%level OR 060H) ; c_clock_spec_eoi db NOT %slave_bit(level%level) ; c_clock_on timer_cnf_seg ends )%' end of the TIMER macro. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' NAME: MASTER_PIC %' %' INPUT: type, master_base_port, edge_vs_level, local_vs_non, delta %' where: %' type is the type of the PIC (8259A or 80130) %' master_base_port is the numerically lowest %' valued port of the PIC. %' edge_vs_level is 0 if edge mode is required %' 1 if level mode is required %' local_vs_non is 0 if master is local %' 1 if master is non-local %' delta is the spacing (in bytes) between ports on the Master %' PIC. %' %' OUTPUT: IMR_port, EOI_port and ISR_port are arrays %' of 9 words which define the functional port %' addresses of the interrupt controllers. %' PIC_info is an array of 9 bytes that indicates %' which Master PIC levels have slaves attached. %' INIT_CMD1_MASTER, INIT_CMD3_MASTER, INIT_CMD5_MASTER %' and INIT_CMD6_MASTER are initialization command %' words required for the Master PIC. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %*define(master_pic(type_p,master_base_port_p,edge_vs_level_p,local_vs_non_p,master_port_delta_p))( ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Definition of the Master PIC ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' cleanup the params: strip them of blanks, tabs, crs and lfs %' %define(type)(%cleanup(%type_p)) %define(master_base_port)(%cleanup(%master_base_port_p)) %define(edge_vs_level)(%cleanup(%edge_vs_level_p)) %define(local_vs_non)(%cleanup(%local_vs_non_p)) %define(master_port_delta)(%cleanup(%master_port_delta_p)) %' %IF (%EQS(%type,%0)) THEN (%' %define(type)(8259A))FI%' %' %IF (%EQS(%master_base_port,%0)) THEN (%' %define(master_base_port)(0C0H))FI%' %' %IF (%EQS(%edge_vs_level,%0)) THEN (%' %define(edge_vs_level)(0))FI%' %' %IF (%EQS(%local_vs_non,%0)) THEN (%' %define(local_vs_non)(0))FI%' %' %IF (%EQS(%master_port_delta,%0)) THEN (%' %define(master_port_delta)(2))FI%' %' Define the master PIC icw1 which is dependent on the PIC type. %' %IF (%EQS(%type,8259A) OR %EQS(%type,8259a))%' %' 'THEN(%define(icw1)(015H))%' this must be expanded to support level triggered mode %' 'ELSE(%' %' '%IF(%EQS(%type,80130))%' %' 'THEN(%define(icw1)(035H))%' %' 'ELSE(ERROR -- %type improper pic type )%' %' 'FI)%' FI%' %' %' Define initialization data for the master. This will be %' redefined by user invocations of the MASTER_PIC macro. %' The order of the definitions in the segment is critical. %' Do not arbitrarily reorder them. %' pic_cnf_seg segment word public 'CODE' %' org 1H db %icw1 db %edge_vs_level db %local_vs_non %' pic_cnf_seg ends %' %' Define masters run-time ports. %' %'define_port(_imr_port,%master_base_port+%master_port_delta,0) _imr_port segment word public 'CODE' org 0 dw 9 dup( %master_base_port + %master_port_delta ) _imr_port ends %' %'define_port(_eoi_port,%master_base_port,0) _eoi_port segment word public 'CODE' org 0 dw 9 dup( %master_base_port ) _eoi_port ends %' %'define_port(_isr_read_port,%master_base_port,0) _isr_read_port segment word public 'CODE' org 0 dw 9 dup( %master_base_port ) _isr_read_port ends %' _pic_info segment byte public 'CODE' org 0 db 80H ; 80 --> master is here db 8 dup (0) ; 0 --> slave is not _pic_info ends %' )%' end of the MASTER_PIC macro. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' NAME: SLAVE_PIC %' %' INPUT: type, slave_base_port, edge_vs_level, master_level, delta %' where: %' type is the type of the PIC (8259A or 80186) %' slave_base_port is the numerically lowest %' valued port of the slave PIC. %' edge_vs_level is 0 if edge mode is required %' 1 if level mode is required %' master_level is the master PIC encoded level %' the slave is connected to. %' delta is the spacing (in bytes) between ports on this Slave %' PIC. %' %' OUTPUT: SLAVE_TABLE is a variable length array %' (null terminated) of pointers to Slave_data %' structures for every slave that is configured. %' Slave_data contains the port addresses for the %' ICWs, the first ICW, the type of PIC and the %' Master PIC level to which the Slave PIC is %' connected. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %*define(slave_pic(type_p,slave_base_port_p,edge_vs_level_p,master_level_p,slave_port_delta_p))( %' %' %' cleanup params: strip cr, lf, esc, tab and spaces %' %define(type)(%cleanup(%type_p)) %define(slave_base_port)(%cleanup(%slave_base_port_p)) %define(edge_vs_level)(%cleanup(%edge_vs_level_p)) %define(master_level)(%cleanup(%master_level_p)) %define(slave_port_delta)(%cleanup(%slave_port_delta_p)) %' %IF (%EQS(%type,%0)) THEN (%' %define(type)(8259A))FI%' %' %IF (%EQS(%slave_base_port,%0)) THEN (%' ERROR --base port must be specified for slave PIC)FI%' %' %IF (%EQS(%edge_vs_level,%0)) THEN (%' %define(edge_vs_level)(0))FI%' %' %IF (%EQS(%master_level,%0)) THEN (%' ERROR -- a master level must be specified for the slave PIC)FI%' %' %IF (%EQS(%slave_port_delta,%0)) THEN (%' %define(slave_port_delta)(2))FI%' $eject ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Master Level %master_level%() Slave PIC Definition ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' test for supported type %' %IF (%EQS(%type,8259A) OR %EQS(%type,8259a) OR %EQS(%type,80186))%' THEN (%' process SLAVE_PIC invocation %' %' define this slaves run time ports %' %IF (%EQS(%type,80186)) THEN(%' %' '%define_port(_imr_port,0FF28H,%master_level+1) %' '%define_port(_eoi_port,0FF22H,%master_level+1) %' '%define_port(_isr_read_port,0FF2CH,%master_level+1) ) ELSE (%' %' '%define_port(_imr_port,%slave_base_port+%slave_port_delta,%master_level+1) %' '%define_port(_eoi_port,%slave_base_port,%master_level+1) %' '%define_port(_isr_read_port,%slave_base_port,%master_level+1) ) FI%' %' %' define slaves icw1 %' %IF(%edge_vs_level EQ 0)%' %' 'THEN(%set(icw1,15H))%' edge triggered mode %' 'ELSE(%set(icw1,1DH))FI%' level triggered mode %' %' declare the slave to be present %' %define_info(_pic_info,80H,%master_level+1)%' 80H --> present %' %' set the slave present bit in the masters icw3 %' pic_cnf_seg segment word public 'CODE' org 0 %set(icw3,%icw3 OR %slave_bit(level%master_level)) db %icw3 pic_cnf_seg ends %' %' define slave initialization information %' cseg segment word public 'CODE' %' slave%master_level%()_data_struc struc slave%master_level%()_icw1_port dw %slave_base_port ; icw1_port dw %eval(%slave_base_port+%slave_port_delta) ; icw2,3,4_port db %IF(%EQS(%type,80186)) THEN (1)%' %' 'ELSE (0) FI ; type db %icw1 ; icw1 for slave db %master_level ; slave's level on master slave%master_level%()_data_struc ends %' %' Declare a variable of the structure type to make %' another entry in the slave table. %' slave%master_level%()_data slave%master_level%()_data_struc <> cseg ends %' %' add an entry to the slave table %' slave_seg segment word public 'CODE' org %slave_index dw cgroup:slave%master_level%()_data.slave%master_level%()_icw1_port dw 0 ; 0 indicates end of data slave_seg ends %set(slave_index,%slave_index+2) %' ) ELSE (%' slave is wrong type - do not process ERROR -- %type is an incorrect slave pic type )FI%' end of test for correct slave PIC type %' )%' end of the SLAVE_PIC macro. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' NAME: NDP_SUPPORT %' %' INPUTS: level %' where: %' level is the encoded interrupt level used by %' the 8087 for error interrupts. %' %' OUTPUT: The ndp_interrupt_level %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %*define(ndp_support(ndp_level_p))(%' %define(ndp_level)(%cleanup(%ndp_level_p)) %' %IF (%EQS(%ndp_level,%0)) THEN (%' %define(ndp_level)(58H))FI%' %' code segment word public 'CODE' NDP_interrupt_level dw %ndp_level code ends public NDP_interrupt_level )%' end NDP_SUPPORT macro. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' CPU TYPE MACRO %' %' INPUT - CPU TYPE %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %*define(cpu_type(cpu_class_p))(%' %define(cpu_class)(%cleanup(%cpu_class_p)) %' %IF (%EQS(%cpu_class,%0)) THEN (%' %define(cpu_class)(8086))FI%' %' %IF (%EQS (%cpu_class,8086)) %' %' 'THEN (%define(cpu_value)(0))%' %' 'ELSE (%' %' '%IF (%EQS (%cpu_class,8088)) %' %' 'THEN (%define(cpu_value)(0))%' %' 'ELSE (%' %' '%IF (%EQS (%cpu_class,80186)) %' %' 'THEN (%define(cpu_value)(0))%' %' 'ELSE (%' %' '%IF (%EQS (%cpu_class,80286)) %' %' 'THEN (%define(cpu_value)(1))%' %' 'ELSE (ERROR -- % type improper cpu type )%' %' 'FI)%' %' 'FI)%' %' 'FI)%' FI %' %' %' code segment word public 'CODE' cpu_type dw %cpu_value ; 0 -> 8086 and 1 -> 80286 code ends public cpu_type )%' end CPU_SUPPORT macro. %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %' %' -- NOTE -- %' The code that follows is assembled in-line to provide %' definitions for the configuration variables. The default %' configuration variable values are provided by invoking the %' configuration macros with the appropriate parameters in NDEVCF.A86 %' Further user invocations of the configuration macros redefine the %' variables as per user supplied parameters. The order of the %' data definitions in the segments is critical. %' --- Do not arbitrarily reorder them. --- %' %';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CGROUP GROUP pic_cnf_seg,_imr_port,_eoi_port,_isr_read_port,_pic_info, & timer_cnf_seg,cseg,slave_seg,code ; ; _imr_port,_eoi_port_isr_read_port,_pic_info must be in this ; order in the GROUP definition for proper PIC initializaion. ; ASSUME cs:cgroup %' %' Declare the Timer initialization and ndp_support variables PUBLIC %' public clock_control_port,clock_x_port,clock_count,clock_mode_word public c_clock_spec_eoi,c_clock_on,c_clock_level %' %' Set up the variables in the timer_cnf_seg. The order of the %' variables in this segment and the order of assignment of these %' variables in the TIMER macro has to be the same. %' timer_cnf_seg segment byte public 'CODE' org 0 clock_control_port dw ? clock_x_port dw ? clock_count dw ? c_clock_level db ? clock_mode_word db ? c_clock_spec_eoi db ? c_clock_on db ? timer_cnf_seg ends %' %' Define macro time variables for icw3. This will be modified %' by any invocations of the SLAVE_PIC macro. %' %set(icw3,0) %' %' Open CSEG in case no SLAVE_PIC macros are invoked %' cseg segment word public 'CODE' cseg ends %' %' Open the CODE segment in case no NDP_support macro is invoked %' code segment word public 'CODE' code ends %' %' Define the list of slave initialization blocks. %' slave_seg segment word public 'CODE' public slave_table slave_table dw 0 %set(slave_index,0) slave_seg ends %' %' NOTE NOTE NOTE !!!! %' The definition of init_cmd3_master MUST be the first in %' this segment so that subsequent invocations of the slave %' macro may redefine it properly. Init_cmd1_master, %' init_cmd5_master and init_cmd6_master are given values %' by invocations of the MASTER_PIC macro. %' The order of the definitions in the segment is critical. %' Do not arbitrarily reorder them. %' pic_cnf_seg segment word public 'CODE' %define_public_byte(init_cmd3_master,0) %define_public_byte(init_cmd1,?) %define_public_byte(init_cmd5_master,0FFH) %define_public_byte(init_cmd6_master,0FFH) %define_public_byte(init_cmd4_master,1DH) pic_cnf_seg ends %' %' Put a label in the beginning of the first port segment. %' It will be referenced by initialization. %' _imr_port segment word public 'CODE' public imr_start imr_start label word _imr_port ends