   ! Make VT Configuration File program
   ! used to manufacture IOVTCONFIG.ASM to be included in SDOS I/O packages...
   ! that use the VT driver

   ! Revision History:
   !
   ! 1.0j 5/17/82
   !      Merged 1.0f and OBMAKEVTCFG.BAS to bring 4-phase I/O package
   !         MAKEVTCFG up to par with VTDRIVER1.0i and j
   !
   ! 1.1A 4/18/83
   !     Modified to generate stack-switch free interrupt poll code for ACIAs
   !     (this is the major difference between VT1.0 and VT1.1 drivers)
   !     Fixed to generate "OKRTS" at end of reset routines
   !     Fixed so ACIA poll chain ignores FE, OVRUN, and PE


   ! 1.1C 1/25/84
   !     Add dcb:iloto,dcb:ilenboi,dcb:ildisoi,dcb:ilsetbaudrate
   !     changed dcb:ilputdev

   !     Changed to handle DPBs with name pointers
   !     Changed for - ringbuffer counts

   ! 1.1C1 4/24/84
   !     Fixed non-acia code generation in DCB

   ! 1.1C2 4/2/85
   !     FIXED STRING SUBCRIPT OUT OF RANGE ERROR
   !     CAUSED BY LARGE CLIMATRON DO FILE


   dim version$/"Make VT Configuration File, V 1.1c2",...
&               " (matches same rev VT driver)"/
   dim arg1$[32],arg2$[32],arg3$[32],arg4$[40],arg5$[40],arg6$[8]
   dim DeviceisACIA[16]
   dim DeviceAddress$[16][15],DeviceDataAddress$[16][15],aciac$[15],aciad$[15]
   dim tab$/:09/,dcbname$[16][32],answer$[16],profilename$[20][32]
   dim profile$(24)
!^L
def makelabel$(a2$)=a2$ cat ":" cat aciac$

subroutine emitlabel(a1$)
   print #1,makelabel$(a1$)
   exit subroutine
end

subroutine emitcode(a3$,a4$,a5$)
   if len(a5$) then print #1,tab$;a3$;tab$;a4$;tab$;a5$
   elseif len(a4$) then print #1,tab$;a3$;tab$;a4$
   else print #1,tab$;a3$
   exit subroutine
end

subroutine emitrmbl(a9$)
   emitcode("rpt",a9$,"")
   emitcode("fcb","0","")
   exit subroutine
end

subroutine emitrmbc(a9)
   emitcode("rpt",num$(a9),"")
   emitcode("fcb","0","")
   exit subroutine
end

subroutine emitequ(a10$,a11$)
   print #1,a10$;tab$;"equ";tab$;a11$
   exit subroutine
end
!^L
subroutine buildbuffers(c3$)

   aciac$=c3$

   emitcode("ifund",makelabel$("outbufsize"),"")
   emitequ(makelabel$("outbufsize"),"80")
   emitcode("fin","","")
   emitcode("ifund",makelabel$("linebufsize"),"")
   emitequ(makelabel$("linebufsize"),"100")
   emitcode("fin","","")
   emitcode("ifund",makelabel$("inbufsize"),"")
   emitequ(makelabel$("inbufsize"),"80")
   emitcode("fin","","")
   print #1,"; inbufsize should be less than linebufsize, in order to"
   print #1,"; avoid too long typed-ahead line"

   emitlabel("outbuf")
   emitcode("rmb",makelabel$("outbufsize"),"")
   emitlabel("inbuf")
   emitcode("rmb",makelabel$("inbufsize"),"")
   emitlabel("linebuf")
   emitcode("rmb",makelabel$("linebufsize"),"")

   exit subroutine

