home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / scnote / tbltdrvr.017 / TbltDrvr.a < prev   
Encoding:
Text File  |  1989-04-02  |  14.8 KB  |  354 lines

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    Sample 'ADBS' Resource
  5. *
  6. *    TbltDrvr
  7. *
  8. *    TbltDrvr.a    -    Assembler Source
  9. *
  10. *    Copyright ⌐ 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    
  14. *                1.00            04/89
  15. *
  16. *    Components:
  17. *                TbltDrvr.a        April 1, 1989
  18. *
  19. *    *******************************************************************
  20. *    
  21. *    ADBS resources are loaded and executed at boot time (before
  22. *    INIT 31), and are made of two main parts, the installation/
  23. *    initialization code and the the actual driver. 
  24. *    
  25. *    In this example, the installation portion allocates memory
  26. *    in the system heap for the service routine and the "optional
  27. *    data area". It installs the driver using the ADB Mgr call SetADBInfo.
  28. *    
  29. *    Generally speaking, ADB devices are intended to be user input devices.
  30. *    The ADB Manager polls the bus every 11 milliseconds to see if a device
  31. *    has new user input data. This is accomplished by sending a talk R0 command
  32. *    to the last active device. The last active device is the last device that
  33. *    had data to send to the host. If another device has data, it can request
  34. *    a poll by sending a service request signal to the host.
  35. *    
  36. *    When a device has responded to a poll, the ADB Manager will call the driver
  37. *    to process the data. This is done a interrupt time (level 1), and
  38. *    The driver is passed the data, by getting a pointer to a pascal string
  39. *    which contains the actual data.
  40. *
  41. *    In this example, the data is in the form of a pointing device's coordinates
  42. *    and button(s) state(s). When the driver gets the data, it stores the 
  43. *    coordinate information in RawMouse and MTemp. We stuff both RawMouse and MTemp,
  44. *    because the tablet is an "absolute" device. It also checks the state of
  45. *    the button, against MBState, and if there has been a change, it will update
  46. *    MBState, and post either a mouseUp or mouseDown event, as appropriate.
  47. *
  48. *    NOTE:    This code demonstrate how to move the cursor position. This information
  49. *            is meant for input device drivers only, this technique should not
  50. *            be used by applications to move the cursor around. It's bad user
  51. *            interface, and nobody likes a bad user interface, so Just Say No!
  52. *    
  53. *    Build commands:
  54. *    
  55. *    asm TbltDrvr.a -lo TbltDrvr.a.lst -l
  56. *    link TbltDrvr.a.o -o 'MrBootDisk:System Folder:System' -rt ADBS=4 -ra =16
  57. *
  58. ***********************************************************************
  59.  
  60.                     STRING    ASIS
  61.                     PRINT    OFF
  62.                     INCLUDE 'Traps.a'
  63.                     INCLUDE 'SysEqu.a'
  64.                     PRINT    ON
  65.  
  66. **************************** Driver Offsets ***************************
  67.  
  68.                                                 ;this is the structure of the "optional data area"
  69. StartDataArea        EQU        0
  70. TabltID                EQU        StartDataArea        ;ID so Apps can find this data (should contain 'TBLT')
  71.                                                 ; this identifies the structure for this driver,
  72.                                                 ; if your structure is different, you should have 
  73.                                                 ; a different ID.
  74. R0Count                EQU        TabltID+4            ;count byte of Pascal data string returned by ADB
  75. R0Data                EQU        R0Count+1            ;data can be up to 8 bytes (but reference from R0Count
  76.                                                 ; for even address access)
  77. R1Count                EQU        R0Data+8            ;count byte of Pascal data string returned by ADB
  78.                                                 ;data can be up to 8 bytes (reference from R1Data
  79. R1Data                EQU        R1Count+1            ; for even address access)
  80. MyFlags                EQU        R1Data+8            ;hi nibble are flags, bit 7 = update system cursor (zero = yes)
  81.                                                 ;bit 6 = new R0 data, bit 5 = new R1 data (1 = new)
  82.                                                 ;lo nibble is the address we ended up at (set by installer)
  83. MyTalkR0            EQU        MyFlags+1            ;This byte used to build a talk R0 cmd byte with our new address
  84. RsrvdPtr            EQU        MyTalkR0+1            ;Back door for Apple (you never know╔)
  85. Scratch                EQU        RsrvdPtr+4            ;scratch area
  86. ADBSvRt                EQU        Scratch+2            ;pointer to service routine
  87. ADBDtAr                EQU        ADBSvRt+4            ;pointer to optional data area
  88. NextjADBProc        EQU        ADBDtAr+4            ;a place to keep pointer to next guy in jADBProc chain
  89. EndDataArea            EQU        NextjADBProc+4        ;this is my end marker & how big it is
  90.  
  91. ******************************** Equates ******************************
  92.  
  93. TalkR0                EQU        $0C                    ;ADB Talk register zero (installer fills in the device address in upper nibble)
  94. TalkR1                EQU        $0D                    ;ADB Talk register one (installer fills in the device address in upper nibble)
  95. DoSysCrsr            EQU        $80                    ;mask for "update system cursor?" flag (in MyFlags)
  96. FreshR0                EQU        $40                    ;mask for new R0 data (in MyFlags)
  97. FreshR1                EQU        $20                    ;mask for new R1 data (in MyFlags)
  98. TabltType            EQU        $7F                    ;Device type of digitizing tablet
  99. jADBProc            EQU        $6B8                ;can't find this in MPW equ's!
  100.  
  101. ************************ Entry and installation ***********************
  102. ***
  103. ***        When the ADBS is loaded and jumped to, it comes here and branches
  104. ***        around the actual driver to the installation code.
  105. ***
  106. ***        On Entry:    A0 = Pointer to this routine
  107. ***                    D0 = ADB device address (0-15)
  108. ***                    D1 = ADB Device Type
  109. ***        
  110. ***********************************************************************
  111.  
  112. Entry    MAIN
  113.  
  114.         ALIGN 2
  115.         
  116.         bra            Installer
  117.         
  118. Entry2                                    ;this is how we enter the relocated installer
  119.         move.l        a2,a0
  120.         _DisposHandle                    ;dispose the original ADBS
  121.         move.l        #0,a2                ;clear this handle
  122.         bra            noChoice            ;now do that installation thang!
  123.         
  124. ************************ My ADB Service Routine ***********************
  125. ***
  126. ***        ADB service routine for digitizing tablets.
  127. ***        
  128. ***        This routine is called as a result of the successful completion
  129. ***        of a Talk R0 or Talk R1 command. The successful completion of Talk R0 means
  130. ***        that the tablet has either new coordinate data or a change in a
  131. ***        button state, or both. This routine is also able to handle the
  132. ***        completion of a Talk R1 command, and will update the data area
  133. ***        with R1's contents.
  134. ***        
  135. ***        On Entry:    A0 = Pointer to Device Data
  136. ***                    A1 = Pointer to this routine
  137. ***                    A2 = Pointer to optional data area
  138. ***                    D0 = ADB Command that got us called
  139. ***        
  140. ***********************************************************************
  141.  
  142. DataCount    EQU        0                            ;this is the format of the tablet data
  143. SwitchWord    EQU        DataCount+1                    ;info about switch(es) state(s)
  144. XCoord        EQU        SwitchWord+2                ;hi byte = LSB of X, lo byte = MSB of X
  145. YCoord        EQU        XCoord+2                    ;hi byte = LSB of Y, lo byte = MSB of Y
  146. ZCoord        EQU        YCoord+2                    ;hi byte = LSB of Z, lo byte = MSB of Z
  147.  
  148. SwitchMask    EQU        $80                            ;bit seven = any button down (if one)
  149.  
  150. MySrvcRt
  151.  
  152.         movem.l        a0-a3/d0-d2,-(a7)            ;save regs we will abuse
  153.         cmp.b        MyTalkR0(a2),d0
  154.         bne            DoOther                        ;if not a Talk R0, see if a Talk R1
  155.                 
  156.         move.b        MyFlags(a2),d1
  157.         andi.b        #DoSysCrsr,d1                ;see if current app wants us to update the system cursor
  158.         bne.s        NoUpdate                    ;if bit 7 set, just update data area, and check button
  159.         
  160.         move.b        YCoord(a0),MTemp            ;move coordinate data into cursor low mem locations
  161.         move.b        YCoord+1(a0),MTemp+1
  162.         move.b        XCoord(a0),MTemp+2
  163.         move.b        XCoord+1(a0),MTemp+3
  164.  
  165.          move.l         MTemp,RawMouse              ;cursor guy likes to see this twice
  166.                                                 ;to make the position absolute. If RawMouse were not
  167.                                                 ;updated, jCrsrTask would attempt to scale the move
  168.         MOVE.B        CrsrCouple,CrsrNew            ; note the change
  169. NoUpdate
  170.         lea            R0Count(a2),a3                ;set up the destination in a3, source is a0
  171.         bsr.s        MoveData                    ;go update the data area
  172.         ori.b        #FreshR0,MyFlags(a2)        ;flag to say the data is new
  173.                                                 ;  The following code with capatalized mnemonics (can
  174.                                                 ;  you say that?) is stolen from the Mac II ROM 
  175.                                                 ;  source. Thanks to the 4th floor, DA3 (or wherever
  176.                                                 ;  they are now╔).
  177.         MOVEQ       #1, D0                        ; D0 holds the event (1 = mouse button down)
  178.         move.b        #$00,d2                        ;our new MBState, assume mouse down
  179.         move.b        SwitchWord+1(a0),d1            ;get switch state
  180.         andi.b        #SwitchMask,d1                ;mask for button(s) down
  181.         bne.s        Down                        ;if zero, no button down
  182.         
  183.         MOVEQ           #2, D0                        ; set D0 to 2 if mouse button is up
  184.         move.b        #$80,d2                        ;well, turns out the button's up
  185.  
  186. Down    MOVE.B      MBState, D1                    ; get copy of last state
  187.         EOR.B       D2, D1                        ; did it change?
  188.         BPL.S       MyExit                        ; if it didn't, no event
  189.  
  190. ; the mouse button changed, do debounce it , only generate event if it wasn't a bounce
  191.         MOVE.L        TICKS,D1                    ; get current system ticks
  192.         SUB.L        MBTICKS,D1                    ; and subtract ticks when the button changed
  193.         CMP.L        #1,D1                        ; was it long enough?
  194.         BLT.S        MyExit                        ; if not, don't post an event
  195.  
  196.         ADD.L        D1,RndSeed                    ; randomize our seed
  197.         MOVE.L        TICKS,MBTICKS                ; since it changed, update the ticks        
  198.  
  199.         AND.B          #$80, D2                    ; just store high bit
  200.         MOVE.B         D2, MBState                    ; also update the state
  201.  
  202. ; post the mouse button event
  203. ;**********************************************************************************************
  204.                                                 ;add call to jCrsrTask!!!!!
  205. ;**********************************************************************************************                                                
  206.         MOVE.L      D0, A0                        ; get event number where it belongs
  207.         MOVEQ        #0, D0                        ; no message
  208.         _PostEvent                                ; post the event
  209.         
  210. MyExit    movem.l        (a7)+,a0-a3/d0-d2            ;restore regs we abused
  211.         rts
  212.         
  213. DoOther
  214.  
  215.         move.b        Myflags(a2),d2
  216.         lsl.b        #4,d2                        ;move address up to hi nibble
  217.         ori.b        #TalkR1,d2                    ;now we've built a Talk R1 at our address
  218.         cmp.b        d2,d0                        ;so we can see if that's why we're here
  219.         bne.s        MyExit                        ;wasn't a Talk R0, or a Talk R1, so get out
  220.         lea            R1Count(a2),a3                ;we got a Talk R1, so point to R1 data area for move
  221.         bsr.s        MoveData                    ;go put the R1 data in the data area
  222.         ori.b        #FreshR1,MyFlags(a2)        ;flag that says data is new
  223.         bra.s        MyExit                        ;all done
  224.         
  225. MoveData                                        ;A0 points to source, A3 points to destination
  226.         movem.l        a0/a3/d0,-(a7)                ;save the regs
  227.         move.w        #$08,d0                        ;get the count (never more than 9 bytes)
  228. MD1        move.b        (a0)+,(a3)+                    ;move a byte at a time╔
  229.         dbra        d0,MD1                        ;until low word of d0 = -1
  230.         movem.l        (a7)+,a0/a3/d0                ;restore the regs
  231.         rts
  232.         
  233. ************************ My ADBReInit  Procedure **********************
  234. ***
  235. ***        ADBReInit Proc for deallocating memory before re-initializing
  236. ***        the ADB Mgr
  237. ***
  238. ***        On Entry:    D0 = 0 for pre processing, 1 for post processing
  239. ***                    A0 = Pointer to this routine
  240. ***        
  241. ***********************************************************************
  242.  
  243. jProc    
  244.         cmpi.b        #1,d0
  245.         beq.s        outtaHere                    ;only do the pre-processing
  246.         move.b        d0,d2
  247.  
  248.         lea            MySrvcRtEnd,a2                ;get a pointer to the data area
  249.         move.l        NextjADBProc(a2),-(a7)        ;push address of next guy in the chain
  250.         move.l        ADBSvRt(a2),a0
  251.         _DisposPtr                                ;dispose the service routine and data area pointer
  252.         move.b        d2,d0                        ;restore d0
  253.         rts
  254.         
  255. outtaHere
  256.         move.l        NextjADBProc(a2),-(a7)        ;push address of next guy in the chain
  257.         rts
  258.         
  259. MySrvcRtEnd                                        ;and begin optional data area
  260.  
  261. ******************************* Installer *****************************
  262. ***        On Entry:    A0 = Pointer to this routine
  263. ***                    D0 = ADB device address (0-15)
  264. ***                    D1 = ADB Device Type
  265. ***********************************************************************
  266. ******************************** Equates ******************************
  267.  
  268. DataSiz                EQU        EndDataArea-StartDataArea    ;this is how big my optional data area is
  269. RoutineSiz            EQU        MySrvcRtEnd-MySrvcRt        ;this is how big my service routine is
  270. NewPtrSiz            EQU        RoutineSiz+DataSiz
  271. jADBProcOffset        EQU        jProc-MySrvcRt                ;offset from NewPtr to my jADBProc (after blockmove)
  272. jmpOffset            EQU        entry2-entry
  273.  
  274. Installer
  275.  
  276.         movem.l        a0-a3/d0-d2,-(a7)            ;protect the virtue of the registers we use
  277.         move.b        d0,d2                        ;save device address for later
  278.         move.l        #0,a2                        ;zero our handle regs (a2 for original ADBS and a3 the new one)
  279.         move.l        #0,a3
  280.         lea            Entry,a0                    ;get a handle on the ADBS
  281.         _RecoverHandle
  282.         move.l        a0,a2                        ;keep this handle around, we need to dispose is later
  283.         cmp.b        #TabltType,d1                ;see if it's our kind of device
  284.         bne            exit                        ;if not, quit
  285.         
  286.         _GetHandleSize                            ;this code relocates the ADBS hi in the heap, to
  287.                                                 ;try and cause the least amount of heap fragmentation
  288.         bmi            exit                        ;something's wrong, let's get outta here
  289.         move.l        d0,d1                        ;we'll need the size later for BlockMove
  290.         _NewHandle    ,SYS                        ;get a new handle of our same size
  291.         bne.s        noChoice                    ;if we can't get memory, go ahead and fragment the sys heap
  292.         move.l        a0,a3                        ;remember the new handle
  293.         _MoveHHi                                ;move this new handle up in the heap (error shouldn't be possible)
  294.         _Hlock                                    ;lock it down (error shouldn't occur)
  295.         move.l        d1,d0                        ;get our size
  296.         move.l        (a0),a1                        ;set up destination ptr
  297.         move.l        (a2),a0                        ;and source
  298.         _BlockMove                                ;move entire ADBS up hi in the heap
  299.                                                 ;do this so that the NewPtr will be as low as
  300.                                                 ;possible in the heap, avoiding fragmentation due to
  301.                                                 ;ADBS being below NewPtr
  302.         adda.l        #jmpOffset,a1                ;a0 now points to Entry2 in the copy of this ADBS
  303.         jmp            (a1)                        ;now we start execution in our MoveHHi'd ADBS 
  304.         
  305. noChoice
  306.         move.l        #NewPtrSiz,d0                ;make a block for the driver and data area
  307.         _NewPtr        ,SYS,CLEAR                    ;we likes our bytes clean, we does
  308.         bne.s        exit                        ;abort if error
  309.         move.l        a0,a1                        ;set up destination for BlockMove
  310.         lea            MySrvcRt,a0                    ;and source pointer
  311.         move.l        #RoutineSiz,d0                ;and how many bytes to move
  312.         _BlockMove                                ;now move the driver into our new ptr (no errors)
  313.         move.l        a1,a0                        ;now create pointer to the data area
  314.         adda.l        #RoutineSiz,a0                ;a0 now points to area past the service routine
  315.         move.l        a0,ADBDtAr(a0)                ;keep pointer to data area in data area
  316.         move.l        a1,ADBSvRt(a0)                ;keep pointer to service routine in data area
  317.                                                 ;initialize the data area
  318.         move.l        #'TBLT',TabltID(a0)            ;set up the drivers data area
  319.         andi.b        #$0F,d2                        ;clear hi nibble of device address
  320.         or.b        d2,MyFlags(a0)                ;fill in our address for the driver's sake
  321.         move.b         d2,d0                        ;set the device addrs for our tablet (for _SetADBInfo)
  322.         lsl.b        #4,d2                        ;now move the address into the hi nibble
  323.         move.b        d2,MyTalkR0(a0)                ;Create a TalkR0 command byte for the drvr to compare with
  324.         ori.b        #TalkR0,MyTalkR0(a0)        ;now we've built a Talk R0 at our address
  325.         move.l        a0,d2                        ;keep pointer to data area for later
  326.                 
  327.         lea         ADBSvRt(a0),a0                ;set up for installing my stuff
  328.         _SetADBInfo                                ;install it!
  329.         tst.w        d0                            ;any error?
  330.         bne.s        badExit                        ;if so, abort
  331.  
  332.         move.l        d2,a0                        ;get pointer to data area back
  333.         move.l        jADBProc,NextjADBProc(a0)    ;get the next guy's address
  334.         lea            jADBProcOffset(a1),a0        ;set up the jADBProc for _ADBReInt (Just in case╔)
  335.         move.l        a0,jADBProc                    ;all done
  336.         
  337. exit    move.l        a2,a0                        ;the handle of the original ADBS
  338.         cmpa.l        #0,a0                        ;make sure it's a real handle
  339.         beq.s        exit2
  340.         _DisposHandle                            ;nuke it!
  341.  
  342. exit2    move.l        a3,a0                        ;enter here with handle to dispose in a3
  343.         cmpa.l        #0,a0                        ;if handle is nil, don't dispose
  344.         beq.s        around
  345.         _DisposHandle                            ;
  346. around    movem.l        (a7)+,a0-a3/d0-d2            ;restore the registers we use
  347.         rts                                        ;Return To Sender
  348.  
  349. badExit                                            ;error occured after allocating new ptr
  350.         move.l        a1,a0
  351.         _DisposPtr                                ;get rid of our pointer
  352.         bra.s        exit
  353.                 
  354.         END