From 912f421144b01f911d02a656f6c0d75f3eecba16 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 24 Jun 2025 09:57:49 -1000 Subject: [PATCH] CONSOLE: Add general support for SET CONSOLE SPEED=nnn The original SET CONSOLE SPEED=nnn was added to a allow direct wired terminal connected to a host system serial port to be a simulator's console. The current change generalizes all console I/O such that speed is a reliable option for direct console connections as well as serial and telnet connections. The simple recipe to get well behaved console output speed is: 1) call tmxr_set_console_units() in the reset routine of the console DEVICE. 2) In the code path that engages console output do something similar to this as appropriate for the system being simulated: void txdb_wr (int32 data) { tto_unit.buf = data & 0377; tto_csr = tto_csr & ~CSR_DONE; CLR_INT (TTO); sim_activate (&tto_unit, tto_unit.wait); } 3) In the output unit's service routine the console output unit's service routine do something similar to this as appropriate for the system being simulated: t_stat tto_svc (UNIT *uptr) { int32 c; c = sim_tt_outcvt (tto_unit.buf, TT_GET_MODE (uptr->flags)); if (c >= 0) { t_stat r; if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ sim_activate (uptr, uptr->wait); /* retry */ return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ } } tto_csr = tto_csr | CSR_DONE; if (tto_csr & CSR_IE) SET_INT (TTO); } The almost all of the current simh simulators already are implemented with logic like the above example. These will work just fine with the newly regulated console speed. --- README.md | 1 + doc/simh.doc | Bin 309248 -> 300544 bytes sim_console.c | 85 ++++++++++++++++++++++++++-------------------- sim_scp_private.h | 5 +++ sim_tmxr.c | 40 +++++++++++++++++----- sim_tmxr.h | 1 + 6 files changed, 86 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 4f6c9cc7..15ff04d4 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ Simulator binaries for x86 Linus, x86 macOS, and Windows for all recent changes - Simulator THROTTLING can only be enabled once per simulator run. This avoids potential errant behaviors when arbitrarily switching throttling settings. - EXAMINE memory commands will now produce minimal output that summarizes multiple successive locations with the same contents and may be aborted by SIGINT (Control-C). - Ethernet enhancements on all platforms and and much simplified platform support on macOS. +- Almost all existing simulators have useful SET CONSOLE SPEED=nnn behaviors in both the bare console session as well as TELNET console sessions. #### All simulators build cleanly under OpenVMS on ia64 systems. diff --git a/doc/simh.doc b/doc/simh.doc index 091d7fe7e0540cc32ec5820a0d59d9e12c2c76d1..e26e17f281077204960e4e91e78328a498d3b98a 100644 GIT binary patch delta 52149 zcmb^42SC)wAL#LH7P~0+u2`{mJ#{VE&K7&`Siy=SV0RVk*(}<`W; zx9{J-i#r=|+Yt@X2#sY)4IFDza?hwqhNZGitMO6>8%avcej@oDNTipf$}MFni`0K; z|DiT*Y}!~Jw4P?L$t_hMX_N++P=^YY8_CN8(-c}ZTwZD}&wMW0OVU8D*A=$BD#s~F z8p-X7#U<%5bA0Y#x&K$!L8T?BM>xF^Kz8DLe^^98{ zv=k_U8ym@3b*_(%wLFsgTD(ohx{{>NReztL-FD+rdPngB!y(jH}YjJzKBpId4C)6rUjBOg}PtcylL@&R{;C8a1 zmrcLc%dg+2wgS_XDwcB7@<#gYly)JWmZm$A7)Yvk9sLQZuk`|?zCY#mvV!T>Rn@bd za`%t({m=WEYyIs1dH24$>EjKVs#dGe(qm+Ws+FtO*k{TZxzlE_tB2dZ!iPE=)uwk0 zb|nY6jvV7Ud{AGHkwe_a*q83yrbQ?FvTox%M!CC{x3}DKAGhrKv|ROv3>-AleaPS; zgT~mqy9~0oykM-$kO40CgZm8_GJJ@8KlefQN$+PrWaKChcl&-L2im)OxRX?)i^@eS z4R&)Kp}pE|(3nB)_HH~jWaJ?G!LDxFz50s>4)Po_U{FQd>7$PZj6P~uyeOb@xY5C& z8WcHChB|Z}Ce&3cC~~<{88S$cEsDS%ri_ww1HovYNs>Cilv%CcM$WAsRpiX|3|Uyf zVS_Ztg82C8Nd7|NuU-v0ap1rKf9;<{(&fa7jp{~qq1!^SJgawy%C*$pJ>~3b#n$p> zjycTzK>so0{by@#AuecVwlptc^tdpHf_X07&eeYNZuxjxH* z>ex}vuf}vGH;*UE1q=>;on+be0&~5Hn+R2_bl{aP9puvLS~0Qf!lX$TId7HdsNkr; z;Hco}D3RKooLZlpT9}-gEK+LUu5xkJsVkYd-c>HBrR3ML8arIJR||F|TNAo-x0an5 z1LX2Kr7B@rB`E@T5r=nKRnIPR*_J#iEd=C8>|5}EcTG4it2pk z;oXCoRqsLWoqEV69Ns**{ovH?Q@0=7-jkg2)lv^`FXDR4?LN1ehZ^WgMAP?_Ct2S1 zaZl=}dq=r~XcpDw?rBA>`KejT0mLVt`9S5A|~U+WIGdYC%JUB zUzbjlSd`CF_9=RblHThl7ZbIfPA%3~p0AZpz1~+YAXnL_R&f&Tig#AmGV$&&m#(mx zK0D#bt%O^F34sZ>5_Tu2)+eVHYN_!&sx|OPH@ULhEj3R|1##bmX787I+#GT86lTdS&+KR zl|9uzT;ytM`k~CIu9%D(N>`E`>wUy?LvoClXsJouH;mMz1T~w7oJ;n~sX7jjn}}9Z zEUECrm|dcarMyWY&o8pT5}YHOL+d<})CL1E5Z=R?Z*?(oVS!ImI4}LK>NA{B+KiO# zs=0CdQTXNXBbUQ3KMMCFwSttNmYR{A8k3w7OVX3!^0K66Jc9Qb-(4m(*~n0SwpOIKNtk8v4(UG1VNh-$Yqg&}Ic(R#P_cyv-rlV9brguJe+++3a2 zQSKwZ%dIW9hB9icQPj2z^HSH2lI=5_@=H=L^oF+^_f~h43s%%?F#1$-YEM#%s`gF3 zbCH&!u~)Y&!4df_Gk!cKDJyD;(R!n&|EQ3qVi5B=jXMZe2f4}RyxqlI#l(e4jjRR# zb)<=PLl3!WQitWitW#DfS;kQ1DLr>m=>0rt_iLG*jfvTLj}ti%6Bi~GK5~~O{$dfk zy;obt){+#<-P+qCB`Uy@qU^;jWe+NBDSQ3#1l_TxShtPWv$DIRTwN_i&ZvO3<7i)b z3rSKwHQNNaQaux6Xp=olJ0@ZuF2k{?B(=qU96{w`4CP@$E40I0^~MC*L2d3S+jTaT zV3k~wRWjT#20pk1Q5>tz|1Te(RX*Bfv5)01=}O$-lJuaD537UwaxV3DC1YN7_(VE` z-4j{9v_4E*9XJ-znpKusVkYlVu@o6pGfa^yWhltTKrxuqz)9pWb`oo%PE+K9HYT<* zyr;?qWm9>zn3r5iZRaKDO;fv~cTXreQzYefA`d=%^YEeda}w3#HH?k?rpPuW#k=IJEJ?Xg1eIYzcl5&;tWgV1 zm-DEO)8)MFw^kwk2tooRHl^~R2u$dTahQ&!xPUvjj~B?t7E6B2#X^|WX|v=UB{S7v zV1TYz1s}Y?YhgQn^~O_*Rxt}0iB6g)4_D9bF=k6AOYPavuj98+ zmJ5rSbVMf%#2}2v1ejW?br#B1bKh%4T0t90ioq+G+NoKV%QX!qwc&EPfW4`cB(=s2 z%*1{ifQijV1>P%Vd!AcprJToX>LE!{J!zKsfa<+?9_ryJPN8gXmdcpNcS5gNUw*u0 z{fJfi$0u>?^yw?7uh1;A<#w4~dW@uA@{u#CQD&o^dUT1LK2OeEF1t%^lyYm+wgg55 zN6MnMUm_RH&4c-iu1@t}Yro|*x0SM-QDn0mOnubfSIUJ8AV&T7nE@MY4?M7ksX#pR9mM?&ov&8YT-Drc~Cu|q=%=M|%|u%Wx(YU1L{Vkq7; zlP5F6MO;EKBJp}Gy*d(*b{x+^h4FO2sDWlMO<+xcF_?gbI5d%+NC?C&m?p7vXfoA` zyr>M*6iFH~MH(y(B{3Qk@fF{Y#w<2^>crCO#&}^C?0*CaOX8!$vN#=1ng_il4_)%rZ@DomW4vflH29{gllT# zJh9=rUe00Y;J1m&+``7Q$k0sn0cEx2wUPcT z_rvaA;jh@0`?04Ep4xWm)cRA2>l3{b7bGUeipvb1DX!>l1AQ10H1wB?s&4*rFE!Gi z4sz;d`8V}`XQQnh!4P56V^qy=yDS$Ha~lbFY{Gp!KA(w zYK85rl#lL|Gpo(F%l3s#izR6*PT(Ux!L*dRM_0A!Zn;RKgjY}Qh29H&a`}nna{9?> zJ&|+|SARd*y?ghT-D`I*pR;_ol4heDjb0tB-S;H)-hcfXE7eS1T-AC3vR@%%uF)ya;Wc^E zj!nK@%kOXcUy+M7u-QPjhs-Dm6Ao^q>%(zGz_f``;9sn|5r=p9gtUG#9{tENm_tgD7T-N;4{8JIv`0IPy;p56V~0L=r5CQ z>)oT)M~1(Ct#zf^4W3|mPQvROq8ojkP?`HLh{weJ%!RnywEvtOcTrcO?ozr|^}sQ? zj2as#XH{RWmvb80`W=_$+9EejaE1rg!Uu&9vUY$yilQVc!GzxEqZSQfWs@&}r=k{W z!x62~?Qb>(;Dli)e2BoHJgUJFqYtxE#ds{jVzf9ymx@+UFbR`!5byC3pHS^69}ni4K1O9 zV+LBIE97OMC8m1ED}pL+CkM5SEalJTQX=#6q$egnAWOZ{PZKjq{qp)JY^z>B zEw@o^+sd|CB4{nimk_n>K4U)1Q^b?AoKJp;L=bD~eCqu_y58 zg5*4q{o3M#x{RfyOuuL3wkWP-LvtD^ie>$XxUF74BUdu#7Io%?ei#imD96~li~g`b zPMbse6D&EXh)PiK5KocwBp=D42!>z;*5NPY31kF@d{EF8-4KNyr_9X!lq3zu2q;0U zLQgZIz%2ZU%{YQUoW>c1A^`=?u%>~6QCNaQcz_IN$t*g;3wv-EY0fdkf`YzgCc`lr zQ{aP(c!X#8iVD<%2@TN!gD?~mu>z~H7pHL^;mCf0Q3(>`#pYM?h?(uMaBU+@44Sz- zN-w57<)ykumGkD-o+u_r{!dhW8B2-5M_Sdt3hm?hWI4~UE`K@d5-_~GXD#yCg^vV*IBq~Q#igjh=z90nzuQL`g zc!yAmDZ%8)aV(SXo=mRgFlP4NU}K}+za|$oi@M|KQgzfoZ73LvNmvSR?8h+#BNXrO z1=%iA|ELBNdSd{#Vi%qv2FfJ{8t}kD9L1YUbfpO-8eV4LhZR_ja73cm6^0g2FdAcV z5@JKv?kY1zNt8!Jw1gLC;|gxV_8OT)3n=J>rC5!Z*H|p=ud|YXa)V%E24=z=8?ggB zL1WeS(^xhEt*1#_h5B8oZgRJHMEr*bUp#d&m==+IS=O5&sCTH`L%n*zSU|ns)tJ_` zg>`+1dJwS}@fI-_@fEQZaTW0tu_TUK2u1ir=tS5=xJ0N#m_&#~ctmJKSVTxfI7Ap; zUb8fMI}e(*owKo_dVIL?g&OsS&DpEdSrDVf8?&}bBYNQLavw+rGGE{&FBO3k0TaQ= zPpRso0UXgD9WX0|+CcA{th{mPrs^8ZGNvst!O}Dh3ww_ zO>KNj_EtBC@WIXf5ILWDRQf(MMx~dshJXc z_=s;%D6cbyLofea(u?pmL^OF4dO-RU6c>z!rxqaIkn13v#}$+%4&|U=942FQ7+nI) zn2tXXjtIO*0?HCh1?}OE@mP6_CV!TM@irT5@WdLdMe#e77z#SV3%l_EIm21r@Cxsd zAh3nTUjm*yxpU{ndF_wM4NF45DefSBM@(+y7dNz&C6PS6b3>h0z*tW83uRBUTc}*3 ztJL<8Rq?Hh{IjBpVy?vhD&61e+igy1F?N3pU-w+F0GF&JM{nzb4^Rc@!+b!0*4bC14SPdTXTL%7e*mZh># z(xV&9BIXJiIEl;nS*G%mF$X9Z4tFfaO88+L_TUIk;XL$$RHPvFFb|8d0e;wx{gJfX zBP0T0U1Eh&>ZP78N({a9y(xJ==uuE8y>%p_xcvan5sy+28Oop@8lo|pAQ3qpnQ4WO zC>b8$A)=9pijNuVpaB}ADca*M?%^@wkmU(O7UV=ODCmj75M8u3F3~=Hc*rh4@h5iu zCH>V%8sAv%3=a=adbZ_h+711wNiP%Y4E6E@KCw&QKj_*;Gy%QfKNiqZKD}(B40`_c z{5~e1PmuR1-8_0?C?;SMCSx6T;vz0TwRG=}kHnh)1ucwrRb938_HVe!eGV#*o-~UP z41*{1+1T(F8S&3&M~}txm1k^#;vkf0!i#C}Lb?}hiKD?wRuyOlqEh6tVf#Htm3c;%MpkRxQv^4kI%4s!_Wr`+P*j@Lu1@}FtDdBm%i*) z|5XgzQY<|L|EB0)f9%f6{Md=5^l1&npn9zu^-Q)mTZc>!*L^}3h2rm63t<;_V^BN| z2!CKVLSgfs9i^C#d6oW2|7mGODXmMGx@12u70n>I zX{z-;$TL;nPxN+nM~t>?7&TP4zhS?}walz%*Q;V>EBZqQzV>EU;vmZIfj=-8ACQPl z-|4SF-@z%J~?K0L)UyhKr>L2`hCj_8T`ScYo|MP?g=WQX?Xf`K+>gEWG~BuvAf z*n}5&hn#GT+oL8LK|y;A!Em_Z01iP;YmjV^6S+|eWl;-tA$DSjeHLPMAJ0fYTluTg zC(8xOXvw6pLh?Ysa{I@d;)9n4uA0362~^9OuSkPU`mqIjZcEwKnU5sF&rX`+~q1qi_3h{g+iL6r;! zsVc@}0$OG?NS)CI+u)BgIE&92wG7kzL$;uVVIpuNHYHPHl3VHqH3 zdlMK}&;TvN1E%-ybL-Zv5cN+7V{Ua(R%05wOQJIlu{`HgBA+9PLxHj|e3;+mb@K3G z(^t8tS)p>03;Ayfs2AvGWzox^=iQh5$KVsJ`a1e(^<=QTFsW-6UE2>GUw(DrciGJ> zO0Qrt7Q*`7K686$PO1jeFaxtO2P<$8p@>J0Tn4EQ6!gI?>_-R;xmnUt4&_k^mC+`* z!7Q~U(GknwjUb$doW~%gLp9Wa0w)Z{9L&ciY(ofcA!lBLR1g(V6di;pF!#c zC%i^nKKi$j`3;ggULpoc0p1Wdp%gMm-H@}eLCS@KD25U!i}I)ntueez8C}w5k}i)T zL?UJUX_XAVn3$N2CidgY)Pw1arPU2aV+(UTQKh01{#Vd{7H|=4t3YdU7BLp_6|og@ z74a0Y6mb+WWG$R>`Kn%@!lwn=7LDTwqnFrA%kIuJ#*?n%xgypg&U%dX@adtm4%-ew zv=dix4K<4xq~Fj7eQ^K>@e(oUU{9OCG` zV->Tgh2Kygsb?3;eG$-St1t_F)`Lh7L+UKVabF@*WkvdfEGDhF}T2v9W|f+Jaz&AahBBWQ&3*4h1br(H~+V z7L_t{rvr@|?@*|;K`M+97>Nz=$2nX;{xY;-lt%^Bz;95H()U?fZt_$dL?^bjXtH5p zmS!s+)7ozZahIjj6nBVQ&l0a{t}?h58&@BzHc0LreXAIAsV6cS9nI~j-{fEtNG*;( zi=Q4ZJyxk>^J6^zGXyUv+DpWMA$!s#U`l4Am%%K`Jp}GJi;K8~%Lqjno+BF8ZxqMv zPxuV4vh;dT%2A0>u@b)6i+z|@p66gU_TXMDuN1BTChDeXb zmAD^k;e+kifjtNS#|Au$480hdcp@=i*Dk-6dxT`LxdzXiJz6K86bmpF}0 z>FgpJR)^|jPUoeDrAK4uvD4F14U5`eX$k~k+F(FDudxrky2%3^^-d4lCg(6dAr!fvV)25CWh}jj+6Sn zofN~cHe$kFm>l#CA}If4UW(QH&X9hE%2f@LCywJgq-q2o{m>twxR1wp1-t5WjTnv* zI9Q$9Jxt;iKHv+|)Zk6f2mSFk4&gQ8kh>;9K{+^K7(B2a=TYo87FpDUg1@i>fw+Ln zxPtpgTdOn6crBiY**FAC)mu$twX_)fh|y2dHObh>*s$}lVTWUP#%|kYc_8Uk>c#@b zdg|hQMpu`{qJsWg!1Q40LD9==U5+2~{GVAqT1#6GG)i6%^c3p>TeWZ=<0CUg;&JI1 zB5)T`$X44RF$|+|0T*EoVe%MH z@Dg#TYcfdnprAW?zzNRSgS`mBO@!kiCf7AcQ!ocAR$>*Ddb}Qe;08~u!fI@(M+-Yc z;xV$;XS9T&@WuvgK_G&08_|ftD<}?;xQB;`#%mOCv@{lNjG_-z#I<(O6V+1g z5Uoe7C&I&dj{bPklT)6>1L~e4#}McZts_TMuHkT5sm~hv>+XCz(ex@VRc!F6LTAjpxnc#l@1|U`W!NY_YtN6v1`c zhO95(h=x$m2|Y0sD%QalXK)Q6uxVtFG9Wv0pf%c{A6zgN{*7pGyGWeEIb6ecWN1wP zhwR9KmS_b9ZP6QjF&4|Q3zzW@d7AKCOn@1y;EO0cL(!&eYePY&re+o?5;O1zHed_( zVjn_q2lo((`-nn;-x))p5^AC;+%O&!5eB6h+uG=cUKoyPn1wCaj)dMEjb!<=9GGM| zHc3pi~QW|1Ik8Rl`1GDeZ`i0N)ZuC&MtkE<`EoKH)nmwxfyT8D8QYKH)Qz_S7dnLh8Wy3wrmgjodB0Hl4RN*cYP# z?W-T+^OQH*rz%Wph;;JZ;vvf;iI2h_ardJed~nDPZ_BaY97M;^GS0b`YW0!IY}sxY zRsTN&PO$$Y)<27rb&>U=ieif5$sG)8;1roXWaVku=A^r%96XdCGcgOR5RA_#+mT42 zJ-VY8dczf-@WOWd*@@~yJl-P#2F6=56x8d&7AZQRGkSEP?F=Nb6w9y*f1+YndL-0G z12ltzPKd?}yuo|ebfa&_BuvJ1tiU>~N2cx!L7|{EoNyXf5Z0ZxbD{@B9|R%{F?fXn zJ=rRRBO0PP6tu@2_+T9}_M(qRMO4C<_?Pit9wlAGjYr}RF7fg4c*)gE%amk2Jsqyy zCnmu>O@AIQ)LtRB7}HI7r*AQGT!404^&xT~Vnk zNv|8dF7){8@lG{J$a)?-_{ zHv>AnL=2+)&=`=ZFS`Y>9|thUiCzso`_Wp_dVtpG3s^ogv<)E-+F^Ctk#{LKIgFH# zW~TCS%@6k_^|ic$N6mb-fWz-Ht8ZS)wq{w940Ij*O9e#b*F=3x!%X;L8+KzqLU0SO z@fP_hL}BO!Q%Lv0U|hfr=!K0Z-GRdPK^P+Yu=u2ofI{h=F&fh_7kX5Vl0J)kM5YLu zqcxl`03H|*FU*1-#l@so;VnKO9}z8tYW>WVm_&0Z=#1{r!#=q`Q9zynbgOR?pIZIV zlZx?hWN_q#$di!=_9WdF_oh7UKX2)qPoo+JrS6fWvC^Dx24m12+%*h@K zsC20f24OJ9;}5LDcI-d|?&C3@!8nk;3b03U)I~!$VIT&>86zoEEq^QmXp|w zE!c%q2*Meh!+Bi54cvq>h~XrL!4(s*1^zgL3%HGkup7+AFglM zf_k=$`Ly9(@|ci;ow|fCIaT99>!DuqfY0hh;y&$3Nl#Vpj4?Vi_$L+lUn)jjGF6_g zZPo)#fOV9r5UEB`;6$_rVm^GJM{qCcAmk&8h0p>DTBAKWVKJ6tCDwY- z73g8V%pH+9LFjKluZE|j6Cu|2{KxS3NK9kmBjV#jLgKlKh>wYgh>5urA9N{*r#y;} zKP)CV9DkU9?N8j)?qnszxIldEwq|l&k%Dnp^9hC_BTXkAGNL{jL2ptDX=k`#CKkhW z0>POuf&Fiog9TWHhj@;U_=0Q`8M?t9MWJ9e=HM^v#?eXas=+CQAj4!{hiXvJ8C@^} zUf7PkW+nkRhP!x(NmE!TFas-a8El#N$1(PiKXP;!t2WgN;v=LL(@` zOzH$vV8#vH!7GlsmEMww$9trkWspjvGu*Kj>*0$$v-#K@MNk0>`eP8LVFqSm7GB{s zls_kj2fu9fYK`@+G5l~#vf1?@mW5)!yD%yT88!I4I7Po&MumjWsqd` zAa|yGvZQ?)f8p?9@zgho2N@epu2X=+h4d{=^-ynPC2_=mx{OxeYTVe>*l2ijQJJa3 zZ5>|gkp7zprj8QPQJ2{A8LsUJL_Ya|3BX+B3LsanGNH zR7C4MF5veiY!jmUQhF?mMcgu~csZjtob~3pc#Al!R@o;3r+6r7|I%!BMindTtIdob^;+k9H5{zy2AtGu^7wI zV;vh5=#Nnd#1%X=GkFYUJxe~O;x*o&n=doPOf19(Y{W%eg7PP$jE(epP~eT#*oA#K zhyZ*^eEUlK7WmyKA^bggqF(7wIWg4m zLB>Mnj(Yr4$N8UxSP!orRy|~?qmnubDF?`?U%ttGRPDe9aonQn>qT$w_+5Nq)7fb6 zDnh1*OApN%!t)xrH?jGOk=TGpr2C7H>(CmmP;m?2P|}Zu7bCF(0f-2#WG*%AlEODbqkFgu2{W=70GE5PmpCRojVi^f0G0Zy;QmK!|7l!BJoPw=*ol~(g9s4^0jFGIB{j=vV*~Ml zk&Bo(sI5mE_nF1>L-05AGpl{KOei+>O%=W)W}_Hymb)azpzV~KMPn7fGz zwvL*JmUX1`D2eEZsEBBYD2M=v!i$270*k_mf{H?l0{*OUeGaBRzR~-d?3jFbV|DTU zO6x;E7LGT%nMEY>zywDqXpK(Tirp~s#_6D-E5wZY;tbB>GQwdWz=uIlkoRv2j>0I1 z&ghCYSc?tV`8VC@XA)mg^$?2;6m&voMB+XkBNjCdvmuW)hVlJatg@0O|qL7j`7hhS{~MLm3yTj+2ci&7$Ook%yP%gZ>u9NS8rH zR7MLZ7=r1TiCH*?7R*YYWjoT&*o>|4$9C+)apXNg7GXlY6SR$HBw9g1YqUXU48lPi z#vMf96VjZdu8|&Dksm`b9G;kfNtlcoSb^IJMivn<0<=4xFnzsq>&{L5?bNQf?xba+a*19KPH@IpWV%d4LpfB!WK4l& zGu`r8g=H#s{IE@~?E!jt@8NCj&+<@J?M`jmK6#S#)TGFR;gr4to*JwGp$hd;(n2n`a4!uz8Nbf*X3f2Oh&;@#7|02B~dZ8Ora0UI5hr$2;8)r0elxrR2UwzT;V38f3f)-Vdz)BUY7UMYg+(3}z||DzO&RY?>|U|pIy+-?;`--%vu z!f=ehJH+ENGCp7pg+^!z1#KP-q|uVd`j8MJ4@#jKTH#YdLPFfDxVX4iPnbr=#f69R zO>S)x8m`qkw@!zjPQDyDeMCziIlcGv-n}A8N*pAT(^B1Mml><7zKe{-#HajP%ixF- zam^7W((j^nM0rx@-#Uu}$ksr7!*{HH#0U+IAF~aLNZd!nQ#LW-{*0Y5sQR42nh?!r z2GNG}(tsDd(F<)Wy^+;7B2vCk!;S;KI%vx(hi^RgGmCiWGap8JB5oiQiTDCNQ)$Ui z9w-=r(eTDf=o#KXdOtFgSv%B2L+Ax*MY<36;J{;AN;rwT&`bD~^am(Us7Z9dA6S3@ z96=`{&<&$71{ZM^dUPIir@3GeU$HZK`g!45g_8|pwo7;YgFuTVUO z{s@(0%oLVHTXaNcbU|;7#4!ZoBCa4BuaM^zgAf!!MJU(|e@L(Cw2=XsaRMiC4q;H< zFh6v}7Bdrn?7@DFk7W>vX;_TIIF3*Fitmu#Qc~oFf}ZG$HCTu9xPa@3LjE{X-?4#@Z1L>C#W#G1T>|%E;0FflsPd6kj)tH0P1Jyu>x|tkXNl?=A!jic z5=9>Ycj#|Fh4f-P!ZXC;J!&$`dQhNe!IiWbhj0vMaS7?kPFCny%tyK$roapHusEKE zc7?=E=w(Rzp4C4TOvW_K#Uflr2#l05EA;Z_C0z;IuoD3|ijRLjYsR>%47nWcJ(ivqbJ+h(@v?`%GMcpR0(JIPPx%%`ccWKW} zs#DQ_SlR_w`fHM&U{$etCF&KXSCC#I1Ye829&0_edMx$W>7mh!trt@-);NkZ9#?S< zNgq)JtXgO6X5E8`qSr!QD9~RwmGpe<#(wDU6Gr+W(%Q&UMihZP98e8i(G&jI4u>?d zR09eI!b7Avnfph4N=H3MrkADrP%_BUT&%=BMB)|RAX`RR%8uVq8+|bdV^KVlER{fG zC~(DAJVS}hveW@%Z~)=RW=n=p6V1#_nnQsr#$Xn1;|^XUe->G43o{Pl5H8{x9>6xM zEER@=KJb7iE+b{3Pt_vCO)mAdmO@(p6L+RuxK})o7^z(>&k=`3>tCx=`Nm@j%TWwn zL?!E$p$Fd*6TqjlS`bv z(45BVlyn7t6;|u;&CVuEb8rslu{FCaRmj1wEn#v_S(*YMa4WrESlQU1Mu$oP!bAyLZACt(s~Z&kb`+x1s_=Fs0O)e z0tI&DEEfu)DD>RUB(3I@%~C9h&rovFsxSldu^6%V1ifgDDP9*Sd04j43j^VT^9Y7G zZS(Wk=g&D!cvNicE&jMLxys+!v&YUJID2+Gf4*nWMyXLzX%)2k=F^vjKbt zzTkjyu(4mMg_iTEAKYWiYOW^UR*z}{B3c%$&=z`>T}hh}iaYoMP8^~|-^g`F6o7)! z@W5)U#X78qAO412erga6(KJ8ZLNgN0(H8x20EZBXC_Ka?yue2&1&ARQ!w0@Nj~fWV zO++9DEBTqmwb+Uyc!U__;mqQBQN+xoA`}=4(?XC9*^v)r5sg=PjW2L0LI(&1eb5(! z;Q_w!_>Av7#%fc`H8+2}L)_N3Yp;i2FCKn9JeF--l1Zr_?hucq?9D1>=AiaG_8F58 zYVRPLzo-B`$a*aGnCbD*%c~bn&-NCwycPNFsX#2iLVUw_xD=J8A^3`KMP(bQO)*)V zu0-2o$_b>7@I6^3eDP+4(L>wwrA8fLcfAOO{@%Mu2U*Rd81GvH`n*<<-iYHk1%2LW znP&kg(DN~h^lT*MM@mzS>Ou|F2HBI^7GuHdLSg`>!3#^U3C*04Gexah!nSAWNOl z89hqV9bp7ULMg-Z%Q8yBm-sJl_%?*ai=>pe8UG;uHeY=p^?;=K(=HE+TGH1o7jdYh z)kV7{)+hOr4+GCGK6uF~T9-JAF8TDMCONtN7@#*;!7Ob|Fo9Mk+Xt6UbJ9*dqrPV~I#tr0c=BN{pCr00(gwIV;QB zmwb}Xk;cIswb^l~9b(1z7^){9#>>|z#o>C_&hX7}Q9BBAPo0Y#RynzpDmRK%j(n_g zb&i~cKp{83$RR(k#BjI@>kKGWXy^S&jKmChV-0p-K~)xH>_Z%?R^tU22o>k?3F)g7 z7UV=N)JJoSfGY*{3K!JM=+PMdbrMQR>$WoI|6w@&Sf8sH+{U%GLQ3l$u z=j}^z>Ltq=8^y_*#Ci8P^PadQotY`+M{^QWl2=Zi)Nb&!D_4wHu5hHqD~_ywd_^2% z{fYy4Z)K%nhn+K)F)P&R4-xxWQ2u`f#GSJ1v9Nr0sGgr9HxG!qXv}6%ndUb$Ofhmg zWH6HWZ8v6pIh zjs1+jn8cbz4T*Wxgn~8LjvUOZIDVD~rS^Z%hmtBUWJU7F1w`Woa@D0PtxKEkL}CcW zVeqf2HIyF zNvA1I)W7Ryb*-IkT{M1i@;=LFA(od|UYzvGH){7?auJ5wwrXsIF+-X({2Ejm^`y~Q z&fM|8#PlD9R1c>fNd~CVsou#gN%*X-RkRuCZ)+BflpQP$9idzr1FC+gswZ9)9gxlC%)1>c$+L!#^h{D$K>%6m#>76nQw6XkJbYnvc^t=Vx=J zAlo$%zqKcR$WHu9oA}`|@$*^Yr=r9!42hrD`MlKf6ER-CoENg^0ZIF{32~lwal&eG z3gE$fvHGdCj%CT?Z!AM?*Bm?`Q!9ZO{(w(Gi`|6+O@! zPUw$8aKSK825A)B;10?ojmIQR!8CZWgIfB7#9Yh=g_Ra#87Q>0605Nm>)?wGAQ;kL z@WU4PgWyOzu?PEAa|xS{X6@%cPFqf#FV2K6&QdK-Bt7_nIODG6gs|dtm*PB<`wV>k zL?wxHtceq4iIY-^lL^I8S>l8w;?xr2+zsM;^y1s>;_JpTl_tK0DZXDNz7w?>r*IB@ z|Hv$fZy400l;U`7aeS&c3{)J+CytyG2Rn(wSj5o{;!|ny8Kn3WO6+MCJB!42z1UtB zgL*OK62l*{3KJ^|v2csUM^vZ-{GjXu$j>GAlJg6Ep=aO==D@FSSBz zv;_r`I-v_FkklPL(F=Xh7yUp%B?>1EhBJm>D28JsTrnDB;Gy;{Zj;G8f#gI?h8a^a z9WyW!voITTK$xTjScoN9ise`V6|1lYK3I=Gu?d^872B`_gjU*(z3k7WW;xF;4hB3b zW#eF!D>n+rT-L@mqq*OHn&wf0#5wv$U*%k@!JI!hgtKOc5d@k^qF9C>5Xr{`j^#Lt z6U=(Bd%>1-zP6NE4l~j`GO@@xu=}|ZpC49dmuO?Y@kgYe5#^{B><(r5sn7BgNQA>M zry~c*66HpN42pD^Fn%C>O$k{w4;Jo8G!wWC~jsC(3n_a($#+{*Yu#}5j(-Qeo#sK7`S1yRGg*nYQDxn6P;EcssS(s*jhQt-v7U79#PFLOzqcIkn zu?undir-7opQOzg|>Qvm3LfpEqo zY{MSxM-V>XE2OgQLBR|xMHF6OVtIN?1mG~P;wI8n;Hzrrh~8KQKfHkX9h0mTIU6`e zVWtX=mi%Ht<1{Mlf)9N zfe$t#7n2XXacnoK712++cMA)<>)X0Ixtyp5v0X@+N zLr_fNwDzcidT=x|X@#yBfWdHsC%jO-6HmlZoI>8Ntd%etUXZ#GW)wp;d>X;|fJYKR zL?XeJ0*<2PkEUBfFAPR5H%>JT^8_Xfu@O7aYYZ(Ffw+YjB;YT18YJ?1P`zl1w)h64 zCmF&-e1pwc&Qp!-2*7!C9Y?2+ZPOt_n?(#&A%3%R#~glw5gX^y(cmyHq4)wafRc-O9{);ln zzmx`qk|>ArsE)d5fTrk(E%3)>+{S=qti&+})36-AIEG8uxttX#a;W@#1-w=gZDd|e zBSx*&)W7%z!{cix5nkghKKamU*O4(4LOE2zPoY_Z*gU$zd5w0Afv0~gY zR?k=sU!1~uyucfLz-MGX&Z3LoP!G;0m@mwJO#Bg!he&^tt`;>=2eYsQhY^Horx^aD zHwIuUcHtRf;2OkYiGw(blV@0ZQ1UG6Ei^<6h#xhZeU|#aLLyk)d5!@EmSQz_Uf@lT z{~|3HV&L^VT0sm}x}X=1AqXGw4bGPsVPY;8;Vs1PQT4yf(uL9R#4!YkW&S*gD;Ri% zoMRj&!~Gi70n-ioa}0$WR>BwOaRZ-W6HG}%X!Xb&N^3_MR77ReL0vRLV>H8XxSN^y zVH@_~2%aMb6~m}2G(Zz5=zxysiVg6?^jnN(uo~;o`!*{ZJio(m4qsps&NeQxqZBHl z9?T7yL`Tq2(DW|dFCHTfJ@2uyz%Y0s1_`i>WO#*gsEPV$gq|3P8CZz**n)!yM7oD8 z5oq>^>ch}S)c*()6Jf?BT*K-oyclVo(ipJ_%MpkR5Zhxn;s1i(5w~zxh@}rf9Hh5| z{T-#mMTEjDp3Gq(mg4Vt>i;N-4DXo{z9VA-VM0z6Mlm#p0$*%G-b9vnG(>X@#V7_>oK8ot7hyNvT+!GW=U zO-#l@+_h!f1#%XSK|w}jM@UwV9YIbzwpP(A8(X#5m77Ct(2h;!UU?Y*-y;!?Q~4O< z<33*EeF3(w(Yzo#LGTDKQNIWWP+}QWRI=xgH;9uqcSjHO$Gl=3uZ$H~i!&uS4ibym zP+5-9a?GoonNW~;1-tU(7O(IDUy!B(8&c?xq7^y33B%xl9+lbt#>6TdI*(4(I7k&2 za072^5Lpzg$&oe?XHgxG+rM$lAquboUd+s-KZYO-;pkMGL))NY9mJ_WU68>5C{lLnpT2yP;Bjss?TtkM9krR!8a`{@9PB@M_2bn79OUFq1DZHlh@m4_mh1a$`*s z4)MlK+(sO}AP3uadEf?54EmkTGEBl0JVi7yStCn~n3glL8ic!T$t-i|s&ruI}JTBA2k;|dCNWV;g0Ax_Da zk=+;BQB#~-qCSb=(GuOz6GJcpuJC{#wjl(!@EUKCzcWV|q7Me+0&XA%@#xTn#}I}{ zICteBTTH`T95pjJi>nAhC?aqdQFsV(60nzejpp4b9h@)#9vF|sScT2-#}4ene*BHI zxPog4M!xRs`GdI{lbUD_an`mxJq?mQB5)s%@eIaZEZ?w4anwaaIAI{1F%%==hH;n( zGp1t}=3xOAV>wp#qW*nJ{Dm#>$1d!{5uC&g+(f_LEP5D)3D^REoPjub*KIt6T^|}R z#L2rlV-?oo1kRyLUowqpPGrc5`Va0;{ov35Iw80Xq$T6~U>b@ujmL%M9u1+OE1Xe! z7!49t&lL-nbi@ACo+|jq|AluMz36Ry{LOpNFy>v8i*H4g#TxEYpv?7 z_h0?js%O3Rch>ss^E>D4v-fZB->}d1`+Yaw;{&#{hc9XVgzYnv`Ai>cJ9HYS%O<*V zq76{wDc5#VsKaeErw;=d$CI?3VX`^&k31`K61GYRi-v7P-K;5d_}sKKn_4N5$#Y+0R$RO;tI`OL!NI zWU6ulwWcb=CKBPTFz%&2{TRgKjOBS=U?+Pyz#$HEgzV3`@Ngj)Q;;HDNhNAflSbUh zJ+!6`?V=Wa8N@IiV+5m^$_(bQfY(^V+iYY%2RO=izT*t>({xCbB9RKz=MGxXlD-UJG-H|0EYexV+ic_`wsMd|Ts&RIxRJVaoUZ)4 zN_6KD3eHf5wBR1P^B~Xi9QkHCLef}7CU5fzyEx2Iip+9Z=1!XNAOm=Y=Xsqs`EXWL zM$_S8z2ilFBE1O70hAnoc~xDZ)XhOSzh6 zQHxfz;XdY&N*c>K!uOmc&s;m4XNQ#G3Z^oh`twy}Ch#;TIZgRgb%3U{=3yRTEYA|n zu|Vx59|gIMJDJNu64LbR+)7hA(Tlg)${zMo@+C(_@rCLP$yA{U;f)Pukj7$`aFSCC zmH*yF%8lckpvueICn?nDuiVKTUgTZ2vyc6h{=2a_n!KV3)0r;J;YAj)j5k^yN>ZA#T)~x8qz-ji$(v*l z-C(hi&AiW6wh`VO;0VX)yv!NkO~SzcEo|eW<=QmGsX#JSs7WnqQJh^GL$Xsqtj~JOk$3z}KrhBKnJFA1VS{y8&Pu|l>QC4~jg2zL zD{Q39CPf#usLjnZq&fG}oqjyZ8n$wf<3!$dEg*?7oO~=Zna={^HoHd9n6}(cSCZcI zXC96DD^I+y{3lsVVKxUoP*bV;p(CdmZ8^dT9{)&rljmb?pJZy#hba5`Cnq^?i!(?f z^=ZgNo}=Ja6`d|ymH!}#u}okZvpCKVWZ!0GN>GX_RAUm8nZYY$vYst$r{*UPfCjXp zBlj_wC|lXiXP+ql?WTH`RGY+2J<-6n8|Dw z@Cqw9!6|C&k~!K$E!xq6FckVh2J;>ta_w%XkJhxMJzeR|AeOR%#(Q*Ngb}}k8PAhU z;yGrsfZ$Wjk=49Kbce-3;`aKG?EHn6bZ02T8Npae?DJPI*HN2{&t#On9N>}9ojpb| zj^~&|jxTi2 z+)Yc`(Vp&vk*R;75G5%^($`TdNc5l={pin7k`5^+y7C}tEahFcv!7!m9@ckoJvY;d z2bjyN?Bg&c|7n|4Cxu$v8nt+ckxV0%#jGLUH@aNPautne!FZ*aKe?2yeC~h7(kRECzbzbi7+7X13qL2JK00Y9~?blkYX}3c`fv_;nG>jD%P@| zciGIR?BgpAaFW0*wA>WoGE%smHr&r>#_=J$^Mr9u5+|tm7v(}v9;7dWd5DpWVjSa{ z!7S!6pJl9OJzLmA#GJ-_l;CnIP?1X1qCNNJRsLxbOUYz2x$>F!OHsVmQCee2-wsC+HoFQ_NDc|HKFZn4wKIH%<3YgT)b)-;>Iy5Yx{BM`IgS%--XS&gcehgy_lSyL{nXD(_Vi}|` z<*7zZt|x{1+(sjs(wq)-rWd_0R{l|m8KkkAx7f}u%9#|KOvi9?EDKr9evWc!A*Y)b zgb{B~F_SZ7GZ!;EMd(Zqdh!^j35r-JYLTBXf~^U6(T<^vXCgD0#Vaf(gSBj9H%B>M z)CBipDkDX?ge0m^kLiSwY+)4J5xymdS#;6b7I)E{u4EUPbRn;?p7CW=7&6KV6JSL- zr=Q&%Tmx1V?b6S7j&h0z;Czb2(&A_?xKf4w1T>1ar zn)>Ig_g~lkFZp9TtaI)ET>C$pXW-oR|Br3Y|JPpfT>C$pwg24jzjN*XT>C$pXW+l? z_un7<_u{$!|6KonHqXHS_x``dAKadWdx!+iCfFuhEU9WxKDxe2Rw!zlYT~7MEkzg$ zqw5K4VHz{J=@#KlG^GVy8wlWF2*W6Umk2VZ@Eq^3iE7P6p>SzGF?$SR2y;m7C%$I* zK=Cf*9xUjRwZp_p^6hZpDU2E^+KgP|g}rcknlKnw+{WQsc93+kbU zIGGe$aUVZKj26e4J4X_m3L9tT7$-SJq=?BK#Z2yCKLm)YtJ{R0%{F`Ew;OBsjvGonuGKJ}^V-xSQm3j?~K63|m@eo64)zE>^ppnlQ z-Pq2F-tBY7-fet+f^z$TANov?KY-Ak-d{Sl+?S= z3=-b!EJIx1#X4;5W{8^?dl;W*bT9iOwRhGe^5p0s)09Yl*jx(EA8P6f$-@-~4G1T1 z9~hy0d1R!S2Xy$G4D$d3m@p-4w(*f?mHpJLDX;^lIa|!;=b5XWUNAR*Bqs;QQ_NYL=#eZnLUO`53ww-u^7UEzRHB-apeey z&AJi}Z{5cn13dGJ8DCi_v6x&2ck+^-@Sc9%d64IgugqdE`}ww7d?d~|$)TUdO9~ho z3GWltJH?nRb4ewG@K#ADIZf6uNwOc4zZCuDi?fi9{wg>B`3$(e{^xi4i+zT_ug_)% z&T9EbM3sj3qKH%?nQN%QwG@6S%LA@ixBOjP@lS5`97;0m7uM;7NbtYNVM{;W@8aL= zqwXKGlf>BTRfAqRm)2PuOuJ$453$|Vf{W5CRtqY}<@~7LsInWD7P<1r_ktD$-Y6g2 zT{S3_vwz;_tKL|BLT1*wk5mu3ofqeRUyXySVZ<&kjJVB9ai8{5@1 zNXj$eS8wgS&0D`-t7yX@>7rk~6>eBKZtRiv!G*E3W%pI2)t5`eXj>>1wB>rNR3!IN!K?2$Mcj?&c{erTw6@7!u*k^sE_Vx`L z#vbk$t|2pHtdkS>0(J(JL+4s{9+Q%yP50b(go5fo94+qoKZfS_>2yt$7>g4<6< z;;NkaF+1T+)xzcyKEk3tb7Q>P^5Y}?C|^SQ7XyON6c#{>gYSp_luE5A4TzgGA=q_6nECLt@L0~dI!d+fx5U|?KQtWTO(Rb$7}f*yIN d_1ga9*A7?y@$0ePF9p4R`)2x)mx4Sw{|AdPT(JNE delta 60034 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 = sim_con_ldsc.rxdeltausecs; +if (sim_con_ldsc.o_uptr == NULL) + return sim_messagef (SCPE_TTOERR, "Can't set port speed. Console Output unit missing.\n"); +r = tmxr_set_line_speed (&sim_con_ldsc, cptr); +if (r == SCPE_OK) + sim_con_ldsc.o_uptr->wait = 0; return r; } @@ -2549,8 +2551,10 @@ while (*cptr != 0) { /* do all mods */ else { if (cvptr) /* if we removed a = sign */ *(--cvptr) = '='; /* restore it */ - if (sim_con_tmxr.master) /* already open? */ - sim_set_notelnet (0, NULL); /* close first */ + if ((sim_con_tmxr.master) || /* already open? */ + (sim_con_ldsc.serport) || + (sim_con_ldsc.console)) + tmxr_close_master (&sim_con_tmxr); /* close first */ r = tmxr_attach (&sim_con_tmxr, &sim_con_unit, gbuf);/* open master socket */ if (r == SCPE_OK) sim_activate_after(&sim_con_unit, 1000000); /* check for connection in 1 second */ @@ -2567,9 +2571,8 @@ t_stat sim_set_notelnet (int32 flag, CONST char *cptr) { if (cptr && (*cptr != 0)) /* too many arguments? */ return SCPE_2MARG; -if (sim_con_tmxr.master == 0) /* ignore if already closed */ - return SCPE_OK; -return tmxr_close_master (&sim_con_tmxr); /* close master socket */ +tmxr_close_master (&sim_con_tmxr); /* close master socket, if open */ +return tmxr_attach (&sim_con_tmxr, &sim_con_unit, "CONSOLE"); } /* Show console Telnet status */ @@ -3049,21 +3052,18 @@ return SCPE_OK; t_stat sim_putchar (int32 c) { -sim_exp_check (&sim_con_expect, c); -if ((sim_con_tmxr.master == 0) && /* not Telnet? */ - (sim_con_ldsc.serport == 0)) { /* and not serial port */ - ++sim_con_pos; /* bookkeeping */ - if (sim_log) /* log file? */ - fputc (c, sim_log); - sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); - return sim_os_putchar (c); /* in-window version */ - } -if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ - if (!sim_con_ldsc.txbfd) /* unbuffered? */ - return SCPE_LOST; /* connection lost */ +if (!sim_con_ldsc.console && /* Non Console */ + !sim_con_ldsc.serport && /* no serial connection */ + ((sim_con_tmxr.master != 0) && /* Telnet but not connected */ + !sim_con_ldsc.conn)) { + if (!sim_con_ldsc.txbfd) /* non-buffered Telnet connection? */ + return SCPE_LOST; /* lost */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ } +if (sim_log) /* log file? */ + fputc (c, sim_log); +sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ ++sim_con_pos; /* bookkeeping */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ @@ -3074,25 +3074,34 @@ t_stat sim_putchar_s (int32 c) { t_stat r; -sim_exp_check (&sim_con_expect, c); -if ((sim_con_tmxr.master == 0) && /* not Telnet? */ - (sim_con_ldsc.serport == 0)) { /* and not serial port */ - ++sim_con_pos; /* bookkeeping */ - if (sim_log) /* log file? */ - fputc (c, sim_log); - sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); - return sim_os_putchar (c); /* in-window version */ - } -if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ +if (!sim_con_ldsc.console && /* Non Console */ + !sim_con_ldsc.serport && /* no serial connection */ + ((sim_con_tmxr.master != 0) && /* Telnet but not connected */ + !sim_con_ldsc.conn)) { if (!sim_con_ldsc.txbfd) /* non-buffered Telnet connection? */ return SCPE_LOST; /* lost */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ sim_con_ldsc.rcve = 1; /* rcv enabled */ } -r = tmxr_putc_ln (&sim_con_ldsc, c); /* Telnet output */ +if (tmxr_txdone_ln (&sim_con_ldsc) == 0) { + if (sim_con_ldsc.txbps) /* rate limiting? */ + sim_con_ldsc.o_uptr->wait = /* Long poll to allow proper scheduling*/ + (int32)((2 * TMLN_SPD_50_BPS * sim_timer_inst_per_sec ()) / USECS_PER_SECOND); + else + sim_con_ldsc.o_uptr->wait = SERIAL_OUT_WAIT; /* "standard" output wait */ + return SCPE_STALL; + } +if (sim_log) /* log file? */ + fputc (c, sim_log); +sim_debug (DBG_XMT, &sim_con_telnet, "sim_putchar_s('%c' (0x%02X)\n", sim_isprint (c) ? c : '.', c); +r = tmxr_putc_ln (&sim_con_ldsc, c); /* Telnet & Console output */ if (r == SCPE_OK) ++sim_con_pos; /* bookkeeping */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ +if (sim_con_ldsc.txbps) /* rate limiting? */ + sim_con_ldsc.o_uptr->wait = 0; /* next one 0 wait */ +else + sim_con_ldsc.o_uptr->wait = SERIAL_OUT_WAIT; /* "standard" output wait */ return r; /* return status */ } @@ -3247,8 +3256,10 @@ return SCPE_OK; t_stat sim_ttinit (void) { sim_con_tmxr.ldsc->mp = &sim_con_tmxr; +sim_con_tmxr.ldsc->expect = &sim_con_expect; sim_register_internal_device (&sim_con_telnet); tmxr_startup (); +sim_set_notelnet (0, NULL); return sim_os_ttinit (); } @@ -3427,7 +3438,7 @@ if (response = buffered_character) { return sim_os_poll_kbd_data (); } -static t_stat sim_os_putchar (int32 out) +t_stat _sim_os_putchar (int32 out) { unsigned int status; char c; @@ -3680,7 +3691,7 @@ return SCPE_OK; #define out_hold_unit sim_con_units[1] -static t_stat sim_os_putchar (int32 c) +t_stat _sim_os_putchar (int32 c) { uint32 now; static uint32 last_bell_time; @@ -3880,7 +3891,7 @@ if (sim_int_char && (buf[0] == sim_int_char)) return (buf[0] | SCPE_KFLAG); } -static t_stat sim_os_putchar (int32 out) +t_stat _sim_os_putchar (int32 out) { char c; @@ -4047,7 +4058,7 @@ if (sim_int_char && (buf[0] == sim_int_char)) return (buf[0] | SCPE_KFLAG); } -static t_stat sim_os_putchar (int32 out) +t_stat _sim_os_putchar (int32 out) { char c; diff --git a/sim_scp_private.h b/sim_scp_private.h index f84d61cd..e7fce015 100644 --- a/sim_scp_private.h +++ b/sim_scp_private.h @@ -404,6 +404,11 @@ struct SEND { int32 extoff; /* extra offset */ }; +/* Private SCP only APIs */ + +t_stat _sim_os_putchar (int32 out); + + #endif /* defined(SIM_SCP_PRIVATE_DONT_REPEAT) */ #ifdef __cplusplus diff --git a/sim_tmxr.c b/sim_tmxr.c index 89280085..95ee87a6 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -771,11 +771,15 @@ else { } } else { - if ((lp->conn == TMXR_LINE_DISABLED) || - ((lp->conn == 0) && lp->txbfd)){ - written = length; /* Count here output timing is correct */ - if (lp->conn == TMXR_LINE_DISABLED) - lp->txdrp += length; /* Record as having been dropped on the floor */ + if (lp->console) + written = (SCPE_OK == _sim_os_putchar (lp->txb[i])) ? 1 : 0; /* write to the sim> session */ + else { + if ((lp->conn == TMXR_LINE_DISABLED) || + ((lp->conn == 0) && lp->txbfd)){ + written = length; /* Count here output timing is correct */ + if (lp->conn == TMXR_LINE_DISABLED) + lp->txdrp += length; /* Record as having been dropped on the floor */ + } } } } @@ -987,9 +991,11 @@ tptr = (char *) calloc (1, 1); if (tptr == NULL) /* no more mem? */ return tptr; -if (lp->destination || lp->port || lp->txlogname || (lp->conn == TMXR_LINE_DISABLED)) { +if (lp->destination || lp->port || lp->txlogname || (lp->conn == TMXR_LINE_DISABLED) || lp->console) { if ((lp->mp->lines > 1) || (lp->port)) sprintf (growstring(&tptr, 32), "Line=%d", (int)(lp-lp->mp->ldsc)); + if (lp->console) + sprintf (growstring(&tptr, 32), "CONSOLE"); if (lp->conn == TMXR_LINE_DISABLED) sprintf (growstring(&tptr, 32), ",Disabled"); if (lp->modem_control != lp->mp->modem_control) @@ -2919,7 +2925,7 @@ ETH_DEV *eth; SOCKET sock; SERHANDLE serport; CONST char *tptr = cptr; -t_bool nolog, notelnet, listennotelnet, nomessage, listennomessage, modem_control, loopback, datagram, packet, disabled; +t_bool nolog, notelnet, listennotelnet, nomessage, listennomessage, modem_control, loopback, datagram, packet, disabled, console; int32 listenbacklog; TMLN *lp; t_stat r = SCPE_OK; @@ -2934,6 +2940,7 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */ if (lp->bpsfactor == 0.0) lp->bpsfactor = 1.0; } +console = FALSE; notelnet = listennotelnet = mp->notelnet; nomessage = listennomessage = mp->nomessage; listenbacklog = mp->backlog; @@ -3077,6 +3084,10 @@ while (*tptr) { strlcpy (speed, cptr, sizeof(speed)); continue; } + if (0 == MATCH_CMD (gbuf, "CONSOLE")) { + console = TRUE; + continue; + } cptr = get_glyph (gbuf, port, ';'); if (sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL, NULL)) return sim_messagef (SCPE_ARG, "Invalid Port Specifier: %s\n", port); @@ -3177,6 +3188,10 @@ while (*tptr) { if (destination[0] || listen[0] || loopback || framer[0]) return sim_messagef (SCPE_ARG, "Can't disable line with%s%s%s%s%s%s%s\n", destination[0] ? " CONNECT=" : "", destination, listen[0] ? " " : "", listen, loopback ? " LOOPBACK" : "", framer[0] ? " SYNC=" : "", framer); } + if (console) { + if (destination[0] || listen[0] || loopback || framer[0] || disabled) + return sim_messagef (SCPE_ARG, "Can't have console line with%s%s%s%s%s%s%s%s\n", destination[0] ? " CONNECT=" : "", destination, listen[0] ? " " : "", listen, loopback ? " LOOPBACK" : "", framer[0] ? " SYNC=" : "", framer, disabled ? " DISABLED" : ""); + } if (destination[0]) { /* Validate destination */ if (framer[0]) @@ -3387,6 +3402,10 @@ while (*tptr) { tmxr_set_line_speed (lp, speed); } } + if (console) { + lp->console = TRUE; + lp->conn = 1; + } if (destination[0]) { if (mp->lines > 1) return sim_messagef (SCPE_ARG, "Ambiguous Destination specification\n"); @@ -3736,6 +3755,8 @@ t_stat tmxr_set_console_units (UNIT *rxuptr, UNIT *txuptr) { extern TMXR sim_con_tmxr; +rxuptr->tmxr = &sim_con_tmxr; +txuptr->tmxr = &sim_con_tmxr; tmxr_set_line_unit (&sim_con_tmxr, 0, rxuptr); tmxr_set_line_output_unit (&sim_con_tmxr, 0, txuptr); return SCPE_OK; @@ -4105,7 +4126,7 @@ return SCPE_OK; The listening socket associated with multiplexer descriptor "mp" is closed and deallocated. In addition, all current Telnet sessions are disconnected. - Serial and outgoing sessions are also disconnected. + Serial, outgoing sessions and console connections are also disconnected. */ t_stat tmxr_close_master (TMXR *mp) @@ -4129,6 +4150,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru conn */ sim_control_serial (lp->serport, 0, TMXR_MDM_DTR|TMXR_MDM_RTS, NULL);/* drop DTR and RTS */ tmxr_close_ln (lp); } + lp->console = FALSE; free (lp->destination); lp->destination = NULL; free (lp->acl); @@ -5215,7 +5237,7 @@ int32 i, t; if (mp == NULL) return SCPE_IERR; for (i = t = 0; i < mp->lines; i++) - if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0)) + if ((mp->ldsc[i].sock != 0) || (mp->ldsc[i].serport != 0) || (mp->ldsc[i].console != 0)) t = t + 1; if (mp->lines > 1) fprintf (st, "%d current connection%s", t, (t != 1) ? "s" : ""); diff --git a/sim_tmxr.h b/sim_tmxr.h index 4d4a62c8..cfcf5041 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -192,6 +192,7 @@ struct tmln { t_bool ser_connect_pending; /* serial connection notice pending */ SOCKET connecting; /* Outgoing socket while connecting */ char *destination; /* Outgoing destination address:port */ + t_bool console; /* simulator I/O to console session */ t_bool loopback; /* Line in loopback mode */ t_bool halfduplex; /* Line in half-duplex mode */ t_bool datagram; /* Line is datagram packet oriented */