name    'MPMDIO'
       title   'Direct MP/M Calls From PL/I-80'
;
;  Note:  The CP/M function get version number (#12) has been
;       included in this module.  If you wish to link both the
;       DIOMOD and the MPMDIO, you must remove the function
;       from this module.
;
;***********************************************************
;*                                                         *
;*      MP/M calls from pl/i for direct i/o                *
;*                                                         *
;*         This interface is re-entrant.                   *
;*                                                         *
;***********************************************************
       public  amemrq  ;absolute memory request (#128)
       public  rmemrq  ;relocatable memory request (#129)
       public  memfr   ;memory free (#130)
       public  poll    ;poll device (#131)
       public  flgwt   ;flag wait (#132)
       public  flgset  ;flag set (#133)
       public  makque  ;make queue (#134)
       public  opnque  ;open queue (#135)
       public  delque  ;delete queue (#136)
       public  rdque   ;read queue - unconditional (#137)
       public  crdque  ;conditional read queue (#138)
       public  wrque   ;write queue - unconditional (#139)
       public  cwrque  ;conditional write queue (#140)
       public  delay   ;delay (#141)
       public  dsptch  ;dispatch (#142)
       public  term    ;terminate calling process (#143)
       public  crproc  ;create process (#144)
       public  setpri  ;set process priority (#145)
       public  attcon  ;attach console (#146)
       public  detcon  ;detach console (#147)
       public  setcon  ;set console (#148)
       public  asncon  ;assign console (#149)
       public  sclicd  ;send CLI command (#150)
       public  clresp  ;call resident system process (#151)
       public  parse   ;parse filename (#152)
       public  getcon  ;get console number (#153)
       public  sysdat  ;return system data page adr (#154)
       public  gettod  ;get time and date (#155)
       public  rpdadr  ;return process descr adr (#156)
       public  abtspr  ;abort specified process (#57)

       public  disabl  ;disable interrupts
       public  enable  ;enable interrupts

       public  vers    ;CP/M function - get version number (#12)
;
;
       extrn   ?bdos
;
;***********************************************************
;*                                                         *
;*      equates for interface to mp/m xdos                 *
;*                                                         *
;***********************************************************
amemrqf equ     128     ;absolute memory request
rmemrqf equ     129     ;relocatable memory request
memfrf  equ     130     ;memory free
pollf   equ     131     ;poll device
flgwtf  equ     132     ;flag wait
flgsetf equ     133     ;flag set
makquef equ     134     ;make queue
opnquef equ     135     ;open queue
delquef equ     136     ;delete queue
rdquef  equ     137     ;read queue - unconditional
crdquef equ     138     ;conditional read queue
wrquef  equ     139     ;write queue - unconditional
cwrquef equ     140     ;conditional write queue
delayf  equ     141     ;delay
dsptchf equ     142     ;dispatch
termf   equ     143     ;terminate calling process
crprocf equ     144     ;create process
setprif equ     145     ;set process priority
attconf equ     146     ;attach console
detconf equ     147     ;detach console
setconf equ     148     ;set console
asnconf equ     149     ;assign console
sclicdf equ     150     ;send CLI command
clrespf equ     151     ;call resident system process
parsef  equ     152     ;parse filename
getconf equ     153     ;get console number
sysdatf equ     154     ;return system data page adr
gettodf equ     155     ;get time and date
rpdadrf equ     156     ;return process descr adr
abtsprf equ     157     ;abort specified process

versf   equ     12      ;get version number (CP/M function)
;
;       utility functions
;***********************************************************
;*                                                         *
;*      general purpose routines used upon entry           *
;*                                                         *
;***********************************************************
getp1i:
       call    getp1
       jmp     ?bdos           ;return through bdos

getp1:  ;get single byte parameter to register e
       mov     e,m             ;low (addr)
       inx     h
       mov     d,m             ;high (addr)
       xchg                    ;hl = .char
       mov     e,m             ;to register e
       ret
;
getp2:  ;gell   getle word parameter to DE
getp2i: ;(equivalent to getp2)
       call    getp1
       inx     h
       mov     d,m             ;get high byte as well
       jmp     ?bdos           ;return through bdos
;
getp3i: ;get single word parameter to DE
       ;perform bdos call and then compliment result
       call    getp2i
       cma
       ret
;
;***********************************************************
;*                                                         *
;***********************************************************
amemrq: ;absolute memory request (#128)
       ;1->addr(memdscr)
       mvi     c,amemrqf       ;abs mem rqst function
       jmp     getp3i          ;DE = .memdscr
                               ;return through bdos
;
;********************rform bdos call and then compliment result
       ca                         *
;***********************************************************
rmemrq: ;relocatable memory request (#129)
       ;1->addr(memdscr)
       mvi     c,rmemrqf       ;rel mem rqst function
       jmp     getp3i          ;DE = .memdscr
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
memfr:  ;memory free (#130)
       ;1->addr(memdscr)
       mvi     c,memfrf        ;memory free function
       jmp     getp2i          ;DE = .memdscr
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
poll:   ;poll device (#131)
       ;1->fixed(7) poll device number
       mvi     c,pollf         ;poll function
       jmp     getp1i          ;device number to E
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
flgwt:  ;flag wait (#132)
       ;1->fixed(7) flag number
       mvi     c,flgwtf        ;flag wait function
       call    getp1i          ;flag number to E
       cma
       ret
;
;***********************************************************
;*                                                         *
;***********************************************************
flgset: ;flag set (#133)
       ;1->fixed(7) flag number
       mvi     c,flgsetf       ;flag set function
       call    getp1i          ;flag number to E
       cma
       ret
;
;***********************************************************
;*                                                         *
;***********************************************************
makque: ;make queue (#134)
       ;1->addr(qcb)
       mvi     c,makquef       ;make queue function
       jmp     getp2i          ;DE = .qcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
opnque: ;open queue (#135)
       ;1->addr(uqcb)
       mvi     c,opnquef       ;open queue function
       jmp     getp3i          ;DE = .uqcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
delque: ;delete queue (#136)
       ;1->addr(qcb)
       mvi     c,delquef       ;delete queue function
       jmp     getp3i          ;DE = .qcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
rdque:  ;read queue - unconditional (#137)
       ;1->addr(uqcb)
       mvi     c,rdquef        ;read queue function
       jmp     getp2i          ;DE = .uqcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
crdque: ;conditional read queue (#138)
       ;1->addr(uqcb)
       mvi     c,crdquef       ;conditional read queue function
       jmp     getp3i          ;DE = .uqcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
wrque:  ;write queue - unconditional (#139)
       ;1->addr(uqcb)
       mvi     c,wrquef        ;write queue function
       jmp     getp2i          ;DE = .uqcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
cwrque: ;conditional write queue (#140)
       ;1->addr(uqcb)
       mvi     c,cwrquef       ;conditional write queue function
       jmp     getp3i          ;DE = .uqcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
delay:  ;delay (#141)
       ;1->number of ticks to delay
       mvi     c,delayf        ;delay function
       jmp     getp2i          ;DE = #ticks
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
dsptch: ;dispatch (#142)
       mvi     c,dsptchf       ;dispatch function
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
term:   ;terminate calling process (#143)
       ;1->terminate code
       mvi     c,termf         ;terminate function
       jmp     getp2i          ;DE = terminate code, where
                               ; if D = FF then keep mem seg
                               ; if E = FF term sys process
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
crproc: ;create process (#144)
       ;1->addr(pdadr)
       mvi     c,crprocf       ;create process function
       jmp     getp2i          ;DE = .pdadr
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
setpri: ;set process priority (#145)
       ;1->fixed(7) priority
       mvi     c,setprif       ;set priority function
       jmp     getp1i          ;priority to E
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
attcon: ;attach console (#146)
       mvi     c,attconf       ;attach console function
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
detcon: ;detach console (#147)
       mvi     c,detconf       ;detach console function
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
setcon: ;set console (#148)
       ;1->fixed(7) console
       mvi     c,setconf       ;set console function
       jmp     getp1i          ;console to E
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
asncon: ;assign console (#149)
       ;1->addr(apb)
       mvi     c,asnconf       ;assign console function
       jmp     getp3i          ;DE = .apb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
sclicd: ;send CLI command (#150)
       ;1->addr(clicmd)
       mvi     c,sclicdf       ;send CLI command function
       jmp     getp2i          ;DE = .clicmd
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
clresp: ;call resident system process (#151)
       ;1->addr(cpb)
       call    getp1           ;DE = .cpb
       inx     h
       mov     d,m
       xchg
       mov     c,m
       inx     h
       mov     b,m             ;BC = cpb.name
       inx     h
       mov     d,h
       mov     e,l             ;DE = .cpb.param
       lxi     h,-14
       dad     sp
       sphl                    ;make room for uqcb+2 on stk
       push    d
;
;       Stack Structure:
;
;       +-----------------------+
;       |   Return Address      |
;       +-----------------------+
;       |                       |
;         uqcb.name(0) - name(7)
;       |                       |
;       +-----------------------+
;       |   uqcb.msgadr         | ---+
;       +-----------------------+    |
;       |   uqcb.pointer        |    |
;       +-----------------------+    |
;       |  (space for .pliproc) | <--+
;       +-----------------------+
;  S--->|   .cpb.param          |
;       +-----------------------+
;
       mov     d,h
       mov     e,l
       inx     h
       inx     h
       inx     h
       inx     h
       mov     m,e
       inx     h
       mov     m,d             ;uqcb.msgadr <-
       inx     h
       mvi     e,8
clresploop:
       ldax    b
       mov     m,a
       inx     b
       inx     h
       dcr     e
       jnz     clresploop
       lxi     b,-12
       dad     b               ;HL = .uqcb
       mvi     c,opnquef
       xchg
       call    ?bdos           ;open the cpb.name queue
       inr     a
       lxi     h,0001h
       pop     d               ;DE = cpb.param
       jz      clresprtn       ;queue not found
       lxi     h,2
       dad     sp
       mvi     c,rdquef
       push    d
       xchg
       call    ?bdos           ;read proc adr from queue
       pop     d               ;DE = cpb.param
       pop     h               ;HL = procadr
       push    h
       lxi     b,clresprtn
       push    b               ;setup return addr
       push    h
       xchg
       ret                     ;call pliproc (param)
clresprtn:                      ;return here from pliproc call
       push    h               ;save returned result
       lxi     h,4
       dad     sp
       xchg                    ;DE = .uqcb
       mvi     c,wrquef
       call    ?bdos           ;write proc adr to queue
       pop     d               ;DE = result returned from pliproc
       lxi     h,14
       dad     sp
       sphl                    ;discard uqcb on stack
       xchg
       ret                     ;return with HL = pliproc()
       ;
;***********************************************************
;*                                                         *
;***********************************************************
parse:  ;parse filename (#152)
       ;1->addr(pfcb)
       mvi     c,parsef        ;parse filename function
       jmp     getp2i          ;DE = .pfcb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
getcon: ;get console number (#153)
       mvi     c,getconf       ;get console function
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
sysdat: ;return system data page adr (#154)
       mvi     c,sysdatf       ;get system data pg adr fn
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
gettod: ;get time and date (#155)
       ;1->addr(todadr)
       mvi     c,gettodf       ;get time and date function
       jmp     getp2i          ;DE = .todadr
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
rpdadr: ;return process descr adr (#156)
       mvi     c,rpdadrf       ;return Proc dscr adr fn
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
abtspr: ;abort specified process (#57)
       ;1->addr(abtpb)
       mvi     c,abtsprf       ;abort specified proc fn
       jmp     getp3i          ;DE = .abtpb
                               ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
disabl: ;disable interrupts
       di
       ret
;
;***********************************************************
;*                                                         *
;***********************************************************
enable: ;enable interrupts
       ei
       ret
;
;***********************************************************
;*                                                         *
;***********************************************************
vers:   ;get version number (#12)  CP/M function
       mvi     c,versf
       jmp     ?bdos           ;return through bdos
;
;***********************************************************
;*                                                         *
;***********************************************************
       end