!******************************** !* emas-2900 fep dx11 handler * !* file: x25_dx11b1s * !******************************** !! stack size = 300 ! n = new compiler ! c = Clock monitoring (needs a real time clock!) ! m = All monitoring ! %owninteger fep no = 9; ! number supplied on load #if ~n %control 1 %include "deimosperm" #else %control x'4001' %include "b_deimosspecs" #fi %begin %conststring (13)vsn = "dx11....1a " #datestring #timestring !************************************************************** ! EMAS Stream Use * ! * ! -2 Control Stream Fep -> Amdahl (Used by this prog) * ! -1 Control Stream Amdahl -> Fep (ditto) * ! * ! 2 Not Used (was for Itp) * ! 3 Not Used * ! 4 RJE Control Stream F -> A * ! 5 RJE Control Stream A -> F * ! 6 FTP Control Stream F -> A * ! 7 FTP " " A -> F * ! 8 XXX Control Stream F -> A * ! 9 XXX " " A -> F * ! * ! 10 - 19 Not used on Amdahl * ! * ! 20 First Interactive User Stream F -> A * ! 21 " " " " A -> F * ! * ! 256 First RJE 'User' Stream F -> A * ! 257 " " " " A -> F * ! * ! 350 First FTP 'User' Stream F -> A * ! 351 " " " " A -> F * ! * ! 400 = Upper = Last Valid stream * !************************************************************** %recordformat dx11f((%integer dxds, dxca, dxcs, %c (%integer dxos %or %byte cusr, cuor), %integer dxba, %c dxbc, dxmo, dxmi, dxcb, dxnd, dxes1, dxmob, dxes2 %or %c %integerarray regs(0:12))) %constrecord (dx11f) %name l == k'076200' %recordformat lev3f((%byteintegerarray a(0:100) %or %c %integer kick flag, from flag, %integerarray i(2:50))) %recordformat mef(%integer buff no, len, %c %byte owner, type, %record (lev3f)lev3) %recordformat controlf(%bytearray b(0:23)) %recordformat mEMASf(%integer buff no, len, %byte owner, type, %c (%integer stream, sub ident, %c p2a, p2b, p3a, p3b, p4a, p4b, p5a, p5b, p6a, p6b, trf buff no %or %c %record (controlf) control) %or %c %bytearray b(0:23)) %recordformat byteaf((%bytearray b(0:200) %or %integerarray a(0:100) %or %c %record (controlf) %array mess(0:7))) %recordformat pe(%byteinteger ser, reply, %c fn, port, %integer buff no, %integer str) %recordformat p2f(%byteinteger ser, reply, %c fn, port, %integer buff no, %integer str) %recordformat qf(%record (mef) %name e) !******************************************************** !* formats of tables, ie stream descriptors, tcps etc * !******************************************************** %recordformat streamf(%byte owner, First Trf, %integer id EMAS, buff no) !************************************************************* !* Commands from the Channel !************************************************************* %constinteger test io = 0; ! + parity ?? %constinteger sense = 4 %constinteger sense id = x'e4' %constinteger read back= x'0c' %constinteger write c = x'01' %constinteger write c sw = x'0100'; ! swabbed %constinteger read c = x'02' %constinteger write control = x'03' %constinteger write control sw = x'0300' ! ******************************************************* ! Dx11 Commands (+Go) ! ****************************************************** %constinteger Fc Reset = 1 %constinteger Fc Input = 3 %constinteger Fc Output = 5 %constinteger Fc Status = 7 !****************************************** !* Amdahl constants !****************************************** %constinteger my device no = x'50' !******************************************************** !* Amdahl transmitter & receiver bits !******************************************************** ! in DXDS %constinteger parer = k'100000' %constinteger nxm = k'040000' %constinteger selrst= k'010000' %constinteger SysRst = k'010000'; ! System reset %constinteger infdsc= k'000400'; ! Interface disconnect ! in DXCS %constinteger bsyen = k'4000'; ! enable busy %constinteger onlina = k'1000'; ! in DXCS %constinteger cubsy = k'400'; ! CU busy %constinteger int on = k'100'; ! in DXCS %constinteger Done = k'200'; ! in DXCS %constinteger StkSta = k'040'; ! Stacked status Indication %constinteger xba = k'030'; ! extended bus bits ! in DXOS (Bottom half is status bits going to Amdahl) %constinteger attn = k'200' %constinteger stamod = k'100'; ! status modifier %constinteger cuend = k'040'; ! Control Unit End %constinteger BSY = k'020'; ! Busy (Only set by Dx11 itself) %constinteger chend = k'010'; ! Channel End %constinteger DevEnd = k'004'; ! Device End %constinteger UCheck = k'002'; ! Unit Check %constinteger UxCep = k'001'; ! Unit Exception ! in DXCB %constinteger onlinB = k'4'; ! Real state of Online ! in DXMO (maintenance Out) %constinteger oplo = k'1000000'; ! Operational Out !************************************************************** !* buffer manager calls (from and to) * !************************************************************** %constinteger buffer here = 0 !********** to buffer manager *********** %constinteger request buffer = 0 %constinteger release buffer = 1 !************************************************************** !* calls to Amdahl link handler * !************************************************************** %constinteger send data = 0 %constinteger low level control = 1 %constinteger here i am = 2 %constinteger Write to Emas = 3 %constinteger stop = 4 %constinteger high lev con len = 24 ! %constinteger low lev con len = 8 !************************************************************** !* replies from Amdahl link handler * !**************************************************************** %constinteger interf addr = 0 %constinteger Input Here = 1 %constinteger Output Done = 2 %constinteger message = 3 %constinteger mainframe up = 4 %constinteger mainframe down = 5 !*************************************************** !* dx11 link states !*************************************************** %constinteger idle = 0 %constinteger wait first 4 status = 1; ! send status when read completes %constinteger wait first 4 = 2; ! waiting for the 'header' transfer %constinteger input trf = 3; ! Doing a Dx11 input (Amdahl->us) %constinteger output trf = 4; ! Doing a Dx11 output (us->amdahl) %constinteger read Control Stream = 5; ! %constinteger write Control stream = 6; ! %constinteger Send status = 7; ! Terminating Status !**************************************************************** !********** various service numbers ************* %constintegername no of small == k'040042'; ! in buff manager seg 2 %constinteger gate ser = 16 %constinteger buffer manager = 17 %constinteger link handler = 18 %constbyteinteger dx11 rx int = -30; ! special int (removes int bit before passing message) %constinteger t3 ser = 21 %constbyteintegername change out zero == k'160310' !************************************************************ ! Layout of Task VM ! Seg Use ! 0 Shared Perm ! 1 Code Segment (better only be one) ! 2 Buffer Seg 6 (So that dx11 can steal buffers (eventually)) ! 3 H/W Registers ! 4 Buffer Area (one at a time) ! 5 DX11 fixed tables (stack area of process DX1B) ! 6 Stack Area ! 7 I/o area ! ************************************************************ ! state variables ! **************************************************************** %owninteger state = 0; ! transmitter state %owninteger down = 1; ! 0 = up, 1 = down %owninteger clock = 0; ! missing interrupt count #if m %owninteger mon = 1; ! monitoring flag #else %owninteger mon = 1; ! monitoring = on #fi %owninteger proc B ser = 0 %owninteger base, PST real, PST, DST1real, DST1, DST2real, DST2, base page %owninteger TT base, TT max, TT pointer, Stack Page, my len %owninteger Current Stream, Current len, Stacked status, Kick to Go = 0 %owninteger tot out l = 0; ! counts control output mess %owninteger Int Expected = 0; ! Action on channel outstanding %owninteger read rej = 0; ! number of 'out of buffers' %owninteger i int %conststring (5) %array names(0:12) = "Dxds", "Dxca", "Dxcs", "Dxos", "Dxba ", "Dxbc ", "Dxmo ", "Dxmi ", "Dxcb ", "Dxnd ", "Dxes1", "Dxmob", "Dxes2" %ownintegerarray special comms(0:6) = Test Io, Sense, Sense ID, Read Back, Write C, Read c, Write Control %ownintegerarray special response(0:6) = 0(*); ! for now %constinteger lower = -2, upper = 400 %ownrecord (streamf) %array sta(lower:upper) %ownrecord (streamf) %name str %ownrecord (qf) mq; ! = k'143362' %ownrecord (mef) %name mes %record (pe) p %integer i, x, k, kk #if m %owninteger m1, m2, m3, m4 #fi %constrecord (byteaf) %name Control In == k'123000'; ! 3000 into seg 5 %constrecord (byteaf) %name Control Out == k'123400' ! Arrays to hold control (Stream -1 & -2) ! transfers to & from the Amdahl %owninteger mon pt = 0 #if c %constinteger mon lim = 1023 #else %constinteger mon lim = 511; ! up while developing #fi %ownbyteintegerarray mon1(0:mon lim) %ownintegerarray mon2(0:mon lim) #if c %constintegername clock st == k'072540'; ! in seg 3 %constintegername clock cnt == k'072544' %constinteger clock start = k'33'; ! 10khz, up, multiple, no ints %ownintegerarray timer(0:mon lim) #fi %recordformat hold bufff(%record (hold bufff) %name link, %integer buff no) %record (holdbufff) %array hba(0:100) %record (holdbufff) %name free hold %ownrecord (hold bufff) %name buffer pool %owninteger no of buff = 0 !************************************************** !* routine specs !************************************************** %routinespec input interrupt %routinespec Interrupt Channel %routinespec user call %routinespec put online %routinespec stop interface %routinespec clock int %routinespec up down(%integer which) %routinespec Do send status(%integer status) %routinespec Put Transfer on(%record (byteaf) %name r, %c %integer buff no, length, disp, type) %routinespec free buffer(%record (mEMASf) %name mes) %record (mEMASf) %mapspec get buffer %routinespec bpush(%record (mef) %name mes,%integer buff no) %integerfn %spec bpop(%record (qf) %name q) %routinespec free buff no(%integer buff no) %record (mef) %map %spec map(%integer buff no) %record (mef) %map %spec map5(%integer buff no) %routinespec fault(%integer stream, type, add) %routinespec monitor(%integer type, info) %routinespec boctal(%integer i) %routinespec octal(%integer i) %routinespec dump regs !********************************************** !* initialisation * !********************************************** map hwr(3); ! map top seg to seg 3 linkin(link handler) linkin(dx11 rx int) printstring(vsn); printstring(datestring) printstring(timestring); newline i = map virt(buffer manager, 6, 2) %cycle i = 100, -1, 2 hba(i-1)_link == hba(i) %repeat free hold == hba(1) ! proc B ser = own id-1 ! base page = map abs(k'140000', 256, Proc B Ser); ! get abs addr os second proc stack ! i = map abs(k'140000', 0, Proc b ser); ! release the absolute mapping ! i = map virt(proc B ser, 6, 5); ! and map it to virtual seg 5 ! ! base is at 120000 - 134000 ! ! Stack Page = map abs(k'140000', 256, Own id) ! ! ! First find a 1k area on a 2000 boundary ! base page = k'6000'; ! this is now FIXED stack page = k'6000' mes == map5(k'6000') base = base page<<6 PST real = (base+k'1777')&k'176000' PST = PST real-base+k'120000'; ! addr in this virt memory TT Base = PST+k'1000'; ! Tumble table base address TT Max = TT Base+k'1000'; ! End of it ! DST1real = PST real+k'2000' DST1 = PST +k'2000' DST2real = PST real+k'2400' DST2 = PST +k'2400' integer(TT Base+i) = 0 %for i = 0, 2, 255*2; ! Zero the Tumble Table %cycle i = 0, 1, 255 byteinteger(Dst1+i) = 0; ! change to 'go away' when we are sure of it byteinteger(Dst2+i) = ChEnd!DevEnd!UCheck; ! ie, go away %repeat %cycle i = 0, 1, 6; ! Now deal with 'real' commands byteinteger(Dst1+special comms(i)) = special response(i) %repeat %for i = 0, 2, 255*2 %cycle; ! set all the PST table to point to Dst2 integer(PST+i) = DST2 real %repeat integer(PST+my device no<<1) = Dst1 real; ! Now allow Sub address 1 through ! sta(2)_id EMAS = 2; ! artificially set stream 2 up p_ser = 0; poff(p); ! wait for fep no fep no = p_fn; ! supplied by load prog printstring("fep"); printsymbol(fepno+'0') newline alarm(50) use tt(t3 ser) put online buffer pool == null #if c clock st = clock start #fi %cycle p_ser = 0; poff(p) %if p_ser = own id %and p_reply = 0 %start; ! clock int alarm(50) %if int # 0 %start %if 'M' <= int <= 'P' %start mon = int-'O' %finish %if int = 'F' %start #if m select output(1) #fi i = mon pt x = 0 %cycle k = mon1(i) %if k # 0 %start printsymbol(k); space kk = mon2(i) %if kk&x'ff00' # 0 %then octal(kk) %else boctal(kk) %if x < 10 %and k = mon1(i+1) %start spaces(2); x = x+1 %else #if c write(timer(i), 5) #fi newline; x = 0 %finish mon1(i) = 0 %finish i = (i+1)&mon lim %repeat %until i = mon pt newline #if m select output(0) #fi int = 'C'; ! Now close the file %finish %if int = 'A' %then put online %if int = 'X' %start dump regs %finish %if int = 'Z' %start stop interface %finish %if int = 'K' %then x=0 %and input interrupt %if int = 'I' %start printstring("Control Buff:") write(tot out l, 1) %cycle i = 0, 1, tot out l write(control out_b(i), 1) %if i&15 = 0 %then newline %repeat newline; int = 0 %finish #if m %if int = 'C' %start; ! close output select output(1); ! select it close output select output(0) printstring("done ") %finish #fi %if int = '?' %start printstring("dx11: buf ="); write(no of buff, 1) printstring(", rej ="); write(read rej, 1) newline printstring("State ="); write(state, 1) printstring(" int ="); write(i int, 1) newline i int = 0 #if m printstring("Buff:Freed, Queued, Requ, max held:") write(m1, 1); write(m2, 1); write(m3, 1); write(m4, 1) newline m1=0;m2=0;m3=0;m4=no of buff #fi %finish int = 0 %finish clock int %continue %finish %if mon # 0 %start; ! monitoring %if p_reply = 0 %then i = p_ser %else i = p_fn monitor('m', i) %if mon # 0 %finish %if p_ser = link handler %start user call %finish %else %if p_ser = dx11 rx int&x'ff' %start input interrupt %finish %repeat !******************************************************** !* routines * !******************************************************** %routine input interrupt !************************************************* !* first part of any transfer is four bytes * !* two byte stream no, two byte max length * !************************************************* %integer dxds, dxca, entry, dxtt, comm %integer error type, stream, max, real trf %integer ind, s2, extra, i, rind %record (mEMASf) %name mEMAS %record (mef) %name mes %record (controlf) %name mess part %record (p2f) p2 %switch state sw(0:Send Status) ! Take Interrupt ! Look at Tumble Table for new entrie(s) l_dxcs = l_dxcs&(~(Done!int on)); ! Take done, ints off ! INTS should already be OFF, this is done ! at Interrupt level real trf = 0 i int = i int+1 %cycle entry = integer(TT pointer) %if entry = 0 %start; ! any more? dxtt = (l_dxes1>>7&x'1fe')+tt base; ! dx11 pointer %if tt pointer = dxtt %then %exit; ! definately finished printstring("TT? "); octal(tt pointer); octal(dxtt); newline tt pointer = tt pointer+2 %continue %finish dxds = entry dxca = integer(TT pointer+2); ! get the 2 entries %if mon < 0 %start printstring("I:"); octal(dxds); octal(dxca); newline %finish %if mon # 0 %start monitor('1', dxds); monitor('1', dxca) %finish integer(TT pointer) = 0; integer(TT pointer+2) = 0 TT pointer = TT pointer+4 %if TT pointer >= TT max %then TT pointer = TT base; !Circular %if dxds&k'176400' # 0 %start; ! Something funny set! %if dxds&SysRst # 0 %start; ! Seen system reset updown(1) %if down = 0; ! Mark it down if its still up printstring("System Reset ") l_dxcs = l_dxcs&(~(bsyen!CuBsy)); ! knock busy enable off %finish state = 0 %continue ! This is NOT good enough %finish %if dxds &2 # 0 %start; ! stacked status l_dxcs = l_dxcs!stksta stacked status = 1 ! %if int expected # 0 %then do send status(attn!chend!devend) %else %c ! do send status(0); ! for now (do nothing) %continue %unless dxds&k'20' # 0; ! nasty (after attn - both set) %finish real trf = 1; ! indicate something good in ! Should we ever get two (valid) entries together ? ! Assume one for now %repeat %if real trf = 0 %start; ! may be something to do %if mon < 0 %start printstring("Int,T="); write(state, 1); newline %finish l_dxcs = l_dxcs!int on; ! put the ints back on %return; ! and go away ! It would appear that an entry is ! always made in the TT if something has happened %finish monitor('S', state) -> state sw(state) state sw(idle): ! 1st activity, what? comm = dxca&x'ff00' %if comm # write c sw %and comm # write control sw %start; ! write command or sense %if comm = 0 %start; ! test i/o %if int expected # 0 %then do send status(attn!DevEnd!ChEnd) %else %c do send status(0); ! send back zero (no pending status) ! state = send status; ! not right apparently !!! %return %finish ! Sense Do send status(ChEnd!DevEnd) state = send status %return %finish Int Expected = 0; ! cancel the request now Put Transfer On(Control In, 0, 4, 0, FcInput); ! read 4 bytes into somewhere handy state = wait first 4 status %if down = 1 %then updown(0); ! Now its up again (Put this somewhere better???) %return state sw(wait first 4 status): ! read completed, send status do send status(DevEnd!chEnd) state = wait first 4 %return state sw(wait first 4):; ! 1st 4 bytes in & another command presented %if dxds # k'200' %start fault(1, '4', dxds) state = 0 -> state sw(Send Status); ! ie, go idle %finish %if down # 0 %then error type = 9 %and -> fail it %if l_dxbc # 0 %start fault(-1, '4', l_dxbc) %finish stream = swab(Control In_a(0)); max = swab(Control In_a(1)) monitor('s', stream) %if mon # 0 monitor('s', max) str == sta(stream) %if stream > 0 %start; ! data coming/going %if str_owner # 0 %start ! lots to do ! if -> amdahl then get buffer from stream area ! if <- amdahl then get buffer from Stream area and read into it mes == map(str_buff no) %if mes == null %then error type = 3 %and -> fail it %if str_first trf = 0 %start str_first trf = 1; ! done already monitor('k', mes_lev3_from flag); ! Is it being set ? monitor('k', mes_lev3_kick flag) mes_lev3_from flag = 12; ! data is 12 bytes in %finish %if stream&1 # 0 %start; ! Dx11 Input Am->Fep Put Transfer on(null, str_buff no, mes_len, mes_lev3_from flag, FC Input) kick to go = 0 state = input trf %else Put Transfer on(null, str_buff no, mes_len, 12, Fc Output) kick to go = mes_lev3_kick flag state = output trf %finish Current Stream = stream; ! remember who is transferring %return %finish error type = 2; extra = stream; ->fail it; ! stream not in use %finish !* must be a control stream transfer ******** %if stream = -2 %start !! inward control stream state = Write Control Stream Put Transfer on(Control Out, 0, Tot Out L, 0, Fc Output) %else !! outward control stream (-1) state = Read Control Stream Put Transfer on(Control In, 0, max, 0, Fc Input) Current Len = max; ! remember what we put on ! nb: pickup length FROM 1st COMMAND and use that %finish %return state sw(Input trf): ! its done the input to dx11 ! check it ?????????????? str == sta(current stream) p_buff no = str_buff no mes == map(str_buff no); str_buff no = 0 mes_len = mes_len+l_dxbc; ! dxbc is neg if at all, unexpired byte count ! bh = bh-1 monitor('i', l_dxbc) -> tell user state sw(Output Trf): ! its done the output from dx11 ! check it ?????????????????? extra = l_Dxbc monitor('o', extra) %if extra # 0 %start; ! only partial trf accepted ! repeat it !!!!!!!!!!!!!!!!! fault(current stream, 'O', extra); ! NB: The repeated transfer MUST start ! on an even bdry, so ? %return %finish str == sta(current stream) free buff no(str_buff no); str_buff no = 0 tell user: str_first trf = 0 p_ser = str_owner; p_reply = link handler p_fn = input here+(current stream&1); ! either buffer OR confirmation p_str = current stream pon(p) %if kick to go # 0 %then kick to go = UxCep do send status(ChEnd!Kick To Go!dev end!int expected) state = send status %return state sw(Write Control Stream): ! ie 11/34 -> Amdahl state = send status; ! nothing more coming in tot out l = 0; ! check mq ?????????????? Do send status(ChEnd!DevEnd) %return state sw(Read Control Stream): ! ie Amdahl -> 11/34 !* after the DMA transfer !! now cycle up the buffer, firing the requests ind = 0; rind = 0 max = l_dxbc+Current Len; ! length of trf monitor('C', max) %if mon # 0 %start %cycle i = 0, 1, 7 monitor('i', control in_b(i)) %repeat %finish %cycle Control In_a(ind) = swab(Control In_a(ind)); ! int value s2 = Control In_a(ind) %if s2 # -1 %start %if mon # 0 %then monitor('l', s2) %if s2 < lower %or s2 > upper %start fault(s2, 's', ind); -> ignore %finish str == sta(s2) %if str_owner = 0 %start printstring("Unclaimed stream from Emas, str =") write(s2, 1); newline %finish %else %start mEMAS == get buffer mess part == control In_mess(rind); ! copy data accross mEMAS_control = mess part !! pick up "id EMAS" if its a connecting messgae %if mEMAS_control_b(4) = 2 %then str_id EMAS = swab(mEMAS_p2b) p2_ser = str_owner; p2_reply = link handler p2_fn = message p2_buff no = mEMAS_buff no pon(p2) %finish %finish ignore: ind = ind+high lev con len//2; rind = rind+1 %exit %if ind >= max>>1 %repeat state = send status Do send status(ChEnd!DevEnd!int expected) %return state sw(Send Status): ! final status has completed ! Check for stacked status & everything OK ????????????????????? %if mon < 0 %then printstring("Sequence Finished ") state = idle l_dxcs = l_dxcs!int on; ! ensure ints are back on %return fail it: fault(stream, 'i', error type) l_Dxcs = l_Dxcs!int on %end %routine Interrupt Channel Int Expected = Attn %return %unless state = idle Do Send Status(Attn) l_dxcs = l_dxcs!Fc Status!stksta; ! Tell Dx11 to send it+ suppressible %end %routine user call !**************************************************** !* reasons * !* 0) send data - high level control * !* 1) low level control * !* 2) here i am - ipl info wanted * !* 3) Write to Emas - Buffer to go (Not needed?) * !* * !* NOTE: The Dx11 handler swabs both the stream * !* number & sub ident of ALL messages for * !* the amdahl, the relevant task MUST swab * !* any other 16 bit quantities going in * !**************************************************** %integer stream, buff no, stm %record (streamf) %name str %record (controlf) %name control %record (mEMASf) %name mEMAS %switch user sw(send data:stop) %if mon # 0 %start monitor('u', p_fn) monitor('u', p_buff no) %finish ->user sw(p_fn) user sw(send data): ! high level control ->Amdahl user sw(low level control): buff no = p_buff no mEMAS == map(buff no) stm = mEMAS_stream %if stm < lower %or stm > upper %then -> stream error str == sta(mEMAS_stream) stream = str_id EMAS %if stream = 0 %start; ! error stream error: printstring("dx11: attempt to send error stream, stream = ") write(stm, 1); write(stream, 1); write(mEMAS_sub ident, 1) write(mEMAS_p2a, 1); newline free buffer(mEMAS); %return; ! junk it %finish mEMAS_stream = stream mEMAS_len = high lev con len; ! hold its length str_buff no = mEMAS_trf buff no; ! nb: on BOTH Inpu & OUT Task passes ! buffer into the task %if mon # 0 %start monitor('u', str_buff no) %finish %if down = 0 %start; ! Amdahl is up ! Swab the stream number (NOT the sub ident as in the 2900 case) mEMAS_stream = swab(mEMAS_stream) ! Q up to 192 bytes (8 messages) in the Record Control OUT ! Then q the rest on mq %if tot out l < 192 %start control == record(addr(control out_b(tot out l))) control = mEMAS_control; ! copy it %if tot out l = 0 %then Interrupt Channel; ! hit it tot out l = tot out l+24; ! ought to be safe to do it now free buffer(mEMAS) %else bpush(mq, buff no) printstring("Q'd! ") %finish !****************************************************** !* note: stream & sub ident are alwys swabbed !******************************************************* %finish %else free buffer(mEMAS); ! junk it %return user sw(here i am): stream = p_str sta(stream)_owner = p_reply; ! enable the stream %return user sw(stop): ! stop the dx11 stop interface %end %routine put online TT pointer = TT base; ! Initialise Tumble Table pointer l_Dxos = pst real; ! set up Tumble Table l_Dxcs = l_dxcs!xba; ! ALL transfers to top of store %cycle l_DxcS = l_dxcs!onLinA; ! Put it online %exit %if l_dxcb&onlinB # 0; ! wait until it goes online %repeat l_dxcs = l_dxcs!int on; ! now put ints on printstring("Online ") %end %routine stop interface %cycle l_dxcs = l_dxcs&(~onlinA); ! knock onlina OFF %exit %if l_dxcb&OnLinb = 0 %repeat l_dxcs = 0; ! Knock int enable OFF printstring("Offline ") %end ! ! routine clock int ! %routine clock int !! handles clock interrupts %integer i %if Int Expected # 0 %start clock = clock+1 monitor('w', clock) %if mon < 0 %and clock&3 = 0 ! %if clock = 10 %and l_txs&ready#0 %then Interrupt Channel %if clock = 20 %start; ! 20 sec timeout fault(state, 'c', Int Expected) up down(1) state = idle int = 'f' %finish %finish %else clock = 0 %end !* routine up down %routine up down(%integer which) %integer i, ser down = which printstring("Emas state ") %if which = 0 %then printstring(" Up") %else printstring(" Down") newline %cycle i = 2, 1, 8; ! send 'status' message to itp, rje, ftp & xxx ser = sta(i)_owner %if ser # 0 %start %if down = 0 %start; ! going up p_ser = ser; p_reply = link handler p_fn = interf addr; p_buff no = addr(l); ! pass 'l' (it may have changed) pon(p) %finish p_ser = ser; p_reply = link handler p_fn = mainframe up+which p_buff no = 0 pon(p) %finish %repeat !* tidy up variables %while %not mq_e == null %cycle free buff no(bpop(mq)) %repeat tot out l = 0 %end %routine Do send status(%integer status) ! NB: Leeds Uses a MOVB to do this ! l_cusr = status %if stacked status # 0 %then l_dxcs = l_dxcs!stksta %and stacked status = 0 l_Dxcs = l_dxcs!Fc Status; ! Tell I/F to send status l_Dxcs = l_Dxcs!int on monitor('x', status) %if mon # 0 %end %routine put transfer on(%record (byteaf) %name r, %c %integer buff no, length, disp, type) %integer abs, index, ipg, xba, fin, x ! this section for testing ONLY %if mon < 0 %start printstring("Trf:") %if type = fc Input %then printstring("A->F") %if type = fc Output %then printstring("F->A") printstring(" L:"); write(length, 1) printstring(" D:"); write(disp, 1) printstring(" B:"); write(buff no, 1) printstring(" A:"); octal(addr(r)) newline %finish %if mon < 0 %start %if buff no # 0 %then r == map(buff no) %cycle fin = 0, 1, length-1 %if type = fc output %then monitor('o', byteinteger(addr(r)+disp+fin)) %repeat %finish l_dxbc = -length; ! set the length in %if buff no = 0 %start; ! from this task space index = addr(r)&k'177700'; ! page address of buffer ipg = addr(r)&k'77'; ! residual within page abs = stack page+(index&k'7700')>>6; ! 18 bits-6 %else abs = buff no ipg = disp %finish xba = 0; ! extended bits %if abs > k'1777' %start; ! need 17*18th bits xba = abs>>7&k'30'; ! shift bits 10&11 down to 3&4 abs = abs&k'1777'; ! keep whats left %finish fin = abs<<6!ipg; ! real address now l_dxba = fin; ! don't want to 'or' in the register xba = xba!type l_dxcs = l_dxcs!xba l_Dxcs = l_Dxcs!int on monitor('t', type) monitor('t', length) monitor('t', disp) monitor('t', buff no) monitor('t', addr(r)) %end %record (mEMASf) %map get buffer %record (pe) p %record (mef) %name mes %record (holdbufff) %name hb p_str = 1; ! short buffer %if buffer pool == null %start; ! have to ask for it p_ser = buffer manager; p_reply = own id p_fn = request buffer ponoff(p) %else hb == buffer pool buffer pool == hb_link p_buff no = hb_buff no hb_link == free hold free hold == hb ! bh = bh-1; ! from buff adds one back on no of buff = noof buff-1 %finish monitor('g', p_buff no) mes == map(p_buff no) mes_owner = own id %result == mes %end %routine free buffer(%record (Memasf) %name mes) %record (pe) p %record (holdbufff) %name hb %if mes_type = 0 %or no of buff > 16 %start p_ser = buffer manager; p_reply = own id p_fn = release buffer p_buff no = mes_buff no ! bh = bh-1 pon(p) %else !! short buffer, so queue it hb == free hold; free hold == hb_link hb_buff no = mes_buff no hb_link == buffer pool buffer pool == hb no of buff = no of buff+1 %finish %end %routine bpush(%record (mef) %name mes, %integer buff no) %record (hold bufff) %name bf bf == free hold free hold == bf_link bf_buff no = buff no push(mes, bf) %end %integerfn bpop(%record (qf) %name q) %record (hold bufff) %name bf %integer x bf == pop(q) x = bf_buff no bf_link == free hold free hold == bf %result = x %end %record (mef) %map map(%integer buff no) ! New compiler - so must get 0 %result == null %if buff no = 0 *mov_1,0 *mov_#8,1; ! desired vm seg no *2 ie 4*2 *mov_#k'2006',2 *iot %result == record(k'100000') %end %record (mef) %map map5(%integer buff no) ! to hold dx11b specific tables (must be in same area as buffers) *mov_1,0 *mov_#10,1; ! seg = 5 *mov_#k'20006',2 *iot %result == record(k'120000') %end %routine free buff no(%integer buff no) ! not mapped, so send it straight back %record (pe) p %return %if buff no = 0; ! rest of code is very loose on this p_ser = buffer manager; p_reply = id p_fn = release buffer p_buff no = buff no pon(p) %end %routine fault(%integer stream, type, add) printstring("dx11: fault "); printsymbol(type) write(stream, 3) printstring(", "); write(add, 1); newline monitor('f', type) %if int # 'a' %end %routine monitor(%integer type, info) mon1(mon pt) = type; mon2(mon pt) = info #if c timer(mon pt) = clock cnt #fi mon pt = (mon pt+1)&mon lim %end %routine boctal(%integer i) %integer n space %cycle n = 6, -3, 0 printsymbol((i>>n)&7+'0') %repeat %end %routine octal(%integer i) %integer n space %if i&x'8000' # 0 %then printsymbol('1') %else printsymbol('0') ! compiler problems %cycle n = 12, -3, 0 printsymbol((i>>n)&7+'0') %repeat %end %routine dump regs %integer i %cycle i = 0, 1, 12 printstring(names(i)); space; octal(l_regs(i)) newline %repeat %end %endofprogram mes_link == buffer pool; buffer pool == mes