|
DataMuseum.dkPresents historical artifacts from the history of: RC3500 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC3500 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 22272 (0x5700) Types: TextFileVerbose Names: »tboot«
└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system └─⟦6b41451d2⟧ └─⟦this⟧ »tboot«
(*$5 4 0 *) (*$5 2 0*) (*$5 7 0*) process boot; type descriptortype = packed record pip : integer; time : packed record compiler_version : 0..31; hour : 0..31; minute : 0..63 end end; const revisionno = 6; (* register stack constants *) regsetsize = 8; ib = 6; (* ib displacement in registerset *) wordsize = 2; addrsize = 4; first_ram_memno = 0; (* memory module number of semaphore module *) sem_first = 64; (* displacement for first of semaphore area in ram module 0 *) monitorlevel = 2; auto_mem_no = 16; (* system semaphore array constants *) system_semno = 24; (* number of system semaphores *) headersize = 32; (* size of headermessage in bytes *) prom_bitmap_index = 30; (* index of eprom bit map in ctrl processor ram *) bootsize = 1024; memtype = 3; last_ramindex = maxint - bootsize; process_kind = 1; promlink = 0; (* promlink command to linker *) (* autoload kinds *) jump = 0; fpa = 2; (* autoload from fpa100 *) ptr = 4; eprom = 6; (* answer bytes to fpa100 *) next_block_answer = 256 + 0; rewind_answer = 256 + 2; finis_answer = 256 + 12; (* controlwords to fpa100 *) repeat_interrupt = 2; start_read = 3; (* start bytes from fpa100 *) status_block = 249; data_block = 251; (* fpa100 status words *) receive_block_end = 16; transmit_block_end = 64; nil_value = addr(base_type(0,1,0,0,0),0); monitorname = 'monitor '; timername = 'timer '; allocatorname = 'allocator '; linkername = 'linker '; printexceptname = 'printexcept '; adamname = 'adam '; var bootloadtest , inittest : boolean; buf : corearray; i : integer; switches : switch_type; index : integer; channel_msg : reference; program_msg : reference; buffer_msg : reference; ram_msg : reference; r : reference; channel_msg_header : message_header; program_msg_header : message_header; bufferheader : message_header; ram_msg_header : message_header; ram_dope : dope_vector; prom_dope : dope_vector; pointer : addr; semref : addr; ram_first : addr; ram_index : integer; ram_pointer : addr; save_ram_first : addr; save_ram_pointer : addr; save_ram_index : integer; pointer_move : boolean := true; bootmoduleno : byte; test : boolean; revisionerror : boolean := false; initboottop : addr; (* top of initbootcode = first of boot descriptorsegment *) bootlevel : integer; prom_first : addr; program_index : integer; program_pointer : addr; program_top : addr; prom_bitmap : mem_map_type; common : shadow; status_in : integer; status_out : integer; block_answer : integer := rewind_answer; block_type : integer; continue_read : boolean; descrsize : integer; descrwords : integer; codewords : integer; bufferindex : integer; last_in_buffer : integer; process monitor(var sem : semaphore); external; process timer(var delay , sem : semaphore); external; process allocator(var sem1, sem2 : semaphore); external; process linker(var sem : semaphore); external; process adam(var sem : semaphore); external; process printexcept; external; procedure asgnaddrpref = stvsd0(var a : addr; p : ^ process_descriptor); external; procedure asgnaddrsec = stvsd0(var a : addr; p : ^ secret_vector); external; procedure assign2 = stvsw0(var map : mem_map_type; mask : integer); external; procedure initscrtref = stvsd0(var s : ^ secret_vector; a : addr); external; function uadd(a,b : integer) : integer; external; function umod(a,b : integer) : integer; external; function umul(a,b : integer) : integer; external; function udiv(a,b : integer) : integer; external; procedure printchar(ch:char); begin writeram(8,ord(ch)); end; procedure printhex (val: integer); type convarr = array (0..15) of char; const hextab = convarr('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); var ch1: integer; begin if val < 0 then begin ch1 := 8; val := val - minint; end else ch1 := 0; printchar (hextab(ch1 + val div (16*16*16))); printchar (hextab(val div (16*16) mod 16)); printchar (hextab(val div 16 mod 16)); printchar (hextab(val mod 16)); end; procedure printaddr( a : addr); begin with a.base do printhex((((- lockbit * 2 + nill) * 256 + moduletype) * 32 + mem_no) * 2 + nullbit); printchar('.'); printhex(a.disp) end; procedure printtext (text:alfa); var i: integer; begin i := 1; while text(i) <> '#' do begin printchar(text(i)); if i = alfalength then text(i) := '#' else i := i + 1; end; end; procedure printnl; var i: integer; begin printchar (cr); printchar (nl); for i := 1 to 10 do printchar(del); end; procedure setexcept; external; procedure except; label rep; begin with own do begin printnl; printtext ('*** # '); printtext ('exception: #'); printhex (exception_mask); printtext (' at: # '); printaddr(exic); printnl; end; rep:goto rep; end; procedure platoninit; begin setexcept; except; end; procedure control(control_word : integer; var ch_msg : reference); external; procedure controlclr(control_word : integer; var ch_msg : reference); external; procedure inword(var word : integer; var ch_msg : reference); external; procedure sense(var status_in : integer; status_out : integer; var ch_msg : reference); external; procedure outword(word : integer; var ch_msg : reference); external; procedure movepointer( offset: integer; dope: dope_vector; var first: addr; var index: integer; var pointer: addr ); var i : integer; begin if offset >= 0 then begin (* test for overflow into next module *) if dope.r.upper_limit - offset < index then begin first.base.mem_no := first.base.mem_no + 1; index := dope.r.lower_limit + 1 (* promword *); offset := 0; end; end; if pointer_move then index := index + offset; defineptr (pointer, first, index, dope); end; (* procedure movepointer *) procedure moveramptr (offset: integer); label rep; begin if ram_first.base.mem_no = bootmoduleno then ram_dope.r.upper_limit := last_ramindex; movepointer (offset, ram_dope, ram_first, ram_index, ram_pointer); if ram_first.base.mem_no = bootmoduleno + 1 then begin printnl; printtext('*** buy more'); printtext(' memory !!!!'); rep: goto rep end; end; procedure move_program_pointer (offset: integer); begin movepointer (offset, prom_dope, prom_first, program_index, program_pointer); end; procedure reserveprom(size : integer); begin pointer_move := false; (* just test room *) move_program_pointer(size - 1); pointer_move := true; end; procedure takeram (size: integer); begin moveramptr (size); ram_msg_header.start := ram_pointer; end; procedure reserveram (size: integer); begin pointer_move := false; (* i.e. just test room *) takeram (size - 1); (* make sure last word is addressable *) pointer_move := true; end; procedure ptrblock; begin sense (status_in, status_out, channel_msg); controlclr(0,channel_msg); inbyteblock (last_in_buffer, 0, ptrbuffersize - 1, buffer_msg, channel_msg); end; procedure fpablock; begin outword (block_answer, channel_msg); controlclr(repeat_interrupt, channel_msg); sense (status_in, status_out, channel_msg); if status_in <> transmit_block_end then block_answer := rewind_answer (* prepare repetition on: reset or autoload etc *) else if block_answer <> finis_answer then begin (* don't read after finis-answer has been sent *) controlclr (start_read, channel_msg); inword (block_type, channel_msg); controlclr (repeat_interrupt, channel_msg); inbyteblock (last_in_buffer, 0, fpabuffersize - 1, buffer_msg, channel_msg); controlclr (repeat_interrupt, channel_msg); sense (status_in, status_out, channel_msg); if status_in <> receive_block_end then block_answer := rewind_answer else if (block_type = status_block) and (last_in_buffer = 8) then block_answer := next_block_answer else if block_type <> data_block then block_answer := rewind_answer; end; if (block_type = data_block) and (block_answer = next_block_answer) then begin if last_in_buffer > 15 then last_in_buffer := last_in_buffer - 15 else begin last_in_buffer := 0; block_answer := finis_answer; end; end else begin last_in_buffer := 0; continue_read := false; (* because starting all over again *) end; end; (* procedure fpablock *) function getbyte: byte; begin if bufferindex >= last_in_buffer then if continue_read then begin selectlevel(bootlevel); if switches.kind = ptr then ptrblock else fpablock; bufferindex := 0; end; if bufferindex < last_in_buffer then begin bufferindex := bufferindex + 1; getbyte := buf (bufferindex); end else getbyte := 0; (* simulate byte *) end; (* procedure getbyte *) function getword : integer; begin getword := uadd(umul(getbyte,256),getbyte) end; procedure prepare_input; begin continue_read := true; bufferindex := 1; last_in_buffer := bufferindex; if switches.kind = ptr then while getbyte = 0 do; (* skip until significant start *) end; procedure reset_input; begin prepare_input; ram_first := save_ram_first; ram_pointer := save_ram_pointer; ram_index := save_ram_index; end; procedure terminate_input; begin if switches.kind = fpa then outword(finis_answer,channel_msg); end; procedure bootcreate(proces : processrec; var sh : shadow; var q : descriptor_segment); (* entry : ram_pointer and ramindex equals first of stack *) (* exit : - - - - top - - *) const stopstate = -1; var storage : integer; size_of_incdescr : integer; size_of_params : integer; begin storage := q.default_appetite; size_of_params := proces.size_of_params div wordsize; size_of_incdescr := q.last_param_offset div wordsize - size_of_params; reserveram (storage); if inittest then begin printtext(', stack=# '); printaddr (ram_pointer); end; lock sh.r as p : ext_incarnation_descriptor do with p do begin pu := 0; level := 0; incstate := stopstate; activequeue := addr_of(chain); chainhead := nil_value; exception_point := q.exception_point; exic := addr(base_type(0,0,0,0,0),0); dumpps := 0; dumpsf := ram_pointer.disp + 1; entry_point := q.entry_point; timer := 0; asgnaddrpref(processref,proces.processref); semchain := nil_value; refchain := nil_value; shadowchain := nil_value; msg_chain := nil_value; exit_point := q.exit_point; exit_semaphore := nil_value; delaychain := nil_value; exitref := nil_value; statistic := nil_value; asgnaddrsec(secret_pointer,own.secret_pointer); incname := q.name; (* set pointer to destination for actual parameters of this incarnation *) moveramptr(size_of_incdescr); (* copy actual params from boot stack to stack of child *) copywords(ram_pointer,proces.firstparam,size_of_params); moveramptr(size_of_params - 1); dumplu := ram_pointer.disp + 1; (* move ram_pointer to last of this stack *) moveramptr(storage - (size_of_incdescr + size_of_params)); dumplm := ram_pointer.disp + 1; maxstack := dumplm; with proces.processref^ do incarnationcount := incarnationcount + 1; (* ram_pointer := top of stack *) moveramptr(1); if inittest then begin printtext(' top=# '); printaddr (ram_pointer); end; end end; (* bootcreate *) procedure bootrun(proces : processrec; var sh : shadow; priority : integer; var q : descriptor_segment); const start_command = 1; begin bootcreate(proces,sh,q); with sh.r^ do begin u1 := start_command; u3 := priority + 128; end; signal(sh.r,own.secret_pointer^(monitorsem)^); wait(sh.r, own.exit_semaphore); end; procedure get_memory_map(var map : mem_map_type; first : integer); var map0, map1 : byte; begin readram(map0,first); readram(map1,first + 1); assign2(map,uadd(umul(map0,256),map1)) end; procedure get_switches(var sw : switch_type); const rtc_level_index = 0; switch0_index = 10; switch1_index = 11; var switch0 : byte; switch1 : byte; begin readram(switch0,switch0_index); readram(switch1,switch1_index); sw.kind := (switch0 div 16)mod 8; sw.module := switch0 mod 16; sw.address := switch1; (* kill rtc interrupts *) writeram(rtc_level_index,0); end; function test_basic_process(var msg : reference) : boolean; forward; procedure skip_program; var codewords : integer; begin lock program_msg as p: descriptor_segment do with p do begin move_program_pointer (descriptor_length div wordsize); codewords := (no_of_pages - 1) * (pagesize div wordsize) + ( last_page_length + 1) div wordsize; end; reserveprom(codewords); program_msg_header.start := program_pointer; lock program_msg as descriptor : descriptortype do if descriptor.time.compiler_version <> revisionno then begin printtext('****warning:'); printtext(' versionerro'); printtext('r at # '); printaddr(program_pointer); printnl; revisionerror := true end; move_program_pointer(codewords); end; procedure include_one_program; const ok = 0; begin program_msg_header.start := program_pointer; if not test_basic_process(program_msg) then begin program_msg^.u1 := promlink; signal(program_msg,own.secret_pointer^(linkersem)^); wait(program_msg,own.exit_semaphore); if program_msg^.u2 <> ok then begin printtext('****warning:'); printtext(' link result'); printhex(program_msg^.u2); printtext(' at #'); printaddr(program_pointer); printnl; end; end; (* move program_pointer to next program descriptor *) skip_program; end; procedure include_programs; var descrsize: integer; begin repeat getinteger (descrsize, program_pointer); if (descrsize > 0) and (descrsize <> #h5555) then include_one_program; until (descrsize <= 0) or (descrsize = #h5555); end; procedure init_ext_header(var msg : ext_message_header; kind , msize : integer; mstart : addr); begin with msg do begin chain := nil_value; owner := nil_value; answer := nil_value; msg_chain := nil_value; stackchain := nil_value; messagekind := kind; size := msize; start := mstart; end; end; procedure initheader(var msg : message_header; kind,msize : integer; mstart : addr); begin with msg do begin owner := ref(own.exit_semaphore); answer := owner; messagekind := kind; size := msize; start := mstart; end; end; procedure send_message_header(var sem : semaphore); begin reserveram (headersize div wordsize); lock ram_msg as p : ext_message_header do begin init_ext_header(p,0,0,nil_value); initextref(r,p); with r^ do begin owner := ref(sem); answer := owner; end; signal(r,sem); end; takeram (headersize div wordsize); end; function test_basic_process(var msg : reference): boolean; const runstate = 0; linkerpriority = 1; timerpriority = 1; priority = 1; begin test := false; lock msg as p : descriptor_segment do begin if inittest then begin printaddr(msg^.start); printtext(': # '); printtext(p.name); printhex(p.kind); end; if p.kind = process_kind then begin if p.name=monitorname then begin bootcreate(monitor(own.secret_pointer^(monitorsem)^),common,p); lock common.r as q : ext_incarnation_descriptor do begin q.level := monitorlevel; q.incstate := runstate; startdriver(q) end; test := true; end else if p.name=timername then bootrun(timer(own.secret_pointer^(timersem)^, own.secret_pointer^(monitorsem)^), common,timerpriority,p) else if p.name = allocatorname then bootrun(allocator(own.secret_pointer^(allocsem)^, own.secret_pointer^(deallocatorsem)^), common,priority,p) else if p.name = linkername then bootrun(linker(own.secret_pointer^(linkersem)^),common,linkerpriority,p) else if p.name = printexceptname then bootrun(printexcept,common,priority,p) else if p.name = adamname then bootrun(adam(own.secret_pointer^(opsem)^),common,priority,p); end; end; if inittest then printnl; test_basic_process := test; end; procedure bootload; begin printnl; printtext ('load from # '); case switches.kind of fpa: begin printtext('fpa in # '); printhex(switches.address) end; ptr: begin printtext('ptr in # '); printhex(switches.address) end; eprom: begin selectlevel(bootlevel); printtext('eprom# '); end otherwise printtext('*** undefine'); printtext('d switchkind'); printhex(switches.kind) end; printnl; initheader (bufferheader, 16384, fpabuffersize div wordsize, addr_of_core(buf)); initref (buffer_msg, bufferheader); initheader (channel_msg_header, minint + switches.address, 0, nil_value); prepare_input; save_ram_first := ram_first; save_ram_pointer := ram_pointer; save_ram_index := ram_index; if (switches.kind = ptr) or (switches.kind = fpa) then repeat if not continue_read then reset_input; repeat descrsize := getword; if (descrsize > 0) and continue_read then begin printchar('.'); (* reserve room for descriptor-segment, and read it *) descrwords := descrsize div wordsize; reserveram (descrwords); if bootloadtest then begin printtext('descr=# '); printhex (ram_pointer.disp); printtext(' size=# '); printhex (descrwords); end; lock ram_msg as core: array(1..maxint) of integer do begin core (1) := descrsize; for i := 2 to descrwords do core (i) := getword; end; if continue_read then begin lock ram_msg as p: descriptor_segment do with p do codewords := (no_of_pages - 1) * (pagesize div wordsize) + (last_page_length + 1) div wordsize; takeram (descrwords); reserveram (codewords); if bootloadtest then begin printtext (' code=# '); printaddr (ram_pointer); printtext (' size=# '); printhex (codewords); end; lock ram_msg as core: array(1..maxint) of integer do for i := 1 to codewords do core(i) := getword; takeram (codewords); end; if bootloadtest then printnl; end; until descrsize <= 0; reserveram(1); lock ram_msg as stopword : integer do stopword := -1; takeram(1); until continue_read; terminate_input; end; (* procedure bootload *) (*******************************************************) (* *) (* mainprogram *) (* *) (*******************************************************) begin platoninit; bootloadtest := false; inittest := false; initboottop := own.chainhead; (* pick up first of boot descriptor passed from initboot *) own.maxstack := -1; own.activequeue := addr_of(own.chain); bootmoduleno := own.activequeue.base.mem_no; (* reset channel 0..123 *) initref(channel_msg,channel_msg_header); for i := 0 to 123 do begin initheader(channel_msg_header,minint + i,0,nil_value); control(0,channel_msg); end; (* reset semaphore area *) own.exit_semaphore.chain := nil_value; ram_dope := dope_vector(range_descriptor(0,maxint),wordsize); prom_dope := ram_dope; ram_first := addr(base_type(0,0,memtype,first_ram_memno,0),0); ram_index := 0; get_switches(switches); bootlevel := switches.address mod 128; takeram(sem_first div wordsize); (* init semaphores to passive *) for i := 1 to system_semno do begin putaddr(ram_pointer,nil_value); takeram(addrsize div wordsize); end; initscrtref(own.secret_pointer,ram_pointer); for i := 1 to system_semno do begin semref := ram_pointer; semref.disp := semref.disp - addrsize * system_semno; putaddr(ram_pointer,semref); takeram(addrsize div wordsize); end; (* init ram-headers etc *) initheader(ram_msg_header,16384,minint,ram_pointer); initref(ram_msg,ram_msg_header); if switches.kind = jump then begin with pointer do begin base := base_type(0,0,memtype,0,0); base.mem_no := switches.module; disp := switches.address end; jumpto(pointer); end; initref(common.r,ram_msg_header); initheader(program_msg_header,16384,minint,initboottop); initref(program_msg,program_msg_header); get_memory_map(prom_bitmap,prom_bitmap_index); bootload; program_top := ram_pointer; program_pointer := initboottop; prom_first := initboottop; prom_first.disp := 0; program_index := program_pointer.disp div wordsize; (* disp must be > 0 *) (* now program_pointer is first of boot descriptor segment *) (* program_msg_header is initialized by the initheadercall *) skip_program; (* now program_pointer is top of bootprogram *) include_programs; (* include autoloaded programs *) prom_first := save_ram_first; program_pointer := save_ram_pointer; program_index := save_ram_index; while program_pointer <> program_top do begin include_programs; move_program_pointer(1); (* skip stopword *) end; i := auto_mem_no; while i < 32 do begin (* move pointers to start of module 'i' *) prom_first.base.mem_no := i; program_pointer := prom_first; program_pointer.disp := 2; program_index := 1; if prom_bitmap (i - auto_mem_no) = 1 then (* note: prom containing boot itself, must be handled specially *) if initboottop.base.mem_no <> i then include_programs; i := prom_first.base.mem_no + 1; end; (* for loop *) (* at this point ram_msg_header describes the rest of *) (* free ram in module *) (* adjust ram_pointer so that ram_pointer.disp mod headersize = 0 *) takeram(headersize div wordsize - ram_index mod(headersize div wordsize)); (* now the rest of free ram is an integral number of message headers *) send_message_header(own.exit_semaphore); (* trick to get correct type of answer sem *) wait(r,own.exit_semaphore); (* signal rest of ram memory to allocator semaphore *) with r^ do begin answer := own.secret_pointer^(stopsem); owner := answer; start := addr(base_type(0,0,memtype,first_ram_memno,0),0);; size := minint; u1 := 0 * 4 + 2; u2 := ram_pointer.base.mem_no; i := ram_pointer.disp; u3 := udiv(i,256); u4 := umod(i,256); end; signal(r,own.secret_pointer^(deallocatorsem)^); if not revisionerror then begin (* set ra bit in my own registerset to release registerset *) setregister(-1 , bootlevel * regsetsize + ib); clearlevel; end; end (* boot *) . «eof»