home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / CPM86 / MSUP.A86 < prev    next >
Text File  |  2000-06-30  |  48KB  |  1,791 lines

  1.  
  2. title    ' Modem Supervisor for Compupro MPM 8-16'
  3.  
  4. ;-----------------------------------------------------------------------;
  5. ;    MSUP - Modem SUPervisor                        ;
  6. ;                                    ;
  7. ;    Version 1.1    08/22/84       <AKS>                ;
  8. ;                                    ;
  9. ;    Copyright (C) 1984     Alex Soya, PO Box 121, Melbourne Beach,    ;
  10. ;                        Fl, 32951        ;
  11. ;                                    ;
  12. ;    MSUP is released to the public domain. Anyone who wishes to    ;
  13. ;    USE MSUP on his system may do so.  The author assumes no    ;
  14. ;    responsibility or liability for use of MSUP.            ;
  15. ;                                    ;
  16. ;    The author, Alex Soya, has sole rights to this program. MSUP    ;
  17. ;    may not be sold without the express, written permission by    ;
  18. ;    the author.                            ;
  19. ;                                    ;
  20. ;    Purpose:                                ;
  21. ;        To intercept Console I/O functions to the XIOS and    ;
  22. ;    handle them localy. To supervise the allocation of Comunication ;
  23. ;    channels to modem programs.                    ;
  24. ;                                    ;
  25. ;        This version is for the CompuPro interfacer 3/4        ;
  26. ;    serial board. Up to two boards (max 16 devices) are supported    ;
  27. ;    The boards must have interrupt jumpers and switches set        ;
  28. ;    as per CompuPro's instructions. The received data is buffered   ;
  29. ;    in a local queue structure. This RSP can also be used with any    ;
  30. ;    standard terminal if a modem is not connected. The only        ;
  31. ;    difference is that the received data does not have the        ;
  32. ;    parity bit removed which is infact an annoying feature in the    ;
  33. ;    XIOS by CompuPro.                        ;
  34. ;                                    ;
  35. ;    The mapping of MPM console numbers to Interfacer 3/4        ;
  36. ;    relative user nos uses the same translation as that of        ;
  37. ;    CompuPro for compatibility reasons:                ;
  38. ;                                    ;
  39. ;    Interfacer 3/4 relative user:     MPM Console:  MPM Printer:    ;
  40. ;  F    -----------------------------     ------------  ------------    ;
  41. ;  I                    7            1        -    ;
  42. ;  R                    6            2        -    ;
  43. ;  S    Interfacer 3 & 4        5            -        1    ;
  44. ;  T                    4            -        0    ;
  45. ;    ---------------------------------------------------------    ;
  46. ;  B                    3            3        -    ;
  47. ;  O    Interfacer 3 only        2            4        -    ;
  48. ;  A                    1            5        -    ;
  49. ;  R                    0            6        -    ;
  50. ;  D                                    ;
  51. ; --------------------------------------------------------------------    ;
  52. ;  S                    8            -         2    ;
  53. ;  E    Interfacer 3 & 4        9            7         -    ;
  54. ;  C                   10            8         -    ;
  55. ;  O                   11            9         -    ;
  56. ;  N    ----------------------------------------------------------    ;
  57. ;  D                   12           10         -    ;
  58. ;    Interfacer 3 only       13           11         -    ;
  59. ;  B                   14           12         -    ;
  60. ;  O                   15           13         -    ;
  61. ;  A                                    ;
  62. ;  R                                    ;
  63. ;  D                                    ;
  64. ;                                    ;
  65. ;    To customize this map change the CTRMAP AND RTCMAP tables.    ;
  66. ;                           =====            ;
  67. ;-----------------------------------------------------------------------;
  68.  
  69.  
  70.  
  71. true    equ    -1
  72. false    equ    not true
  73.  
  74.  
  75. cr    equ    13        ; Carriage Return
  76. lf    equ    10        ; Line Feed
  77. eof    equ    1ah        ; End Of File marker
  78. xon    equ    'Q'-40h        ; ^Q
  79. xoff    equ    'S'-40h        ; ^S
  80.  
  81.  
  82.  
  83. ; Consoles handled by RSP:
  84. ;
  85. ;
  86. lowcon      equ      1        ; Lowest Console number handled
  87. highcon      equ      13        ; Highest Console number handled
  88. lowprnt      equ      0        ; Lowest Printer handled
  89. highprnt  equ      2        ; Highest Printer handled
  90.  
  91. qdepth    equ    128            ; Lenght of circular que buffers
  92.  
  93.  
  94.  
  95.  
  96. ; Interrupt Vector addresses:
  97. ; The interfacer 3/4 uses VI2 for receive and VI3 for transmit. The particular
  98. ; Usart or device that interrupted must be determined in the corresponding
  99. ; ISR
  100. ;
  101. ;
  102. ;
  103. rint2    equ    (40h+2)*4        ; Receive interrupt vector address VI2
  104. tint3    equ    (40h+3)*4        ; Transmit interrupt vect. address VI3
  105.  
  106.  
  107.  
  108. ; Flags used by this RSP:
  109. ; flags 30h through 50h are used by this rsp and should not be used by any
  110. ; other processes.
  111. ;
  112. ;
  113. ;
  114. fbase  equ    30h            ; lowest flag used
  115. fwait  equ    fbase            ; Flag to wait for ever
  116.             ; fbase+1h through fbase+16 are for receive
  117.             ; ready, fbase+17 through fbase+32  are for
  118.             ; transmit ready on devices 1 - 16
  119.  
  120.  
  121.  
  122. ; MPM function numbers
  123. ;
  124. ;
  125. f_open    equ    15        ; Open Disk File Function
  126. f_close equ    16        ; Close Disk File
  127. f_rseq    equ    20        ; Read Sequential from Disk file function
  128. f_dmao    equ    26        ; Set DMA Offset
  129. f_dmab    equ    51        ; Set DMA Base
  130. f_poll    equ    131        ; Poll Device
  131. waitf    equ    132        ; Wait for selected flag to set
  132. setf    equ    133        ; Set selected flag to wake up waiting process
  133. f_mkque equ    134        ; Make a Que
  134. f_opque equ    135        ; Open Que
  135. f_wrque equ    139        ; Write Que
  136. getsys    equ    154        ; Get sysdat segment to ES
  137.  
  138.  
  139.  
  140. ; SYSDAT offsets
  141. ;
  142. ;
  143. supentr equ    0        ; Supervisor entry offset
  144. xiossys equ    28h        ; offset to XIOS entry in system data area
  145. dispsys equ    38h        ; offset to dispatcher entry address
  146.  
  147.  
  148.  
  149. ; Interrupt controller comands
  150. ;
  151. ;
  152. ;
  153. nseoi    equ    20h        ; none specific End of Interrupt
  154.  
  155.                 ; This is for the PICs located on the
  156.                 ; System Support 1 board. If you use
  157.                 ; a different Interrupt Controller you need
  158.                 ; to modify any of the PIC dependent routine
  159.                 ; (service) for your environment
  160.  
  161.  
  162.  
  163. ; System Support I  PIC ports:
  164. ;
  165. ;
  166. ;
  167. ss1base equ    50h        ; System Support I base port
  168. mpic0    equ    ss1base+0    ; Master PIC port 0
  169. mpic1    equ    ss1base+1    ; Master PIC port 1
  170. spic0    equ    ss1base+2    ; Slave PIC port 0
  171. spic1    equ    ss1base+3    ; Slave PIC port 1
  172.  
  173.  
  174.  
  175. ; CompuPro Interfacer 3/4 ports:
  176. ;
  177. ;
  178. ;
  179. i4base    equ    10h        ; Interfacer 3/4 base port
  180. i4data    equ    i4base        ; Data port
  181. i4stat    equ    i4base+1    ; Status port
  182. i4mode    equ    i4base+2    ; Usart mode register
  183. i4comd    equ    i4base+3    ; Usart Command register
  184. i4tint    equ    i4base+4    ; Transmit interrupt status register
  185. i4rint    equ    i4base+5    ; Receive Interrupt status register
  186. i4slct    equ    i4base+7    ; Relative user select register
  187.  
  188.  
  189.  
  190. ; Status port bit maps (on read):
  191. ;
  192. ;
  193. ;
  194. i4tbmt    equ    01h        ; Transmit buffer empty
  195. i4dav    equ    02h        ; Data available
  196. i4txem    equ    04h        ; Change in DSR or DCD or Transmit shift empty
  197. i4pe    equ    08h        ; Parrity error on character received
  198. i4or    equ    10h        ; Overrun error
  199. i4fe    equ    20h        ; framing error
  200. i4dcd    equ    40h        ; Data Carrier Detect condition
  201. i4dsr    equ    80h        ; Data Set Ready Condition
  202.  
  203.  
  204. ; Set up file constants:
  205. ;
  206. ;
  207. ;
  208. lnlen    equ    80        ; max line length of COMCH, TTYS or LPRS entry
  209.  
  210.  
  211.  
  212. ;-----------------------------------------------------------------------;
  213. ; exec: Rsp execution entry.                        ;
  214. ;                                    ;
  215. ;    The RSP starts executing here. Here the COMCH, TTYSC and LPRSC    ;
  216. ;    files are read and used to set up the interrupt masks for the    ;
  217. ;    Interfacer 3/4 board.                        ;
  218. ;                                    ;
  219. ;    The Mutual eXclusion ques MXmodem1 through MXmodem8 are made    ;
  220. ;    and written to if the corresponding console number in the    ;
  221. ;    COMCH file exists. The modem program must open the MXmodemN    ;
  222. ;    ques with N beeing the number of a Comm. channel. If the modem    ;
  223. ;    program reads from the que it effectively blocks any other    ;
  224. ;    process to gain access to that que and thus the corresponding    ;
  225. ;    Communication Channel.                        ;
  226. ;                                    ;
  227. ;    Also the XIOS entry point is moved to the local XIOS function    ;
  228. ;    intercepter.                            ;
  229. ;                                    ;
  230. ;-----------------------------------------------------------------------;
  231. ;
  232. ;
  233. ;
  234. exec:    mov    ax,cs            ; set up 8080 model (cs=ds)
  235.     pushf                ; disable interrupts while messing
  236.     cli                ; with stack regs
  237.     mov    ss,ax
  238.     mov    sp,offset lstack
  239.     mov    ds,ax
  240.  
  241.     mov    cl,146            ; Attach Console so Shell does not
  242.     int    224            ; grab it.
  243.  
  244.     popf
  245.     mov    cl,getsys        ; Get SYSDAT to ES
  246.     int    224
  247.     pushf                ; stop interrupts again
  248.     cli                ; while changing interrupt vectors
  249.  
  250.     push    ds            ; set up interrupt vector addresses
  251.     mov    ax,0            ; vectors are in segment 0
  252.     mov    ds,ax
  253.     mov    word ptr .rint2,offset i4rxint    ; receive interrupt handler
  254.     mov    word ptr .rint2+2,cs    ; and our segment
  255.     mov    word ptr .tint3,offset i4txint    ; transmit interrupt handler
  256.     mov    word ptr .tint3+2,cs    ; and segment
  257.     pop    ds
  258.  
  259.     mov    ax,es:.xiossys        ; get current XIOS offset
  260.     mov    xios,ax            ; build real xios dispatch address
  261.     mov    ax,es:.xiossys+2    ; get segment of real xios
  262.     mov    xios+2,ax
  263.     mov    ax, offset xintcpt    ; overlay xios interceptors address
  264.     mov    es:.xiossys,ax        ; to old xios vectors
  265.     mov    ax,cs
  266.     mov    es:.xiossys+2,ax
  267.  
  268.     mov    ax,es:.supentr+2    ; get segment of MPM supervisor
  269.     mov    supvsr+2,ax        ; and keep to us
  270.  
  271.     mov    ax,es:.dispsys        ; Now get dispatchers offset
  272.     mov    disp,ax
  273.     mov    ax,es:.dispsys+2    ; and its segment
  274.     mov    disp+2,ax
  275.  
  276.     popf                ; now we can resume with interrupts
  277.  
  278.  
  279.     call    rdsetup            ; set up MXmodemN ques and prepare
  280.                     ; masks for interfacer 3/4
  281.     mov    cl,9            ; send message: 'we are active' to
  282.     mov    dx, offset hellomsg    ; system console
  283.     int    224
  284.  
  285.     mov    cl,147            ; detach from Console, so Shell can
  286.     int    224            ; get a hold of it.
  287.  
  288. forever:mov    cl,waitf        ; CODE MAY BE ADDED HERE TO ALLOW
  289.     mov    dl,fwait        ; REMOTE TERMINALS TO BE MONITORED FOR
  290.     int    224            ; PROCCESS ABORTION ON LOSS OF CARRIER
  291.     jmps    forever            ; AND LOGON PROGRAM LOAD
  292.  
  293.  
  294.  
  295. hellomsg    db    cr,lf,' Msup - Modem Supervisor active. (C) Alex Soya'
  296.         db    cr,lf,'$'
  297.  
  298.  
  299.  
  300.  
  301.  
  302. ;-----------------------------------------------------------------------;
  303. ;                                    ;
  304. ; rdsetup:   Read the set up files TTYSC, LPRSC, and COMCH        ;
  305. ;                                    ;
  306. ;         These files contain the parameters for the Consoles,    ;
  307. ;         Printers, and Comunication Channels.            ;
  308. ;         They are read in here to determine which channels        ;
  309. ;         on the Interfacer 3/4 board are used so that the proper    ;
  310. ;         Interrupt mask can be set up.                ;
  311. ;                                    ;
  312. ;         The files TTYSC and LPRSC are as per COMPUPROS specs for    ;
  313. ;         their TTYS and LPRS files used by SHELL.            ;
  314. ;                                    ;
  315. ;         The file COMCH is used to determine which Interfacer 3/4    ;
  316. ;         device is used as a Communications Channel for the        ;
  317. ;         Modem. Proper Mutual EXclusion Ques are set up depending    ;
  318. ;         on the COMCH file entries.                    ;
  319. ;                                    ;
  320. ;         The COMCH format is as:                    ;
  321. ;                                    ;
  322. ;         N: Comment <CR><LF>                    ;
  323. ;                                    ;
  324. ;         Where N = the Console number corresponding to the        ;
  325. ;         Modem Port.                        ;
  326. ;                                    ;
  327. ;         eg:                            ;
  328. ;         2: Phone line 1                    ;
  329. ;         3: Phone line 2                    ;
  330. ;                                    ;
  331. ;         will turn consoles 2 and 3 into Comm. channels. DO NOT    ;
  332. ;         include these into the TTYS and TTYSC files as they will    ;
  333. ;         then be grabed by the shell.                ;
  334. ;                                    ;
  335. ;-----------------------------------------------------------------------;
  336. ;
  337. ;
  338. ;
  339. rdsetup:
  340.     mov    fopflg,0        ; File is still closed
  341. nxcom:    mov    dx,offset comfcb    ; Open COMCH file and prepare to read
  342.     call    getline            ; one line.
  343.     jne    ttyf            ; No more in ComCH file.
  344.     call    parscom            ; proccess one line
  345.     jmps    nxcom            ; and get next line
  346.  
  347. ttyf:    mov    fopflg,0        ; File Closed now
  348. nxtty:    mov    dx,offset ttyfcb    ; now process the TTYS file
  349.     call    getline
  350.     jne    lprf
  351.     call    parstty
  352.     jmps    nxtty
  353. ;
  354. lprf:    mov    fopflg,0        ; File Closed again
  355. nxlpr:    mov    dx, offset lprfcb    ; and finaly the LRPS file
  356.     call    getline
  357.     jne    done
  358.     call    parslpr
  359.     jmps    nxlpr
  360. done:    ret
  361. ;
  362. ;
  363. ;
  364. ;-----------------------------------------------------------------------;
  365. ; getline:    Get one line from file of which the FCB is in DX.        ;
  366. ;          If fopflg = 0, the file is closed and is opened first    ;
  367. ;          to read the next line.                    ;
  368. ;          Closes file if no more data available.            ;
  369. ;                                    ;
  370. ; Entry     ->  DX = FCB offset                        ;
  371. ;         fopflg = 0 if file closed, Not 0 if file already open    ;
  372. ;                                    ;
  373. ; Return ->  lnbuff  contains one physical line including cr,lf to    ;
  374. ;             indicate the end of the line.            ;
  375. ;                                    ;
  376. ;         fopflg = FFh after file was opened.            ;
  377. ;                                    ;
  378. ;-----------------------------------------------------------------------;
  379. ;
  380. ;
  381. ;
  382. getline:
  383.     push    dx            ; save FCB offset
  384.     mov    di, offset lnbuff    ; point to line buffer
  385.     mov    si,dmasrc        ; get dma posit from last move
  386.     mov    bx,dmaoff        ; and the count
  387.     cmp    byte ptr fopflg,0    ; first line we are getting ?
  388.     jne    search            ; no, see whats in dma buffer
  389.  
  390.     mov    dx, offset dmabuf    ; Yes, open file first 
  391.     mov    cl, f_dmao
  392.     int    224
  393. ;
  394.     mov    dx,cs            ; Set DMA Segment address
  395.     mov    cl, f_dmab
  396.     int    224
  397. ;
  398.     pop    dx ! push dx        ; get FCB offset
  399.     mov    cl, f_open        ; open the file
  400.     int    224
  401. ;
  402.     mov    di, offset lnbuff    ; init line buffer offset
  403.     cmp    al,0ffh
  404.     jne    rdnxt            ; if open successfull, read record
  405.     or    al,al
  406.     pop    dx
  407.     ret                ; else return to caller
  408. ;
  409. ;
  410. ;
  411. rdnxt:    mov    fopflg,-1        ; the file is open now
  412. beatme: pop    dx ! push    dx        ; Read next record of file
  413.     mov    cl, f_rseq
  414.     int    224
  415.     xor    bx,bx
  416.     or    al,al
  417.     mov    si, offset dmabuf    ; start at beginning of buffer
  418.     je    srterm            ; if good read, move one line to line
  419.     jmp    clcom            ; buffer, else close file.
  420. ;
  421. srterm: mov    ax,ds            ; force es=ds
  422.     mov    es,ax
  423. ;
  424. search: cmp    dmabuf[bx],lf        ; search for end of line marker
  425.     je    lf_fnd            ; or until end of buffer is reached
  426.     cmp    dmabuf[bx],eof        ; is it the end of the file
  427.     je    clcom            ; that means we are done
  428.     cmp    bx,127            ; end of buffer reached ?
  429.     je    en_buf
  430.     inc    bx
  431.     jmps    search            ; nope... keep looking
  432. ;
  433. en_buf: inc    bx
  434.     mov    dx,si
  435.     sub    dx, offset dmabuf
  436.     mov    cx,bx            ; get # of bytes to move
  437.     sub    cx,dx            ; adjust for last move
  438. rep    movsb                ; copy part of line over to lnbuffer
  439.     jmp    beatme            ; get rest of line and copy it.
  440. ;
  441. lf_fnd: inc    bx
  442.     mov    dx,si
  443.     sub    dx, offset dmabuf
  444.     mov    cx,bx 
  445.     sub    cx,dx
  446. rep    movsb
  447. ;
  448.     pop    dx            ; get back FCB
  449.     xor    al,al            ; tell caller new line is ready
  450.     mov    word ptr dmasrc,si    ; save si for next time round
  451.     mov    word ptr dmaoff,bx    ; same with bx
  452.     ret
  453. ;
  454. ;
  455. clcom:    pop    dx            ; close file
  456.     mov    cl, f_close
  457.     int    224
  458.     mov    al,-1            ; and indicate to caller
  459.     or    al,al            ; that its all over
  460.     ret                ; and all done
  461. ;
  462. ;
  463. ;
  464. parscom:mov    al,lnbuff        ; get first charcter in line
  465.     cmp    al,30h+1            ; is it in range ?
  466.     jl    pdn
  467.     cmp    al,30h+8        ; we support up to 8 com channels
  468.     jg    pdn
  469.     mov    qpdnam+7,al
  470.     mov    cl,f_mkque            ; and make the que
  471.     push    bx
  472.     sub    al,30h                ; Form interrupt mask
  473.     call    formsk
  474.     dec    al
  475.     rol    al,1                ; compute que descriptor
  476.     mov    bl,al                ; offset
  477.     mov    bh,0
  478.     mov    dx,qdtbl[bx]
  479.     pop    bx
  480.     int    224
  481.     mov    cl,f_opque            ; open the que 
  482.     mov    dx, offset mxqpb
  483.     int    224
  484.     mov    cl,f_wrque            ; Write to que
  485.     mov    dx, offset mxqpb        ; so now its available
  486.     int    224
  487. pdn:    ret    
  488. ;
  489. ;
  490. parstty:
  491.     mov    al,lnbuff        ; get the first char in a line
  492.     cmp    al,30h+lowcon
  493.     jl    ttyld
  494.     cmp    al,30h+9        ; in range ?
  495.     jg    ttyld            ; nope... skip it
  496.     sub    al,30h            ; make device number
  497.     call    formsk            ; yeap, add to interrupt mask
  498.     call    protc            ; determine protocoll used
  499. ttyld:    ret                ; done with this line.
  500. ;
  501. ;
  502. parslpr:
  503.     mov    al,lnbuff        ; get the first char in a line
  504.     cmp    al,30h+lowprnt
  505.     jl    lprld
  506.     cmp    al,30h+highprnt        ; in range ?
  507.     jg    lprld
  508.     sub    al,30h-highcon-1    ; make a device number
  509.     call    formsk
  510.     call    protc            ; determine protocoll used
  511. lprld:    ret
  512.  
  513.  
  514.  
  515. ;-----------------------------------------------------------------------;
  516. ;                                    ;
  517. ; formsk:    Form Interrupt Mask                    ;
  518. ;                                    ;
  519. ; Entry     -> al = device number (1 to 16)                ;
  520. ;                                    ;
  521. ; return -> imask = imask or (bit corresponding to device number)    ;
  522. ;                                    ;
  523. ;-----------------------------------------------------------------------;
  524. ;
  525. ;
  526. ;
  527. formsk: push    ax
  528.     push    cx            ; save'm
  529.     mov    cl,al            ; convert to exact user number
  530.     call    conctr
  531.     mov    ax,1            ; make mask for this user number
  532.     rol    ax,cl
  533.     or    word ptr imask,ax    ; or mask into present mask
  534.     pop    cx
  535.     pop    ax            ; get'm back
  536.     ret                ; and we are done
  537. ;
  538. ;
  539.  
  540.  
  541. imask    dw    0        ; mask to enable interrupts on I3/4 Interrupt
  542.                 ; mask registers
  543.                 ; low byte  = first board 
  544.                 ; high byte = second board
  545.  
  546. ;-----------------------------------------------------------------------;
  547. ;                                    ;
  548. ;  protc:   Determine the protocol used on device            ;
  549. ;                                    ;
  550. ;  entry  ->  al= device number                        ;
  551. ;          lnbuff = input line from set up file TTYSC or LPTSC    ;
  552. ;                                    ;
  553. ;  return ->  fills in table hndshk for the device            ;
  554. ;                                    ;
  555. ;-----------------------------------------------------------------------;
  556. ;
  557. ;
  558. ;
  559. protc:    push    ax
  560.     push    bx
  561.     push    ax
  562.     mov    bx, offset lnbuff    ; point to line buffer and
  563.     call    fndel            ; and find first delimiter
  564.     call    fndel            ; find second delimiter
  565.     inc    bx            ; now we should have handshake value
  566.     mov    al,byte ptr [bx]
  567.     pop    bx            ; bx=device number
  568.     xor    bh,bh            ; make 16 bit index
  569.     sub    al,30h            ; got handshake, deasccie
  570.     cmp    al,3            ; in range ?
  571.     jg    def            ; nope, use default
  572.     cmp    al,0
  573.     jb    def
  574.     mov    byte ptr hndshk[bx],al    ; and stuff handshake argument
  575.     pop    bx
  576.     pop    ax
  577.     ret
  578. ;
  579. def:    mov    byte ptr hndshk[bx],0    ; default is no handshake
  580.     pop    bx
  581.     pop    ax
  582.     ret
  583. ;
  584. ;
  585. fndel:    inc    bx            ; skip first one
  586.     cmp    byte ptr [bx],':'    ; match ?
  587.     jne    fndel            ; Nope, try next one
  588. delfn:    ret                ; yeap.. return to caller, bx=match
  589. ;
  590. ;
  591. ;
  592. hndshk    db    0,0,0,0        ; hand shake table 0= no hand shake
  593.     db    0,0,0,0        ;           1 = DTR
  594.     db    0,0,0,0        ;           2 = Xon Xoff
  595.     db    0,0,0,0        ;           3 = DTR & Xon Xoff
  596.     db    0        ; bit 7 indicates X-ON awaited
  597.     db    0        ; for device 1 through 16 (0 handled in XIOS)
  598.  
  599.  
  600.  
  601.  
  602. qdtbl    dw    offset mxqd1            ; Que descriptor table
  603.     dw    offset mxqd2
  604.     dw    offset mxqd3
  605.     dw    offset mxqd4
  606.     dw    offset mxqd5
  607.     dw    offset mxqd6
  608.     dw    offset mxqd7
  609.     dw    offset mxqd8
  610.  
  611. quebuf    rb 10            ; que descriptors must be unique in RSPs
  612.  
  613. mxqd1    dw    0        ; Mutual exclusion que descriptior
  614.     dw    0
  615.     dw    3        ; a Mutual exclusion que that can not be
  616.     db    'MXmodem1'    ; be deleted
  617.     dw    0        ; message lenght is 0
  618.     dw    1        ; 1 message at a time
  619.     dw    0
  620.     dw    0
  621.     dw    0
  622.     dw    0
  623.     dw    offset quebuf    ; must point to buffer for RSP
  624.  
  625.  
  626. mxqd2    dw    0        ; Mutual exclusion que descriptior
  627.     dw    0
  628.     dw    3        ; a Mutual exclusion que that can not be
  629.     db    'MXmodem2'    ; be deleted
  630.     dw    0        ; message lenght is 0
  631.     dw    1        ; 1 message at a time
  632.     dw    0
  633.     dw    0
  634.     dw    0
  635.     dw    0
  636.     dw    offset quebuf    ; must point to buffer for RSP
  637.  
  638.  
  639. mxqd3    dw    0        ; Mutual exclusion que descriptior
  640.     dw    0
  641.     dw    3        ; a Mutual exclusion que that can not be
  642.     db    'MXmodem3'    ; be deleted
  643.     dw    0        ; message lenght is 0
  644.     dw    1        ; 1 message at a time
  645.     dw    0
  646.     dw    0
  647.     dw    0
  648.     dw    0
  649.     dw    offset quebuf    ; must point to buffer for RSP
  650.  
  651.  
  652. mxqd4    dw    0        ; Mutual exclusion que descriptior
  653.     dw    0
  654.     dw    3        ; a Mutual exclusion que that can not be
  655.     db    'MXmodem4'    ; be deleted
  656.     dw    0        ; message lenght is 0
  657.     dw    1        ; 1 message at a time
  658.     dw    0
  659.     dw    0
  660.     dw    0
  661.     dw    0
  662.     dw    offset quebuf    ; must point to buffer for RSP
  663.  
  664.  
  665. mxqd5    dw    0        ; Mutual exclusion que descriptior
  666.     dw    0
  667.     dw    3        ; a Mutual exclusion que that can not be
  668.     db    'MXmodem5'    ; be deleted
  669.     dw    0        ; message lenght is 0
  670.     dw    1        ; 1 message at a time
  671.     dw    0
  672.     dw    0
  673.     dw    0
  674.     dw    0
  675.     dw    offset quebuf    ; must point to buffer for RSP
  676.  
  677.  
  678. mxqd6    dw    0        ; Mutual exclusion que descriptior
  679.     dw    0
  680.     dw    3        ; a Mutual exclusion que that can not be
  681.     db    'MXmodem6'    ; be deleted
  682.     dw    0        ; message lenght is 0
  683.     dw    1        ; 1 message at a time
  684.     dw    0
  685.     dw    0
  686.     dw    0
  687.     dw    0
  688.     dw    offset quebuf    ; must point to buffer for RSP
  689.  
  690.  
  691. mxqd7    dw    0        ; Mutual exclusion que descriptior
  692.     dw    0
  693.     dw    3        ; a Mutual exclusion que that can not be
  694.     db    'MXmodem7'    ; be deleted
  695.     dw    0        ; message lenght is 0
  696.     dw    1        ; 1 message at a time
  697.     dw    0
  698.     dw    0
  699.     dw    0
  700.     dw    0
  701.     dw    offset quebuf    ; must point to buffer for RSP
  702. ;
  703. ;
  704. mxqd8    dw    0        ; Mutual exclusion que descriptior
  705.     dw    0
  706.     dw    3        ; a Mutual exclusion que that can not be
  707.     db    'MXmodem8'    ; be deleted
  708.     dw    0        ; message lenght is 0
  709.     dw    1        ; 1 message at a time
  710.     dw    0
  711.     dw    0
  712.     dw    0
  713.     dw    0
  714.     dw    offset quebuf    ; must point to buffer for RSP
  715.  
  716.  
  717. mxqpb    dw    0        ; MXmodemn Que Parameter Block
  718.     dw    0
  719.     dw    1
  720.     dw    offset quebuf
  721. qpdnam    db    'MXmodem '
  722. ;
  723. ;
  724. ;
  725. ;
  726. comfcb    db    1,'COMCH   '    ; dr,f1-f8
  727.     db    '   '        ; t1-t3
  728.     db    0        ; ex
  729.     db    0,0        ; cs,rs
  730.     db    0        ; rc
  731.     db    0,0,0,0,0    ; d0
  732.     db    0,0,0,0,0    ; d5..
  733.     db    0,0,0,0,0    ; d10
  734.     db    0        ; dn
  735.     db    0        ; cr
  736.     db    0,0,0        ; r0,r1,r2
  737. ;
  738. ;
  739. ;
  740. ttyfcb    db    1,'TTYSC   '    ; dr,f1-f8
  741.     db    '   '        ; t1-t3
  742.     db    0        ; ex
  743.     db    0,0        ; cs,rs
  744.     db    0        ; rc
  745.     db    0,0,0,0,0    ; d0
  746.     db    0,0,0,0,0    ; d5..
  747.     db    0,0,0,0,0    ; d10
  748.     db    0        ; dn
  749.     db    0        ; cr
  750.     db    0,0,0        ; r0,r1,r2
  751. ;
  752. ;
  753. ;
  754. lprfcb    db    1,'LPRSC   '    ; dr,f1-f8
  755.     db    '   '        ; t1-t3
  756.     db    0        ; ex
  757.     db    0,0        ; cs,rs
  758.     db    0        ; rc
  759.     db    0,0,0,0,0    ; d0
  760.     db    0,0,0,0,0    ; d5..
  761.     db    0,0,0,0,0    ; d10
  762.     db    0        ; dn
  763.     db    0        ; cr
  764.     db    0,0,0        ; r0,r1,r2
  765. ;
  766. ;
  767. ;
  768. fopflg    db    0        ; fopflg to flag if first time access to file
  769. dmabuf    rb    128        ; dma buffer
  770. dmasrc    dw    0        ; filled in later
  771. dmaoff    dw    0        ; same with him
  772. lnbuff    rb    lnlen        ; 80 byte line buffer.
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779. ;-----------------------------------------------------------------------;
  780. ; xintcpt: Intercept calls to the xios and pass control to internal    ;
  781. ;       handler.                            ;
  782. ;                                    ;
  783. ; Entry       ->  al =  XIOS function number                ;
  784. ;           cx =  First Argument                    ;
  785. ;           dx =  Second Argument                    ;
  786. ;                                    ;
  787. ; Return   ->  ax = bx - return value or error code            ;
  788. ;                                    ;
  789. ;-----------------------------------------------------------------------;
  790. ;
  791. ;
  792. xintcpt:push    ds        ; save DS of caller (saved on his stack)
  793.     push    es        ; es must be the same when returning to SUP
  794.     mov    bx,cs        ; we need our own DS here
  795.     mov    ds,bx
  796.     mov    bl,al        ; Get Xios function number
  797.     xor    bh,bh        ; make 16 bit
  798.     rol    bx,1        ; compute index into jump table
  799.     jmp    functbl[bx]    ; call the function
  800.  
  801.  
  802.  
  803. ;-----------------------------------------------------------------------;
  804. ;                                    ;
  805. ;  realxios: If a function is to be handled by the real xios        ;
  806. ;         this routine passes control to the real xios after        ;
  807. ;         restoring the DS and ES register of the calling process.    ;
  808. ;                                    ;
  809. ; Entry       ->  al =  XIOS function number                ;
  810. ;           cx =  First Argument                    ;
  811. ;           dx =  Second Argument                    ;
  812. ;                                    ;
  813. ; Return   ->  is from XIOS as per XIOS return parameters.        ;
  814. ;                                    ;
  815. ;-----------------------------------------------------------------------;
  816. ;
  817. ;
  818. realxios:
  819.     pop    es
  820.     pop    ds            ; get them back
  821.     jmpf    dword ptr xios
  822.  
  823.  
  824.  
  825. ;-----------------------------------------------------------------------;
  826. ;                                    ;
  827. ;  retcpt:  Return from localy handled xios function.            ;
  828. ;                                    ;
  829. ;  Entry  ->   ax = return argument                    ;
  830. ;                                    ;
  831. ;  Return ->   To calling process with bx=ax as per XIOS specs        ;
  832. ;           DS poped of local stack and thus restored to callers    ;
  833. ;           value                            ;
  834. ;                                    ;
  835. ;-----------------------------------------------------------------------;
  836. ;
  837. ;
  838. retcpt: pop    es            ; return last users Data segment
  839.     pop    ds            ; and extra segment
  840.     mov    bx,ax            ; bx=ax return values
  841.     retf                ; and back to caller
  842.  
  843.  
  844.  
  845.  
  846. ;-----------------------------------------------------------------------;
  847. ; conin:                                ;
  848. ; const:    Test if device    is handled localy for input, status    ;
  849. ; conout:    and output service. If not jumpt to corresponding    ;
  850. ; lstout:    function in the real XIOS                ;
  851. ; lstst:                                ;
  852. ; polldev:                                ;
  853. ;-----------------------------------------------------------------------;
  854. ;
  855. ;
  856. conin:    cmp    cl,lowcon        ; Check if the console is handled
  857.     jb    realxios        ; localy. If not, let the XIOS handle
  858.     cmp    cl,highcon        ; it
  859.     jg    realxios
  860.     call    inchr
  861.     jmp    retcpt
  862. ;
  863. const:    cmp    cl,lowcon 
  864.     jb    realxios
  865.     cmp    cl,highcon
  866.     jg    realxios 
  867.     call    qst
  868.     jmp    retcpt
  869. ;
  870. conout: cmp    dl,lowcon
  871.     jb    realxios
  872.     cmp    dl,highcon
  873.     jg    realxios
  874.     call    outchr
  875.     jmp    retcpt
  876. ;
  877. lstout: cmp    dl,lowprnt
  878.     jb    realxios
  879.     cmp    dl,highprnt
  880.     jg    realxios
  881.     add    dl,highcon+1    ; make device number
  882.     call    outchr
  883.     jmp    retcpt
  884. ;
  885. lstst:    cmp    cl,lowprnt
  886.     jb    realxios
  887.     cmp    cl,highprnt
  888.     jg    realxios
  889.     call    stlst
  890.     jmp    retcpt
  891. ;
  892. ;
  893. ;
  894. ;
  895. polldev:
  896.     cmp     cl, 0            ; intercept Poll devices 0 to 15
  897.     jb     realxios
  898.     cmp     cl, 15
  899.     jg     realxios
  900.     call     pdsr             ; valid port, so go an poll it
  901.     jmp     retcpt
  902.  
  903.  
  904.  
  905. ;-----------------------------------------------------------------------;
  906. ;                                    ;
  907. ; functbl  XIOS function table. Each entry in this table contains    ;
  908. ;       the offset for the corresponding function number.        ;
  909. ;                                    ;
  910. ;       You may intercept your own XIOS functions here if you wish    ;
  911. ;       by changing the corresponding entry to the offset of your    ;
  912. ;       local handler. If a function is to be handled by the actual    ;
  913. ;       XIOS enter the offset of REALXIOS.                ;
  914. ;                                    ;
  915. ;                                    ;
  916. ;                                    ;
  917. ;-----------------------------------------------------------------------;
  918. ;
  919. ;
  920. functbl dw    offset const        ; 0 Console status
  921.     dw    offset conin        ; 1 Console input
  922.     dw    offset conout        ; 2 Console output
  923.     dw    offset lstout        ; 3 List output
  924.     dw    offset realxios        ; 4 Punch output
  925.     dw    offset realxios        ; 5 Reader input
  926.     dw    offset realxios        ; 6 Home
  927.     dw    offset realxios        ; 7 Select disk
  928.     dw    offset realxios        ; 8 Set track
  929.     dw    offset realxios        ; 9 Set sector
  930.     dw    offset realxios        ;10 Set DMA address
  931.     dw    offset realxios        ;11 Read a record
  932.     dw    offset realxios        ;12 Write a record
  933.     dw    offset lstst        ;13 List status
  934.     dw    offset realxios        ;14 Sector translation
  935.     dw    offset realxios        ;15 Set DMA segment
  936.     dw    offset realxios        ;16 Get segment table
  937.     dw    offset polldev        ;17 Poll selected device
  938.     dw    offset realxios        ;18 Enable tick clock
  939.     dw    offset realxios        ;19 Disable tick clock
  940.     dw    offset realxios        ;20 Return max. number of consoles
  941.     dw    offset realxios        ;21 Return max. number of list devices
  942.     dw    offset realxios        ;22 Select memory
  943.     dw    offset realxios        ;23 Idle
  944.     dw    offset realxios        ;24 Flush buffers
  945.  
  946.  
  947.  
  948. ;-----------------------------------------------------------------------;
  949. ;                                    ;
  950. ; inchr:  Input a character from que. If que is empty wait for a    ;
  951. ;      character to be put into it by ISR.                ;
  952. ;                                    ;
  953. ; Entry      -> cl = MPM Console Number                    ;
  954. ;                                    ;
  955. ; Return  -> al = Character input                    ;
  956. ;                                    ;
  957. ;-----------------------------------------------------------------------;
  958.  
  959. inchr:    call    mapctq            ; map console to que offset
  960.     call    qempt            ; Check if there is anything in the que
  961.     jne    inchr1            ; al=ff and NZ if a character is ready
  962.  
  963.     push    cx            ; save console number
  964.     mov    dl,fbase
  965.     add    dl,cl            ; wait for flag corresponding to this
  966.     mov    cl,waitf        ; console to be set indicating a char
  967.     call    supif            ; has arrived
  968.     pop    cx            ; restore console number
  969.     jmp    inchr            ; in case of erroneous flag set
  970.  
  971. inchr1: pushf                ; No interrupts now ......
  972.     cli
  973.     call    qdel            ; get a character from the que
  974.     popf
  975.     ret                ; and exit back to caller
  976.  
  977.  
  978. ;-----------------------------------------------------------------------;
  979. ;                                    ;
  980. ; qst:    Return Status of Que for corresponding Console            ;
  981. ;    The first call to here will also enable the interupt mask    ;
  982. ;    register on the Interfacer 3/4 board. This way any console    ;
  983. ;    not in the TTYS file can still be enabled if so required.    ;
  984. ;    Done here, because on the CompuPro system all internal set up    ;
  985. ;    is done before entering Multi User Mode. Here we can be        ;
  986. ;    relatively sure that all is done by the SHELL before we stick    ;
  987. ;    our stuff in.                            ;
  988. ;                                    ;
  989. ; Entry     -> cl = MPM Console Number                    ;
  990. ;                                    ;
  991. ; Return -> al =  00 if no character ready                ;
  992. ;          ff if character ready                    ;
  993. ;                                    ;
  994. ;-----------------------------------------------------------------------;
  995. ;
  996. ;
  997. qst:    cmp    setmsk,0        ; Is Interrupt mask already set ?
  998.     jne    qst1            ; yeap, so just get the status.
  999.     pushf
  1000.     cli
  1001.     xor    al,al            ; first select first board
  1002.     out    i4slct,al
  1003.     mov    ax,word ptr imask
  1004.     out    i4rint,al        ; now we got the mask set up
  1005.     or    byte ptr setmsk,al
  1006.     mov    al,8            ; and the second board
  1007.     out    i4slct,al
  1008.     xchg    al,ah
  1009.     out    i4rint,al
  1010.     or    byte ptr setmsk,al    ; flag that we dont do it again
  1011.     popf
  1012.  
  1013. qst1:    call    mapctq            ; find que for this console
  1014.     call    qempt            ; check if anything is in the que
  1015.                     ; al = 0 if no character is ready
  1016.                     ; al = ff if character is waiting to be
  1017.     ret                ; picked up.
  1018.  
  1019. setmsk    db    0        ; 0 indicates mask not set up yet.
  1020.  
  1021.  
  1022.  
  1023. ;-----------------------------------------------------------------------;
  1024. ;                                    ;
  1025. ; outchr:  Output a character to console                ;
  1026. ;                                    ;
  1027. ; Entry     -> cl = character                        ;
  1028. ;        dl = device number                        ;
  1029. ;                                    ;
  1030. ; Return -> none                            ;
  1031. ;                                    ;
  1032. ;-----------------------------------------------------------------------;
  1033. ;
  1034. ;
  1035. ;
  1036. outchr: push    cx            ; save the character
  1037.     mov    cl,dl            ; get device number
  1038.     call    conctr            ; Convert to Interfacer 3/4 user #
  1039.     xor    dh,dh            ; make 16 bit device number
  1040.     mov    bx,dx            ; make index
  1041.     test    byte ptr hndshk[bx],3    ; using DTR or XON/XOFF handshakes ?
  1042.     je    nhnd            ; nope ignore it
  1043.     call    pdsr            ; yeap, see if dsr indicates ready
  1044.     or    al,al            ; Device busy ?
  1045.     jne    nhnd            ; nope it ok.
  1046.  
  1047.     push    bx
  1048.     push    cx            ; yeap, then put us on poll list
  1049.     push    dx
  1050.     mov    dl,cl            ; set up for MPM poll function
  1051.     mov    cl,f_poll
  1052.     call    supif            ; will return when dsr is ready
  1053.     pop    dx
  1054.     pop    cx            ; now we are ready
  1055.     pop    bx
  1056.  
  1057. nhnd:    mov    ch,cl            ; user port in ch, console in dl
  1058.     mov    ax,cx
  1059.     pop    cx            ; get back character
  1060.     mov    ch,ah
  1061.     xchg    ch,cl            ; ch= character, cl = exact user
  1062.     pushf                ; cant have interrupts now
  1063.     cli
  1064.     call    select            ; select proper usart
  1065.     in    al,i4stat        ; get USART status
  1066.     popf
  1067.     test    al,i4tbmt        ; ready to send a char ?
  1068.     jnz    i4out            ; yeap send him out..
  1069.  
  1070.     push    cx            ; keep'm
  1071.     mov    ax,1            ; set twmask to wait
  1072.     shl    ax,cl            ; compute mask
  1073.     or    word ptr twmsk,ax
  1074.     mov    ax,word ptr twmsk    ; send currently active masks
  1075.     pushf
  1076.     cli
  1077.     xor    cl,cl
  1078.     call    select
  1079.     out    i4tint,al        ; to enable interrupts on first board
  1080.     mov    cl,8
  1081.     call    select
  1082.     mov    al,ah
  1083.     out    i4tint,al        ; and the second board
  1084.     popf
  1085.  
  1086.     push    dx
  1087.     add    dl,fbase+16        ; compute flag
  1088.     mov    cl,waitf        ; Wait for Tx flag to set
  1089.     call    supif
  1090.     pop    dx
  1091.     pop    cx
  1092.  
  1093. i4out:    pushf                ; cant have interrupts now
  1094.     cli
  1095.     mov    al,ch            ; get character
  1096.     call    select            ; select uart
  1097.     out    i4data,al        ; send character
  1098.     popf                ; interrupts ok again
  1099.     ret                ; and back to caller
  1100.  
  1101.  
  1102.  
  1103. ;-----------------------------------------------------------------------;
  1104. ;                                    ;
  1105. ; stlst:  Return List device output status                ;
  1106. ;                                    ;
  1107. ; entry -> cl = list device number                    ;
  1108. ;                                    ;
  1109. ; return -> al = ffh if device ready                    ;
  1110. ;         0   if device not ready                ;
  1111. ;                                    ;
  1112. ;-----------------------------------------------------------------------;
  1113. ;
  1114. ;
  1115. ;
  1116. stlst:    add    cl,highcon+1        ; make device number
  1117.     call    conctr            ; convert to i4 user number
  1118.     pushf                ; no interrupts now
  1119.     cli
  1120.     call    select            ; select proper port
  1121.     in    al,i4stat        ; get status
  1122.     popf                ; interrupts ok now
  1123.     test    al,i4tbmt        ; ready ?
  1124.     jnz    lstrdy            ; yeap.. go say so
  1125.     xor    al,al            ; nope
  1126.     ret
  1127. lstrdy: call    pdsr            ; USART is ready, but what about the
  1128.     ret                ; printer itself ?
  1129.  
  1130.  
  1131.  
  1132. ;-----------------------------------------------------------------------;
  1133. ; pdsr:       Poll DSR. This is Xios function 17 which is not used        ;
  1134. ;       in the CompuPro XIOS. Used by MSUP to poll the DSR line    ;
  1135. ;       for DTR handshaking, and Xon/Xoff status.            ;
  1136. ;       Other systems which need to use Poll device numbers that    ;
  1137. ;       are not assigned yet.                    ;
  1138. ;                                    ;
  1139. ; Entry     -> CL = Device number 0 through 15 beeing ports 0 through 15    ;
  1140. ;         on Interfacer 3/4 board.                ;
  1141. ;                                    ;
  1142. ; Return -> AL = FFh if device ready                    ;
  1143. ;         00h if not ready                    ;
  1144. ;                                    ;
  1145. ;-----------------------------------------------------------------------;
  1146. ;
  1147. ;
  1148. ;
  1149. pdsr:    pushf                ; disable interrupts
  1150.     cli
  1151.     call    select            ; select USART
  1152.     in    al,i4stat        ; get status
  1153.     popf                ; we can have interrupts again
  1154.     push    bx
  1155.     push    cx            ; save'm
  1156.     push    dx
  1157.     call    conrtc            ; make device number
  1158.     mov    bl,cl            ; make it index to handshake table
  1159.     xor    bh,bh
  1160.     mov    dl,byte ptr hndshk[bx]    ; get handshake status
  1161.     and    dl,2+128        ; XOFF active ?
  1162.     cmp    dl,2+128
  1163.     mov    dl,0ffh            ; assume its not active
  1164.     jne    podsr            ; Nope, not active for sure
  1165.     xor    dl,dl            ; it is active, so device not ready
  1166.  
  1167. podsr:    test    byte ptr hndshk[bx],1    ; are we using DTR handshake ?
  1168.     je    dsrset            ; nope so DSR is set anyway
  1169.  
  1170.     test    al,i4dsr        ; dsr set ?
  1171.     jne    dsrset            ; yeap go set flags
  1172.     xor    al,al            ; nope, not ready say so
  1173.     jmps    pdtdn
  1174. dsrset: or    al,0ffh            ; its ready, say so 
  1175. pdtdn:    and    al,dl            ; mask in XOFF status
  1176.     pop    dx
  1177.     pop    cx
  1178.     pop    bx            ; restore'em 
  1179.     ret                ; poll is done
  1180.  
  1181.  
  1182.  
  1183. ;-----------------------------------------------------------------------;
  1184. ;                                    ;
  1185. ; mapctq:  Map Console to Que offset                    ;
  1186. ;                                    ;
  1187. ; Entry     -> cl = Console Number                        ;
  1188. ;                                    ;
  1189. ; Return -> si = Que offset                        ;
  1190. ;                                    ;
  1191. ;-----------------------------------------------------------------------;
  1192. ;
  1193. ;
  1194. mapctq: push    bx            ; save him
  1195.     mov    bl,cl            ; make 16 bit console number
  1196.     xor    bh,bh
  1197.     sub    bx,lowcon        ; first handled console gets first que
  1198.     rol    bx,1            ; *2 so its index into table
  1199.     mov    si,quetbl[bx]        ; get que offset to si
  1200.     pop    bx
  1201.     ret
  1202. ;
  1203. ;
  1204. quetbl    dw    offset que1        ; Table containing Que offsets
  1205.     dw    offset que2
  1206.     dw    offset que3
  1207.     dw    offset que4
  1208.     dw    offset que5
  1209.     dw    offset que6
  1210.     dw    offset que7
  1211.     dw    offset que8
  1212.     dw    offset que9
  1213.     dw    offset que10
  1214.     dw    offset que11
  1215.     dw    offset que12
  1216.     dw    offset que13
  1217.     dw    offset que14
  1218.     dw    offset que15
  1219.     dw    offset que16    ; we could have up to 16 input devices !
  1220.  
  1221.  
  1222.  
  1223. ;-----------------------------------------------------------------------;
  1224. ;                                    ;
  1225. ; i4rxint:  Interfacer 4 vector for receive data interrupts.        ;
  1226. ;                                    ;
  1227. ;-----------------------------------------------------------------------;
  1228. ;
  1229. ;
  1230. ;
  1231. i4rxint:
  1232.     push    dx            ; save him here.. restored by service
  1233.     mov    dx,offset i4risr    ; address of actual ISR
  1234.     jmp    service            ; jump to ISR via service
  1235.  
  1236.  
  1237.  
  1238. ;-----------------------------------------------------------------------;
  1239. ;                                    ;
  1240. ; i4txint:  Interfacer 3/4 vector for transmit ready interrupts.    ;
  1241. ;                                    ;
  1242. ;-----------------------------------------------------------------------;
  1243. ;
  1244. ;
  1245. ;
  1246. i4txint:
  1247.     push    dx            ; save her
  1248.     mov    dx,offset i4tisr    ; Transmit ready ISR offset
  1249.     jmp    service            ; and service it
  1250.  
  1251.  
  1252.  
  1253. ;-----------------------------------------------------------------------;
  1254. ;                                    ;
  1255. ; i4risr: Interfacer 3/4 Interrupt service routine.            ;
  1256. ;      Determines which console caused an interrupt to occur        ;
  1257. ;      and reads the character into the corresponding que.        ;
  1258. ;      Sets proper flag to wake up sleeping proccess.        ;
  1259. ;                                    ;
  1260. ;                                    ;
  1261. ;-----------------------------------------------------------------------;
  1262. ;
  1263. ;
  1264. i4risr: mov    cl,15            ; start with highest exact user
  1265. rescan: call    select            ; select user to be scanned
  1266.     mov    bx,1            ; make mask for this port
  1267.     rol    bx,cl
  1268.     test    word ptr imask,bx    ; valid device ?
  1269.     je    nxtsn            ; nope... skip it
  1270.     in    al,i4rint        ; get receive interrupt status
  1271.     cmp    cl,7            ; is this the second board ?
  1272.     jg    rscnd            ; yeap, test that mask
  1273.     and    al,bl            ; did interrupt occur here ?
  1274.     je    nxtsn            ;   No, Scan next user
  1275.     jmps    rget            ; yes, go get the sucker
  1276. rscnd:    and    al,bh            ; did interrupt occur on second board?
  1277.     je    nxtsn            ; nope, scan next one
  1278. rget:    call    getchr            ;   yes, get character to que
  1279. nxtsn:    dec    cl            ; next relative users turn
  1280.     jne    rescan            ; go and scan him
  1281.     ret
  1282. ;
  1283. ;
  1284. ;
  1285. getchr: in    al,i4data        ; Read the character
  1286.     push    cx            ; save for later
  1287.     call    conrtc            ; convert exact user to device #
  1288.     mov    bl,cl            ; make index
  1289.     xor    bh,bh            ; to handshake table
  1290.     test    byte ptr hndshk[bx],2    ; XON-XOFF handshaking active ?
  1291.     je    noxoff            ; nope... dont filter XON/XOFF
  1292.     cmp    al,xoff            ; handshaking active, is it Xoff?
  1293.     jne    xontst            ; nope test for Xon
  1294.     or    byte ptr hndshk[bx],128 ; yeap, set xoff received flag for dev.
  1295. xontst: cmp    al,xon            ; is it XON ?
  1296.     jne    noxoff            ; nope... just a character
  1297.     and    byte ptr hndshk[bx],7fh ; yeap, clear xoff flag
  1298.     jmps    getd            ; and we are done
  1299.  
  1300. noxoff: call    mapctq            ; get offset for q
  1301.     call    queins            ; insert the character into que
  1302.     mov    dl,fbase        ; compute flag for this console
  1303.     add    dl,cl
  1304.     mov    cl,setf            ; and set to wake up proccess waiting
  1305.     call    supif            ; call MPM supervisor interface
  1306. getd:    pop    cx            ; restore relative user
  1307.     ret
  1308.  
  1309.  
  1310.  
  1311. ;-----------------------------------------------------------------------;
  1312. ;                                    ;
  1313. ; i4tisr:   Transmit buffer empty Interrupt Service Handler        ;
  1314. ;        Determines which device has pending output and        ;
  1315. ;        sets flag to wake up the task waiting for the        ;
  1316. ;        USART Transmit buffer to clear.                ;
  1317. ;                                    ;
  1318. ;-----------------------------------------------------------------------;
  1319. ;
  1320. ;
  1321. ;
  1322. i4tisr: mov    al,8            ; read from second board first 
  1323.     out    i4slct,al        ; read from it
  1324.     in    al,i4tint        ; get interrupt status
  1325.     mov    ah,al            ; make it high byte of mask
  1326.     xor    al,al            ; now its the first boards turn
  1327.     out    i4slct,al
  1328.     in    al,i4tint        ; gotcha
  1329.     and    ax, word ptr twmsk    ; mask only those that are wanted
  1330.     mov    dx,1            ; dx = mask 
  1331.     mov    bl,0            ; bl = exact user
  1332.  
  1333. tscn:    test    ax,dx            ; is he ready
  1334.     jnz    txver            ; yeap... go get him
  1335.     rol    dx,1            ; next port
  1336.     inc    bl
  1337.     cmp    bl,16            ; all done ?
  1338.     jb    tscn            ; nope, keep going till we got the one
  1339.  
  1340. txver:    not    dx            ; set bit to NOT active for this port
  1341.     and    dx,word ptr twmsk
  1342.     mov    word ptr twmsk,dx    ; update mask
  1343.     mov    al,8            ; second board first
  1344.     out    i4slct,al
  1345.     mov    al,dh            ; and tx int mask on port
  1346.     out    i4tint,al
  1347.     xor    al,al            ; now first board
  1348.     out    i4slct,al
  1349.     mov    al,dl
  1350.     out    i4tint,al
  1351.     mov    cl,bl            ; now set flag
  1352.     call    conrtc            ; for this device
  1353.     mov    dl,fbase+16
  1354.     add    dl,cl
  1355.     mov    cl,setf
  1356.     jmp    supif
  1357. ;
  1358. ;
  1359. ;
  1360. twmsk    dw    0            ; bit map keeping track of which device
  1361.                     ; is waiting for transmit to clear
  1362.  
  1363.  
  1364. ;-----------------------------------------------------------------------;
  1365. ;                                    ;
  1366. ; conrtc: Convert Exact user to Console number                ;
  1367. ;      The conversion is not always a MPM console number.        ;
  1368. ;      If a exact user port is a Printer port then the a console    ;
  1369. ;      Number returned is equal to HIGHCON + PRINTER NUMBER        ;
  1370. ;      as the hardware handling of printer and consoles is        ;
  1371. ;      identical, the same routines may be used without having to    ;
  1372. ;      make exceptions for printer devices. THUS --> IF THE        ;
  1373. ;      RETURNED CONSOLE NUMBER IS GREATER THAN THE HIGHEST CONSOLE    ;
  1374. ;      NUMBER SUPPORTED, IT IS A PRINTER.                ;
  1375. ;                                    ;
  1376. ; Entry     -> cl = exact Interfacer 3/4 user number            ;
  1377. ;                                    ;
  1378. ; Return -> cl = Corresponding Console/Device number            ;
  1379. ;                                    ;
  1380. ;-----------------------------------------------------------------------;
  1381. ;
  1382. ;
  1383. conrtc: push    bx        ; save him
  1384.     mov    bl,cl        ; make 16 bit of user number
  1385.     xor    bh,bh
  1386.     mov    cl,rtcmap[bx]    ; get corresponding console number
  1387.     pop    bx
  1388.     ret
  1389.  
  1390.  
  1391. rtcmap    db    6        ; exact user 0 --> console 6
  1392.     db    5        ; exact user 1 --> console 5
  1393.     db    4        ; exact user 2 --> console 4
  1394.     db    3        ; exact user 3 --> console 3
  1395.     db    14        ; exact user 4 --> printer 0 (uses que 14)
  1396.     db    15        ; exact user 5 --> printer 1 (uses que 15)
  1397.     db    2        ; exact user 6 --> console 2
  1398.     db    1        ; exact user 7 --> console 1
  1399.     db    16        ; exact user 8 --> printer 2 (uses que 16)
  1400.     db    7        ; exact user 9 --> console 7
  1401.     db    8        ; exact user A --> console 8
  1402.     db    9        ; exact user B --> console 9
  1403.     db    10        ; exact user C --> console 10
  1404.     db    11        ; exact user D --> console 11
  1405.     db    12        ; exact user E --> console 12
  1406.     db    13        ; exact user F --> console 13
  1407.  
  1408.  
  1409.  
  1410. ;-----------------------------------------------------------------------;
  1411. ;                                    ;
  1412. ; conctr:    Convert Console to exact user number.            ;
  1413. ;        Performs the inverse function of conrtc.        ;
  1414. ;                                    ;
  1415. ; entry     ->   cl = Device/Console number                ;
  1416. ;                                    ;
  1417. ; return ->   cl = Interfacer 3/4 user number                ;
  1418. ;                                    ;
  1419. ;-----------------------------------------------------------------------;
  1420. ;
  1421. ;
  1422. ;
  1423. conctr: push    bx            ; save'm
  1424.     xor    bx,bx
  1425.     sub    cl,lowcon        ; compute 16 bit index to table
  1426.     mov    bl,cl
  1427.     mov    cl,ctrmap[bx]        ; get user number from the table
  1428.     pop    bx
  1429.     ret                ; and we are done
  1430. ;
  1431. ;
  1432. ctrmap    db    7            ; Console 1 ---> exact user 7
  1433.     db    6            ; Console 2 ---> exact user 6
  1434.     db    3            ; Console 3 ---> exact user 3
  1435.     db    2            ; Console 4 ---> exact user 2
  1436.     db    1            ; Console 5 ---> exact user 1
  1437.     db    0            ; Console 6 ---> exact user 0
  1438.     db    9            ; console 7 ---> exact user 9
  1439.     db    10            ; console 8 ---> exact user 10
  1440.     db    11            ; console 9 ---> exact user 11
  1441.     db    12            ; console 10 --> exact user 12
  1442.     db    13            ; console 11 --> exact user 13
  1443.     db    14            ; console 12 --> exact user 14
  1444.     db    15            ; console 13 --> exact user 15
  1445.     db    4            ; Printer 0 ---> exact user 4
  1446.     db    5            ; Printer 1 ---> exact user 5
  1447.     db    8            ; Printer 2 ---> exact user 8
  1448.  
  1449.  
  1450.  
  1451. ;-----------------------------------------------------------------------;
  1452. ;                                    ;
  1453. ; select:      Selects relative user on Interfacer 3/4 board        ;
  1454. ;                                    ;
  1455. ; Entry      ->  cl = relative user number                    ;
  1456. ;                                    ;
  1457. ; Return  ->  none                            ;
  1458. ;                                    ;
  1459. ;-----------------------------------------------------------------------;
  1460. ;
  1461. ;
  1462. ;
  1463. select: push    ax
  1464.     mov    al,cl            ; send relative user number to
  1465.     out    i4slct,al        ; select port
  1466.     pop    ax
  1467.     ret
  1468.  
  1469.  
  1470.  
  1471. ;-----------------------------------------------------------------------;
  1472. ;  qempt:     Checks if que is empty.                    ;
  1473. ;                                    ;
  1474. ;  entry  -> si = que offset                        ;
  1475. ;                                    ;
  1476. ;  return -> Que empty:       al = 0, Z is Set                ;
  1477. ;         Char in que:  al = FF, Z not set                ;
  1478. ;-----------------------------------------------------------------------;
  1479.  
  1480.  
  1481. qempt:    push    bx        ; lets not destroy anything other than al
  1482.     mov    bx,cs:word ptr 2[si]    ; get rear of que
  1483.     cmp    cs:word ptr[si],bx    ; if front = rear then
  1484.     mov    al, 0
  1485.     je    qstat            ;   que := empty
  1486.     mov    al, 0ffh        ; else que:= not empty
  1487. qstat:    pop    bx
  1488.     or    al,al
  1489.     ret
  1490.  
  1491. ;-----------------------------------------------------------------------;
  1492. ; qfull:  test if que is full.                        ;
  1493. ;                                    ;
  1494. ; entry     -> si = que offset                        ;
  1495. ;                                    ;
  1496. ; return -> NZ = ok, Z = que FULL                    ;
  1497. ;                                    ;
  1498. ;-----------------------------------------------------------------------;
  1499.  
  1500. qfull: mov    bx,cs:word ptr[si]    ; if front + 1 = rear then
  1501.        call    incqptr            ;   que=full
  1502.        cmp    bx,cs:word ptr 2[si]
  1503.        ret                ; Z = full, NZ = ok
  1504.  
  1505.  
  1506. ;-----------------------------------------------------------------------;
  1507. ; incqptr:  Increment the Que pointer. Takes care of wrap arround    ;
  1508. ;        if end of que area is reached                ;
  1509. ; entry      -> BX = pointer                        ;
  1510. ; return  -> BX = pointer + 1 increment                    ;
  1511. ;-----------------------------------------------------------------------;
  1512. ;
  1513. ;
  1514. incqptr:inc    bx            ; point to next que offset
  1515.     cmp    bx,qdepth        ; end of que area reached ?
  1516.     jne    incd            ; if not we are done
  1517.     xor    bx,bx            ; yeap... lets wrap
  1518. incd:    ret
  1519.  
  1520.  
  1521.  
  1522. ;-----------------------------------------------------------------------;
  1523. ; queins: insert a character into que. If que is full the character    ;
  1524. ;      is just droped.                        ;
  1525. ;                                    ;
  1526. ; entry        -> al = character                        ;
  1527. ;           si = que offset                        ;
  1528. ;                                    ;
  1529. ; return -> none                            ;
  1530. ;-----------------------------------------------------------------------;
  1531.  
  1532. queins: push    ax
  1533.     call    qfull            ; find out if the que is full
  1534.     pop    ax            ; Z -> ok, NZ -> full
  1535.     je    qind            ; if que is full then loos data
  1536.     mov    bx,cs: word ptr[si]    ; else que[front]=item
  1537.     mov    cs:byte ptr 4[si+bx],al
  1538.     call    incqptr            ; front = front + 1
  1539.     mov    cs:word ptr[si],bx
  1540. qind:    ret
  1541.  
  1542.  
  1543. ;-----------------------------------------------------------------------;
  1544. ; qdel:     delete a character from que                    ;
  1545. ;                                    ;
  1546. ; entry       -> si = que offset                        ;
  1547. ;                                    ;
  1548. ; return   -> al = character                        ;
  1549. ;-----------------------------------------------------------------------;
  1550.  
  1551.  
  1552. qdel:    call    qempt            ; anything in the que ?
  1553.     je    qdeld            ; nope, so nothing we can get out...
  1554.     mov    bx,cs:word ptr 2[si]    ; al = que[rear]
  1555.     mov    al,cs:byte ptr 4[si+bx]
  1556.     call    incqptr            ; rear = rear+1
  1557.     mov    cs:word ptr 2[si],bx
  1558. qdeld:    ret
  1559.  
  1560.  
  1561. que1    dw    0        ; front of que
  1562.     dw    0        ; rear of que
  1563.     rb    qdepth        ; here is the que area.
  1564.  
  1565. que2    dw    0        ; front of que
  1566.     dw    0        ; rear of que
  1567.     rb    qdepth        ; here is the que area.
  1568.  
  1569. que3    dw    0        ; front of que
  1570.     dw    0        ; rear of que
  1571.     rb    qdepth        ; here is the que area.
  1572.  
  1573. que4    dw    0        ; front of que
  1574.     dw    0        ; rear of que
  1575.     rb    qdepth        ; here is the que area.
  1576.  
  1577. que5    dw    0        ; front of que
  1578.     dw    0        ; rear of que
  1579.     rb    qdepth        ; here is the que area.
  1580.  
  1581. que6    dw    0        ; front of que
  1582.     dw    0        ; rear of que
  1583.     rb    qdepth        ; here is the que area.
  1584.  
  1585. que7    dw    0        ; front of que
  1586.     dw    0        ; rear of que
  1587.     rb    qdepth        ; here is the que area.
  1588.  
  1589. que8    dw    0        ; front of que
  1590.     dw    0        ; rear of que
  1591.     rb    qdepth        ; here is the que area.
  1592.  
  1593. que9    dw    0        ; front of que
  1594.     dw    0        ; rear of que
  1595.     rb    qdepth        ; here is the que area.
  1596.  
  1597. que10    dw    0        ; front of que
  1598.     dw    0        ; rear of que
  1599.     rb    qdepth        ; here is the que area.
  1600.  
  1601. que11    dw    0        ; front of que
  1602.     dw    0        ; rear of que
  1603.     rb    qdepth        ; here is the que area.
  1604.  
  1605. que12    dw    0        ; front of que
  1606.     dw    0        ; rear of que
  1607.     rb    qdepth        ; here is the que area.
  1608.  
  1609. que13    dw    0        ; front of que
  1610.     dw    0        ; rear of que
  1611.     rb    qdepth        ; here is the que area.
  1612.  
  1613. que14    dw    0        ; front of que
  1614.     dw    0        ; rear of que
  1615.     rb    qdepth        ; here is the que area.
  1616.  
  1617. que15    dw    0        ; front of que
  1618.     dw    0        ; rear of que
  1619.     rb    qdepth        ; here is the que area.
  1620.  
  1621. que16    dw    0        ; front of que
  1622.     dw    0        ; rear of que
  1623.     rb    qdepth        ; here is the que area.
  1624.  
  1625.  
  1626.  
  1627. ;-----------------------------------------------------------------------;
  1628. ;                                    ;
  1629. ; Service:  Called from interrupt routines to save the state of        ;
  1630. ;        the machine and call the selected interrupt service        ;
  1631. ;        routine.  After completion of the service routine        ;
  1632. ;        it restores the state of the machine and jumps to        ;
  1633. ;        the dispatcher to return from the interrupt.        ;
  1634. ;                                    ;
  1635. ;  Entry  ->    Old DX pushed on the stack                ;
  1636. ;        DX = Address of the interrupt service routine        ;
  1637. ;                                    ;
  1638. ;-----------------------------------------------------------------------;
  1639. ;
  1640. ;
  1641. ;
  1642. service:push    ds            ;Save machine state
  1643.     mov    cs:word ptr intss,ss
  1644.     mov    cs:word ptr intsp,sp
  1645.     mov    cs:word ptr axsave,ax
  1646.     mov    ax,cs
  1647.     mov    ds,ax                ; 8080 model  cs=ds
  1648.     mov    ss,ax                ; Set up local stack
  1649.     mov    sp,offset istack
  1650.     push    word ptr axsave            ; Save all the registers
  1651.     push    bx
  1652.     push    cx
  1653.     push    bp
  1654.     push    si
  1655.     push    di
  1656.     push    es
  1657.  
  1658.     call    dx                ; Call ISR
  1659.  
  1660.     mov    al,nseoi            ; Send End Of Int. to PIC's
  1661.     out    mpic0,al            ; Master PIC
  1662.  
  1663.     pop    es                ; Restore machine state
  1664.     pop    di
  1665.     pop    si
  1666.     pop    bp
  1667.     pop    cx
  1668.     pop    bx
  1669.     pop    ax
  1670.     mov    ss,word ptr intss
  1671.     mov    sp,word ptr intsp
  1672.     pop    ds
  1673.     pop    dx
  1674.     jmpf    cs:dword ptr disp        ; Jump to MP/M dispatcher
  1675.  
  1676.  
  1677.  
  1678. ;-----------------------------------------------------------------------;
  1679. ;                                    ;
  1680. ; supif:  Call MP/M supervisor.                        ;
  1681. ;                                    ;
  1682. ; Entry     ->    CX = Function #                        ;
  1683. ;        DX = Parameter                        ;
  1684. ;                                    ;
  1685. ; Return ->    AX = Return value                    ;
  1686. ;        BX = AX                            ;
  1687. ;        CX = RTM error code                    ;
  1688. ;                                    ;
  1689. ;-----------------------------------------------------------------------;
  1690. ;
  1691. ;
  1692. ;
  1693. supif:    mov    ch,0        ;Clear high byte of function number
  1694.     push    es
  1695.     push    ds
  1696.     mov    ds,word ptr sysdat
  1697.     mov    si,.68h
  1698.     mov    es,ds:10h[si]        ; get uda of current proccess
  1699.     callf    cs:dword ptr supvsr
  1700.     pop    ds
  1701.     pop    es
  1702.     ret
  1703.  
  1704.  
  1705.  
  1706. xios    dw    0        ;Offset address of XIOS
  1707. sysdat    dw    0        ;Segment of XIOS and system data segment
  1708.  
  1709. supvsr    dw    3        ;Entry to the supervisor = offset 3
  1710.     dw    0        ;Segment filled in later
  1711.  
  1712. disp    dw    0        ; MPM dispatcher offset
  1713.     dw    0        ; and segment
  1714.  
  1715. axsave    dw    0        ; save area for AX
  1716. intss    dw    0        ; SS
  1717. intsp    dw    0        ; and SP  for ISRs
  1718.  
  1719.  
  1720.     rb    128
  1721. istack    db    0        ; Stack for interrupt service
  1722.  
  1723.     rb    128        ; Make sure to allow enough stack space
  1724. lstack    db    0        ; stack for MSUP execution entry point
  1725.  
  1726.  
  1727.  
  1728.  
  1729.     dseg
  1730.  
  1731.     org    0h    ; 0 if used as RSP
  1732.  
  1733. ;
  1734. ; RSP header
  1735. ;
  1736.  
  1737. sdatseg dw    0,0,0
  1738.     dw    0,0,0
  1739.     dw    0,0
  1740.  
  1741.     org    10h
  1742.     
  1743. pd    dw    0,0        ;Link,thread
  1744.     db    0        ;Status
  1745.     db    190        ;Priority
  1746.     dw    5        ;Flags
  1747.     db    'Msup    '    ;Name
  1748.     dw    offset uda/10h    ;Uda seg
  1749.     db    0,0        ;Disk,user
  1750.     db    0,0        ;Load dsk,usr
  1751.     dw    0        ;Mem
  1752.     dw    0,0        ;Dvract,wait
  1753.     db    0,0
  1754.     dw    0
  1755.     db    0        ;Console
  1756.     db    0,0,0
  1757.     db    0        ;List
  1758.     db    0,0,0
  1759.     dw    0,0,0,0
  1760.  
  1761.     org    40h
  1762.     
  1763. uda    dw    0,0,0,0        ;0
  1764.     dw    0,0,0,0
  1765.     dw    0,0,0,0        ;10h
  1766.     dw    0,0,0,0
  1767.     dw    0,0,0,0        ;20h
  1768.     dw    0,0,0,0
  1769.     dw    0,0,offset stack,0 ;30h
  1770.     dw    0,0,0,0 
  1771.     dw    0,0,0,0        ;40h
  1772.     dw    0,0,0,0
  1773.     dw    0,0,0,0        ;50h
  1774.     dw    0,0,0,0
  1775.     dw    0,0,0,0        ;60h
  1776.  
  1777.     org    140h
  1778.  
  1779.     dw    0cccch,0cccch,0cccch
  1780.     dw    0cccch,0cccch,0cccch
  1781.     dw    0cccch,0cccch,0cccch
  1782.     dw    0cccch,0cccch,0cccch
  1783.     dw    0cccch,0cccch,0cccch
  1784. stack    dw    offset exec    ;Start offset
  1785.     dw    0        ;Start seg
  1786.     dw    0        ;Init flags
  1787.  
  1788.  
  1789.     end    
  1790.  
  1791.