end
!^L
subroutine buildcustomcode(c1$,d1$)

   aciac$=c1$ \ aciad$=d1$

   print #1,tab$;"if";tab$;"iodriverinit"

   emitlabel("reset")
   emitcode("ldaa","#%00000011","reset ACIA")
   emitcode("staa",aciac$,"")
   emitcode("ldaa","#%10010101","in int; 8 D + 1 S; no parity; /16")
   emitcode("staa",aciac$,"")
   emitcode("ldaa",aciad$,"clear any input interrupt")
   emitcode("okrts","","")

   print #1,tab$;"fin";tab$;"iodriverinit"

   print #1,tab$;"if";tab$;"iodriverbody"


   emitlabel("ilgetdev")
   emitcode("ldab",aciac$,"get the status first (becuz reading data clears it)")
   emitcode("ldaa",aciad$,"get the interrupt-causing data")
   emitcode("jmp","ilgetdevstatusfromacia","the rest is common code")

   emitlabel("tlcheckready")
   emitcode("ldaa",aciac$,"get the status")
   emitcode("rora","","shift *DCD into carry bit")
   emitcode("rora","","")
   emitcode("rora","","")
   emitcode("rts","","")


   emitlabel("iloto")
   emitlabel("ildisoi")
   emitcode("ldaa","#%10010101","in int; 8 D + 1 S; no parity; /16")
   emitcode("staa",aciac$,"")
   emitlabel("rts") \ emitcode("rts","","")

   emitlabel("ilenboi")
   emitcode("ldaa","#%10110101","enable output interrupts")
   emitcode("staa",aciac$,"")
   emitcode("ldaa",aciac$,"")
   emitcode("bita","#%00000010","test TDRE bit")
   emitcode("rts","","")

    print #1,tab$;"fin";tab$;"iodriverbody"

   exit subroutine

end
!^L
subroutine buildpollchain(c9$,c11$)

   aciac$=c9$
   aciad$=c11$

   emitcode("ldaa",aciac$,"test irq")
   emitcode("bpl",makelabel$("noint"),"b/ no int here")
   emitcode("ldx",makelabel$("#dcb"),"look more closely")
   emitcode("cmpa","#%10000010","handle output only interrupt pronto!")
   emitcode("bne",makelabel$("notoutput"),"")
   emitlabel("gotoutput")
   emitcode("jmp","sdos+sdos:vtoutputint","")
   emitlabel("notoutput")
   emitcode("bita","#%00000100","data carrier detect dropped ?")
   emitcode("bne",makelabel$("dcddrop"),"")
   emitcode("bita","#%00000001","receiver data register full ?")
   emitcode("beq",makelabel$("notinput"),"b/ no, probably IRQ and FE or *CTS glitch")
   emitcode("jmp","sdos+sdos:vtinputint","")
   emitlabel("dcddrop")
   emitcode("ldab",aciad$,"clear interrupt caused by ~dcd")
   emitlabel("notinput")
   emitcode("bita","#%00000010","output requested with ~dcd or fe?")
   emitcode("bne",makelabel$("gotoutput"),"b/ yup!")
   emitlabel("rti")
   emitcode("rti","","")
   emitlabel("noint")

   exit subroutine

end
!^L
subroutine builddcb(c2$,d2$,n1$,p1$,p2$,p3$)

   aciac$=c2$
   aciad$=p3$
!  give the device a name

   emitlabel("dcbname")
   emitcode("fcc","/" cat d2$ cat "/","")
   emitcode("fcb","0","")

!  clear dcb

   emitcode("ifund","ttydcb","")
   print #1,"ttydcb"
   emitcode("fin","ttydcb","")
   emitlabel("dcb") \ emitrmbl("dcb:vtsize")

!  output dcb header

   emitcode("org",makelabel$("dcb") cat "+dcb:name","")
   emitcode("fdb",makelabel$("dcbname"),"")
   if len(n1$)
   then aciac$=n1$ \ emitcode("fdb",makelabel$("dcb"),"") \ aciac$=c2$
   else emitcode("fdb","nextdevicedcb","")
   emitcode("fdb","sdos+sdos:vtdispatch","")

!  serve ACIA

   emitcode("org",makelabel$("dcb") cat "+dcb:reset","")
   emitcode("jmp",makelabel$("reset"),"")
   emitcode("okrts","","dump nothing")
   emitcode("if","m6800!m6801","")
   emitcode("nop","","")
   emitcode("fin","","")
   if aciad$ <> "" then
       emitcode("staa",aciad$,"output data")
       emitcode("rti","","")
   else
       emitcode("jmp",makelabel$("ilputdev"),"not acia output")
       emitcode("swi","","")
   fi
   emitcode("jmp",makelabel$("ilgetdev"),"")
   emitcode("jmp","illdeviceop","no extra control calls defined")
   emitcode("jmp","illdeviceop","no extra status calls defined")
   emitcode("jmp",makelabel$("tlcheckready"),"go check for acia ready")

   emitcode("jmp",makelabel$("ilenboi"),"Enable Output Interrupts")
   emitcode("jmp",makelabel$("ildisoi"),"Disable Output Interrupts")
   emitcode("jmp",makelabel$("iloto"),"Reset Output Timeout")
   emitcode("errorrts",makelabel$("ilsetbaudrate"),"Set Baud Rate")

