home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Workbench / Dvices / NEW8N1.LHA / 8n1_000.s < prev    next >
Encoding:
Text File  |  1996-11-20  |  57.5 KB  |  1,926 lines

  1. ********************************************************************************
  2. **                                          **
  3. **  Name       : 8n1_000.s                              **
  4. **  Copyright  : © Copyright 96                           **
  5. **  Author     : Iain Barclay                              **
  6. **  Created    : 19 Nov 96                              **
  7. **  Version    : 37.22                                  **
  8. **                                          **
  9. ********************************************************************************
  10.      ;
  11.      ;      SNMA specific options
  12.      ;
  13.      IFD      SNMA
  14.      ;
  15.      CPU      M68010
  16.      ;
  17.      SNMAOPT  Q,A,M,T,E-
  18.      ;
  19.      ELSE
  20.      machine 68010
  21.      OPT !
  22.      ENDC
  23.      ;
  24.      INCDIR   "dcc:Ainclude/"
  25.      ;
  26.      ;
  27.      ;
  28. DEBUG     SET    0
  29. NEWCODE  SET    1
  30. EOFCODE  SET    0
  31. SETDSR     SET    0
  32. NCOMM     SET    0
  33.      ;
  34.      ;
  35.      ;
  36.      SECTION  text,CODE
  37.      ;
  38.      ;
  39.      ;
  40. DEVICES_SERIAL_I_OBSOLETE  EQU        1
  41.      ;
  42.      ;
  43.      ;
  44.      INCLUDE  "exec/lists.i"
  45.      INCLUDE  "exec/memory.i"
  46.      INCLUDE  "exec/resident.i"
  47.      INCLUDE  "exec/devices.i"
  48.      INCLUDE  "exec/execbase.i"
  49.      INCLUDE  "exec/io.i"
  50.      INCLUDE  "exec/ports.i"
  51.      INCLUDE  "exec/errors.i"
  52.      INCLUDE  "exec/initializers.i"
  53.      INCLUDE  "intuition/preferences.i"
  54.      INCLUDE  "devices/timer.i"
  55.      INCLUDE  "devices/serial.i"
  56.      INCLUDE  "hardware/custom.i"
  57.      INCLUDE  "hardware/cia.i"
  58.      INCLUDE  "hardware/intbits.i"
  59.      INCLUDE  "hardware/adkbits.i"
  60.      INCLUDE  "resources/misc.i"
  61.      INCLUDE  "exec/alerts.i"
  62.      INCLUDE  "exec/macros.i"
  63.      INCLUDE  "8n1.device_rev.i"
  64.      ;
  65.      ;      Define hardware references
  66.      ;
  67.      XREF      _AbsExecBase
  68.      XREF      _custom
  69.      XREF      _intena,_intenar,_intreq,_intreqr
  70.      XREF      _ciab,_ciabpra
  71.      XREF      _serper,_serdat,_serdatr
  72.      XREF      _adkcon,_adkconr
  73.      ;
  74.      ;      Exec Functions
  75.      ;
  76.      XREF      _LVORemDevice,_LVOOpenDevice,_LVOCloseDevice
  77.      XREF      _LVOSupervisor
  78.      XREF      _LVORemove,_LVORemHead,_LVOAddTail
  79.      XREF      _LVOAllocMem,_LVOFreeMem,_LVOCopyMem
  80.      XREF      _LVOReplyMsg
  81.      XREF      _LVOSendIO,_LVOAbortIO
  82.      XREF      _LVODisable,_LVOEnable
  83.      XREF      _LVOFindName
  84.      XREF      _LVOOpenResource
  85.      XREF      _LVOAddIntServer,_LVORemIntServer
  86.      XREF      _LVOSetIntVector
  87.      XREF      _LVOAlert
  88.      XREF      _LVOOpenLibrary,_LVOCloseLibrary
  89.      ;
  90.      ;      Misc Resource Functions
  91.      ;
  92.      XREF      _LVOAllocMiscResource,_LVOFreeMiscResource
  93.      ;
  94.      ;      Intuition Functions
  95.      ;
  96.      XREF      _LVOGetPrefs
  97.      ;
  98.      ;      Mask used to get rid of the printer bits.
  99.      ;
  100. PRTMASK  EQU      (CIAF_PRTRPOUT|CIAF_PRTRBUSY)
  101.      ;
  102.      ;      Autovector offsets
  103.      ;
  104. LVL1VEC  EQU      (1-1)*4+$64
  105. LVL5VEC  EQU      (5-1)*4+$64
  106.      ;
  107.      ;      Device base
  108.      ;
  109.      STRUCTURE Base8n1,LIB_SIZE
  110.      UBYTE      vb_SaveDDRA
  111.      UBYTE      vb_SavePRA
  112.      APTR      vb_MiscBase
  113.      APTR      vb_OldLevel1
  114.      APTR      vb_OldLevel5
  115.      ULONG      vb_SegList
  116.      ULONG      vb_DefBaud
  117.      ULONG      vb_DefRBufLen
  118.      ULONG      vb_CurRBuf
  119.      ULONG      vb_CurRBufLen
  120.      ULONG      vb_CurBaud
  121.      UBYTE      vb_SerFlags
  122.      UBYTE      vb_Initialized
  123.      LABEL      sizeof_Base8n1
  124.      ;
  125.      ;
  126.      ;
  127. DISABLE  MACRO
  128.      IFNC      '\1',''
  129.      move.w   #INTF_\1,_intena
  130.      ELSE
  131.      jsr      _LVODisable(a6)
  132.      ENDC
  133.      ENDM
  134.      ;
  135. ENABLE     MACRO
  136.      IFNC      '\1',''
  137.      move.w   #INTF_SETCLR|INTF_\1,_intena
  138.      ELSE
  139.      jsr      _LVOEnable(a6)
  140.      ENDC
  141.      ENDM
  142.      ;
  143.      ;
  144.      ;
  145. PUTDEBUG macro      ;[msg]
  146.      ifge      DEBUG-2
  147.      movem.l  a0/a1/d0/d1,-(sp)
  148.      lea      (.msg\@,pc),a0  ;Point to static format string
  149.      lea      (4*4,sp),a1      ;Point to args
  150.      XREF      DPutFmt
  151.      bsr      DPutFmt
  152.      movem.l  (sp)+,d0/d1/a0/a1
  153.      bra.b      .end\@
  154.  
  155. .msg\@     dc.b      \1,10,0
  156.      CNUL      0,4
  157. .end\@
  158.      endc
  159.      endm
  160.      ;
  161.      ;
  162.      ;
  163. DEBUG1     MACRO
  164.      IFEQ       DEBUG-1
  165.      XREF      _SendText
  166.      move.l   \2,-(sp)
  167.      pea.l      debug1s\@$
  168.      pea.l      Name
  169.      jsr      _SendText(pc)
  170.      lea.l      12(sp),sp
  171.      bra.b      debug1x\@$
  172. debug1s\@$:
  173.      dc.b      \1,0
  174.      CNOP      0,2
  175. debug1x\@$:
  176.      ENDC
  177.      ENDM
  178. DEBUG0     MACRO
  179.      XREF      _SendText
  180.      pea.l      debug1s\@$
  181.      pea.l      Name
  182.      jsr      _SendText(pc)
  183.      addq      #8,sp
  184.      bra.b      debug1x\@$
  185. debug1s\@$:
  186.      dc.b      \1,0
  187. debug1x\@$:
  188.      ENDM
  189.  
  190. DEBUGIO  MACRO
  191.      IFEQ      DEBUG-1
  192.      lea.l      \1,a0
  193.      jsr      printIO
  194.      ENDC
  195.      ENDM
  196.      ;
  197.      ;
  198.      ;
  199. Start:
  200.      moveq      #-1,d0                  ; set return code
  201.      rts                          ; return
  202.      ;
  203.      ;      RamLib looks for this romtag
  204.      ;
  205. ROMTag     DC.W      RTC_MATCHWORD               ; RT_MATCHWORD
  206.      DC.L      ROMTag                  ; RT_MATCHTAG
  207.      DC.L      ENDTag                  ; RT_ENDSKIP
  208.      DC.B      RTF_AUTOINIT                  ; RT_FLAGS
  209.      DC.B      VERSION                  ; RT_VERSION
  210.      DC.B      NT_DEVICE                  ; RT_TYPE
  211.      DC.B      0                      ; RT_PRI
  212.      DC.L      Name                      ; RT_NAME
  213.      DC.L      IdString                  ; RT_IDSTRING
  214.      DC.L      Init                      ; RT_INIT
  215.      ;
  216.      ;      Perform device initialization
  217.      ;
  218. InitRoutine:
  219.      exg      d0,a0                   ; swap seglist and base
  220.      move.l   d0,vb_SegList(a0)              ; store seglist in base
  221.      move.l   a6,SysBase                  ; store in global storage
  222.      exg      a0,d0                   ; swap them back
  223.      rts                          ; return
  224.      ;
  225.      ;
  226.      ;
  227. dev_Open:
  228.      DEBUG1   "Devstart %lx",#Start
  229.      move.l   a5,-(sp)                  ; save registers
  230.      movea.l  a6,a5                   ; save base
  231.      movea.l  SysBase(pc),a6              ; get ExecBase
  232.      ;
  233.      tst.l      d0                      ; unit 0 specified?
  234.      bne.b      50$                      ; nope, error (who cares?)
  235.      ;
  236.      tst.w      LIB_OPENCNT(a5)              ; currently open?
  237.      bne.b      10$                      ; yep, go process
  238.      ;
  239.      move.b   IO_SERFLAGS(a1),vb_SerFlags(a5)     ; save flags
  240.      ;
  241.      tst.b      vb_Initialized(a5)              ; already initialized?
  242.      bne.b      40$                      ; yep, skip initialization
  243.      ;
  244.      bsr      initResources               ; go alloc resources
  245.      tst.l      d0                      ; initialized?
  246.      bne.b      50$                      ; nope, error
  247.      ;
  248.      bra.b      40$                      ; go exit
  249.      ;
  250. 10$     moveq      #SerErr_DevBusy,d0              ; preset error status
  251.      btst.b   #SERB_SHARED,vb_SerFlags(a5)          ; opened shared?
  252.      beq.b      50$                      ; nope, error
  253.      btst.b   #SERB_SHARED,IO_SERFLAGS(a1)          ; requesting shared?
  254.      beq.b      50$                      ; nope, error
  255.      ;
  256.      ;      Initialize I/O request
  257.      ;
  258. 40$     moveq      #8,d0                   ; get char size
  259.      move.b   d0,IO_READLEN(a1)              ; set read length
  260.      move.b   d0,IO_WRITELEN(a1)              ; set write length
  261.      moveq      #1,d0                   ; get stop bits
  262.      move.b   d0,IO_STOPBITS(a1)              ; set stop bits
  263.      move.b   IO_SERFLAGS(a1),d0
  264.      ori.b      #SERF_XDISABLED|SERF_RAD_BOOGIE|SERF_QUEUEDBRK|SERF_7WIRE,d0 ;flags
  265.      andi.b   #~(SERF_PARTY_ODD|SERF_PARTY_ON),d0 ; not used
  266.      move.b   d0,IO_SERFLAGS(a1)
  267.      move.l   vb_CurBaud(a5),IO_BAUD(a1)          ; set baud
  268.      move.l   vb_CurRBufLen(a5),IO_RBUFLEN(a1)    ; set read buffer length
  269.      ;
  270.      addq.w   #1,LIB_OPENCNT(a5)              ; incr open count
  271.      andi.b   #~(1<<LIBB_DELEXP),LIB_FLAGS(a5)    ; clear expunge bit
  272.      moveq      #0,d0                   ; no error
  273.      ;
  274. 50$     move.b   d0,IO_ERROR(a1)              ; store error code
  275.      movea.l  a5,a6                   ; restore base
  276.      move.l   (sp)+,a5                  ; restore registers
  277.      rts                          ; return
  278.      ;
  279.      ;      Attempt to allocate one of the serial resources.
  280.      ;
  281. allocResource:
  282.      move.l   a6,-(sp)                  ; save base pointer
  283.      move.l   d0,-(sp)                  ; save unit
  284.      lea.l      Name(pc),a1                  ; get lock name
  285.      move.l   vb_MiscBase(a5),a6              ; get MiscBase
  286.      jsr      _LVOAllocMiscResource(a6)          ; go allocate it
  287.      tst.l      d0                      ; did we get it?
  288.      beq.b      20$                      ; yep, branch
  289.      ;
  290.      ;      It's in use, so we try to locate the device using the string
  291.      ;      returned and attempt to remove it.
  292.      ;
  293.      movea.l  SysBase(pc),a6              ; get ExecBase
  294.      ;
  295.      movea.l  d0,a1                   ; get ptr to serial name
  296.      lea.l      DeviceList(a6),a0              ; get ptr to device list
  297.      jsr      _LVOFindName(a6)              ; go find it
  298.      tst.l      d0                      ; found?
  299.      beq.b      10$                      ; nope, branch
  300.      ;
  301.      movea.l  d0,a1                   ; xfer device ptr
  302.      jsr      _LVORemDevice(a6)              ; remove it
  303.      ;
  304.      ;      We then retry the allocate.
  305.      ;
  306. 10$     move.l   (sp),d0                  ; get unit
  307.      lea.l      Name(pc),a1                  ; get lock name
  308.      movea.l  vb_MiscBase(a5),a6              ; get MiscBase
  309.      jsr      _LVOAllocMiscResource(a6)          ; go allocate it
  310.      ;
  311. 20$     addq.l   #4,sp                   ; restore stack ptr
  312.      movea.l  (sp)+,a6                  ; restore base ptr
  313.      rts                          ; return
  314.      ;
  315.      ;
  316.      ;
  317. initResources:
  318.      move.l   a1,-(sp)                  ; save register
  319.      ;
  320.      lea.l      miscresource(pc),a1              ; ptr to resource name
  321.      jsr      _LVOOpenResource(a6)              ; go open it
  322.      move.l   d0,vb_MiscBase(a5)              ; save base
  323.      ;
  324.      moveq      #MR_SERIALPORT,d0              ; set unit number
  325.      bsr.b      allocResource               ; go allocate it
  326.      tst.l      d0                      ; did we get it?
  327.      bne.b      20$                      ; nope, error
  328.      ;
  329.      moveq      #MR_SERIALBITS,d0              ; set unit number
  330.      bsr.b      allocResource               ; go allocate it
  331.      tst.l      d0                      ; did we get it?
  332.      bne.b      10$                      ; nope, error
  333.      ;
  334.      bsr      getPrefs                  ; get default preferences
  335.      tst.l      d0                      ; got 'em?
  336.      beq.b      30$                      ; yep, branch
  337.      ;
  338.      moveq      #MR_SERIALBITS,d0              ; set unit
  339.      movea.l  vb_MiscBase(a5),a6              ; get MiscBase
  340.      jsr      _LVOFreeMiscResource(a6)          ; release the resource
  341.      ;
  342. 10$     moveq      #MR_SERIALPORT,d0              ; set unit
  343.      movea.l  vb_MiscBase(a5),a6              ; get MiscBase
  344.      jsr      _LVOFreeMiscResource(a6)          ; release the resource
  345.      movea.l  SysBase(pc),a6              ; restore ExecBase
  346.      ;
  347. 20$     moveq      #SerErr_DevBusy,d0              ; set error status
  348.      bra      40$                      ; go return
  349.      ;
  350. 30$     moveq      #0,d1                   ; clear flags
  351.      moveq      #UNIT_VBLANK,d0              ; set unit
  352.      lea.l      timerReq(pc),a1              ; ptr to timer request
  353.      lea.l      timerdevice(pc),a0              ; ptr to device name
  354.      jsr      _LVOOpenDevice(a6)              ; go open it
  355.      ;
  356.      DISABLE                      ; disable interrupts
  357.      ;
  358.      lea.l      _ciab,a1                  ; get ptr to ciab
  359.      move.b   ciaddra(a1),d0
  360.      move.b   d0,vb_SaveDDRA(a5)              ; save DDR value
  361.      andi.b   #PRTMASK,d0                  ; make serial bits input
  362.      move.b   ciapra(a1),d1
  363.      ori.b      #CIAF_COMDTR|CIAF_COMRTS,d0          ; make DTR/RTS output
  364.      move.b   d1,vb_SavePRA(a5)              ; save PR value
  365.      andi.b   #CIAF_COMDTR|CIAF_COMRTS|PRTMASK,d0 ; turn on DTR/RTS
  366.      move.b   d0,ciaddra(a1)
  367.      andi.b   #CIAF_COMCTS|CIAF_COMDSR|PRTMASK,d1 ; make CTS/DSR input
  368.      move.b   d1,ciapra(a1)
  369.      ;
  370.      moveq      #INTB_PORTS,d0              ; get interrupt number
  371.      lea.l      VBInterrupt(pc),a1              ; get interrupt ptr
  372.      jsr      _LVOAddIntServer(a6)              ; add it to the list
  373.      ;
  374.      bsr      getVBR                  ; get vector base (in A0)
  375.      ;
  376.      move.l   LVL1VEC(a0),vb_OldLevel1(a5)          ; save original vector
  377.      lea.l      level1(pc),a1               ; get new vector ptr
  378.      move.l   a1,LVL1VEC(a0)              ; set new vector
  379.      ;
  380.      move.l   LVL5VEC(a0),vb_OldLevel5(a5)          ; save original vector
  381.      lea.l      level5(pc),a1               ; get new vector ptr
  382.      move.l   a1,LVL5VEC(a0)              ; set new vector
  383.      ;
  384.      lea.l      _custom,a1                  ; get ptr to custom chips
  385.      move.w   #INTF_RBF|INTF_TBE,intreq(a1)       ; clear pending interrupts
  386.      move.w   #INTF_SETCLR|INTF_RBF|INTF_TBE,intena(a1) ; enable RBF & TBE
  387.      ;
  388.      addq.b   #1,vb_Initialized(a5)           ; set flag
  389.      moveq      #0,d0                   ; set good status
  390.      ;
  391.      ENABLE                       ; enable interrupts
  392.      ;
  393. 40$     movea.l  (sp)+,a1                  ; restore register
  394.      rts                          ; return
  395.      ;
  396.      ;      Get system preferences
  397.      ;
  398. getPrefs:
  399.      move.l   a1,-(sp)                  ; save registers
  400.      ;
  401.      lea.l      intuitlib(pc),a1              ; ptr to library name
  402.      moveq      #0,d0                   ; can't use OldOpenLibrary as this will not be supported.
  403.      jsr      _LVOOpenLibrary(a6)              ; go open it (any version)
  404.      movea.l  d0,a6                   ; get intuition base
  405.      ;
  406.      move.l   #(pf_SerParShk+3)&$fffffffc,d0      ; size we need (aligned)
  407.      suba.l   d0,sp                   ; reserve space
  408.      ;
  409.      movea.l  sp,a0                   ; set data area ptr
  410.      jsr      _LVOGetPrefs(a6)              ; get preferences
  411.      ;
  412.      movea.l  a6,a1                   ; get intuition base
  413.      movea.l  SysBase(pc),a6              ; restore ExecBase
  414.      jsr      _LVOCloseLibrary(a6)              ; close it
  415.      ;
  416.      moveq      #$0f,d1                  ; set mask
  417.      and.b      pf_SerStopBuf(sp),d1              ; get bufsize index
  418.      addq.l   #8,d1                   ; calc shift value
  419.      moveq      #2,d0                   ; get 1<<1
  420.      lsl.l      d1,d0                   ; get default bufsize
  421.      move.l   d0,vb_DefRBufLen(a5)              ; and store
  422.      ;
  423.      moveq      #0,d1                   ; clear upper half
  424.      move.w   pf_BaudRate(sp),d1              ; get baud rate
  425.      add.l      d1,d1                   ; generate offset
  426.      move.w   baudTable(pc,d1.w),d1           ; get default baud
  427.      move.l   d1,vb_DefBaud(a5)              ; and store
  428.      ;
  429.      bsr      internalReset               ; go init baud and buffer
  430.      ;
  431.      lea.l      (pf_SerParShk+3)&$fffffffc(sp),sp   ; restore stack
  432.      movea.l  (sp)+,a1                  ; restore registers
  433.      rts                          ; return ( status in D0 )
  434.      ;
  435.      ;      Preferences baud lookup table
  436.      ;
  437. baudTable:
  438.      dc.w      112,300,1200,2400,4800,9600,19200,31250,38400,57600,62400,64800
  439.      ;
  440.      ;      Set exception vectors
  441.      ;
  442. getVBR:
  443.      move.l   a5,-(sp)                  ; save registers
  444.      suba.l   a0,a0                   ; ptr to vector base (68000)
  445.      btst.b   #AFB_68010,AttnFlags+1(a6)          ; 68010 or higher?
  446.      beq.b      10$                      ; nope, go set vector
  447.      lea.l      20$(pc),a5                  ; ptr to routine
  448.      jsr      _LVOSupervisor(a6)              ; get into supervisor state
  449. 10$     movea.l  (sp)+,a5                  ; restore register
  450.      rts                          ; return
  451. 20$     movec.l  vbr,a0                  ; get vector base
  452.      rte                          ; return
  453.      ;
  454.      ;
  455.      ;
  456. freeResources:
  457.      move.l   a1,-(sp)                  ; save registers
  458.      ;
  459.      DISABLE                      ; disable interrupts
  460.      ;
  461.      bsr      getVBR                  ; get vector base (in A0)
  462.      ;
  463.      moveq      #1,d0                   ; set not restored code
  464.      ;
  465.      lea.l      level1(pc),a1               ; get our vector ptr
  466.      cmpa.l   LVL1VEC(a0),a1              ; do they match?
  467.      bne      10$                      ; nope, can't restore
  468.      ;
  469.      lea.l      level5(pc),a1               ; get our vector ptr
  470.      cmpa.l   LVL5VEC(a0),a1              ; do they match?
  471.      bne      10$                      ; nope, can't restore
  472.      ;
  473.      move.l   vb_OldLevel1(a5),LVL1VEC(a0)          ; restore original vector
  474.      move.l   vb_OldLevel5(a5),LVL5VEC(a0)          ; restore original vector
  475.      ;
  476.      moveq      #INTB_PORTS,d0              ; get interrupt number
  477.      lea.l      VBInterrupt(pc),a1              ; get interrupt ptr
  478.      jsr      _LVORemIntServer(a6)              ; remove it from the list
  479.      ;
  480.      lea.l      _custom,a0
  481.      move.w   #INTF_RBF|INTF_TBE,d0           ; indicate serial interrupts
  482.      move.w   d0,_intena(a0)              ; disable interrupts
  483.      move.w   d0,_intreq(a0)              ; clear pending interrupts
  484.      ;
  485.      bsr      freeBuf                  ; free allocated buffers
  486.      ;
  487.      lea.l      _ciab,a0                  ; get pointer to ciab
  488.      move.b   ciaddra(a0),d0              ; get DDR value
  489.      andi.b   #PRTMASK,d0                  ; save printer bits
  490.      ori.b      #~PRTMASK,d0                  ; set serial bits to output
  491.      move.b   d0,ciaddra(a0)              ; store value
  492.      ;
  493.      move.b   ciapra(a0),d0               ; get PR value
  494.      andi.b   #PRTMASK,d0                  ; mask out serial bits
  495.      move.b   vb_SavePRA(a5),d1              ; get saved value
  496.      andi.b   #~PRTMASK,d1                  ; mask out printer bits
  497.      or.b      d1,d0                   ; combine the two
  498.      move.b   d0,ciapra(a0)               ; and store
  499.      ;
  500.      move.b   ciaddra(a0),d0              ; get DDR value
  501.      andi.b   #PRTMASK,d0                  ; mask out serial bits
  502.      move.b   vb_SaveDDRA(a5),d1              ; get saved value
  503.      andi.b   #~PRTMASK,d1                  ; mask out printer bits
  504.      or.b      d1,d0                   ; combine the two
  505.      move.b   d0,ciaddra(a0)              ; and store
  506.      ;
  507.      lea.l      timerReq(pc),a1              ; get ptr to timer request
  508.      jsr      _LVOCloseDevice(a6)              ; go close it
  509.      ;
  510.      movea.l  vb_MiscBase(a5),a6              ; get MiscBase
  511.      moveq      #MR_SERIALBITS,d0              ; set unit
  512.      jsr      _LVOFreeMiscResource(a6)          ; release the resource
  513.      ;
  514.      moveq      #MR_SERIALPORT,d0              ; set unit
  515.      jsr      _LVOFreeMiscResource(a6)          ; release the resource
  516.      movea.l  SysBase(pc),a6              ; restore ExecBase
  517.      ;
  518.      ENABLE                       ; enable interrupts
  519.      ;
  520.      subq.b   #1,vb_Initialized(a5)           ; clear flag
  521.      moveq      #0,d0                   ; free up everything
  522.      ;
  523. 10$     movea.l  (sp)+,a1                  ; restore registers
  524.      rts                          ; return
  525.      ;
  526.      ;      Device Close routine
  527.      ;
  528. dev_Close:
  529.      ;
  530.      moveq      #-1,d0                  ; invalidate
  531.      move.l   d0,IO_DEVICE(a1)              ;   device
  532.      ;
  533.      subq.w   #1,LIB_OPENCNT(a6)              ; decr open count
  534.      bne.b      dev_Null                  ; still open? yep, branch
  535.      ;
  536.      move.l   a5,-(sp)                  ; save registers
  537.      movea.l  a6,a5                   ; save base
  538.      movea.l  SysBase(pc),a6              ; get ExecBase
  539.      ;
  540.      bsr      freeResources               ; free allocated resources
  541.      ;
  542.      movea.l  a5,a6                   ; restore base
  543.      movea.l  (sp)+,a5                  ; restore registers
  544.      ;
  545.      tst.l      d0                      ; freed?
  546.      bne.b      dev_Null                  ; nope, can't expunge, exit
  547.      ;
  548.      clr.b      vb_SerFlags(a6)              ; clear flags
  549.      ;
  550.      btst.b   #LIBB_DELEXP,LIB_FLAGS(a6)          ; delayed expunge set?
  551.      beq.b      dev_Null                  ; nope, go exit
  552.      ;
  553.      ;      Device Expunge routine (also fall through from dev_Close)
  554.      ;
  555. dev_Expunge:
  556.      ori.b      #1<<LIBB_DELEXP,LIB_FLAGS(a6)       ; Set expunge flag
  557.      tst.w      LIB_OPENCNT(a6)              ; currently open?
  558.      bne.b      dev_Null                  ; yep, so just exit
  559.      ;
  560.      move.l   vb_SegList(a6),d0              ; get seglist ptr
  561.      movem.l  d0/a5/a6,-(sp)              ; save registers (save D0!)
  562.      ;
  563.      movea.l  a6,a5                   ; save base
  564.      movea.l  SysBase(pc),a6              ; get ExecBase
  565.      movea.l  a5,a1                   ; get base
  566.      jsr      _LVORemove(a6)              ; Remove it
  567.      ;
  568.      movea.l  a5,a1                   ; get base
  569.      moveq      #0,d0                   ; clear work
  570.      move.w   LIB_NEGSIZE(a5),d0              ; calculate
  571.      suba.w   d0,a1                   ;   memory address
  572.      add.w      LIB_POSSIZE(a5),d0              ;     and size
  573.      jsr      _LVOFreeMem(a6)              ; free it
  574.      ;
  575.      movem.l  (sp)+,d0/a5/a6              ; restore registers
  576.      rts                          ; return (seglist in D0!)
  577.      ;
  578.      ;      Device "ExtFunc" routine
  579.      ;
  580. dev_Null:
  581.      moveq      #0,d0                   ; set return code
  582.      rts                          ; return
  583.      ;
  584.      ;
  585.      ;
  586.      IFEQ      DEBUG-1
  587. printIO:
  588.      movem.l  d0-d7/a0-a6,-(sp)
  589.      addq.l   #1,ioctr
  590.      move.l   ioctr,-(sp)
  591.      move.l   a1,-(sp)
  592.      move.l   a0,-(sp)
  593.      pea.l      0$
  594.      pea.l      Name
  595.      DISABLE  TBE|INTF_PORTS
  596.      jsr      _SendText(pc)
  597.      ENABLE   TBE|INTF_PORTS
  598.      lea.l      20(sp),sp
  599.  
  600.      moveq      #0,d0
  601.      move.w   IO_COMMAND(a1),d0
  602.      move.l   d0,-(sp)
  603.      move.l   MN_REPLYPORT(a1),-(sp)
  604.      moveq      #0,d0
  605.      move.b   LN_TYPE(a1),d0
  606.      move.l   d0,-(sp)
  607.      pea.l      1$
  608.      pea.l      Name
  609.      DISABLE  TBE|INTF_PORTS
  610.      jsr      _SendText(pc)
  611.      ENABLE   TBE|INTF_PORTS
  612.      lea.l      20(sp),sp
  613.  
  614.      move.l   IO_LENGTH(a1),-(sp)
  615.      moveq      #0,d0
  616.      move.b   IO_ERROR(a1),d0
  617.      move.l   d0,-(sp)
  618.      move.b   IO_FLAGS(a1),d0
  619.      move.l   d0,-(sp)
  620.      pea.l      2$
  621.      pea.l      Name
  622.      DISABLE  TBE|INTF_PORTS
  623.      jsr      _SendText(pc)
  624.      ENABLE   TBE|INTF_PORTS
  625.      lea.l      20(sp),sp
  626.  
  627.      move.l   IO_EXTFLAGS(a1),-(sp)
  628.      move.l   IO_RBUFLEN(a1),-(sp)
  629.      move.l   IO_ACTUAL(a1),-(sp)
  630.      pea.l      3$
  631.      pea.l      Name
  632.      DISABLE  TBE|INTF_PORTS
  633.      jsr      _SendText(pc)
  634.      ENABLE   TBE|INTF_PORTS
  635.      lea.l      20(sp),sp
  636.  
  637.      moveq      #0,d0
  638.      move.b   IO_WRITELEN(a1),d0
  639.      move.l   d0,-(sp)
  640.      move.b   IO_READLEN(a1),d0
  641.      move.l   d0,-(sp)
  642.      move.l   IO_BAUD(a1),-(sp)
  643.      pea.l      4$
  644.      pea.l      Name
  645.      DISABLE  TBE|INTF_PORTS
  646.      jsr      _SendText(pc)
  647.      ENABLE   TBE|INTF_PORTS
  648.      lea.l      20(sp),sp
  649.  
  650.      moveq      #0,d0
  651.      move.w   IO_STATUS(a1),d0
  652.      move.l   d0,-(sp)
  653.      moveq      #0,d0
  654.      move.b   IO_SERFLAGS(a1),d0
  655.      move.l   d0,-(sp)
  656.      move.b   IO_STOPBITS(a1),d0
  657.      move.l   d0,-(sp)
  658.      pea.l      5$
  659.      pea.l      Name
  660.      DISABLE  TBE|INTF_PORTS
  661.      jsr      _SendText(pc)
  662.      ENABLE   TBE|INTF_PORTS
  663.      lea.l      20(sp),sp
  664.      movem.l  (sp)+,d0-d7/a0-a6
  665.      rts
  666. 0$     dc.b      '%ls - I/O     %8lx, Cnt = %ld',0
  667. 1$     DC.B      'Type    %8ld     ReplyPort %8lx    Command  %8ld',0
  668. 2$     DC.B      'Flags   %8lx     Error     %8ld    Length   %8ld',0
  669. 3$     DC.B      'Actual  %8ld     RBufLen   %8ld    ExtFlags %8lx',0
  670. 4$     DC.B      'Baud    %8ld     ReadLen   %8ld    WriteLen %8ld',0
  671. 5$     DC.B      'StopBit %8ld     SerFlags  %8lx    Status   %8lx',0
  672.      ;
  673.      ;
  674.      ;
  675. abortIOs dc.b      'Abort Start',0
  676. abortIOe dc.b      'Abort End',0
  677. abortIOa dc.b      'Aborting',0
  678. beginIOs dc.b      'Begin Start',0
  679. beginIOe dc.b      'Begin End',0
  680. openIO     dc.b      'Open IO',0
  681. replyIO  dc.b      'replyIO',0
  682.      ds.l      0
  683. ioctr     dc.l      0
  684.      ENDC
  685.      ;
  686. cmdTable dc.w      cmd_Invalid-cmdTable              ; CMD_INVALID
  687.      dc.w      cmd_Reset-cmdTable              ; CMD_RESET
  688.      dc.w      cmd_Read-cmdTable              ; CMD_READ
  689.      dc.w      cmd_Write-cmdTable              ; CMD_WRITE
  690.      dc.w      cmd_Invalid-cmdTable              ; CMD_UPDATE
  691.      dc.w      cmd_Clear-cmdTable              ; CMD_CLEAR
  692.      dc.w      cmd_Invalid-cmdTable              ; CMD_STOP
  693.      dc.w      cmd_Invalid-cmdTable              ; CMD_START
  694.      dc.w      cmd_Flush-cmdTable              ; CMD_FLUSH
  695.      dc.w      sdcmd_Query-cmdTable              ; SDCMD_QUERY
  696.      dc.w      sdcmd_Break-cmdTable              ; SDCMD_BREAK
  697. endTable dc.w      sdcmd_SetParams-cmdTable          ; SDCMD_SETPARAMS
  698.      ;
  699.      ;      Device BeginIO routine
  700.      ;
  701. dev_BeginIO:
  702.      move.l   a5,-(sp)                  ; save register
  703.      movea.l  a6,a5                   ; save base
  704.      movea.l  SysBase(pc),a6              ; get ExecBase
  705.      DEBUGIO  beginIOs
  706.      ;
  707.      move.b   #NT_MESSAGE,LN_TYPE(a1)          ; set type
  708.      clr.b      IO_ERROR(a1)                  ; clear error
  709.      ;
  710.      andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),IO_FLAGS(a1) ; clear flags
  711.      ;
  712.      move.w   IO_COMMAND(a1),d0              ; get command
  713.      add.w      d0,d0                   ; multiply by 2
  714.      cmpi.w   #endTable-cmdTable,d0           ; in range?
  715.      bhi.b      30$                      ; nope, error
  716.      ;
  717.      move.w   cmdTable(pc,d0.w),d0              ; get routine offset
  718.      jsr      cmdTable(pc,d0.w)              ; go do it
  719.      tst.l      d0                      ; I/O completed?
  720.      bne.b      19$                      ; nope, go return
  721.      ;
  722. 10$     DEBUGIO  beginIOe
  723.      btst.b   #IOB_QUICK,IO_FLAGS(a1)          ; need to reply?
  724.      bne.b      20$                      ; nope, branch
  725. 15$     jsr      _LVOReplyMsg(a6)              ; send it back
  726.      ;
  727. 19$     andi.b   #~(1<<IOB_QUICK),IO_FLAGS(a1)         ; clear quick bit
  728. 20$     movea.l  a5,a6                   ; restore base
  729.      movea.l  (sp)+,a5                  ; restore register
  730.      rts                          ; return
  731.      ;
  732. 30$     move.b   #IOERR_NOCMD,IO_ERROR(a1)          ; invalid command
  733.      bra.b      10$                      ; branch
  734.      ;
  735.      ;      Device AbortIO routine
  736.      ;
  737. dev_AbortIO:
  738.      move.l   a5,-(sp)                  ; save registers
  739.      movea.l  a6,a5                   ; save base
  740.      movea.l  SysBase(pc),a6              ; get ExecBase
  741.      DEBUGIO  abortIOs
  742.      ;
  743.      DISABLE                      ; disable interrupts
  744.      ;
  745.      move.b   IO_FLAGS(a1),d1
  746.      btst.b   #IOSERB_QUEUED,d1              ; queued request?
  747.      bne.b      40$                      ; yep, branch
  748.      ;
  749.      btst.b   #1<<IOSERB_ACTIVE,d1              ; active request?
  750.      bne.b      10$                      ; nope, just exit
  751.      ;
  752.      move.w   IO_COMMAND(a1),d0              ; get command
  753.      subq.w   #CMD_READ,d0                  ; was it a read?
  754.      beq.b      20$                      ; yep, go process
  755.      ;
  756.      subq.w   #CMD_WRITE-CMD_READ,d0          ; was it a write?
  757.      beq.b      30$                      ; yep, go process
  758.      ;
  759.      subq.w   #SDCMD_BREAK-CMD_WRITE,d0          ; was it a break?
  760.      beq.b      30$                      ; yep, go process
  761.      ;
  762.      ;      Fall through or enter from below
  763.      ;
  764. 10$     ENABLE                       ; enable ints and return
  765. 15$     movea.l  a5,a6                   ; restore base
  766.      movea.l  (sp)+,a5                  ; restore registers
  767.      rts                          ; return
  768.      ;
  769.      ;      Abort an active read request
  770.      ;
  771. 20$     clr.l      cr_IOReq                  ; no longer active
  772.      bra.b      50$                      ; go set flags
  773.      ;
  774.      ;      Abort an active write request
  775.      ;
  776. 30$     clr.l      cw_Length                  ; no longer active
  777.      clr.l      cw_IOReq                  ; no longer active
  778.      move.l   cw_Buffer(pc),d0              ; get buffer ptr
  779.      sub.l      IO_DATA(a1),d0              ; calc number of bytes xfer'd
  780.      move.l   d0,IO_ACTUAL(a1)              ; store
  781.      ;
  782.      ;      Force a TBE interrupt to get the next write going.
  783.      ;
  784.      move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  785.      bra.b      50$                      ; go set flags
  786.      ;
  787.      ;      Remove I/O from queue.
  788.      ;
  789. 40$     move.l   a1,-(sp)                  ; save ptr
  790.      jsr      _LVORemove(a6)              ; remove it
  791.      movea.l  (sp)+,a1                  ; restore ptr
  792.      ;
  793.      ;      Set error and return I/O
  794.      ;
  795. 50$     move.b   #IOERR_ABORTED,IO_ERROR(a1)          ; set error code
  796.      move.b   IO_FLAGS(a1),d1              ; get flags
  797.      ori.b      #1<<IOSERB_ABORT,d1              ; set abort flag
  798.      andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),d1  ; clear flags
  799.      move.b   d1,IO_FLAGS(a1)              ; store flags
  800.      DEBUGIO  abortIOe
  801.      btst.b   #1<<IOB_QUICK,d1              ; need to reply?
  802.      bne.b      10$                      ; nope, branch
  803.      jsr      _LVOReplyMsg(a6)              ; send it back
  804.      bra.b      10$                      ; branch to return
  805.      ;
  806.      ;      Abort all active/queued commands and reset internal state
  807.      ;
  808. cmd_Reset:
  809.      move.l   a1,-(sp)                  ; save I/O request
  810.      bsr.b      cmd_Flush                  ; go abort queued requests
  811.      ;
  812.      DISABLE                      ; disable interrupts
  813.      ;
  814.      ;      This must follow the DISABLE
  815.      ;
  816.      exg      a5,a6                   ; exchange base and ExecBase
  817.      ;
  818.      move.l   cr_IOReq(pc),d0              ; active read?
  819.      beq.b      10$                      ; nope, branch
  820.      movea.l  d0,a1                   ; get I/O request
  821.      bsr      dev_AbortIO                  ; go abort it
  822.      ;
  823.      ;
  824.      ;
  825. 10$     move.l   cw_IOReq(pc),d0              ; active write?
  826.      beq.b      20$                      ; nope, branch
  827.      movea.l  d0,a1                   ; get I/O request
  828.      bsr      dev_AbortIO                  ; go abort it
  829.      ;
  830. 20$     exg      a5,a6                   ; restore base and ExecBase
  831.      movea.l  (sp)+,a1                  ; restore I/O request
  832.      moveq      #8,d0                   ; get char size
  833.      move.b   d0,IO_READLEN(a1)              ; set read length
  834.      move.b   d0,IO_WRITELEN(a1)              ; set write length
  835.      moveq      #1,d0                   ; get stop bits
  836.      move.b   d0,IO_STOPBITS(a1)              ; set stop bits
  837.      move.l   vb_DefBaud(a5),IO_BAUD(a1)          ; set to default baud
  838.      move.l   vb_DefRBufLen(a5),IO_RBUFLEN(a1)    ; set to default buflen
  839.      bsr      internalReset               ; go set/verify parameters
  840.      move.b   d0,IO_ERROR(a1)              ; set error code
  841.      ENABLE                       ; enable interrupts
  842.      ;
  843.      ;      Set RC and return
  844.      ;
  845.      moveq      #0,d0                   ; I/O complete
  846.      rts                          ; return
  847.      ;
  848.      ;      Abort all "queued" requests, leaving all active alone.
  849.      ;
  850. cmd_Flush:
  851.      movem.l  a1/a2,-(sp)                  ; save registers
  852.      DISABLE                      ; disable interrupts
  853.      ;
  854.      ;      Abort all queued read requests.
  855.      ;
  856.      lea.l      readQ(pc),a2                  ; get ptr to read queue
  857.      bsr.b      20$                      ; branch to abort
  858.      ;
  859.      ;      Abort all queued write requests.
  860.      ;
  861.      lea.l      writeQ(pc),a2               ; get ptr to write queue
  862.      bsr.b      20$                      ; branch to abort
  863.      ;
  864.      ;      Enable, restore, and return to caller
  865.      ;
  866.      ENABLE                       ; enable interrupts
  867.      movem.l  (sp)+,a1/a2                  ; restore registers
  868.      ;
  869.      ;      Set RC and return
  870.      ;
  871.      moveq      #0,d0                   ; I/O complete
  872.      ;
  873.      ;      !!!NOTE!!!  In a mad attempt to save 2 bytes, this RTS is used
  874.      ;      by the subroutine below.  Why waste 'em?  B-)
  875.      ;
  876. 10$     rts                          ; return ( used below too!! )
  877.      ;
  878.      ;      Subroutine to remove and reply each I/O request.
  879.      ;
  880. 20$     movea.l  a2,a0                   ; get list ptr
  881.      jsr      _LVORemHead(a6)              ; get I/O request
  882.      tst.l      d0                      ; end of list?
  883.      beq.b      10$                      ; yep, branch to return
  884.      ;
  885.      movea.l  d0,a1                   ; get I/O request
  886.      andi.b   #~(1<<IOSERB_QUEUED),IO_FLAGS(a1)   ; no longer queued
  887.      moveq      #IOERR_ABORTED,d0              ; indicate aborted
  888.      move.b   d0,IO_ERROR(a1)              ; store status
  889.      ;
  890.      jsr      _LVOReplyMsg(a6)              ; send it back
  891.      bra.b      20$                      ; continue with next
  892.      ;
  893.      ;      Process a CMD_READ request.
  894.      ;
  895. cmd_Read:
  896.      ;
  897.      ;      Zero length requests just get returned.
  898.      ;
  899.      clr.l      IO_ACTUAL(a1)               ; clear bytes read
  900.      move.l   IO_LENGTH(a1),d0              ; get length and test
  901.      beq.b      20$                      ; yep, leave
  902.      ;
  903.      ;      This can be used to circumvent a bug in NComm 3.0 which
  904.      ;      references the buffer even when there was nothing read.
  905.      ;
  906.     IFNE     NCOMM
  907.      move.l   IO_DATA(A1),a0              ; get data pointer
  908.      clr.b      (a0)                      ; clear first byte in buffer
  909.     ENDC
  910.      ;
  911.      ;      The disable counter works just like exec's TDNestCnt field.  It's
  912.      ;      initialized to -1.  After incrementing, if it is 0, then we
  913.      ;      can attempt to process this request immediately.  If it's > 0,
  914.      ;      then we're already disabled and we must queue this request.
  915.      ;
  916.      addq.b   #1,disableRead              ; incr disable count
  917.      bgt.b      50$                      ; >0, already disabled
  918.      ;
  919.      ;      If we're already processing an request, this one has to wait
  920.      ;      until that one is done, so go queue it.
  921.      ;
  922.      move.l   cr_IOReq(pc),d1              ; have an active request?
  923.      bne.b      50$                      ; yep, go queue this one
  924.      ;
  925.      ;      If we don't have enough bytes to satisfy this request then go
  926.      ;      queue it.
  927.      ;
  928.      cmp.l      i_InCnt(pc),d0              ; length > current bytes?
  929.      bgt.b      50$                      ; yep, go queue it
  930.      ;
  931.      ;      Setup fields and go copy the data
  932.      ;
  933.      move.l   IO_DATA(a1),cr_OutPtr           ; get/set output ptr
  934.      move.l   IO_LENGTH(a1),cr_Length          ; get/set output count
  935.      bsr      copyData                  ; go copy 'em
  936.      moveq      #0,d0                   ; I/O complete
  937.      ;
  938.      ;      We're done, so back off the disable counter.
  939.      ;
  940. 10$     subq.b   #1,disableRead              ; decr disable count
  941.      ;
  942.      ;      Return to caller
  943.      ;
  944. 20$     rts                          ; return
  945.      ;
  946.      ;      Just set flags and queue.  The read interrupt will handle it.
  947.      ;
  948. 50$     ori.b      #1<<IOSERB_QUEUED,IO_FLAGS(a1)      ; indicate queued
  949.      ;
  950.      ;      Add this request to the end.
  951.      ;
  952.      DISABLE                      ; disable interrupts
  953.      lea.l      readQ(pc),a0                  ; get pointer to read queue
  954.      move.l   a1,-(sp)                  ; save I/O request
  955.      jsr      _LVOAddTail(a6)              ; and queue it
  956.      movea.l  (sp)+,a1                  ; restore I/O request
  957.      ENABLE                       ; enable interrupts
  958.      ;
  959.      ;      Indicate that this request was not handled immediatly.
  960.      ;
  961.      moveq      #1,d0                   ; I/O not complete
  962.      bra.b      10$                      ; branch to return
  963.      ;
  964.      ;      Process a CMD_WRITE request.
  965.      ;
  966. cmd_Write:
  967.      clr.l      IO_ACTUAL(a1)               ; clear bytes written
  968.      move.l   IO_LENGTH(a1),d0              ; get length and test
  969.      beq.b      wbexit                  ; yep, leave
  970.      ;
  971.      ;      Entry point for Break command and fall through from cmd_Write.
  972.      ;
  973. sdcmd_Break:
  974.      ;
  975.      ;      Just set flags and queue. The TBE interrupt will handle it.
  976.      ;
  977.      ori.b      #1<<IOSERB_QUEUED,IO_FLAGS(a1)      ; indicate queued
  978.      ;
  979.      ;      Protect.
  980.      ;
  981.      DISABLE                      ; disable interrupts
  982.      ;
  983.      ;      Add request to end of queue.
  984.      ;
  985.      lea.l      writeQ(pc),a0               ; get queue list ptr
  986.      move.l   a1,-(sp)                  ; save I/O request
  987.      jsr      _LVOAddTail(a6)              ; and queue it
  988.      movea.l  (sp)+,a1                  ; restore I/O request
  989.      ;
  990.      ;      If we have an active request, don't force interrupt.
  991.      ;
  992.      move.l   cw_IOReq(pc),d0              ; have an active request?
  993.      bne.b      10$                      ; yep, branch
  994.      ;
  995.      ;      Force a TBE interrupt to get the writes going.
  996.      ;
  997.      move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  998.      ;
  999.      ;      Enable, set RC and return to caller.
  1000.      ;
  1001. 10$     ENABLE                       ; enable interrupts
  1002.      moveq      #1,d0                   ; I/O not complete
  1003. wbexit     rts                          ; return
  1004.      ;
  1005.      ;      Resets serial read buffer
  1006.      ;
  1007.      ;      Since this routine is called internally, it must NOT reference
  1008.      ;      the I/O request.
  1009.      ;
  1010. cmd_Clear:
  1011.      DISABLE                      ; disable interrupts
  1012.      ;
  1013.      ;      Load registers
  1014.      ;
  1015.      move.l   vb_CurRBuf(a5),d0              ; get internal buffer ptr
  1016.      move.l   vb_CurRBufLen(a5),d1              ; and internal buffer len
  1017.      lea.l      i_BufPtr(pc),a0              ; get ptr internal control
  1018.      ;
  1019.      ;      Initialize global buffer variables
  1020.      ;
  1021.      move.l   d0,(a0)                  ; store buffer ptr
  1022.      move.l   d0,4(a0)                  ; set current input ptr
  1023.      move.l   d0,8(a0)                  ; set current output ptr
  1024.      add.l      d1,d0                   ; add buffer length
  1025.      move.l   d0,12(a0)                  ; store ptr to end of buffer
  1026.      clr.l      16(a0)                  ; clear byte cnt
  1027.      move.l   vb_CurBaud(a5),d0              ; get internal baud
  1028.      lsr.l      #4,d0                   ; divide by 16
  1029.      sub.l      d0,d1                   ; subtract from length
  1030.      move.l   d1,20(a0)                  ; set threshold
  1031.      ;
  1032.      ;      Enable, set RC and return.
  1033.      ;
  1034.      ENABLE                       ; enable interrupts
  1035.      moveq      #0,d0                   ; I/O complete
  1036.      rts                          ; return
  1037.      ;
  1038.      ;
  1039.      ;
  1040. cmd_Invalid
  1041.      move.b   #IOERR_NOCMD,IO_ERROR(a1)          ; set bad status
  1042.      moveq      #0,d0                   ; I/O complete
  1043.      rts                          ; return
  1044.      ;
  1045.      ;      Returns number of bytes currently in internal buffer and
  1046.      ;      current serial port status.
  1047.      ;
  1048.      ;      NOTE:  Not completely compatible with standard serial.device
  1049.      ;      since it doesn't return the upper byte of IO_STATUS.
  1050.      ;
  1051. sdcmd_Query:
  1052.      DISABLE                      ; disable interrupts
  1053.      moveq      #0,d0                   ; clear d0
  1054.      move.b   _ciabpra,d0                  ; get PR register
  1055.      andi.w   #~PRTMASK,d0                  ; zap printer bits
  1056.      ;
  1057.      ;      Uncomment the following to turn on the DSR bit.  This was done
  1058.      ;      for a user whose DSR pin did not function.
  1059.      ;
  1060.     IFNE SETDSR
  1061.      andi      #~(1<<CIAB_COMDSR),d0             ; set DSR
  1062.     ENDC
  1063.      ;
  1064.      ;
  1065.      ;
  1066.      move.w   d0,IO_STATUS(a1)              ; store status
  1067.      move.l   i_InCnt(pc),IO_ACTUAL(a1)          ; byte left in buffer
  1068.      ;
  1069.      ;      Enable, set RC and return.
  1070.      ;
  1071.      ENABLE                       ; enable interrupts
  1072.      moveq      #0,d0                   ; I/O complete
  1073.      rts                          ; return
  1074.      ;
  1075.      ;
  1076.      ;
  1077. sdcmd_SetParams:
  1078.      ;
  1079.      ;      Validate the read, write, and stop bit lengths.
  1080.      ;
  1081.      moveq      #8,d0                   ; get char length
  1082.      cmp.b      IO_READLEN(a1),d0              ; 8 bit chars for read?
  1083.      bne.b      40$                      ; nope, branch
  1084.      cmp.b      IO_WRITELEN(a1),d0              ; 8 bit chars for write?
  1085.      bne.b      40$                      ; nope, branch
  1086.      moveq      #1,d0                   ; get stop bits
  1087.      cmp.b      IO_STOPBITS(a1),d0              ; 1 stop bit?
  1088.      bne.b      40$                      ; nope, branch
  1089.      ;
  1090.      ;      Get and validate the baud rate.
  1091.      ;
  1092.      move.l   IO_BAUD(a1),d1              ; get baud from I/O req
  1093.      bne.b      20$                      ; specified?
  1094.      move.l   vb_CurBaud(a5),d1              ; get current baud from base
  1095.      bne.b      20$                      ; specified?
  1096.      move.l   vb_DefBaud(a5),d1              ; get default baud from base
  1097. 20$     cmpi.l   #110,d1                  ; too low?
  1098.      blt.b      40$                      ; error
  1099.      cmpi.l   #292000,d1                  ; too high?
  1100.      bgt.b      40$                      ; error
  1101.      ;
  1102.      ;      Get and validate the buffer length.
  1103.      ;
  1104.      move.l   IO_RBUFLEN(a1),d0              ; get buffer length
  1105.      bne.b      30$                      ; specified?
  1106.      move.l   vb_CurRBufLen(a5),d0              ; get current from base
  1107.      bne.b      30$                      ; specified?
  1108.      move.l   vb_DefRBufLen(a5),d0              ; get default from base
  1109.      ;
  1110. 30$     bsr.b      internalReset               ; go init baud and buffer
  1111. 35$     move.b   d0,IO_ERROR(a1)              ; set error code
  1112.      bne.b      39$
  1113.      ;
  1114.      ;      If the 7wire bit is not on, we will only use 3-wire protocol
  1115.      ;
  1116.      moveq      #0,d0                   ; clear flag
  1117.      btst.b   #SERB_7WIRE,IO_SERFLAGS(a1)          ; use 7wire handshaking?
  1118.      beq.b      36$                      ; nope, branch
  1119.      moveq      #1,d0                   ; set flag
  1120. 36$     move.b   d0,Handshake                  ; store flag
  1121.      ;
  1122.      ;      Set RC and return.
  1123.      ;
  1124. 39$     moveq      #0,d0                   ; I/O complete
  1125.      rts                          ; return
  1126.      ;
  1127.      ;      Invalid parm detected.
  1128.      ;
  1129. 40$     moveq      #SerErr_InvParam,d0              ; set error
  1130.      bra.b      35$                      ; go return
  1131.      ;
  1132.      ;      Reset the buffer and baud rate
  1133.      ;
  1134.      ;      Registers:  D0 = Buffer length
  1135.      ;              D1 = Baud rate
  1136.      ;
  1137. internalReset:
  1138.      ;
  1139.      ;      Disable interrupts.
  1140.      ;
  1141.      DISABLE                      ; disable interrupts
  1142.      ;
  1143.      ;      Save buffer length and go set serper.
  1144.      ;
  1145.      move.l   d0,-(sp)                  ; save D0
  1146.      move.l   d1,d0                   ; get baud rate
  1147.      bsr.b      setPeriod                  ; go set the serper register
  1148.      move.l   (sp)+,d0                  ; restore D0
  1149.      ;
  1150.      ;      Determine if the buffer length is adequate for the selected CPS.
  1151.      ;      If not, use 64K for the length.
  1152.      ;
  1153.      move.l   vb_CurBaud(a5),d1              ; get current baud
  1154.      lsr.l      #$3,d1                  ; divide by 8
  1155.      cmp.l      d1,d0                   ; buflen > CPS
  1156.      bhi.b      10$                      ; yep, branch
  1157.      move.l   #65536,d0                  ; else use 64K
  1158.      ;
  1159. 10$     bsr.b      allocBuf                  ; go allocate a new buffer
  1160.      ;
  1161.      ;      Enable and return to caller.
  1162.      ;
  1163.      ENABLE                       ; enable interrupts
  1164.      rts                          ; return (D0 has status)
  1165.      ;
  1166.      ;      Set serial period register
  1167.      ;
  1168. setPeriod:
  1169.      cmp.l      vb_CurBaud(a5),d0              ; current baud = new baud?
  1170.      beq.b      40$                      ; yep, just exit
  1171.      move.l   d0,vb_CurBaud(a5)              ; save new baud
  1172.      move.l   d0,d1                   ; save again
  1173.      lsl.l      #3,d0                   ; baud *= 8
  1174.      sub.l      d1,d0                   ; baud -= saved baud
  1175.      move.l   #25000000,d1                  ; get NTSC base
  1176.      cmpi.b   #50,PowerSupplyFrequency(a6)          ; PAL machine?
  1177.      bne.b      10$                      ; nope, branch
  1178.      move.l   #24772416,d1                  ; get PAL base
  1179. 10$     cmpi.l   #$FFFF,d0                  ; Divide
  1180.      ble.b      20$                      ;
  1181.      lsr.l      #5,d0                   ;
  1182.      divu.w   d0,d1                   ;
  1183.      andi.l   #$FFFF,d1                  ;
  1184.      lsr.l      #5,d1                   ;
  1185.      bra.b      30$                      ;
  1186. 20$     divu.w   d0,d1                   ;
  1187. 30$     move.w   d1,_serper                  ; set period value
  1188. 40$     rts
  1189.      ;
  1190.      ;      Allocate new internal buffer
  1191.      ;
  1192. allocBuf:
  1193.      cmp.l      vb_CurRBufLen(a5),d0              ; len same as previous?
  1194.      beq.b      10$                      ; yep, so no need to alloc
  1195.      move.l   d0,d1                   ; save length
  1196.      movem.l  d1/a1,-(sp)                  ; save registers
  1197.      moveq      #MEMF_PUBLIC,d1              ; public memory
  1198.      jsr      _LVOAllocMem(a6)              ; go allocate it
  1199.      movem.l  (sp)+,d1/a1                  ; restore registers
  1200.      tst.l      d0                      ; did we get it?
  1201.      beq.b      20$                      ; if zero, error
  1202.      bsr.b      freeBuf                  ; go free previous buffer
  1203.      move.l   d0,vb_CurRBuf(a5)              ; store new ptr
  1204.      move.l   d1,vb_CurRBufLen(a5)              ; and length
  1205.      bsr      cmd_Clear                  ; go setup buffer
  1206. 10$     moveq      #0,d0                   ; success
  1207.      rts                          ; return
  1208. 20$     moveq      #SerErr_BufErr,d0              ; set error status
  1209.      rts                          ; return
  1210.      ;
  1211.      ;      Free internal buffer
  1212.      ;
  1213. freeBuf:
  1214.      movem.l  d0-d1/a0-a1,-(sp)              ; save registers
  1215.      move.l   vb_CurRBuf(a5),d0              ; is one there?
  1216.      beq.b      10$                      ; no so branch
  1217.      movea.l  d0,a1                   ; get ptr
  1218.      move.l   vb_CurRBufLen(a5),d0              ; get length
  1219.      clr.l      vb_CurRBuf(a5)              ; clear
  1220.      clr.l      vb_CurRBufLen(a5)              ; clear
  1221.      jsr      _LVOFreeMem(a6)              ; free it
  1222. 10$     movem.l  (sp)+,d0-d1/a0-a1              ; restore registers
  1223.      rts                          ; return
  1224.      ;
  1225.      ;      Checks CTS status and if clear generates a TBE interrupt or
  1226.      ;      requeues the timer request.
  1227.      ;
  1228.      ;      Entered from Exec using the MsgPort callback.
  1229.      ;
  1230.      ;      Input:   a6 = ExecBase
  1231.      ;      Output:  none
  1232.      ;
  1233.      ;      No need to preserve d0/d1/a0/a1
  1234.      ;
  1235. timerRtn:
  1236.      lea.l      timerReq(pc),a1              ; get ptr to timer request
  1237.      jsr      _LVORemove(a6)              ; remove request
  1238.      ;
  1239.      ;      If we were breaking, reset adkcon.
  1240.      ;
  1241.      lea      _custom,a0                  ; get ptr to custom regs
  1242.      btst.b   #ADKB_UARTBRK,_adkconr(a0)          ; were we breaking?
  1243.      beq.b      10$                      ; nope, skip reset
  1244.      ;
  1245.      move.w   #ADKF_UARTBRK,_adkcon(a0)          ; stop breaking
  1246.      ;
  1247.      ;
  1248.      ;
  1249. 10$     move.b   Handshake(pc),d0              ; are we handshaking?
  1250.      beq.b      20$                      ; nope, generate interrupt
  1251.      btst.b   #CIAB_COMCTS,_ciabpra(a0)          ; clear to send?
  1252.      beq.b      20$                      ; yep, go start writing
  1253.      ;
  1254.      lea.l      timerReq(pc),a1              ; get ptr to timer request
  1255.      move.l   #1000,IOTV_TIME+TV_MICRO(a1)          ; wait for .001 seconds
  1256.      jsr      _LVOSendIO(a6)              ; go queue it
  1257.      bra.b      30$                      ; branch to return
  1258.      ;
  1259.      ;      CTS is clear so generate TBE interrupt to restart writing
  1260.      ;
  1261. 20$     move.w   #INTF_SETCLR|INTF_TBE,_intreq(a0)   ; set TBE interrupt
  1262. 30$     rts                          ; return
  1263.      ;
  1264.      ;      Non serial interrupt
  1265.      ;
  1266. level1n:
  1267.      movem.l  d0-d1/a0-a1/a5-a6,-(sp)          ; save registers
  1268.      lea      _custom,a0                  ; get ptr to custom regs
  1269.      move.w   intenar(a0),d1              ; get enabled interrupts
  1270.      and.w      intreqr(a0),d1              ; and in requested interrupts
  1271.      movea.l  SysBase(pc),a6              ; get ExecBase
  1272.      ;
  1273.      btst      #INTB_DSKBLK,d1              ; Disk block done?
  1274.      beq.b      10$                      ; nope, branch
  1275.      ;
  1276.      movem.l  IVDSKBLK(a6),a1/a5              ; get data and code ptrs
  1277.      pea.l      20$(pc)                  ; push return address
  1278.      jmp      (a5)                      ; jump to routine
  1279.      ;
  1280. 10$     btst      #INTB_SOFTINT,d1              ; software interrupt?
  1281.      beq.b      20$                      ; nope, branch
  1282.      ;
  1283.      movem.l  IVSOFTINT(a6),a1/a5              ; get data and code ptrs
  1284.      pea.l      20$(pc)                  ; push return address
  1285.      jmp      (a5)                      ; jump to routine
  1286.      ;
  1287. 20$     movem.l  (sp)+,d0-d1/a0-a1/a5-a6          ; restore registers
  1288.      rte                          ; return
  1289.      ;
  1290.      ;      Level 1 interrupt handler
  1291.      ;
  1292. level1:
  1293.      btst.b   #INTB_INTEN,_intenar              ; interrupts enabled?
  1294.      beq.b      35$                      ; nope, ignore
  1295.      btst.b   #INTB_SOFTINT,_intreqr+1          ; software interrupt?
  1296.      bne.b      level1n                  ; nope, branch
  1297.      btst.b   #INTB_TBE,_intreqr+1              ; xmit buffer empty?
  1298.      beq.b      level1n                  ; nope, invoke old handler
  1299.      ;
  1300.      ;      Handle "Transmit Buffer Empty" interrupt (write)
  1301.      ;
  1302.      move.w   #INTF_TBE,_intreq              ; clear interrupt
  1303.      move.l   d0,-(sp)                  ; save D0 (faster than MOVEM)
  1304.      move.l   a0,-(sp)                  ; save A0 (faster than MOVEM)
  1305.      ;
  1306.      ;      If we're not handshaking, bypass it.
  1307.      ;
  1308. 10$     move.b   Handshake(pc),d0              ; are we handshaking?
  1309.      beq.b      20$                      ; nope, skip CTS test
  1310.      btst.b   #CIAB_COMCTS,_ciabpra           ; clear to send?
  1311.      bne.b      40$                      ; nope, branch
  1312.      ;
  1313.      ;      If cw_Length goes negative here, we are either done with a
  1314.      ;      request or we were called as a result of a fake interrupt
  1315.      ;      to force us to get the next request going.
  1316.      ;
  1317. 20$     subq.l   #1,cw_Length                  ; decr write length
  1318.      blt.b      60$                      ; < zero, done, branch
  1319.      ;
  1320.      ;      Currently processing a request.
  1321.      ;
  1322.      movea.l  cw_Buffer(pc),a0              ; get buffer ptr
  1323.      move.w   #256,d0                  ; set stop bit
  1324.      move.b   (a0)+,d0                  ; get next byte
  1325.      move.l   a0,cw_Buffer                  ; store buffer ptr
  1326.      move.w   d0,_serdat                  ; store in serdat reg
  1327.      ;
  1328. 30$     movea.l  (sp)+,a0                  ; restore registers
  1329.      move.l   (sp)+,d0                  ; restore registers
  1330. 35$     rte                          ; return
  1331.      ;
  1332.      ;      Queue a timer request to recheck CTS status
  1333.      ;
  1334. 40$     movem.l  d1/a1/a6,-(sp)              ; save registers
  1335.      lea.l      timerReq(pc),a1              ; get ptr to timer request
  1336.      move.l   #1000,IOTV_TIME+TV_MICRO(a1)          ; wait for .001 seconds
  1337.      movea.l  SysBase(pc),a6              ; get ExecBase
  1338.      jsr      _LVOSendIO(a6)              ; queue the request
  1339.      movem.l  (sp)+,d1/a1/a6              ; restore registers
  1340.      bra.b      30$                      ; go return
  1341.      ;
  1342.      ;      There aren't anymore requests, so clear and exit
  1343.      ;
  1344. 50$     clr.l      cw_Length-Start(a6)              ; clear length
  1345.      clr.l      cw_IOReq-Start(a6)              ; clear
  1346.      movem.l  (sp)+,d1/a1/a6              ; restore registers
  1347.      bra.b      30$                      ; go return
  1348.      ;
  1349.      ;      Write request completed
  1350.      ;
  1351. 60$     movem.l  d1/a1/a6,-(sp)              ; save registers
  1352.      ;
  1353.      move.l   cw_IOReq(pc),d0              ; active I/O request?
  1354.      beq.b      70$                      ; nope, branch
  1355.      ;
  1356.      ;      Reply it and setup for next
  1357.      ;
  1358.      movea.l  d0,a1                   ; get I/O request
  1359.      andi.b   #~(1<<IOSERB_ACTIVE),IO_FLAGS(a1)   ; no longer active
  1360.      clr.b      IO_ERROR(a1)                  ; no error
  1361.      movea.l  SysBase(pc),a6              ; get ExecBase
  1362.      DEBUGIO  replyIO
  1363.      jsr      _LVOReplyMsg(a6)              ; return I/O request
  1364.      ;
  1365. 70$     lea.l      Start(pc),a6                  ; get section base
  1366.      ;
  1367.      lea.l      writeQ(pc),a1               ; get ptr to write queue
  1368.      move.l   (a1),a0                  ; get head of list
  1369.      move.l   (a0),d0                  ; get successor
  1370.      beq.b      50$                      ; end of list? yep, branch
  1371.      ;
  1372.      ;      Remove the node from the list
  1373.      ;
  1374.      move.l   d0,(a1)                  ; make new head
  1375.      exg.l      d0,a0                   ; swap nodes
  1376.      move.l   a1,LN_PRED(a0)              ; store predecessor
  1377.      ;
  1378.      move.l   d0,a1                   ; get I/O request
  1379.      ;
  1380.      ;      If it's a BREAK, then branch to process as such.
  1381.      ;
  1382.      cmpi.w   #SDCMD_BREAK,IO_COMMAND(a1)          ; BREAK command?
  1383.      beq.b      100$                      ; yep, branch
  1384.      ;
  1385.      ;      Check for absolute length
  1386.      ;
  1387.      move.l   IO_DATA(a1),a0              ; get data ptr
  1388.      moveq      #-1,d1                  ; get value
  1389.      move.l   IO_LENGTH(a1),d0              ; get length
  1390.      cmp.l      d1,d0                   ; length = -1?
  1391.      bne.b      90$                      ; nope, skip scan
  1392.      ;
  1393.      ;      Scan the data for null to calc the length
  1394.      ;
  1395.      move.l   a0,d1                   ; save data ptr
  1396.     IFNE NEWCODE
  1397.     ; Buffer size is multiple of 64bytes so we can safely move a long
  1398. 80$     move.l   (a0),d0                  ; move a long into d0
  1399.      tst.b      d0                      ; does it equal 0? (first byte)
  1400.      beq.b      84$                      ; yep, finish
  1401.      lsr.l      #8,d0                   ; shift too second byte
  1402.      tst.b      d0                      ; does it equal 0? (second byte)
  1403.      beq.b      83$                      ; yep, finish
  1404.      lsr.l      #8,d0                   ; shift too third byte
  1405.      tst.b      d0                      ; does it equal 0? (third byte)
  1406.      beq.b      82$                      ; yep, finish
  1407.      lsr.l      #8,d0                   ; shift too fourth byte
  1408.      tst.b      d0                      ; does it equal 0? (fourth byte)
  1409.      beq.b      81$                      ; yep, finish
  1410.      addq.l   #4,a0                   ; update pointer
  1411.      bra.b      80$                      ; loop
  1412. 81$
  1413.      addq.l   #1,a0                   ; inc pointer
  1414. 82$
  1415.      addq.l   #1,a0                   ; inc pointer
  1416. 83$
  1417.      addq.l   #1,a0                   ; inc pointer
  1418. 84$
  1419.      addq.l   #1,a0                   ; inc pointer
  1420.      suba.l   d1,a0                   ; calc # of bytes
  1421.      move.l   a0,d0                   ; xfer
  1422.     ELSE
  1423. 80$     tst.b      (a0)+                   ; does it equal 0?
  1424.      bne.b      80$                      ; nope, so continue
  1425.      suba.l   d1,a0                   ; calc # of bytes+1
  1426.      move.l   a0,d0                   ; xfer
  1427.      subq.l   #1,d0                   ; calc # of bytes
  1428.     ENDC
  1429.      movea.l  d1,a0                   ; get data ptr
  1430.      ;
  1431. 90$     move.l   d0,IO_ACTUAL(a1)              ; go ahead and set it
  1432.      move.b   IO_FLAGS(a1),d1
  1433.      andi.b   #~(1<<IOSERB_QUEUED),d1          ; no longer queued
  1434.      ori.b      #1<<IOSERB_ACTIVE,d1              ; make it active
  1435.      move.b   d1,IO_FLAGS(a1)
  1436.      move.l   d0,cw_Length-Start(a6)          ; store length
  1437.      move.l   a0,cw_Buffer-Start(a6)          ; store buffer ptr
  1438.      move.l   a1,cw_IOReq-Start(a6)           ; store I/O request ptr
  1439.      ;
  1440.      movem.l  (sp)+,d1/a1/a6              ; restore registers
  1441.      bra      10$                      ; go start request
  1442.      ;
  1443.      ;      Start the BREAK.
  1444.      ;
  1445. 100$     move.b   IO_FLAGS(a1),d1
  1446.      andi.b   #~(1<<IOSERB_QUEUED),d1          ; no longer queued
  1447.      ori.b      #1<<IOSERB_ACTIVE,d1              ; make it active
  1448.      move.b   d1,IO_FLAGS(a1)
  1449.      clr.l      cw_Length-Start(a6)              ; clear length
  1450.      move.l   a1,cw_IOReq-Start(a6)           ; store I/O request ptr
  1451.      move.w   #ADKF_SETCLR|ADKF_UARTBRK,_adkcon   ; start break
  1452.      move.l   IO_BRKTIME(a1),d0              ; get break time
  1453.      lea.l      timerReq(pc),a1              ; get ptr to timer request
  1454.      move.l   d0,IOTV_TIME+TV_MICRO(a1)          ; set the timeout
  1455.      movea.l  SysBase(pc),a6              ; get ExecBase
  1456.      jsr      _LVOSendIO(a6)              ; queue the request
  1457.      movem.l  (sp)+,d1/a1/a6              ; restore registers
  1458.      bra      30$                      ; go exit
  1459.      ;
  1460.      ;      Non serial interrupt
  1461.      ;
  1462. level5n:
  1463.      movem.l  d0-d1/a0-a1/a5-a6,-(sp)          ; save registers
  1464.      lea      _custom,a0                  ; get ptr to custom regs
  1465.      move.w   intenar(a0),d1              ; get enabled interrupts
  1466.      and.w      intreqr(a0),d1              ; and in requested interrupts
  1467.      movea.l  SysBase(pc),a6              ; get ExecBase
  1468.      btst      #INTB_DSKSYNC,d1              ; Disk synchronized?
  1469.      beq.b      10$                      ; nope, branch
  1470.      movem.l  IVDSKSYNC(A6),a1/a5              ; get data and code ptrs
  1471.      jsr      (a5)                      ; branch to routine
  1472. 10$     movem.l  (sp)+,d0-d1/a0-a1/a5-a6          ; restore registers
  1473.      rte                          ; return
  1474.      ;
  1475.      ;      Default Level 5 handler
  1476.      ;
  1477. level5:
  1478.      btst.b   #INTB_INTEN,_intenar              ; interrupts enabled?
  1479.      beq.b      45$                      ; nope, ignore
  1480.      btst.b   #INTB_RBF,_intreqr              ; receive buffer full?
  1481.      beq.b      level5n                  ; nope, invoke old handler
  1482.      ;
  1483.      move.l   a0,-(sp)                  ; save registers
  1484.      move.l   a1,-(sp)                  ; save registers
  1485.      lea      _custom,a1                  ; get ptr to custom regs
  1486.      ;
  1487. 10$     btst.b   #7,_serdatr(a1)              ; Overrun?
  1488.      bne.b      50$                      ; yep, branch
  1489.      ;
  1490. 20$     movea.l  i_BufIn(pc),a0              ; get current ptr
  1491.      move.b   _serdatr+1(a1),(a0)+              ; store received byte
  1492.      move.w   #INTF_RBF,_intreq(a1)           ; clear RBF interrupt
  1493.      addq.l   #1,i_InCnt                  ; incr bytes in buffer
  1494.      ;
  1495.      cmpa.l   i_BufEnd(pc),a0              ; hit end of buffer?
  1496.      beq.b      60$                      ; yep, branch
  1497. 30$     move.l   a0,i_BufIn                  ; store input ptr
  1498.      ;
  1499.      subq.l   #1,i_Thresh                  ; close to full buffer?
  1500.      beq.b      70$                      ; yep, branch
  1501.      ;
  1502. 40$     btst.b   #INTB_RBF,_intreqr(a1)          ; receive buffer full?
  1503.      bne.b      10$                      ; yep, go get another byte
  1504.      ;
  1505.      movea.l  (sp)+,a1                  ; restore registers
  1506.      movea.l  (sp)+,a0                  ; restore registers
  1507. 45$     rte                          ; return
  1508.      ;
  1509.      ;      We've missed some data, so set overrun flag.
  1510.      ;
  1511. 50$     addq.b   #1,Overrun                  ; set overrun flag
  1512.      bra.b      20$                      ; continue
  1513.      ;
  1514.      ;      Hit physical end of buffer, so wrap to the start of the buffer.
  1515.      ;
  1516. 60$     movea.l  i_BufPtr(pc),a0              ; get buffer ptr
  1517.      bra.b      30$                      ; continue
  1518.      ;
  1519.      ;      Hit buffer threshold, so tell other end not to send any more
  1520.      ;      data.
  1521.      ;
  1522. 70$     tst.b      Handshake                  ; are we handshaking?
  1523.      beq.b      40$                      ; nope, skip RTS
  1524.      ori.b      #1<<CIAB_COMRTS,_ciabpra          ; block further input
  1525.      bra.b      40$                      ; go return
  1526.      ;
  1527.      ;
  1528.      ;
  1529. level2:
  1530.      ;
  1531.      ;      If there's nothing in the buffer, there's no point in going
  1532.      ;      any further.
  1533.      ;
  1534.      move.l   i_InCnt(pc),d0              ; anything in the buffer?
  1535.      bne.b      20$                      ; yep, branch
  1536. 10$     moveq      #0,d0                   ; set Z flag
  1537.      rts                          ; return
  1538.      ;
  1539.      ;      If we've been "disabled" then get out.
  1540.      ;
  1541. 20$     move.b   disableRead(pc),d0              ; internally disabled?
  1542.      bge.b      10$                      ; yep, get out of here
  1543.      lea.l      Start(pc),a5                  ; get base
  1544.      ;
  1545.      ;      If we have an active request, branch down and try to fulfill it.
  1546.      ;
  1547.      move.l   cr_IOReq(pc),d0              ; get and test active I/O
  1548.      bne.b      30$                      ; nzero, active, branch
  1549.      ;
  1550.      ;      Get first node in list and test if empty.
  1551.      ;
  1552.      move.l   (a1),a0                  ; get head of list
  1553.      move.l   (a0),d0                  ; get successor
  1554.      beq.b      10$                      ; end of list? yep, branch
  1555.      ;
  1556.      ;      Remove the node from the list
  1557.      ;
  1558.      move.l   d0,(a1)                  ; make new head
  1559.      exg.l      d0,a0                   ; swap nodes
  1560.      move.l   a1,LN_PRED(a0)              ; store predecessor
  1561.      ;
  1562.      ;      Setup fields for processing a read request
  1563.      ;
  1564.      movea.l  d0,a1                   ; get I/O request
  1565.      move.b   IO_FLAGS(a1),d1
  1566.      andi.b   #~(1<<IOSERB_QUEUED),d1          ; no longer queued
  1567.      ori.b      #1<<IOSERB_ACTIVE,d1              ; make it active
  1568.      move.b   d1,IO_FLAGS(a1)
  1569.      move.l   a1,cr_IOReq-Start(a5)           ; store I/O request
  1570.      move.l   IO_DATA(a1),cr_OutPtr-Start(a5)     ; get/set output ptr
  1571.      move.l   IO_LENGTH(a1),cr_Length-Start(a5)   ; get/set output count
  1572.      ;
  1573.      ;      Process an active I/O request
  1574.      ;
  1575. 30$     movea.l  SysBase(pc),a6              ; get ExecBase
  1576.      move.l   d0,a1                   ; get I/O request
  1577.      bsr      copyData                  ; go copy 'em
  1578.      tst.l      d0                      ; done with request?
  1579.      beq.b      10$                      ; nope, branch
  1580.      ;
  1581.      ;      the request has been satisfied, so return it.
  1582.      ;
  1583.      clr.l      cr_IOReq-Start(a5)              ; clear request
  1584.      andi.b   #~(1<<IOSERB_ACTIVE),IO_FLAGS(a1)   ; no longer active
  1585.      DEBUGIO  replyIO
  1586.      jsr      _LVOReplyMsg(a6)              ; return I/O
  1587.      bra.b      10$
  1588.      ;
  1589.      ;      Registers:
  1590.      ;      Entry:   A1        Ptr to I/O Request
  1591.      ;           A6        ExecBase
  1592.      ;      Exit:    D0        ZERO - request not done, do not reply it
  1593.      ;                NZERO - request done, reply it
  1594.      ;
  1595. copyData:
  1596.      ;
  1597.      ;      Process an active I/O request (or fall through from above)
  1598.      ;
  1599.      movem.l  d2-d5/a1-a5,-(sp)              ; save registers
  1600.      lea.l      Start(pc),a5                  ; get base
  1601.      movea.l  a1,a4                   ; get I/O request
  1602.      ;
  1603.      movea.l  i_BufOut(pc),a2              ; get current bufout ptr
  1604.      movea.l  cr_OutPtr(pc),a3              ; get current output ptr
  1605.      move.l   cr_Length(pc),d2              ; get current bytes needed
  1606.      move.l   i_InCnt(pc),d3              ; get current bytes in buffer
  1607.      ;
  1608.      ;      If we don't have enough bytes to satisfy the request,
  1609.      ;      set the length to the number of bytes we do have.
  1610.      ;
  1611.      cmp.l      d2,d3                   ; enuf to satisfy request?
  1612.      bge.b      15$                      ; yep, so branch
  1613.      move.l   d3,d2                   ; # to copy = # in buffer
  1614.      bra.b      15$                      ; branch to loop entry
  1615.      ;
  1616.      ;      Start of copy loop.
  1617.      ;
  1618. 10$     movea.l  i_BufPtr(pc),a2              ; reset bufout to start
  1619.      ;
  1620.      ;      Entry point of copy loop.
  1621.      ;
  1622. 15$     move.l   d2,d3                   ; xfer # of bytes to copy
  1623.      ;
  1624.      ;      If the copy will extend past the end of the buffer, we can
  1625.      ;      only copy the number of bytes to the end this go around.
  1626.      ;
  1627.      move.l   i_BufEnd(pc),d0              ; get ptr to end of buf
  1628.      sub.l      a2,d0                   ; calc # of bytes to end
  1629.      cmp.l      d0,d3                   ; # to copy < # to end?
  1630.      blt.b      20$                      ; yep, branch
  1631.      move.l   d0,d3                   ; get bytes to end
  1632.      ;
  1633.      ;      Registers:
  1634.      ;
  1635.      ;      A2 = pointer from which data will be copied
  1636.      ;      A3 = pointer to which data will be copied
  1637.      ;      D2 = number of bytes that need to be copied
  1638.      ;      D3 = number of bytes to copy this iteration
  1639.      ;
  1640.     IFNE EOFCODE
  1641. 20$     btst.b   #SERB_EOFMODE,IO_SERFLAGS(a4)       ; EOFMODE requested?
  1642.      beq.b      30$                      ; nope, just go copy
  1643.      ;
  1644.      ;      EOFMODE was specified so copy characters 1 at a time until
  1645.      ;      we hit an EOF character, the output butter has filled, or
  1646.      ;      the input buffer has drained.
  1647.      ;
  1648.      move.l   d3,d0                   ; get length
  1649.      ;
  1650. 21$     move.b   (a2)+,d1                  ; get byte
  1651.      ; This way the term char IS copied (cause of crash?)
  1652.      move.b   d1,(a3)+                  ; put in output buffer
  1653.      ;
  1654.      lea.l      IO_TERMARRAY(a4),a1              ; get termarry ptr
  1655.      cmp.b      (a1),d1                  ; found term char?
  1656.      bge.b      22$                      ; possibly, branch
  1657.      cmp.b      1(a1),d1                  ; found term char?
  1658.      bge.b      22$                      ; possibly, branch
  1659.      cmp.b      2(a1),d1                  ; found term char?
  1660.      bge.b      22$                      ; possibly, branch
  1661.      cmp.b      3(a1),d1                  ; found term char?
  1662.      bge.b      22$                      ; possibly, branch
  1663.      cmp.b      4(a1),d1                  ; found term char?
  1664.      bge.b      22$                      ; possibly, branch
  1665.      cmp.b      5(a1),d1                  ; found term char?
  1666.      bge.b      22$                      ; possibly, branch
  1667.      cmp.b      6(a1),d1                  ; found term char?
  1668.      bge.b      22$                      ; possibly, branch
  1669.      cmp.b      7(a1),d1                  ; found term char?
  1670.      bgt.b      23$                      ; nope, branch
  1671. 22$     beq.b      24$                      ; term char found?
  1672.      ;
  1673.      ;      Didn't find a term character, so continue with the copy loop
  1674.      ;
  1675. 23$
  1676.      subq.l   #1,d0                   ; decr length counter
  1677.      bne.b      21$                      ; continue if more
  1678.      bra.b      40$                      ; done with copy, branch
  1679.      ;
  1680.      ;      We've found a termination character.
  1681.      ;
  1682. 24$     clr.l      cr_Length-Start(a5)              ; done with request
  1683.      bra.b      50$                      ; branch
  1684.     ELSE
  1685. 20$
  1686.     ENDC
  1687.      ;
  1688.      ;      EOFMODE not specified, so just do a bulk copy.
  1689.      ;
  1690.      ;      XXX POSSIBLE SPEEDUP XXX
  1691.      ;
  1692.      ;      For short copies it would be quicker to have a simple inline
  1693.      ;      loop, but what's short???  It would be different by CPU.
  1694.      ;
  1695. 30$     move.l   d3,d0                   ; get length
  1696.      movea.l  a3,a1                   ; where to put it
  1697.      movea.l  a2,a0                   ; where to get it
  1698.      jsr      _LVOCopyMem(a6)              ; copy it
  1699.      adda.l   d3,a2                   ; update bufout
  1700.      adda.l   d3,a3                   ; update outptr
  1701.      ;
  1702.      ;      Fall through and entered from EOFMODE loop
  1703.      ;
  1704.      ;      If the following calculation results in a value greater than
  1705.      ;      zero, then we have a buffer wrap and need to process the
  1706.      ;      remaining bytes at the beginning of the buffer.
  1707.      ;
  1708. 40$     sub.l      d3,d2                   ; calc bytes left to copy
  1709.      bgt      10$                      ; >0, more to copy, branch
  1710.      ;
  1711.      ;
  1712.      ;
  1713. 50$     move.l   a3,d1                   ; get outptr
  1714.      sub.l      cr_OutPtr(pc),d1              ; calc length
  1715.      move.l   a3,cr_OutPtr-Start(a5)          ; update outptr
  1716.      ;
  1717.      ;      Update output ptr and I/O request
  1718.      ;
  1719.      move.l   a2,i_BufOut-Start(a5)           ; store bufout ptr
  1720.      add.l      d1,IO_ACTUAL(a4)              ; update I/O request
  1721.      ;
  1722.      ;      Update number of bytes left in the buffer.
  1723.      ;
  1724.      sub.l      d1,i_InCnt-Start(a5)              ; calc bytes left in buffer
  1725.      ;
  1726.      ;      If the threshold becomes positive here, then, if requested,
  1727.      ;      tell the other end that it's okay to start sending more data.
  1728.      ;
  1729.      add.l      d1,i_Thresh-Start(a5)           ; calc thresh and test
  1730.      ble.b      60$                      ; <= 0, need more data, skip
  1731.      tst.b      Handshake-Start(a5)              ; are we handshaking?
  1732.      beq.b      60$                      ; nope, skip RTS
  1733.      andi.b   #~(1<<CIAB_COMRTS),_ciabpra            ; ready to receive more data
  1734.      ;
  1735.      ;      Set error if we've had any overruns.
  1736.      ;
  1737. 60$     tst.b      Overrun-Start(a5)              ; did overrun occur?
  1738.      beq.b      70$                      ; nope, branch
  1739.      clr.b      Overrun-Start(a5)              ; reset overrun flag
  1740.      move.b   #SerErr_LineErr,IO_ERROR(a4)          ; set error code
  1741.      ;
  1742.      ;      Calc number of bytes left to copy.  If the result is greater
  1743.      ;      than zero, then we have more to copy so return an incomplete
  1744.      ;      status.
  1745.      ;
  1746. 70$     moveq      #0,d0                   ; assume I/O incomplete
  1747.      sub.l      d1,cr_Length-Start(a5)          ; update length and test
  1748.      bgt.b      90$                      ; >0, more to do, branch
  1749.      ;
  1750.      ;      We've completed the I/O request either by copying the requested
  1751.      ;      of bytes or by finding an EOFMODE character, so return a "reply"
  1752.      ;      status.
  1753.      ;
  1754.      moveq      #1,d0                   ; indicate reply
  1755.      ;
  1756.      ;      Restore and exit
  1757.      ;
  1758. 90$     movem.l  (sp)+,d2-d5/a1-a5              ; restore registers
  1759.      rts                          ; return (status in D0)
  1760.      ;
  1761.      ;      Align data
  1762.      ;
  1763.      CNOP      0,4
  1764.      ;
  1765.      ;
  1766.      ;
  1767. Init:
  1768.      DC.L      sizeof_Base8n1
  1769.      DC.L      funcTab
  1770.      DC.L      dataTab
  1771.      DC.L      InitRoutine
  1772.      ;
  1773.      ;
  1774.      ;
  1775. funcTab:
  1776.      DC.W      -1
  1777.      DC.W      dev_Open-funcTab
  1778.      DC.W      dev_Close-funcTab
  1779.      DC.W      dev_Expunge-funcTab
  1780.      DC.W      dev_Null-funcTab
  1781.      DC.W      dev_BeginIO-funcTab
  1782.      DC.W      dev_AbortIO-funcTab
  1783.      DC.W      -1
  1784.      ;
  1785.      ;
  1786.      ;
  1787. dataTab:
  1788.      INITBYTE LN_TYPE,NT_DEVICE
  1789.      INITLONG LN_NAME,Name
  1790.      INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  1791.      INITWORD LIB_VERSION,VERSION
  1792.      INITWORD LIB_REVISION,REVISION
  1793.      INITLONG LIB_IDSTRING,IdString
  1794.      DC.W      0
  1795.      ;
  1796.      ;      String Constants
  1797.      ;
  1798. miscresource:
  1799.      DC.B      "misc.resource",0
  1800. timerdevice:
  1801.      DC.B      "timer.device",0
  1802. intuitlib:
  1803.      DC.B      "intuition.library",0
  1804. Name:
  1805.      DC.B      "8n1.device",0
  1806. IdString:
  1807.      VSTRING
  1808.      ;
  1809.      ;      End of checksummed area.  (Realigns data too!)
  1810.      ;
  1811. ENDTag:
  1812.      CNOP      0,4
  1813.      ;
  1814.      ;      Global SysBase (Use instead of AbsExecBase for speed)
  1815.      ;
  1816. SysBase:
  1817.      DC.L      0
  1818.      ;
  1819.      ;      Internal buffer tracking (DO NOT CHANGE THE ORDER!!!!)
  1820.      ;
  1821. i_BufPtr:
  1822.      DC.L      0
  1823. i_BufIn:
  1824.      DC.L      0
  1825. i_BufOut:
  1826.      DC.L      0
  1827. i_BufEnd:
  1828.      DC.L      0
  1829. i_InCnt:
  1830.      DC.L      0
  1831. i_Thresh:
  1832.      DC.L      0
  1833.      ;
  1834.      ;      Used while processing a read request.
  1835.      ;
  1836. cr_IOReq:
  1837.      DC.L      0
  1838. cr_OutPtr:
  1839.      DC.L      0
  1840. cr_Length:
  1841.      DC.L      0
  1842.      ;
  1843.      ;      List head for read requests
  1844.      ;
  1845. readQ:
  1846.      DC.L      readQ+MLH_TAIL
  1847.      DC.L      0
  1848.      DC.L      readQ
  1849.      ;
  1850.      ;      Write control.
  1851.      ;
  1852. cw_Length:
  1853.      DC.L      0
  1854. cw_Buffer:
  1855.      DC.L      0
  1856. cw_IOReq:
  1857.      DC.L      0
  1858.      ;
  1859.      ;      List head for write requests
  1860.      ;
  1861. writeQ:
  1862.      DC.L      writeQ+MLH_TAIL
  1863.      DC.L      0
  1864.      DC.L      writeQ
  1865.      ;
  1866.      ;
  1867.      ;
  1868. timerPort:
  1869.      DC.L      0                      ; LN_SUCC
  1870.      DC.L      0                      ; LN_PRED
  1871.      DC.B      NT_MSGPORT                  ; LN_TYPE
  1872.      DC.B      0                      ; LN_PRI
  1873.      DC.L      0                      ; LN_NAME
  1874.      DC.B      3                      ; MP_FLAGS (undoc'ed)
  1875.      DC.B      0                      ; MP_SIGBIT
  1876.      DC.L      timerRtn                  ; MP_SIGTASK
  1877.      DC.L      timerPort+MP_MSGLIST+LH_TAIL          ; LH_HEAD
  1878.      DC.L      0                      ; LH_TAIL
  1879.      DC.L      timerPort+MP_MSGLIST              ; LH_TAILPRED
  1880.      DC.B      0                      ; LH_TYPE
  1881.      DC.B      0                      ; LH_pad
  1882.      DC.W      0                      ; long align
  1883.      ;
  1884.      ;
  1885.      ;
  1886. timerReq:
  1887.      DC.L      0                      ; LN_SUCC
  1888.      DC.L      0                      ; LN_PRED
  1889.      DC.B      NT_MESSAGE                  ; LN_TYPE
  1890.      DC.B      0                      ; LN_PRI
  1891.      DC.L      0                      ; LN_NAME
  1892.      DC.L      timerPort                  ; MN_REPLYPORT
  1893.      DC.W      IOTV_SIZE                  ; MN_LENGTH
  1894.      DC.L      0                      ; IO_DEVICE
  1895.      DC.L      0                      ; IO_UNIT
  1896.      DC.W      TR_ADDREQUEST               ; IO_COMMAND
  1897.      DC.B      0                      ; IO_FLAGS
  1898.      DC.B      0                      ; IO_ERROR
  1899.      DC.L      0                      ; TV_SECS
  1900.      DC.L      0                      ; TV_MICROS
  1901.      ;
  1902.      ;
  1903.      ;
  1904. VBInterrupt:
  1905.      DC.L      0                      ; LN_SUCC
  1906.      DC.L      0                      ; LN_PRED
  1907.      DC.B      NT_INTERRUPT                  ; LN_TYPE
  1908.      DC.B      0                      ; LN_PRI
  1909.      DC.L      Name                      ; LN_NAME
  1910.      DC.L      readQ                   ; IS_DATA
  1911.      DC.L      level2                  ; IS_CODE
  1912.      ;
  1913.      ;      Global flags
  1914.      ;
  1915. Overrun:
  1916.      DC.B      0
  1917. Handshake:
  1918.      DC.B      1
  1919. disableRead:
  1920.      DC.B      -1
  1921.      ;
  1922.      ;
  1923.      ;
  1924.      END
  1925.  
  1926.