.title natvmode - Native mode code for MERLIN .ident /010100/ ;+ ; Abstract: natvmode ; ; This module is a native mode procedure to implement ; extended functions for the compatibility mode ; version of MERLIN which cannot be easily performed ; in compatibility mode. ; ; Calling sequence: ; ; = natvmode (xfer_array, cli_callback, ihd, ifd, ; linkopt, junk, parms) ; ; Arguments: ; ; The only arguments which have any relevance at the ; user level are contained in the 'parms' parameter. ; This is facility-dependent. ; ; Nonstandard features: ; ; 1. Written in Macro-32 ; 2. Requires the compatibility mode program to use ; the undocumented VMS "elephant" directive. This ; directive allows a compatibility mode program to ; execute code in a native mode image. ; ; Written: 03-Apr-1981, -1.0.0-, Bruce C. Wright ; Modified: 25-Nov-1981, -1.1.0-, Bruce C. Wright ; Changed mailbox names to be prefixed with MBX_ to ; avoid naming conflicts. ; Verified: 25-Nov-1981, -1.1.0-, Bruce C. Wright ;- ; ; The facilities provided by this module are: ; ; 1. Reading/writing from VAX/VMS mailboxes. The facilities ; provided by the Application Migration Executive are not ; completely compatible with many PDP-11 systems becuase ; they do not implement variable-length send/receive ; (along with several other things like send and request). ; ; 2. A number of terminal handler functions are not available ; under the compatibility mode emulator. In particular, ; it is not possible to obtain the terminal type and some ; of the terminal characteristics under the emulator. The ; VAX/VMS operating system allows up to 8 foreign terminals ; (/FT1 through /FT8), and RSX has foreign terminal types ; defined (T.USR0...) but the compatibility mode emulator ; translates all foreign terminals to T.UNK (unknown type), ; making the facility provided by the AME useless in any ; production setting. ; ; 3. Running the locally-written SORT package from under the ; compatibility mode emulator is not possible: there is ; no way for a compatibility mode image to execute the ; native mode sort as a replacement to the compatibility ; mode sort, the SPWN$ directive does not function properly ; under compatibility mode, and the send data and request ; receiver directive only works if the target task is ; CRF...! This is a ludicrous state of affairs which this ; module partially corrects. ; ; 4. Spooler support is provided in this package. Although ; VAX/VMS has a very nice spooler system which is accessable ; to native mode images, there is no way to use the facility ; from compatibility mode unless you restrict everything to ; going to the default queue, one copy, and no forms. This ; too is an unsatisfactory situation. ; ; It would be nice to be able to provide these facilities without ; having to go to such lengths to bypass the operating system. ; However, under the current Application Migration Executive, this ; is not possible. DEC has indicated that they do not consider ; the support of the AME at any reasonable level of functionality ; to be a high priority; until they do, we must make do as best ; we can any way we can. ; ; ; Define compatibility mode symbols ; TC.WID = 1. ; Terminal width TC.LPP = 2. ; Length of page in lines TC.RSP = 3. ; Receive baud rate TC.XSP = 4. ; Transmitter baud rate TC.STB = 5. ; Stop bit required TC.ISL = 6. ; Subline number on interface TC.RAT = 7. ; Readahead type TC.TTP = 8. ; Terminal type TC.SCR = 9. TC.SCP = 10. ; Terminal is a CRT TC.HFL = 11. ; Horizontal fill requirement TC.VFL = 12. ; Vertical fill required TC.NL = 13. ; Terminal generates 'newline,' not 'cr' TC.SFF = 14. ; Full simulation of form-feed TC.HFF = 15. ; Hardware form-feed available TC.LVF = 16. ; LA-36 with vertical format TC.HHT = 17. ; Hardware horizontal tab TC.NST = 18. ; Nonstandard tab stops TC.BSP = 19. ; Backspace is available TC.ACR = 20. ; Automatic cr/lf to be supplied TC.SMR = 21. ; Enable lower case input TC.SMP = 22. ; Force lower case input TC.SMO = 23. ; Enable lower case output TC.CCF = 24. ; ^C flushes typeahead TC.ALT = 25. ; Terminal generates ALTMODE rather than ESC TC.IMG = 26. ; No writes/broadcasts from other terminals TC.NKB = 27. ; No keyboard (no input from terminal) TC.NPR = 28. ; No printer (no output to terminal) TC.ESQ = 29. ; Escape sequence support TC.LCP = 30. ; Terminal has local copy TC.PAR = 31. ; Parity checking to be done TC.EPA = 32. ; Terminal has even parity TC.DLU = 33. ; Terminal is a dialup line TC.BLK = 34. ; Terminal is in block mode TC.FRM = 35. ; Terminal is in forms mode TC.HLD = 36. ; Terminal in hold screen mode TC.TAP = 37. ; Low-speed tape reader available TC.CEQ = 38. ; Compatible escape sequences TC.NEC = 39. TC.SLV = 40. TC.PRI = 41. TC.UC0 = 42. ; User characteristic 0 TC.UC1 = 43. ; User characteristic 1 TC.UC2 = 44. ; User characteristic 2 TC.UC3 = 45. ; User characteristic 3 TC.UC4 = 46. ; User characteristic 4 TC.UC5 = 47. ; User characteristic 5 TC.UC6 = 48. ; User characteristic 6 TC.UC7 = 49. ; User characteristic 7 TC.UC8 = 50. ; User characteristic 8 TC.UC9 = 51. ; User characteristic 9 TC.FDX = 52. ; Full duplex terminal TC.BIN = 53. ; Terminal is in binary mode TC.REM = 54. TC.8BC = 55. TC.P8B = 56. ; Pass-8 bits device TC.TBF = 57. TC.CTS = 58. TC.MAX = 59. ; ; Terminal baud rate equates ; S.0 = 1. ; 0 baud (line turned off) S.50 = 2. ; 50 baud S.75 = 3. ; 75 baud S.100 = 4. ; 100 baud S.110 = 5. ; 110 baud S.134 = 6. ; 134 baud S.150 = 7. ; 150 baud S.200 = 8. ; 200 baud S.300 = 9. ; 300 baud S.600 = 10. ; 600 baud S.1200 = 11. ; 1200 baud S.1800 = 12. ; 1800 baud S.2000 = 13. ; 2000 baud S.2400 = 14. ; 2400 baud S.3600 = 15. ; 3600 baud S.4800 = 16. ; 4800 baud S.7200 = 17. ; 7200 baud S.9600 = 18. ; 9600 baud S.EXTA = 19. ; External clock A S.EXTB = 20. ; External clock B ; ; Terminal type codes ; T.UNK0 = 0. ; Unknown terminal T.AS33 = 1. ; ASR-33 teletype T.KS33 = 2. ; KSR-33 teletypt T.AS35 = 3. ; ASR-35 teletype T.L30S = 4. ; LA-30S DECwriter T.L30P = 5. ; LA-30P DECwriter T.LA36 = 6. ; LA-36 DECwriter T.VT05 = 7. ; VT05 terminal T.VT50 = 8. ; VT50 terminal T.VT52 = 9. ; VT-52 terminal T.VT55 = 10. ; VT-55 terminal T.VT61 = 11. ; VT-61 terminal T.L180 = 12. ; LA-180 terminal T.V100 = 13. ; VT-100 terminal T.L120 = 14. ; LA-120 terminal T.SCR0 = 15. ; SCRIPS line T.USR0 = 16. ; User 0 T.USR1 = T.USR0+1 ; User 1 T.USR2 = T.USR1+1 ; User 2 T.USR3 = T.USR2+1 ; User 3 T.USR4 = T.USR3+1 ; User 4 ; ; Local terminal types ; T.PLAS = 19. ; Plasma panel T.HP48 = 20. ; HP-2648 terminal T.HP21 = 21. ; HP-2621 terminal T.ADM1 = 22. ; ADM-1 terminal T.AD31 = 23. ; ADM-31 terminal T.ADM3 = 24. ; ADM-3 terminal T.MBEE = 25. ; Minibee terminal T.SBEE = 26. ; Superbee terminal T.DIAB = 27. ; Diablo terminal T.GE30 = 28. ; GE-30 hardcopy terminal T.ACT4 = 29. ; ACT-4 terminal T.TEKT = 30. ; Tektronix terminal T.MICR = 31. ; Microprocessor terminal .mcall $dibdef, $jpidef, $dcdef, $smrdef .mcall $getdev_s, $assign_s, $dassgn_s .mcall $qiow_s, $crembx_s, $getjpi_s .mcall $waitfr_s, $trnlog_s, $sndsmb_s ; $dibdef $jpidef ; Job Process Information options $dcdef $smrdef ; Spooler Symbiont options ; ; Define parameter list ; p_xfer_array = 4 ; Transfer array p_cli_callback = 8 ; CLI callback p_ihd = 12 ; ihd p_ifd = 16 ; ifd p_linkopt = 20 ; link options flags p_junk = 24 ; ???? p_parms = 28 ; Parameters from compatibility mode ; ; Static storage ; mbx_read_chan: .long 0 ; Mailbox channel for reading. sysout: .ascid /SYS$OUTPUT/ .even ; ; Define translation tables ; .macro iasequ iastype,vmstype,routine .word iastype .if b routine .word 0 .iff .word routine-iastertbl .endc .long vmstype .endm iastertbl: iasequ tc.acr,0 ; automatic cr/lf to be supplied iasequ tc.alt,0 ; terminal requires ALTMODE iasequ tc.bin,tt$m_passall,xbt ; terminal to operate in binary mode iasequ tc.blk,0 ; terminal to operate in block mode iasequ tc.bsp,0 ; terminal recognises backspace iasequ tc.ceq,0 ; compatible escape sequences iasequ tc.ccf,0 ; ^C flushes typeahead. iasequ tc.dlu,tt$m_remote,xbt ; dialup line iasequ tc.epa,0 ; even parity iasequ tc.esq,tt$m_escape,xbt ; escape sequence support iasequ tc.fdx,0 ; full duplex mode iasequ tc.frm,0 ; terminal in forms mode iasequ tc.hff,tt$m_mechform,xbt ; terminal recognises form feed and vt. iasequ tc.hfl,0 ; horizontal fill requirement iasequ tc.hht,tt$m_mechtab,xbt ; terminal recognises horizontal tab iasequ tc.hld,tt$m_holdscreen,xbt ; terminal in hold screen mode iasequ tc.img,tt$m_nobrdcst,xbt ; no writes from other terminals iasequ tc.isl,0 ; subline number on interface iasequ tc.lcp,0 ; device has local copy iasequ tc.lpp,0,xpage ; length of page in lines iasequ tc.lvf,0 ; LA36 with vertical format option iasequ tc.nkb,0 ; no keyboard on device iasequ tc.nl,0 ; 'newline' generated instead of 'cr' iasequ tc.npr,0 ; terminal has no printer (no output) iasequ tc.nst,0 ; nonstandard tab stops iasequ tc.par,0 ; parity checking is to be done. iasequ tc.p8b,tt$m_eightbit,xbt ; pass-8 bits device iasequ tc.rat,0 ; readahead type iasequ tc.rsp,0,xspeed ; read baud rate iasequ tc.scp,tt$m_scope,xbt ; terminal is scope device iasequ tc.sff,0 ; full simulation of form-feed iasequ tc.smo,tt$m_lower,xbt ; lower case output iasequ tc.smp,tt$m_lower,xbt ; force lower case input iasequ tc.smr,tt$m_lower,xbt ; enable lower case input iasequ tc.tap,0 ; low-speed tape reader iasequ tc.ttp,0,xtype ; terminal type iasequ tc.stb,0 ; stop bit required. iasequ tc.vfl,0 ; vertical fill required iasequ tc.wid,0,xwidth ; terminal width iasequ tc.xsp,0,xspeed ; terminal transmit speed iasequ 0,0 ; end of table ; ; Terminal type table ; iastertyp: .word dt$_ttyunkn,t.unk0 ; Unknown terminal .word dt$_la36,t.la36 ; LA-36 .word dt$_vt05,t.vt05 ; VT05 .word dt$_vt52,t.vt52 ; VT52 .word dt$_vt55,t.vt55 ; VT55 .word dt$_vt5x,t.vt50 ; VT5x .word dt$_la180,t.l180 ; LA-180 .word dt$_vt100,t.v100 ; VT-100 .word dt$_la120,t.l120 ; LA-120 ; ; Local terminal types patched in here ; .word dt$_ft1,t.adm1 ; ADM-1 .word dt$_ft2,t.ad31 ; ADM-31 .word dt$_ft3,t.adm3 ; ADM-3 .word dt$_ft4,t.hp48 ; HP-2648 .word dt$_ft5,t.hp21 ; HP-2621 .word dt$_ft6,t.diab ; Diablo .word dt$_ft7,t.tekt ; Tektronix .word dt$_ft8,t.micr ; Microprocessor .word 0,0 ; End of table ; ; Main line code ; natvmode:: .word ^m movl p_parms(ap),r11 ; Pick up the parameter list. casew (r11)+,#0,#6 ; Branch to appropriate routine. 10$: .word crembx-10$ ; Create mailbox .word reambx-10$ ; Read from mailbox .word reimbx-10$ ; Read immediate from mailbox .word wrimbx-10$ ; Write to mailbox .word simtty-10$ ; Simulate Terminal driver .word simsor-10$ ; Execute SORT procedure. .word simspr-10$ ; Simulate SPR... functions movw #-98,r0 ; Ilegal function. ret ; And return to the caller. ; ; Function 0. Create mailbox ; ; Argument list: ; (none) ; crembx: bsbw alloc_mbx ; Allocate mailbox if necessary. ret ; And return. ; ; Function 1. Read from mailbox ; ; Argument list: ; code+2 - Address of mailbox buffer ; code+4 - Length of mailbox buffer ; code+6 - 8-byte VMS I/O status block ; ; reambx: movl #io$_readvblk,r8 ; Show to read mailbox brb read_mbx ; And read the mailbox ; ; Function 2. Read immediate from mailbox ; ; Argument list: ; code+2 - Address of mailbox buffer ; code+4 - Length of mailbox buffer ; code+6 - 8-byte VMS I/O status block ; ; Stack offsets ; read_buffer = -16 ; Buffer area for sending process name read_iost = read_buffer-8 ; I/O status block. read_len = read_iost-4 ; Length of buffer. read_itmlst = read_len-16 ; Item list for $getjpi service. read_size = -read_itmlst ; Size of stack frame. ; reimbx: movl #io$_readvblk!io$m_now,r8 ; Show to read mailbox read_mbx: subl2 #read_size,sp ; Allocate a stack frame. movzwl (r11)+,r10 ; Pick up dest. address. movzwl (r11)+,r9 ; Pick up dest. length. clrq (r11) ; Clear I/O status block. bsbw alloc_mbx ; Allocate a mailbox. mnegw #1,(r11) ; -1 => alloc_mbx failed blbs r0,20$ ; J if ok. 10$: brw 90$ ; Leave on error. 20$: mnegw #2,(r11) ; -2 => Illegal buffer. subl2 #6,r9 ; Decrement from length of buffer bleq 10$ ; J if buffer too small. $qiow_s chan=mbx_read_chan, - func=r8, - iosb=(r11), - p1=6(r10), - p2=r9 blbs r0,30$ ; J if success. mnegw #3,(r11) ; -3 => $qio failed ret ; And return. 30$: cmpw #ss$_normal,(r11) ; Normal return? bneq 85$ ; J if not. addw2 #6,2(r11) ; Adjust size of I/O status block. movw #16,read_itmlst(fp) ; Set length of buffer in item list movw #jpi$_prcnam,read_itmlst+2(fp) ; Set code of item to find. moval read_buffer(fp),read_itmlst+4(fp) ; Set up buffer address. moval read_len(fp),read_itmlst+8(fp) ; Set up return length. clrl read_itmlst+12(fp) ; Signal last entry in item list $getjpi_s pidadr=4(r11), - itmlst=read_itmlst(fp), - iosb=read_iost(fp) blbc r0,60$ ; J on error. $waitfr_s efn=0 ; Wait for request to complete blbs r0,70$ ; J on success. 60$: clrl read_len(fp) ; Get a zero-length process name. 70$: movc5 read_len(fp),read_buffer(fp),#^a/ /, - #6,(r10) ; Move in the name. ret ; And return to the caller. 85$: mnegw #4,(r11) ; -4 => Mailbox read failed. 90$: ret ; And return to the caller. ; ; Subroutine to create a mailbox if necessary. ; ; Argument list: ; (none) ; ; Returns: ; As returned by system services in r0. ; ; Stack offsets ; cre_desc = 0 ; Character string descriptor cre_len = cre_desc ; Length in character descriptor cre_addr = cre_desc+4 ; Address in character descriptor cre_mbxname = cre_addr+4 ; Mailbox name (to be concatenated ; with below). cre_name = cre_mbxname+4 ; Returned name of process. cre_itmlst = cre_name+16 ; Item list to $getjpi cre_size = cre_itmlst+16 ; Size of area. ; alloc_mbx: tstl mbx_read_chan ; A channel already allocated? beql 1$ ; J if not, reallocate it. brw 99$ ; And leave --- no need to reallocate. 1$: pushr #^m ; Save r11 subl2 #cre_size,sp ; Allocate space on stack. movl sp,r11 ; Get a temporary "frame" movw #16,cre_itmlst(r11) ; Set up length of item. movw #jpi$_prcnam,cre_itmlst+2(r11) ; Set up get proc. name. moval cre_name(r11),cre_itmlst+4(r11) ; Point to process name. moval cre_len(r11),cre_itmlst+8(r11) ; Set return length addr clrl cre_itmlst+12(r11) ; And last item - end of list $getjpi_s itmlst=cre_itmlst(r11) blbc r0,90$ ; J if error. moval cre_mbxname(r11),r0 ; point to the mailbox name. movl r0,cre_addr(r11) ; Set up string descriptor. movl #^a/MBX_/,(r0)+ ; Mailbox name = ; MBX_processname addl2 #4,cre_len(r11) ; Adjust the length. cmpw cre_len(r11),#10 ; Length too large? bleq 30$ ; J if not. movw #10,cre_len(r11) ; Set length = 6 30$: locc #^a/:/,cre_len(r11),cre_mbxname(r11) ; Find a : if any. beql 35$ ; J if none found. movb #^a/./,(r1) ; Otherwise, move in a . brb 30$ ; And try to find another. 35$: $crembx_s prmflg=0, - chan=mbx_read_chan, - maxmsg=#256, - promsk=#^x0f565, - lognam=cre_desc(r11) 90$: addl2 #cre_size,sp ; Free up stack space. popr #^m ; Recover r11 99$: rsb ; And return to the caller. ; ; Function 3. Write to mailbox ; ; Argument list: ; code+2 - Address of mailbox buffer ; code+4 - Length of mailbox buffer ; code+6 - Address of compatibility mode ; character descriptor of target mailbox ; code+8 - 8-byte VMS I/O status block ; wri_desc = -8 ; Descriptor for write mailbox wri_name = wri_desc - 10 ; Name of write mailbox wri_chan = wri_name - 4 ; Channel on which write is done wri_size = -wri_chan ; Length of stack frame. ; wrimbx: subl2 #wri_size,sp ; Allocate space on stack. movzwl (r11)+,r10 ; Pick up dest. address. movzwl (r11)+,r9 ; Pick up dest. length. movzwl (r11)+,r8 ; Pick up address of task. movzwl (r11)+,r7 ; Pick up length of taskname. clrq (r11) ; Clear I/O status block. bsbw alloc_mbx ; allocate the mailbox. ; (this won't be used by write ; but should be allocated here ; to avoid any race conditions). mnegw #1,(r11) ; -1 => allocation failed. blbs r0,5$ ; Keep going if no errors. brw 90$ ; Leave on error. 5$: moval wri_name(fp),r6 ; Get address of mailbox name. movl r6,wri_desc+4(fp) ; Set the address in descriptor movl #^a/MBX_/,(r6)+ ; Mailbox name = ; MBX_processname cmpl r7,#6 ; Process name <= 6 characters? bleq 10$ ; J if so. movl #6,r7 ; Force process name = 6 characters. 10$: movc3 r7,(r8),(r6) ; Move in the process name. addl2 #4,r7 ; Adjust the length of the string. locc #^a/ /,r7,wri_name(fp) ; Locate first blank (if any) subl2 r0,r7 ; Adjust length of string. movl r7,wri_desc(fp) ; set up length of name. 20$: locc #^a/:/,r7,wri_name(fp) ; Try to find a : beql 30$ ; J if none there. movb #^a/./,(r1) ; Replace it with a . brb 20$ ; And try again. 30$: mnegw #2,(r11) ; -2 => $assign failed $assign_s devnam=wri_desc(fp), - chan=wri_chan(fp) blbc r0,90$ ; Leave on error. mnegw #3,(r11) ; -3 => $qiow failed $qiow_s chan=wri_chan(fp), - func=#io$_writevblk!io$m_now, - iosb=(r11), - p1=(r10), - p2=r9 blbc r0,90$ ; Leave on error. cmpw #ss$_normal,(r11) ; I/O normal? bneq 80$ ; J if not. $dassgn_s chan=wri_chan(fp) ; Deassign channel. blbs r0,90$ ; leave with success if ok. mnegw #5,(r11) ; -5 => $dassgn failed brb 90$ ; And leave. 80$: mnegw #4,(r11) ; -4 => Write to mailbox failed 90$: ret ; And return. ; ; Function 4. Simulate terminal driver functions. ; ; Stack offsets ; tty_buffersize = 100 ; Size of tty buffer area. tty_buffer = -tty_buffersize ; Buffer for $getdev service. tty_desc = tty_buffer-8 ; Character descriptor of buffer. tty_trnbuf = tty_desc-64 ; Translation buffer tty_trndesc = tty_trnbuf-8 ; Descriptor for translation buffer tty_junk = tty_trndesc-4 ; Junk area for sys$trnlog tty_size = -tty_junk ; Size of stack frame. ; simtty: subl2 #tty_size,sp ; Allocate stack frame. movl #64,tty_trndesc(fp) ; Set up translation buffer moval tty_trnbuf(fp),tty_trndesc+4(fp) ; ... And descriptor moval sysout+8,sysout+4 ; ... set up another char. descriptor. $trnlog_s lognam=sysout, - rsllen=tty_trndesc(fp), - rslbuf=tty_trndesc(fp), - acmode=tty_junk(fp), - table=tty_junk(fp) blbc r0,15$ ; Leave on error. cmpb #^O<33>,@tty_trndesc+4(fp) ; Process permanent? bneq 10$ ; J if not. addl2 #4,tty_trndesc+4(fp) ; Skip past first part of name. subl2 #4,tty_trndesc(fp) ; And decrement length. 10$: movl #tty_buffersize,tty_desc(fp) ; Set up ... moval tty_buffer(fp),tty_desc+4(fp) ; ... descriptor. $getdev_s devnam=tty_trndesc(fp), - prilen=tty_desc(fp), - pribuf=tty_desc(fp) blbs r0,20$ ; j if everything ok. cmpl r0,#ss$_bufferovf ; Overflow is ok (we're only beql 20$ ; interested in first bytes) cmpl r0,#ss$_nonlocal ; Network is ok. beql 20$ ; ... 15$: brb 90$ ; Leave if fatal error. 20$: movl tty_desc+4(fp),r9 ; Point to the buffer returned. movzwl (r11)+,r0 ; Pick up address of buffer. movzwl (r11)+,r8 ; Get length of list. ashl #-1,r8,r8 ; Divide length by 2. beql 90$ ; Leave if 0 movl r0,r11 ; Point to buffer. 30$: movb (r11)+,r7 ; Get characteristic to find. moval iastertbl,r6 ; Point to translation table. 40$: cmpb r7,(r6) ; Found match? beql 50$ ; J if so. addl2 #8,r6 ; Get to next element in table. tstb (r6) ; At end of table? bneq 40$ ; J if not. clrb (r11)+ ; Clear unknown value. brb 60$ ; And continue. 50$: movzwl 2(r6),r1 ; Get offset of routine. moval iastertbl,r2 ; Get address of table. addl2 r2,r1 ; Absolutise offset to subroutine. jsb (r1) ; Call the subroutine. 60$: sobgtr r8,30$ ; And loop over entire buffer. 90$: movl #1,r0 ; Success. ret ; And return. ; ; Subroutine to examine a bit field. ; xbt: clrl r1 ; Set the output code bitl 4(r6),8(r9) ; Is the appropriate bit set? beql 10$ ; J if not. incl r1 ; Set r1 = 1 if so. 10$: movb r1,(r11)+ ; Output the bit rsb ; And return to the caller. ; ; Subroutine to return Page size ; xpage: movb 11(r9),(r11)+ ; Output the page length. rsb ; And return to the caller. ; ; Subroutine to return speed ; xspeed: movb #16,(r11)+ ; Fake 4800. baud for now. rsb ; And return to the caller. ; ; Subroutine to return terminal type ; xtype: moval iastertyp,r6 ; Point to the terminal table. 10$: cmpb (r6),5(r9) ; Right terminal type? beql 20$ ; J if so. addl2 #4,r6 ; To next entry. tstw (r6) ; At end of table? bneq 10$ ; J if not. movb #t.unk0,(r11)+ ; Output unknown terminal. rsb ; And return to the caller. 20$: movb 2(r6),(r11)+ ; Output unknown terminal. rsb ; And return to the caller. ; ; Subroutine to return page width ; xwidth: movb 6(r9),(r11)+ ; Output the width. rsb ; And return to the caller. ; ; Function 5. Execute SORT procedures ; simsor: movl #1,r0 ; Success. ret ; And return. ; ; Function 6. Execute Spooler functions ; spr_buffer = -80 ; Buffer for send to Spooler symbiont spr_bufaddr = spr_buffer-4 ; Pointer to buffer (string descr) spr_len = spr_bufaddr-4 ; Length of buffer (string descr) spr_size = -spr_len ; Size of stack space. ; simspr: subl2 #spr_size,sp ; Allocate space off stack. moval spr_buffer(fp),spr_bufaddr(fp) ; Set up string descr. moval spr_buffer(fp),r9 ; Point to buffer. movw #smr$k_enter,(r9)+ ; Put code into buffer. movb #5,(r9)+ ; Get the size of the name. movb (r11)+,(r9)+ ; Move in first byte of name movb (r11)+,(r9)+ ; Move in second byte of name. cvtbl (r11)+,r8 ; Get the device number. rotl #-4,r8,r7 ; Divide by 16 (in effect) addb3 #^a/A/,r7,(r9)+ ; Output the controller number. ; rotl #-3,r8,r7 ; Divide by 8 (in effect) ; bicb2 #^x0fe,r7 ; Mask off unneeded bits. ; addb3 #^a/0/,r7,(r9)+ ; Output a 0 or 1 bicb2 #07,r8 ; Isolate low order bits. addb3 #^a/0/,r8,(r9)+ ; Output low order device number. movb #^a/:/,(r9)+ ; And output a : movl #10,r8 ; Get size of remainder. 10$: clrb (r9)+ ; Clear out remainder of buffer. sobgtr r8,10$ ; ... ; incl r11 ; Skip the priority. movw (r11)+,r10 ; Get copies, forms, delete. ; movb #7,(r9)+ ; Get device length of user file. movb #^a/_/,(r9)+ ; Output a _ movb (r11)+,(r9)+ ; Output low order device name movb (r11)+,(r9)+ ; Output high order device name. cvtwl (r11)+,r8 ; Get the device unit number. rotl #-4,r8,r7 ; Divide by 16 (in effect) addb3 #^a/A/,r7,(r9)+ ; Output the controller number. rotl #-3,r8,r7 ; Divide by 8 (in effect) bicb2 #^x0fe,r7 ; Mask off unimportant bits. addb3 #^a/0/,r7,(r9)+ ; Output the high order device num bicb2 #7,r8 ; Mask off all but low order bits addb3 #^a/0/,r8,(r9)+ ; Finish up the device number. movb #^a/:/,(r9)+ ; And end device name with : movl #8,r8 ; Get remaining length of name 20$: clrb (r9)+ ; Clear remaining device name sobgtr r8,20$ ; And loop over device name. movw (r11)+,(r9)+ ; Output the file ID movw (r11)+,(r9)+ ; ... movw (r11)+,(r9)+ ; ... movw (r11)+,(r9)+ ; Output the directory ID movw (r11)+,(r9)+ ; ... movw (r11)+,(r9)+ ; ... ; movc5 #0,(r0),#0,#20,(r9) ; Clear out the file name buffer. movl r9,r7 ; Get the file name area into r7 clrb (r7)+ ; Skip past the length. bsbw r50cvt3 ; Convert file name to Ascii movb #^a/./,(r7)+ ; Add in a . for file type. bsbw r50cvt1 ; Convert file type to Ascii ; movb #^a/;/,(r7)+ ; Add in a ; for version. tstw (r11)+ ; Skip past file version number. subl r9,r7 ; Compute length of string. decl r7 ; Minus one for length byte. cvtlb r7,(r9) ; Put it into the file name string. addl2 #20,r9 ; Skip over the file name area. ; movb #smo$k_copies,(r9)+ ; Select copies option. bicl3 #^x0ffffffe0,r10,r6 ; Get the number of copies. bneq 40$ ; J if specified correctly. movl #1,r6 ; Otherwise supply default. 40$: movb r6,(r9)+ ; Output number of copies. ; rotl #-5,r10,r6 ; Shift forms to right hand side bicl2 #^x0fffffff8,r6 ; Clear off high order garbage. movb #smo$k_formtype,(r9)+ ; Output form type code. movb r6,(r9)+ ; Output the forms. ; bitw #^o040000,r10 ; Is the preserve indicator on? bneq 50$ ; J if so. movb #smo$k_delete,(r9)+ ; Mark file for delete after printing. ; 50$: subl2 spr_bufaddr(fp),r9 ; Get size of buffer. movl r9,spr_len(fp) ; And set it in the string descriptor. clrq (r11) ; Clear I/O status. bsbw alloc_mbx ; Allocate a mailbox channel if reqd blbc r0,90$ ; J if error. ; $sndsmb_s msgbuf=spr_len(fp), - ; Send message to symbiont. chan=mbx_read_chan ; Mailbox to send message. blbc r0,90$ ; Leave on error. ; $qiow_s efn=0, - ; Event flag number chan=mbx_read_chan, - func=#io$_readvblk, - iosb=(r11), - p1=spr_buffer(fp), - p2=#80 blbc r0,90$ ; J on error. movl #1,r0 ; Success. ret ; And return. 90$: mnegw #1,(r11) ; Show error. mnegw #1,r0 ; Show error. ret ; And return. ; ; Subroutine to convert from Radix-50 words to Ascii ; ; Borrowed from the RSX AME. ; ; On input, ; ; r7 = address of target string ; r11 = address of Radix-50 words ; ; On output, ; ; r0 = ; r1 = ; r7 = address of next byte in target string ; r11 = address of next word to convert ; ; A blank will stop conversion. ; r50cvt3: movzwl (r11)+,r0 ; Get a word to convert bsbb cvt ; Convert it r50cvt2: movzwl (r11)+,r0 ; Get a word to convert bsbb cvt ; Convert it r50cvt1: movzwl (r11)+,r0 ; Get a word to convert cvt: clrl r1 ; Clear scratch space in r1 ediv #40,r0,r0,-(sp) ; Divide ediv #40,r0,r0,-(sp) ; out the ediv #40,r0,r0,-(sp) ; Radix-50 cvtlb (sp)+,(r7) ; Pick up first Radix-50 character. bsbb 50$ ; Convert to Ascii cvtlb (sp)+,(r7) ; Pick up second Radix-50 character bsbb 50$ ; Convert to Ascii cvtlb (sp)+,(r7) ; Pick pu third Radix-50 character. 50$: tstb (r7) ; Found a blank? beql done ; J if so - no more convert. cmpb #27,(r7) ; Letter? bgtru 60$ ; J if so. beql 55$ ; J if $ addb2 #9,(r7) ; Adjust the . 55$: addb2 #-55,(r7) ; Adjust . and $ 60$: addb2 #64,(r7)+ ; Adjust letters. done: rsb ; And return to the caller. .end natvmode