!  emit output and input timeout blocks

   emitcode("org",makelabel$("dcb") cat "+dcb:outputtoblk","")

   emitcode("ifund","ttytimeouts","")
   print #1,"ttytimeouts"
   emitcode("fin","ttytimeouts","")
   emitlabel("outputtoblk")
   emitcode("fdb",makelabel$("inputtoblk"),"")
   emitcode("fdb","0","")
   emitcode("fdb","sdos+sdos:vtoutputto","")
   emitcode("fdb",makelabel$("dcb"),"")

   emitcode("org",makelabel$("dcb") cat "+dcb:inputtoblk","")

   emitlabel("inputtoblk")
   if len(n1$)
   then aciac$=n1$ \ emitcode("fdb",makelabel$("outputtoblk"),"") \ aciac$=c2$
   else
      emitcode("fdb","nexttimeout","")
      print #1,"nexttimeout";tab$;"set";tab$;"ttytimeouts"
   fi
   emitcode("fdb","0","")
   emitcode("fdb","sdos+sdos:vtinputto","")
   emitcode("fdb",makelabel$("dcb"),"")
!^L
!  serve buffer management

   emitcode("org",makelabel$("dcb") cat "+dcb:ringinbase","")
   emitcode("fdb",makelabel$("inbuf"),"")
   emitcode("fdb",makelabel$("-inbufsize"),"")

   emitcode("org",makelabel$("dcb") cat "+dcb:ringoutbase","")
   emitcode("fdb",makelabel$("outbuf"),"")
   emitcode("fdb",makelabel$("-outbufsize"),"")

   emitcode("org",makelabel$("dcb") cat "+dcb:ringoutthreshold","")
   emitcode("fcb",makelabel$("outbufsize") cat "//10","")

   emitcode("org",makelabel$("dcb") cat "+dcb:linebuf","")
   emitcode("fdb",makelabel$("linebuf"),"")

   emitcode("org",makelabel$("dcb") cat "+dcb:linebuflen","")
   emitcode("fcb",makelabel$("linebufsize"),"")

   emitcode("org",makelabel$("dcb") cat "+dcb:tlputbuf","")
   emitcode("fcb","$7E,0,0","")

   emitcode("org",makelabel$("dcb") cat "+dcb:profile","")
   emitcode("fcb",p1$,"profile Number")
   emitcode("fdb",p2$,"profile Name pointer")

   emitcode("org",makelabel$("dcb") cat "+dcb:doneflag","")
   emitcode("fcb","1","device not busy")

   emitcode("org",makelabel$("dcb") cat "+dcb:oilquiescent","")
   emitcode("fcb","1","interrupt not expected")

   emitcode("org",makelabel$("dcb") cat "+dcb:vtsize","")
!^L
!  emit TCB, TOBs, and stack

   emitcode("ifund","ttytcb","")
   print #1,"ttytcb"
   emitcode("fin","ttytcb","")
   emitlabel("tcb")
   if len(n1$)
   then aciac$=n1$ \ emitcode("fdb",makelabel$("tcb"),"") \ aciac$=c2$
   else emitcode("fdb","nexttcb","")
   emitcode("fdb",makelabel$("tcbstack"),"")
   emitcode("fdb","0,0,0,0,0,0","")
   emitcode("org",makelabel$("tcb") cat "+tcb:scratchpad+dcbpointer","")
   emitcode("fdb",makelabel$("dcb"),"")
   emitcode("org",makelabel$("tcb") cat "+tcb:size","")

   emitcode("rmb","env:minstack*2-env:size","")
   emitlabel("tcbstack") \ emitrmbl("env:size")
   emitcode("org","*-env:cc","")
   emitlabel("stack")
   emitcode("org",makelabel$("tcbstack") cat "+env:p","")
   emitcode("fdb","sdos+sdos:vtedittask","")
   emitcode("org",makelabel$("tcbstack") cat "+env:cc","")
   emitcode("fcb","$80*m6809","set 'E' flag for 6809")
   emitcode("org",makelabel$("stack") cat "+env:cc","")

   exit subroutine

end
!^L
   print Version$
   print "Copyright (c) 1981 Software Dynamics"


!   profilenames$[1]="malvt" \ profilenames$[2]="adm1"
!   profilenames$[3]="adm3" \ profilenames$[4]="soroc120"
!   profilenames$[5]="h19" \ profilenames$[6]="hardcopyvt"
!   profilenames$[7]="tvi912c"
!   profilenames$[9]="mallpt" \ profilenames$[10]="cenlpt"
!   profilenames$[11]="rs232lpt"

