home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols200 / vol247 / connect.a86 < prev    next >
Encoding:
Text File  |  1994-07-13  |  16.3 KB  |  599 lines

  1. ;CONNECT.A86 - Connect current Virtual console to another virtual
  2. ;           console. FOR MCDOS only.
  3.  
  4. ;           Written only for the sake of learning about MCDOS
  5. ;           so could be full of bugs.
  6. ;
  7. ;           Author : Alex Soya     - Nov. 1984
  8. ;
  9. ;           Type a Control-Z to get out of Connect.
  10. ;
  11.  
  12. ;CCPM function calls
  13.  
  14.  
  15. P_TERMCPM    equ      0    ; Terminate and release all resources
  16. C_READ        equ      1    ; Read a character from the Default Console
  17. C_WRITE        equ      2    ; Write a character to the Default Console
  18. C_RAWIO        equ      6    ; Direct Console I/O with Default Console
  19. C_WRITESTR    equ      9    ; Print ASCII string to default console 
  20. C_STAT        equ     11    ; Obtain Status of Default Console
  21. DEV_WAITFLAG    equ    132    ; Wait for a System Flag
  22. DEV_SETFLAG    equ    133    ; Set a system Flag
  23. Q_OPEN        equ    135    ; Open A system queue
  24. Q_WRITE        equ    139    ; Write a message to a System Queue
  25. S_SYSDAT    equ    154    ; Return address of System Data Segment
  26. P_PDADR        equ    156    ; Return address of the process descriptor
  27.  
  28.  
  29.  
  30. cr        equ    13
  31. lf        equ    10
  32. cntrl_Z        equ    'Z'-40h
  33.  
  34. OPTION        equ    05dh    ; Command line Option can be found here.
  35. BASEFLAG    equ    40h    ; BaseFlag + console # used for qbuffer
  36. QDEPTH        equ     40    ; # of bytes in output Circular Que buffer
  37.  
  38.  
  39. ; Sysdat Offsets:
  40. ;
  41. ;
  42. SUPENTR        equ     0h    ; Supervisor entry offset
  43. XIOSSYS        equ    28h    ; Offset to Xios vector
  44.  
  45.  
  46.     CSEG
  47.  
  48. connect:
  49.     pushf ! pop bx            ; No interrupts during stack switches
  50.     cli
  51.     mov    ax,ds
  52.     mov    ss,ax
  53.     mov    sp, offset stack
  54.     push bx ! popf            ; Now we have our own stack.
  55.  
  56.     mov    cs:Word Ptr DSKEEP,DS    ; Keep the Data Segment here
  57.  
  58.     call    makesys            ; make us a system process.
  59.     call    gtarg            ; Get target console number
  60.     jz    valcon            ; If Console NOT valid then
  61.     mov    dx, offset invmsg    ;   Write error message. 
  62.     mov    cl, C_WRITESTR
  63.     int    224
  64.     jmps    qexit            ;   and terminate
  65.  
  66. valcon: mov    Byte Ptr TCON, al    ; Save the Target console #
  67.     mov    Word Ptr VQNAM, dx    ; Make proper Queue name
  68.     mov    dx, offset VINQPB    ; open VINQ que for target console
  69.     mov    cl, Q_OPEN
  70.     int    224
  71.     cmp    ax,0h            ; If Not Open then
  72.     jz    qopnd            
  73.     mov    dx, offset nopmsg    ;    Write an error message
  74.     mov    cl, C_WRITESTR
  75.     int    224
  76.     jmps    qexit            ;    and terminate
  77.                     ; endif
  78. qopnd:    call    ovlxios            ; overlay the xios jump vectors
  79.  
  80. mainloop:
  81.     call    tready            ;repeat main loop:
  82.     jz    local            ; if (target = ready) then
  83.     call    tget            ;   get target character
  84.     call    lput            ;   put character to local console
  85.                     ; endif
  86. local:    call    lready
  87.     jz    mainloop        ; if (local = ready) then
  88.     call    lget            ;   get local character
  89.     cmp    al,cntrl_Z        ;   check for abort
  90.     jz    exit            ;   if abort then exit
  91.     call    tput            ;   put character to target console
  92.     jmps    mainloop        ;until abort
  93.  
  94. exit:    call    restxios        ; restore xios vectors
  95. qexit:    call    makeus            ; make us a user process again
  96.     mov    cl,P_TERMCPM        ; and terminate us
  97.     int    224
  98.  
  99. DSKEEP    dw    2
  100.  
  101. ;-----------------------------------------------------------------------;
  102. ; makesys:    Set the current process as a systems process in PD flag ;
  103. ;        field.                            ;
  104. ;                                    ;
  105. ;    Entry  -> None                            ;
  106. ;    Return <- none                            ;
  107. ;                                    ;
  108. ;    Regs used:  ax, bx, cx, es                    ;
  109. ;                                    ;
  110. ;-----------------------------------------------------------------------;
  111. ;
  112. ;
  113. ;
  114. makesys:
  115.     mov    cl,P_PDADR        ; Obtain process descriptor address
  116.     int    224
  117.     mov    bx,ax            ; bx := offset(PD); es := segment(PD)
  118.     or    es:word ptr 6[bx],1    ; PD.FLAG := PD.FLAG or SYSTEM
  119.     ret                ;end makesys
  120.  
  121.  
  122.  
  123. ;-----------------------------------------------------------------------;
  124. ; makeus:  Reset the system attribute in PD flag            ;
  125. ;                                    ;
  126. ;    Entry  -> None                            ;
  127. ;    Return <- None                            ;
  128. ;                                    ;
  129. ;-----------------------------------------------------------------------;
  130. ;
  131. ;
  132. ;
  133. makeus: mov    cl,P_PDADR        ; Obtain PD address
  134.     int    224
  135.     mov    bx,ax            ; bx:= offset(PD); es:= segment(PD)
  136.     and    es:Word Ptr 6[bx],0feh    ; mask PD.FLAG.System
  137.     ret
  138.  
  139.  
  140.  
  141.  
  142. ;-----------------------------------------------------------------------;
  143. ;gtarg        Get console number as option from command tail        ;
  144. ;                                    ;
  145. ;    entry  -> none                            ;
  146. ;                                    ;
  147. ;    Return <- DX = 2 byte ASCII value from buffer ( 0 - 99)        ;
  148. ;          AL = Integer 0 - 99                    ;
  149. ;          FLAG = Z if valid Option, NZ if Invalid option    ;
  150. ;                                    ;
  151. ;    Regs used : AX,DX,CX                        ;
  152. ;                                    ;
  153. ;-----------------------------------------------------------------------;
  154. ;
  155. ;
  156. ;
  157. gtarg:    cmp    Byte Ptr .OPTION,' '    ; If No Tail then No Option
  158.     je    nooption        ;else
  159.     mov    dx, word ptr .OPTION    ; DX := Option
  160.     mov    ax,dx            ; AX := Option (in Ascii)
  161.     sub    al,'0'            ; Convert AX to binary in AL
  162.     cmp    ah,'0'
  163.     jb    no_tens            ; If second digit then 
  164.     cmp    ah,'9'
  165.     ja    no_tens            ;    adjust
  166.     sub    ah,'0'
  167.     mov    ch,ah
  168.     mov    cl,10
  169.     mul    cl            ;    make first digit the tens
  170.     add    al,ch            ;    AL = binary(DX)
  171. no_tens:                ; end if
  172.     cmp    al,0            ; is option in range
  173.     jb    nooption        ;  Nope, so no option found
  174.     cmp    al,99            
  175.     jg    nooption
  176.  
  177.     xor    ah,ah            ; set flag
  178.     ret
  179. nooption:
  180.     or    ah,0ffh
  181.     ret
  182.  
  183.  
  184.  
  185. ;-----------------------------------------------------------------------;
  186. ; ovlxios:  Overlays the XIOS jump vectors in SYSDAT with that of    ;
  187. ;        xiosintcpt, Keeps the old XIOS jump vector at XIOS and    ;
  188. ;        fills in the SUPVSR segment.                ;
  189. ;                                    ;
  190. ;    Entry  -> None                            ;
  191. ;    Return <- Fills in: XIOS, SYSDAT, SUPVSR (segment) and        ;
  192. ;          SYSDAT SEGMENT XIOS VECTOR                ;
  193. ;                                    ;
  194. ;    Regs used: ax,bx,cx,ex                               
  195. ;
  196. ;-----------------------------------------------------------------------;
  197. ;
  198. ;
  199. ;
  200. ovlxios:
  201.     mov    cl,S_SYSDAT        ; Get Sysdat Segment to ES
  202.     int    224
  203.     pushf                ; No interrupts while messing
  204.     cli                ; with Sysdat vectors
  205.     mov    ax,es:.XIOSSYS        ; Get current Xios Offset
  206.     mov    cs:XIOS,ax        ; and keep it here
  207.     mov    ax,es:.XIOSSYS+2    ; get segment of real xios
  208.     mov    XIOS+2,ax
  209.     mov    ax, offset xiosintcpt    ; overlay xios interceptor offset
  210.     mov    es:.XIOSSYS,ax        ; to Sysdat Xios vector offset
  211.     mov    ax,cs            ; overlay xios interceptor segment
  212.     mov    es:.XIOSSYS+2,ax    ; to Sysdat Xios vector segment
  213.  
  214.     mov    ax,es:.SUPENTR+2    ; Get Segment of Supervisor
  215.     mov    SUPVSR+2,ax        ; and keep it for us
  216.     popf                ; Interrupts OK again.
  217.     ret
  218.  
  219.  
  220.  
  221. ;-----------------------------------------------------------------------;
  222. ; tready:   See if a character from the target console is ready, ie    ;
  223. ;        is a character in the circular queue buffer.        ;
  224. ;                                    ;
  225. ;    Entry  -> nothing                        ;
  226. ;                                    ;
  227. ;    Return <- Flag = NZ if char is ready, Z if not            ;
  228. ;          AL = FFh if char is ready, 0 if not            ;
  229. ;                                    ;
  230. ;    Regs used: None                            ;
  231. ;-----------------------------------------------------------------------;
  232. ;
  233. ;
  234. ;
  235. tready: mov    si, offset OUTQUE    ; Here is our Que
  236.     call    qempt
  237.     pushf
  238.     jnz    treadr            ; If Writer waiting then
  239.     cmp    Byte Ptr BFULL,0ffh
  240.     jne    treadr
  241.     mov    Byte Ptr BFULL,0h    ;    Set Flag to indicate que empty
  242.     mov    dl, BASEFLAG        ;    Compute Flag for this console
  243.     add    dl, Byte Ptr TCON    ;    and set it.
  244.     mov    cl, DEV_SETFLAG
  245.     int    224
  246. treadr: popf
  247.     ret
  248.  
  249.  
  250.  
  251. ;-----------------------------------------------------------------------;
  252. ; tget: Get the target character, i.e. Take it out of the Queue buffer    ;
  253. ;                                    ;
  254. ;    Entry  -> None                            ;
  255. ;    Return <- AL = Character                    ;
  256. ;                                    ;
  257. ;    Regs used: AX, SI, BX                        ;
  258. ;-----------------------------------------------------------------------;
  259. ;
  260. ;
  261. ;
  262. tget:    mov    si, offset OUTQUE    ; This is the Que Buffer
  263.     call    qdel            ; Go get the char
  264.     ret
  265.  
  266.  
  267.  
  268. ;-----------------------------------------------------------------------;
  269. ; lput: Send a character to local console                ;
  270. ;                                    ;
  271. ;    Entry  -> AL = Character                    ;
  272. ;    Return <- none                            ;
  273. ;                                    ;
  274. ;    Regs used: AX, CX, DX                        ;
  275. ;-----------------------------------------------------------------------;
  276. ;
  277. ;
  278. lput:    mov    dl,al            ; Character to send to DL
  279.     mov    cl, C_WRITE        ; Use System C_Write function
  280.     int    224
  281.     ret
  282.  
  283.  
  284.  
  285. ;-----------------------------------------------------------------------;
  286. ; lready:    Obtain status of local console                ;
  287. ;                                    ;
  288. ;    Entry  -> none                            ;
  289. ;    Return <- AL = 01h if Char ready, 00h if not ready        ;
  290. ;          Flag = Z if not ready, NZ if ready            ;
  291. ;                                    ;
  292. ;    Regs used: AX, BX, CX                        ;
  293. ;-----------------------------------------------------------------------;
  294. ;
  295. ;
  296. ;
  297. lready: mov    cl,C_STAT    ; Use System C_stat function
  298.     int    224
  299.     or    al,al        ; Set Return Flag
  300.     ret
  301.  
  302.  
  303.  
  304. ;-----------------------------------------------------------------------;
  305. ; lget:     Get a character from the local console                ;
  306. ;                                    ;
  307. ;    Entry  -> None                            ;
  308. ;    Return <- AL = character                    ;
  309. ;                                    ;
  310. ;-----------------------------------------------------------------------;
  311. ;
  312. ;
  313. lget:    mov    cl,C_RAWIO
  314.     mov    dl,0fdh
  315.     int    224
  316.     ret
  317.  
  318.  
  319.  
  320. ;-----------------------------------------------------------------------;
  321. ; tput: Send a character to target console. Does this by writing the    ;
  322. ;    character to the target consoles VINQn System Queuq.        ;
  323. ;                                    ;
  324. ;    Entry  -> AL = Character to send                ;
  325. ;    Return <- AX = AX on entry.                    ;
  326. ;                                    ;
  327. ;-----------------------------------------------------------------------;
  328. ;
  329. ;
  330. ;
  331. tput:    push    ax
  332.     mov    ah,0            ; Null the High Byte
  333.     mov    Word Ptr Qbuf,AX    ; Put the character into Queue buffer
  334.     mov    dx, offset VINQPB    ; DX := Queue Parameter Block offset
  335.     mov    cl, Q_WRITE
  336.     int    224            ; and send a message
  337.     pop    ax
  338.     ret
  339.  
  340.  
  341.  
  342. ;-----------------------------------------------------------------------;
  343. ; restxios:  Restore the original XIOS jump vectors in SYSDAT page    ;
  344. ;                                    ;
  345. ;    Entry  -> Assumes original XIOS vectors stored at XIOS in Code    ;
  346. ;          Segment.                        ;
  347. ;    Return <- None                            ;
  348. ;                                    ;
  349. ;-----------------------------------------------------------------------;
  350. ;
  351. ;
  352. ;
  353. restxios:
  354.     mov    cl,S_SYSDAT        ; Get Sysdat segment to ES
  355.     int    224
  356.     pushf                ; No interupts while messing
  357.     cli                ; With SYSDAT values
  358.     mov    ax,cs:XIOS        ; Get Xios offset
  359.     mov    es:.XIOSSYS,ax        ; and restore it in SYSDAT
  360.     mov    ax,cs:XIOS+2        ; Get Segment for Xios
  361.     mov    es:.XIOSSYS+2,ax    ; and restore it too.
  362.     popf                ; Interrupts are ok again
  363.     ret                ; back to caller.
  364.  
  365.  
  366.  
  367.  
  368. ;-----------------------------------------------------------------------;
  369. ; xiosintcpt:    Intercept call to XIOS and handle IO_CONOUT function    ;
  370. ;        for target console locally.                ;
  371. ;                                    ;
  372. ;    Entry  -> AL = XIOS function number                ;
  373. ;          CL = Character to send                ;
  374. ;          DL = Virtual console to send to            ;
  375. ;                                    ;
  376. ;    Return <- Jumps to XIOS with all registers preserved        ;
  377. ;          Except Flag, which is not used by XIOS        ;
  378. ;          functions.                        ;
  379. ;-----------------------------------------------------------------------;
  380. ;
  381. ;
  382. xiosintcpt:
  383.  
  384.     push    ds
  385.     mov    ds, Word Ptr DSKEEP    ; Get this Data Segment
  386.     cmp    al,2            ; if XIOS function = 2 (Console Output)
  387.     jne    jxios            ;    and
  388.     cmp    dl, Byte Ptr TCON    ;    Console = Target Console
  389.     jne    jxios            ;   then
  390.     call    qinsert            ;    Insert char in queue
  391. jxios:    pop    ds
  392.     jmpf    cs:Dword Ptr XIOS    ; Goto realxios
  393.  
  394.  
  395. ;-----------------------------------------------------------------------;
  396. ; qinsert:  Insert a character into the que. If Que is full, wait until ;
  397. ;        Some space has been made. Uses System Flags to wait for    ;
  398. ;        empty queue.                        ;
  399. ;                                    ;
  400. ; Entry     -> CL = Character                        ;
  401. ; Return <- none                            ;
  402. ;                                    ;
  403. ; Regs used: All Registers preserved except flag Reg            ;
  404. ;-----------------------------------------------------------------------;
  405. ;
  406. ;
  407. ;
  408. qinsert:
  409.     push    ax
  410.     push    bx            ; Save'm
  411.     push    cx
  412.     push    dx
  413.     push    si
  414.     push    di
  415.     push    bp
  416.     mov    si, offset OUTQUE    ; Get Circular Que offset
  417.     call    qfull            ; If Que is full then
  418.     jnz    insrt            ;   Wait for empty queue flag
  419.     push    si
  420.     push    cx
  421.     mov    Byte Ptr BFULL,0ffh    ;   Tell Reader to set Flag when empty
  422.     mov    dl,BASEFLAG        ;   Compute flag for this console
  423.     add    dl, Byte Ptr TCON    ;   flag := BaseFlag + Console #
  424.     mov    cl, DEV_WAITFLAG    ;   lets wait for the flag
  425.     call    supif            ;   direct supervisor call
  426.     pop    cx
  427.     pop    si            ; end if
  428.  
  429. insrt:    mov    al,cl            ; Character to send in al
  430.     call    queins            ; insert Character into que
  431.     pop    bp
  432.     pop    di
  433.     pop    si
  434.     pop    dx
  435.     pop    cx
  436.     pop    bx            ; restore them
  437.     pop    ax
  438.     ret
  439.  
  440.  
  441.  
  442.  
  443.  
  444. ;-----------------------------------------------------------------------;
  445. ; qempt:   Check to see if Que is empty                    ;
  446. ;                                    ;
  447. ;  entry  -> si = que offset                        ;
  448. ;                                    ;
  449. ;  return -> Que empty:       al = 0, Z is Set                ;
  450. ;         Char in que:  al = FF, Z not set                ;
  451. ;-----------------------------------------------------------------------;
  452.  
  453.  
  454. qempt:    push    bx        ; lets not destroy anything other than al
  455.     mov    bx,word ptr 2[si]    ; get rear of que
  456.     cmp    word ptr[si],bx ; if front = rear then
  457.     mov    al, 0
  458.     je    qstat            ;   que := empty
  459.     mov    al, 0ffh        ; else que:= not empty
  460. qstat:    pop    bx
  461.     or    al,al
  462.     ret
  463.  
  464. ;-----------------------------------------------------------------------;
  465. ; qfull:  test if que is full.                        ;
  466. ;                                    ;
  467. ; entry     -> si = que offset                        ;
  468. ;                                    ;
  469. ; return -> NZ = ok, Z = que FULL                    ;
  470. ;                                    ;
  471. ;-----------------------------------------------------------------------;
  472.  
  473. qfull: mov    bx,word ptr[si] ; if front + 1 = rear then
  474.        call    incqptr            ;   que=full
  475.        cmp    bx,word ptr 2[si]
  476.        ret                ; Z = full, NZ = ok
  477.  
  478.  
  479. ;-----------------------------------------------------------------------;
  480. ; incqptr:  Increment the Que pointer. Takes care of wrap arround    ;
  481. ;        if end of que area is reached                ;
  482. ; entry      -> BX = pointer                        ;
  483. ; return  -> BX = pointer + 1 increment                    ;
  484. ;-----------------------------------------------------------------------;
  485. ;
  486. ;
  487. incqptr:inc    bx            ; point to next que offset
  488.     cmp    bx,qdepth        ; end of que area reached ?
  489.     jne    incd            ; if not we are done
  490.     xor    bx,bx            ; yeap... lets wrap
  491. incd:    ret
  492.  
  493.  
  494.  
  495. ;-----------------------------------------------------------------------;
  496. ; queins: insert a character into que. If que is full the character    ;
  497. ;      is just droped.                        ;
  498. ;                                    ;
  499. ; entry        -> al = character                        ;
  500. ;           si = que offset                        ;
  501. ;                                    ;
  502. ; return -> none                            ;
  503. ;-----------------------------------------------------------------------;
  504.  
  505. queins: push    ax
  506.     call    qfull            ; find out if the que is full
  507.     pop    ax            ; Z -> ok, NZ -> full
  508.     je    qind            ; if que is full then loos data
  509.     mov    bx, word ptr[si]    ; else que[front]=item
  510.     mov    byte ptr 4[si+bx],al
  511.     call    incqptr            ; front = front + 1
  512.     mov    word ptr[si],bx
  513. qind:    ret
  514.  
  515.  
  516. ;-----------------------------------------------------------------------;
  517. ; qdel:     delete a character from que                    ;
  518. ;                                    ;
  519. ; entry       -> si = que offset                        ;
  520. ;                                    ;
  521. ; return   -> al = character                        ;
  522. ;-----------------------------------------------------------------------;
  523.  
  524.  
  525. qdel:    call    qempt            ; anything in the que ?
  526.     je    qdeld            ; nope, so nothing we can get out...
  527.     mov    bx,word ptr 2[si]    ; al = que[rear]
  528.     mov    al,byte ptr 4[si+bx]
  529.     call    incqptr            ; rear = rear+1
  530.     mov    word ptr 2[si],bx
  531. qdeld:    ret
  532.  
  533.  
  534.  
  535.  
  536. ;-----------------------------------------------------------------------;      
  537.  
  538. ; supif:    Call CCP/M Supervisor                    ;
  539. ;                                    ;
  540. ; Entry     ->  CX = System call number                    ;
  541. ;         DX = Parameter                        ;
  542. ;         DS = Segment address if DX is an offset into a structure    ;
  543. ;         ES = User Data Area                    ;
  544. ;                                    ;
  545. ; Return ->  AX = BX = Return                        ;
  546. ;         CX = Error Code                        ;
  547. ;         ES = UDA Segment (as on Entry)                ;
  548. ;                                    ;
  549. ; Regs Used: DX, SI, DI, BP are NOT preserved..                ;
  550. ;                                    ;
  551. ;-----------------------------------------------------------------------;
  552. ;
  553. ;
  554. supif:    mov    ch,0        ; Clear High byte of function number
  555.     push    es
  556.     push    ds
  557.     mov    ds, Word Ptr Sysdat
  558.     mov    si,.68h
  559.     mov    es,ds:10h[si]    ; Get UDA of current process
  560.     callf    cs:dword ptr SUPVSR
  561.     pop    ds
  562.     pop    es
  563.     ret
  564.  
  565.  
  566.  
  567. XIOS    dw    0        ; Offset address of XIOS
  568. SYSDAT    dw    0        ; Segment of XIOS and System Data Segment
  569.  
  570. SUPVSR    dw    3        ; Entry to supervisor, offset = 3
  571.     dw    0        ; Segment filled in later
  572.     
  573.     DSEG
  574.  
  575.     Org 100h
  576.  
  577.  
  578. TCON    db    0        ; Target Console Number
  579. BFULL    db    0        ; Flag indicating buffer is full
  580. OUTQUE    dw    0        ; front of que
  581.     dw    0        ; rear of que
  582.     rb    qdepth        ; here is the que area.
  583.  
  584. INVMSG    db    ' Invalid Virtual Console Number.',cr,lf
  585.     db    ' usage: CONNECT nn',cr,lf
  586.     db    ' nn - Virtual Console number',cr,lf,'$'
  587.  
  588. NOPMSG    db    ' Unable to open Input Queue.',cr,lf,'$'
  589.  
  590. VINQPB    dw    0,0,0        ; VINQnn Parameter Block
  591.     dw    offset Qbuf
  592.     db    'VINQ'        ; Primary Queue name
  593. VQNAM    db    '    '        ; Secondary Queue name (Console number)
  594.  
  595. QBUF    db    40h * 2        ; can have 40 messages times 2 bytes each
  596.  
  597.     rw    31
  598. stack    dw    0
  599.