home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume6 / glib / part08 / mac-mdr.a < prev    next >
Encoding:
Text File  |  1989-05-14  |  14.1 KB  |  541 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ; $Id: mac-mdr.a,v 1.6 89/05/06 17:13:33 lee Exp $
  3. ;
  4. ; midi driver
  5. ;
  6. ; also includes a millisecond relative-time counter with 5 mS resolution
  7. ;
  8. ; Steven A. Falco  - moss!saf
  9. ; 3/6/87
  10. ; $Log:    mac-mdr.a,v $
  11. ; Revision 1.6  89/05/06  17:13:33  lee
  12. ; rel. to comp.sources.misc
  13. ;
  14. ; portions taken from article in nov 85 mactutor by Kirk Austin
  15. ;
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17. ;
  18.         BRANCH    SHORT        ; use short displacements
  19.         CASE    ON        ; be case-sensitive
  20.         STRING    PASCAL        ; use pascal-style strings
  21. ;
  22. ; timer constants
  23. ;
  24. TIME_INC    EQU    5        ; granularity of timer
  25. MS5        EQU    3917        ; VIA tics per 5 ms (1.2766 uS each)
  26. ;
  27. T1VEC        EQU    24        ; lvl1 trap table offset
  28. MAX_BYTE    EQU    $FF        ; like it says
  29. VIAT1EN        EQU    $C0        ; enable timer 1 interrupts
  30. VIAT1DI        EQU    $40        ; diable timer 1  interrupts
  31. VIARUN        EQU    $40        ; make T1 free-run
  32. VIASTOP        EQU    $3F        ; put T1 in single-shot mode
  33. ;
  34. ; queue lengths
  35. ;
  36. TxQSize        EQU    $100        ; transmit buffer length
  37. RxQSize        EQU    $100        ; receive buffer length
  38. ;
  39. ; queue state flags
  40. ;
  41. midi_em        EQU    $FF        ; queue is empty
  42. midi_ne        EQU    $00        ; queue is not empty
  43. ;
  44. ; The following are stack offsets given that an item is passed
  45. ; by the MPW C compiler and LINK/UNLK is used. DANGER!!!  MPW C
  46. ; always passes in a long value.
  47. ;
  48. ; Note that in Pascal, a byte is passed as a short rather than a long...
  49. ; so Get_Byte would be $9.  Also, in C, the caller cleans up, while in
  50. ; Pascal the callee cleans up.
  51. ;
  52. Get_Byte    EQU    $000B
  53. Get_Short    EQU    $000A
  54. Get_Long    EQU    $0008
  55. ;
  56. ; select one based on oscillator frequency used in hardware
  57. ;
  58. ;C_baud        EQU    %01000100    ; 500 KHz
  59. C_baud        EQU    %10000100    ; 1 MHz
  60. ;C_baud        EQU    %11000100    ; 2 MHz
  61. ;
  62. ; misc controls in SCC chip
  63. ;
  64. No_W_Req    EQU    0
  65. Rx_off        EQU    %11000000
  66. Tx_off        EQU    %01100010
  67. TRxC        EQU    %00101000
  68. Brgen_off    EQU    0
  69. Rx_on        EQU    %11000001
  70. Tx_on        EQU    %01101010
  71. DCD_int        EQU    %00001000
  72. RstExtSt    EQU    %00010000
  73. EnInt        EQU    %00010011
  74. MIntEn        EQU    %00001010
  75. EnMoInt        EQU    %00000001
  76. No_Vec        EQU    %00000010
  77. aReset        EQU    %10000000
  78. rstTBE        EQU    $28
  79. rstEERR        EQU    $30
  80. NoData        EQU    $FFFF
  81. ;
  82. ; misc offsets in trap table
  83. ;
  84. arxIO        EQU    24
  85. atxIO        EQU    16
  86. aspRC        EQU    28
  87. ;
  88. ; SR masks for interrupt control
  89. ;
  90. spl3        EQU    $0300        ;set interrupt level to 3
  91. ;
  92. ; SCC registers
  93. ;
  94. SCC0        EQU    0
  95. SCC1        EQU    1
  96. SCC2        EQU    2
  97. SCC3        EQU    3
  98. SCC4        EQU    4
  99. SCC5        EQU    5
  100. SCC6        EQU    6
  101. SCC7        EQU    7
  102. SCC8        EQU    8
  103. SCC9        EQU    9
  104. SCC10        EQU    10
  105. SCC11        EQU    11
  106. SCC12        EQU    12
  107. SCC13        EQU    13
  108. SCC14        EQU    14
  109. SCC15        EQU    15
  110. ;
  111. ; macro to enqueue a byte to be transmitted (can't use a subroutine
  112. ; 'cause we expect the stack to be in a certain state!)
  113. ;
  114.         MACRO
  115.         TxEnqueue
  116.         MOVE    TxByteIn(A5),D0        ; where to put it (offset)
  117.         LEA    TxQueue(A5),A2        ; base of queue
  118.         MOVE.B    Get_Byte(A6),0(A2,D0)    ; copy it from the stack to the queue
  119.         ADDQ    #1,D0            ; bump offset
  120.         CMP    #TxQSize,D0        ; did it wrap?
  121.         BNE    @1            ; nope
  122.         MOVE    #0,D0            ; you betcha'
  123. @1        MOVE    D0,TxByteIn(A5)        ; replace it
  124.         ENDM
  125. ;
  126. ; macro for delay (SCC is slow compared to 68000)
  127. ;
  128.         MACRO
  129.         Delay
  130.         MOVE.L    (SP),(SP)
  131.         ENDM
  132. ;
  133. ; macro to load an SCC register (double moves are on purpose - slow down)
  134. ;
  135.         MACRO
  136.         Lscc    &sreg,&val
  137.         MOVE.B    &sreg,D0
  138.         MOVE.B    D0,(A0)
  139.         Delay
  140.         MOVE.B    &val,D0
  141.         MOVE.B    D0,(A0)
  142.         Delay
  143.         ENDM
  144. ;
  145. ; debug traps for Macsbug
  146. ;
  147. Dbgb        OPWORD    $A9FF        ; breakpoint
  148. Dbgs        OPWORD    $ABFF        ; print string and breakpoint
  149. ;
  150. ; debug macro
  151. ;
  152.         MACRO
  153.         Dbs    &string
  154. ;        PEA    &string
  155. ;        Dbgs
  156.         ENDM
  157. ;
  158. ; chip addresses and offsets
  159. ;
  160.         PRINT    OFF
  161.         INCLUDE    'SysEqu.a'
  162.         PRINT    ON
  163. ;
  164. ; this code must always be resident so we load it in Main segment to
  165. ; guarantee that.  (Ever call an interrupt handler that wasn't resident?)
  166. ;
  167.         SEG    'Main'
  168. ;
  169. ; global area
  170. ;
  171.         EXPORT (midi_txst, midi_rxst, midi_time):DATA
  172. ;
  173. CtlOffset    DS.W    1            ; channel control offset
  174. DataOffset    DS.W    1            ; channel data offset
  175. ChnReset    DS.B    1            ; SCC channel reset select
  176. RxIntOffset    DS.W    1            ; for dispatch table
  177. TxIntOffset    DS.W    1            ; likewise
  178. SpecRecCond    DS.W    1            ; and one more
  179. ;
  180. TxQueue        DS.B    TxQSize            ; Tx data queue
  181. midi_txst    DS.B    1            ; the queue state
  182. TxByteIn    DS.W    1            ; offset for enqueue
  183. TxByteOut    DS.W    1            ; offset for dequeue
  184. ;
  185. RxQueue        DS.B    RxQSize            ; and the Rx queue
  186. midi_rxst    DS.B    1            ; the queue state
  187. RxByteIn    DS.W    1            ; offset for enqueue
  188. RxByteOut    DS.W    1            ; offset for dequeue
  189. ;
  190. midi_time    DS.L    1            ; mS relative-time value
  191. old_via_v    DS.L    1            ; old VIA vector
  192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  193. ; The following are interrupt handlers.  The system saves registers
  194. ; D0-D3 and A0-A3 so we don't...
  195. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  196.  
  197. ;
  198. ; handler for time increment task
  199. ;
  200. up_it        PROC    ENTRY
  201.         MOVEM.L    A5,-(SP)        ; we also use D0-D1/A0
  202.         MOVE.L    CurrentA5,A5        ; we need the globals
  203. ;        
  204.         Dbs    #'time interrupt'
  205. ;    
  206.         MOVE.L    VIA,A0            ; via base register
  207.         MOVE.L    #vT1C,D0        ; low byte of counter
  208.         MOVE.B    0(A0,D0),D1        ; reading clears the interrupt
  209. ;        
  210.         MOVEQ    #TIME_INC,D0        ; how much?
  211.         ADD.L    D0,midi_time(A5)    ; kick it up
  212. ;        
  213.         MOVEM.L (SP)+,A5
  214.         RTS
  215.         ENDP
  216. ;
  217. ; interrupt handler for received characters
  218. ;
  219. RxIntHand    PROC    ENTRY
  220.         MOVEM.L    A5,-(SP)        ; we also use D0-D1/A0-A2
  221.         MOVE.L    CurrentA5,A5        ; we need the globals
  222.         MOVE.L    SCCRd,A0        ; hardware addresses
  223.         MOVE.L    SCCWr,A1
  224. ;
  225.         Dbs    #'rx interrupt'
  226. ;
  227.         MOVE    DataOffset(A5),D0    ; ... offset
  228.         MOVE.B    0(A0,D0),D1        ; read the data - it's here given the interrupt
  229.         Delay
  230.         LEA    RxQueue(A5),A2        ; base of destination queue
  231.         MOVE    RxByteIn(A5),D0        ; ... offset
  232.         MOVE.B    D1,0(A2,D0)        ; store it
  233.         MOVE.B    #midi_ne,midi_rxst(A5)    ; guaranteed not empty
  234.         ADDQ    #1,D0            ; we filled one
  235.         CMP    #RxQSize,D0        ; wrapped it?
  236.         BNE    @1            ; not yet
  237.         MOVE    #0,D0            ; yes - reset to top
  238. ;
  239. @1        MOVE    D0,RxByteIn(A5)        ; replace the offset
  240. ;
  241.         MOVEM.L    (SP)+,A5        ; restore context
  242.         RTS                ; back to user
  243.         ENDP
  244. ;
  245. ; interrupt handler for transmitted characters
  246. ;
  247. TxIntHand    PROC    ENTRY
  248.         MOVEM.L    A5,-(SP)        ; we also use D0-D1/A0-A2
  249.         MOVE.L    CurrentA5,A5
  250.         MOVE.L    SCCRd,A0        ; read base
  251.         MOVE.L    SCCWr,A1        ; write base
  252. ;
  253.         Dbs    #'tx interrupt'
  254. ;
  255.         TST.B    midi_txst(A5)        ; is there something to write?
  256.         BEQ    @1            ; no - pity
  257.         MOVE    CtlOffset(A5),D0    ; offset to control
  258.         MOVE.B    #rstTBE,0(A1,D0)    ; we saw the empty...
  259.         Delay
  260.         BRA    TxIExit            ; nothing to be done
  261. ;
  262. @1        MOVE    TxByteOut(A5),D0    ; offset of something to send
  263.         LEA    TxQueue(A5),A2        ; base of queue
  264.         MOVE    DataOffset(A5),D1    ; offset to hardware
  265.         MOVE.B    0(A2,D0),0(A1,D1)    ; move it out
  266.         Delay
  267.         ADDQ    #1,D0            ; we used it up
  268.         CMP    #TxQSize,D0        ; wrapped?
  269.         BNE    @2            ; no...
  270.         MOVE    #0,D0            ; 'fraid so
  271. ;
  272. @2        MOVE    D0,TxByteOut(A5)    ; remember position
  273.         MOVE    TxByteIn(A5),D1        ; see about the input side
  274.         CMP    D0,D1            ; now empty?
  275.         BNE    TxIExit            ; no - just exit
  276.         MOVE.B    #midi_em,midi_txst(A5)    ; it's empty
  277. ;
  278. TxIExit
  279.         MOVEM.L    (SP)+,A5        ; be polite
  280.         RTS
  281.         ENDP
  282. ;
  283. ; a stub for special conditions - we sort-of handle them
  284. ;
  285. Stub        PROC    ENTRY
  286.         MOVEM.L    A5,-(SP)        ; we also use A0-A1
  287.         MOVE.L    CurrentA5,A5
  288.         MOVE.L    SCCRd,A0        ; read base
  289.         MOVE.L    SCCWr,A1        ; write base
  290. ;
  291.         Dbs    #'stub interrupt'
  292. ;
  293.         MOVE    CtlOffset(A5),D0    ; offset to control
  294.         MOVE.B    #rstEERR,0(A1,D0)    ; we saw the botch, clear it
  295.         Delay
  296.         MOVEM.L    (SP)+,A5
  297.         RTS
  298.         ENDP
  299. ;
  300. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  301. ; The following routines interface to MPW C.  It considers D0-D1/A0-A1 as
  302. ; scratch.  So do we.  Returned values are placed in D0 (32 bits always)
  303. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  304. ;
  305. ; init routine - must call this first to set up stuff!
  306. ;
  307. midi_init    PROC    EXPORT
  308.         MOVE    #aCtl,CtlOffset(A5)
  309.         MOVE    #aData,DataOffset(A5)
  310.         MOVE.B    #aReset,ChnReset(A5)
  311.         MOVE    #arxIO,RxIntOffset(A5)
  312.         MOVE    #atxIO,TxIntOffset(A5)
  313.         MOVE    #aspRC,SpecRecCond(A5)
  314. ;
  315.         MOVE    SR,-(SP)        ; save interrupts
  316.                         ; we use D0-D1/A0-A1
  317.         ORI    #spl3,SR        ; interrupts of 4 or better only        
  318. ;
  319.         Dbs    #'init routine'
  320. ;
  321.         MOVE.L    SCCRd,A1        ; get base address
  322.         ADD    CtlOffset(A5),A1    ; ... control
  323.         MOVE.B    (A1),D0            ; dummy read to clear SCC WR0
  324.         Delay
  325. ;
  326. ; set up SCC channel A
  327. ;
  328.         MOVE.L    SCCWr,A0        ; another base address
  329.         ADD    CtlOffset(A5),A0    ; ... control
  330.         Lscc    #SCC9,ChnReset(A5)    ; reset channel
  331.         Lscc    #SCC4,#C_baud        ; set clock rate
  332.         Lscc    #SCC1,#No_W_Req        ; no write request
  333.         Lscc    #SCC3,#Rx_off        ; turn it off
  334.         Lscc    #SCC5,#Tx_off        ; him too
  335.         Lscc    #SCC9,#No_Vec        ; not vectored interrupts
  336.         Lscc    #SCC11,#TRxC        ; set clock source
  337.         Lscc    #SCC14,#Brgen_off    ; no break gen
  338.         Lscc    #SCC3,#Rx_on        ; now turn channel back on
  339.         Lscc    #SCC5,#Tx_on        ; these on too
  340.         Lscc    #SCC15,#DCD_int        ; Mr. Mousie on
  341.         Lscc    #SCC0,#RstExtSt        ; reset ext status
  342.         Lscc    #SCC0,#RstExtSt        ; reset ext status
  343.         Lscc    #SCC1,#EnInt        ; enable interrupts
  344.         Lscc    #SCC9,#MIntEn        ; master interrupt
  345. ;
  346. ; install trap vectors
  347. ;
  348.         MOVE.L    #Lvl2DT,A0        ; dispatch table
  349.         MOVE    RxIntOffset(A5),D0    ; ... offset
  350.         LEA    RxIntHand,A1        ; pointer to handler
  351.         MOVE.L    A1,0(A0,D0)        ; load the pointer into the dispatch table
  352.         MOVE    TxIntOffset(A5),D0    ; ... offset
  353.         LEA    TxIntHand,A1        ; another pointer
  354.         MOVE.L    A1,0(A0,D0)        ; load it
  355.         MOVE    SpecRecCond(A5),D0    ; ... offset
  356.         LEA    Stub,A1            ; dummy handler
  357.         MOVE.L    A1,0(A0,D0)        ; load it
  358. ;
  359. ; clear queues
  360. ;
  361.         CLR    RxByteIn(A5)        ; clear circ. buffer pointers
  362.         CLR    RxByteOut(A5)
  363.         MOVE.B    #midi_em,midi_rxst(A5)    ; mark it empty
  364.         CLR    TxByteIn(A5)
  365.         CLR    TxByteOut(A5)
  366.         MOVE.B    #midi_em,midi_txst(A5)    ; mark it empty
  367. ;
  368. ; get the timer going
  369. ;
  370.         CLR.L    midi_time(A5)        ; start clean
  371. ;
  372. ;        save old interrupt vector - write ours
  373.         MOVE.L    #Lvl1DT,A0        ; via trap table base
  374.         MOVEQ    #T1VEC,D0        ; offset to t1 trap
  375.         MOVE.L    0(A0,D0),old_via_v(A5)    ; save the old one
  376.         LEA    up_it,A1        ; our trap handler
  377.         MOVE.L    A1,0(A0,D0)        ; set our handler in place
  378. ;
  379.         MOVE.L    VIA,A0            ; via base register
  380. ;
  381. ;        set the mode of operation - free running
  382.         MOVE.L    #vACR,D0        ; offset to ACR
  383.         MOVE.B    0(A0,D0),D1        ; read old acr value
  384.         AND.B    #VIASTOP,D1        ; drop any existing T1 bits
  385.         OR.B    #VIARUN,D1        ; set the free-run bit
  386.         MOVE.B    D1,0(A0,D0)        ; put it back
  387. ;
  388. ;        set the latches and counters
  389.         MOVE.L    #vT1C,D0        ; low byte of timer
  390.         MOVE.B    #(MS5 ** MAX_BYTE),0(A0,D0) ; write low byte
  391.         MOVE.L    #vT1CH,D0        ; high byte of timer
  392.         MOVE.B    #((MS5 >> 8) ** MAX_BYTE),0(A0,D0) ; write high byte
  393. ;
  394.         MOVE.L    #vIER,D0        ; enable/disable register
  395.         MOVE.B    #VIAT1EN,0(A0,D0)    ; enable that interrupt!
  396. ;
  397.         MOVE    (SP)+,SR        ; interrupts on
  398.         RTS
  399.         ENDP
  400. ;
  401. ; midi_tx - send a byte to the midi port (we expect the stack to contain a long)
  402. ;
  403. midi_tx        PROC    EXPORT
  404.         LINK    A6,#0            ; remember where our argument is
  405.         MOVE    SR,-(SP)        ; save interrupts
  406.         MOVEM.L    A2,-(SP)        ; we also use D0/A0-A1
  407.         ORI    #spl3,SR        ; interrupts of 4 or better only
  408. ;
  409.         Dbs    #'transmit routine'
  410. ;
  411.         TST.B    midi_txst(A5)        ; check the flag
  412.         BNE    TxQE            ; queue empty - send direct
  413.         ; something here - just add to queue
  414.         TxEnqueue
  415.         BRA    TxExit            ; go home    
  416. ;
  417. TxQE        ; must write directly to device (maybe)
  418.         MOVE.L    SCCRd,A0        ; read base
  419.         MOVE.L    SCCWr,A1        ; write base
  420.         MOVE    CtlOffset(A5),D0    ; ... offset
  421.         BTST.B    #txBE,0(A0,D0)        ; is the device ready
  422.         BNE    FirstByte        ; yes - do direct write
  423.         ; device busy - add to queue - interrupt will wake up
  424.         ; handler and send it out when the device is free
  425.         TxEnqueue
  426.         MOVE.B    #midi_ne,midi_txst(A5)    ; now it's not empty
  427.         BRA    TxExit            ; done
  428. ;
  429. FirstByte    ; it really wants this byte...
  430.         MOVE    DataOffset(A5),D0    ; ... offset
  431.         Delay
  432.         MOVE.B    Get_Byte(A6),0(A1,D0)    ; copy it from the stack to the device
  433.         Delay
  434. ;
  435. TxExit        ; clean up the world
  436.         MOVEM.L    (SP)+,A2        ; restore registers
  437.         MOVE    (SP)+,SR        ; and interrupts
  438.         UNLK    A6
  439.         RTS                ; in C, the caller cleans up
  440.         ENDP
  441. ;
  442. ; midi_rx - get a byte from the port (leave it in D0 as a long)
  443. ; We return -1 if nothing is available
  444. ;
  445. midi_rx        PROC    EXPORT
  446.         ; don't need link 'cause nothing is passed in
  447.         MOVE    SR,-(SP)        ; save the interrupts
  448.         MOVEM.L    D2/A2,-(SP)        ; we also use D0-D1/A0-A1
  449.         ORI    #spl3,SR        ; interrupts of 4 or better only
  450. ;
  451.         Dbs    #'receive routine'
  452. ;
  453.         TST.B    midi_rxst(A5)        ; any data available?
  454.         BEQ    @1            ; yes
  455.         MOVE.W    #NoData,D0        ; no-data flag
  456.         EXT.L    D0            ; sign-extend it
  457.         BRA    RxExit            ; C returns stuff in D0
  458. ;
  459. @1        MOVE    RxByteOut(A5),D2    ; ... offset
  460.         LEA    RxQueue(A5),A2        ; and base
  461.         CLR.L    D0            ; start off empty
  462.         MOVE.B    0(A2,D2),D0        ; get the byte
  463.         ADDQ    #1,D2            ; up the offset
  464.         CMP    #RxQSize,D2        ; wrapped around?
  465.         BNE    @2            ; not yet
  466.         MOVE    #0,D2            ; yes - reset it to the top
  467. ;
  468. @2        MOVE    D2,RxByteOut(A5)    ; and save it
  469.         MOVE    RxByteIn(A5),D1        ; now look at the input side
  470.         CMP    D2,D1            ; is the queue now empty?
  471.         BNE    RxExit            ; no - don't worry about it
  472.         MOVE.B    #midi_em,midi_rxst(A5)    ; yes - set the flag
  473. ;
  474. RxExit
  475.         MOVEM.L    (SP)+,D2/A2        ; restore registers
  476.         MOVE    (SP)+,SR        ; and interrupts
  477.         RTS
  478.         ENDP
  479. ;
  480. ; reset the modem port - must call before quitting because the trap
  481. ; vectors will be invalid once we exit!!!
  482. ;
  483. midi_reset    PROC    EXPORT
  484.         MOVE    #aCtl,CtlOffset(A5)    ; prepare globals
  485.         MOVE    #aData,DataOffset(A5)
  486.         MOVE.B    #aReset,ChnReset(A5)
  487.         MOVE    #arxIO,RxIntOffset(A5)
  488.         MOVE    #atxIO,TxIntOffset(A5)
  489.         MOVE    #aspRC,SpecRecCond(A5)
  490. ;
  491.         MOVE    SR,-(SP)        ; save interrupts
  492.                         ; we use A0
  493.         ORI    #spl3,SR        ; interrupts of 4 or better only
  494. ;
  495.         Dbs    #'reset routine'
  496. ;
  497.         MOVE.L    SCCWr,A0        ; base for writing
  498.         ADD    CtlOffset(A5),A0    ; and the offset
  499. ;
  500.         Lscc    #SCC9,ChnReset(A5)    ; reset channel
  501.         Lscc    #SCC15,#DCD_int        ; Mr. Mousie stays on
  502.         Lscc    #SCC0,#RstExtSt        ; reset ext status
  503.         Lscc    #SCC0,#RstExtSt        ; reset ext status
  504.         Lscc    #SCC1,#EnMoInt        ; enable mouse interrupts
  505.         Lscc    #SCC9,#MIntEn        ; master interrupt
  506. ;
  507. ; pull out the plug on the timer
  508. ;
  509. ;        first disable interrupts
  510.         MOVE.L    VIA,A0            ; base of via
  511.         MOVE.L    #vIER,D0        ; interrupt control reg.
  512.         MOVE.B    #VIAT1DI,0(A0,D0)    ; kill the interrupts
  513. ;
  514. ;        next set back to single shot mode
  515.         MOVE.L    #vACR,D0        ; offset to ACR
  516.         MOVE.B    0(A0,D0),D1        ; read old acr value
  517.         AND.B    #VIASTOP,D1        ; drop any existing T1 bits
  518.         MOVE.B    D1,0(A0,D0)        ; put it back
  519. ;
  520. ;        set the latches to 0
  521.         MOVE.L    #vT1C,D0        ; lower latch/counter
  522.         CLR.B    0(A0,D0)        ; clear it too
  523.         MOVE.L    #vT1CH,D0        ; offset to upper latch/counter
  524.         CLR.B    0(A0,D0)        ; clear it
  525. ;
  526. ;        restore old trap vector
  527.         MOVE.L    #Lvl1DT,A0        ; dispatch table
  528.         MOVEQ    #T1VEC,D0        ; vector offset
  529.         MOVE.L    old_via_v(A5),0(A0,D0)    ; reset the vector
  530. ;
  531. ; We don't turn the other vectors back to where they were...
  532. ; We also don't leave any of our interrupts enabled so it's OK
  533. ;
  534.         MOVE    (SP)+,SR        ; interrupts on
  535.         RTS
  536.         ENDP
  537. ;
  538.         END
  539.  
  540.