!   definedprofiles[1]=1 \ definedprofiles[9]=9 \ ! malleable vt & lpt
!   definedprofiles[6]=1                        \ ! hardcopy vt
!^L
   create #1,"iovtconfig.asm" \ VTDeviceCount=0
   querydone=false
   repeat
      input "Enter unique device address (ACIA control port)? " answer$
      if error when
         if len(answer$) then
            aciac=val(answer$)
            DeviceAddress$[VTDeviceCount+1]="$" cat hex$(aciac)[2,4]
            input "Is the device an ACIA (<CR>='yes')? " answer$
            DeviceIsACIA(VTDeviceCount+1)=...
&                       answer$="" or Find(UpperCase$(answer$),"Y")=1
            if DeviceIsACIA(VTDeviceCount+1)
            then
                input "...ACIA data port address? " aciad
                DeviceDataAddress$[VTDeviceCount+1]="$" cat hex$(aciad)[2,4]
            else
                DeviceDataAddress$[VTDeviceCount+1]= ""
! Generate JMP ilputdev$"aciac" for target of no acia 4/24/84
            fi
            input "...and the desired device name? " answer$
            input "...and the device profile? " profile$
            profilename$[VTDeviceCount+1]=profile$
            dcbname$[VTDeviceCount+1]=uppercase$(answer$)
            ! all data about device entered, and nothing went sour!
            VTDeviceCount=VTDeviceCount+1
         else querydone=true
      then print "oops! you goofed..."
   unless querydone

   maxprofiles=VTDeviceCount

   repeat
      input "additional profile name to include? " profile$
      if profile$ <> "" then
         maxprofiles=maxprofiles+1
         profilename$[maxprofiles]=profile$
         ! we could check to see if profile name was legal here...
         ! note: must allow profile number, too...
! RCW I donot think this would be proper because...
!     what if you are generating with dpbs which are not included in
!     this programs name list or systems.
!     MakeVtcfg11d... departs from names in programs so checking would
!     be of no use and besides we know the I/O package builder should know
!     what DPBs he has in IOVTDPBS.ASM???

      fi
   unless profile$=""

   print #1,tab$;"if";tab$;"iodriverbody"

   for i=1 to maxprofiles  do
      print  #1,tab$;"ifund";tab$;"profile.";profilename$[i]
      print  #1,"profile.";profilename$[i];tab$;"equ";tab$;"1"
      print  #1,tab$;"fin";tab$;"profile.";profilename$[i]
   end

   emitcode("page","VT Device-Specific Code","")

   print #1,tab$;"fin";tab$;"iodriverbody"

   for ix=1 to VTDeviceCount do
      arg1$=DeviceAddress$[ix] \ arg2$=DeviceDataAddress$[ix]
      if DeviceisACIA(ix) then buildcustomcode(arg1$,arg2$)
   end

   print #1,tab$;"if";tab$;"iodriverpoll"

   emitcode("page","VT Interrupt Poll Chain","")

   print #1,"vt:interruptpollchain";tab$;"; should be first in poll chain"

   for ix=1 to VTDeviceCount do
      arg1$=DeviceAddress$[ix]
      arg2$=DeviceDataAddress$[ix]
      if DeviceisACIA(ix)
      then buildpollchain(arg1$,arg2$)
      else Print #1,"*  poll code for ";arg1$;" should go here"
   end

   print #1,tab$;"fin";tab$;"iodriverpoll"

   print #1,tab$;"if";tab$;"iodriverram"

   print #1,"ntimeouts";tab$;"set";tab$;
   print #1,using "###",VTDeviceCount*2;
   print #1,"+ntimeouts"

   emitcode("page","VT Ring Buffers","")
   print #1,"ttybuffers"

   for ix=1 to VTDeviceCount do
      arg1$=DeviceAddress$[ix]
      buildbuffers(arg1$)
   end

   emitcode("page","VT DCBs","")

   for ix=1 to VTDeviceCount do
    arg1$=DeviceAddress$[ix] \ arg2$=dcbname$[ix] \ arg3$=DeviceAddress$[ix+1]
      arg4$="profilenum." cat profilename$[ix]
      arg5$="profileloc." cat profilename$[ix]
      arg6$=DeviceDataAddress$[ix]
      if ix=VTDeviceCount then call builddcb(arg1$,arg2$,"",arg4$,arg5$,arg6$)
      else call builddcb(arg1$,arg2$,arg3$,arg4$,arg5$,arg6$)
   end

   print #1,tab$;"fin";tab$;"iodriverram"

   exit

end
