home *** CD-ROM | disk | FTP | other *** search
- *
- * Apple Macintosh Developer Technical Support
- *
- * Sample 'ADBS' Resource
- *
- * TbltDrvr
- *
- * TbltDrvr.a - Assembler Source
- *
- * Copyright ⌐ 1989 Apple Computer, Inc.
- * All rights reserved.
- *
- * Versions:
- * 1.00 04/89
- *
- * Components:
- * TbltDrvr.a April 1, 1989
- *
- * *******************************************************************
- *
- * ADBS resources are loaded and executed at boot time (before
- * INIT 31), and are made of two main parts, the installation/
- * initialization code and the the actual driver.
- *
- * In this example, the installation portion allocates memory
- * in the system heap for the service routine and the "optional
- * data area". It installs the driver using the ADB Mgr call SetADBInfo.
- *
- * Generally speaking, ADB devices are intended to be user input devices.
- * The ADB Manager polls the bus every 11 milliseconds to see if a device
- * has new user input data. This is accomplished by sending a talk R0 command
- * to the last active device. The last active device is the last device that
- * had data to send to the host. If another device has data, it can request
- * a poll by sending a service request signal to the host.
- *
- * When a device has responded to a poll, the ADB Manager will call the driver
- * to process the data. This is done a interrupt time (level 1), and
- * The driver is passed the data, by getting a pointer to a pascal string
- * which contains the actual data.
- *
- * In this example, the data is in the form of a pointing device's coordinates
- * and button(s) state(s). When the driver gets the data, it stores the
- * coordinate information in RawMouse and MTemp. We stuff both RawMouse and MTemp,
- * because the tablet is an "absolute" device. It also checks the state of
- * the button, against MBState, and if there has been a change, it will update
- * MBState, and post either a mouseUp or mouseDown event, as appropriate.
- *
- * NOTE: This code demonstrate how to move the cursor position. This information
- * is meant for input device drivers only, this technique should not
- * be used by applications to move the cursor around. It's bad user
- * interface, and nobody likes a bad user interface, so Just Say No!
- *
- * Build commands:
- *
- * asm TbltDrvr.a -lo TbltDrvr.a.lst -l
- * link TbltDrvr.a.o -o 'MrBootDisk:System Folder:System' -rt ADBS=4 -ra =16
- *
- ***********************************************************************
-
- STRING ASIS
- PRINT OFF
- INCLUDE 'Traps.a'
- INCLUDE 'SysEqu.a'
- PRINT ON
-
- **************************** Driver Offsets ***************************
-
- ;this is the structure of the "optional data area"
- StartDataArea EQU 0
- TabltID EQU StartDataArea ;ID so Apps can find this data (should contain 'TBLT')
- ; this identifies the structure for this driver,
- ; if your structure is different, you should have
- ; a different ID.
- R0Count EQU TabltID+4 ;count byte of Pascal data string returned by ADB
- R0Data EQU R0Count+1 ;data can be up to 8 bytes (but reference from R0Count
- ; for even address access)
- R1Count EQU R0Data+8 ;count byte of Pascal data string returned by ADB
- ;data can be up to 8 bytes (reference from R1Data
- R1Data EQU R1Count+1 ; for even address access)
- MyFlags EQU R1Data+8 ;hi nibble are flags, bit 7 = update system cursor (zero = yes)
- ;bit 6 = new R0 data, bit 5 = new R1 data (1 = new)
- ;lo nibble is the address we ended up at (set by installer)
- MyTalkR0 EQU MyFlags+1 ;This byte used to build a talk R0 cmd byte with our new address
- RsrvdPtr EQU MyTalkR0+1 ;Back door for Apple (you never know╔)
- Scratch EQU RsrvdPtr+4 ;scratch area
- ADBSvRt EQU Scratch+2 ;pointer to service routine
- ADBDtAr EQU ADBSvRt+4 ;pointer to optional data area
- NextjADBProc EQU ADBDtAr+4 ;a place to keep pointer to next guy in jADBProc chain
- EndDataArea EQU NextjADBProc+4 ;this is my end marker & how big it is
-
- ******************************** Equates ******************************
-
- TalkR0 EQU $0C ;ADB Talk register zero (installer fills in the device address in upper nibble)
- TalkR1 EQU $0D ;ADB Talk register one (installer fills in the device address in upper nibble)
- DoSysCrsr EQU $80 ;mask for "update system cursor?" flag (in MyFlags)
- FreshR0 EQU $40 ;mask for new R0 data (in MyFlags)
- FreshR1 EQU $20 ;mask for new R1 data (in MyFlags)
- TabltType EQU $7F ;Device type of digitizing tablet
- jADBProc EQU $6B8 ;can't find this in MPW equ's!
-
- ************************ Entry and installation ***********************
- ***
- *** When the ADBS is loaded and jumped to, it comes here and branches
- *** around the actual driver to the installation code.
- ***
- *** On Entry: A0 = Pointer to this routine
- *** D0 = ADB device address (0-15)
- *** D1 = ADB Device Type
- ***
- ***********************************************************************
-
- Entry MAIN
-
- ALIGN 2
-
- bra Installer
-
- Entry2 ;this is how we enter the relocated installer
- move.l a2,a0
- _DisposHandle ;dispose the original ADBS
- move.l #0,a2 ;clear this handle
- bra noChoice ;now do that installation thang!
-
- ************************ My ADB Service Routine ***********************
- ***
- *** ADB service routine for digitizing tablets.
- ***
- *** This routine is called as a result of the successful completion
- *** of a Talk R0 or Talk R1 command. The successful completion of Talk R0 means
- *** that the tablet has either new coordinate data or a change in a
- *** button state, or both. This routine is also able to handle the
- *** completion of a Talk R1 command, and will update the data area
- *** with R1's contents.
- ***
- *** On Entry: A0 = Pointer to Device Data
- *** A1 = Pointer to this routine
- *** A2 = Pointer to optional data area
- *** D0 = ADB Command that got us called
- ***
- ***********************************************************************
-
- DataCount EQU 0 ;this is the format of the tablet data
- SwitchWord EQU DataCount+1 ;info about switch(es) state(s)
- XCoord EQU SwitchWord+2 ;hi byte = LSB of X, lo byte = MSB of X
- YCoord EQU XCoord+2 ;hi byte = LSB of Y, lo byte = MSB of Y
- ZCoord EQU YCoord+2 ;hi byte = LSB of Z, lo byte = MSB of Z
-
- SwitchMask EQU $80 ;bit seven = any button down (if one)
-
- MySrvcRt
-
- movem.l a0-a3/d0-d2,-(a7) ;save regs we will abuse
- cmp.b MyTalkR0(a2),d0
- bne DoOther ;if not a Talk R0, see if a Talk R1
-
- move.b MyFlags(a2),d1
- andi.b #DoSysCrsr,d1 ;see if current app wants us to update the system cursor
- bne.s NoUpdate ;if bit 7 set, just update data area, and check button
-
- move.b YCoord(a0),MTemp ;move coordinate data into cursor low mem locations
- move.b YCoord+1(a0),MTemp+1
- move.b XCoord(a0),MTemp+2
- move.b XCoord+1(a0),MTemp+3
-
- move.l MTemp,RawMouse ;cursor guy likes to see this twice
- ;to make the position absolute. If RawMouse were not
- ;updated, jCrsrTask would attempt to scale the move
- MOVE.B CrsrCouple,CrsrNew ; note the change
- NoUpdate
- lea R0Count(a2),a3 ;set up the destination in a3, source is a0
- bsr.s MoveData ;go update the data area
- ori.b #FreshR0,MyFlags(a2) ;flag to say the data is new
- ; The following code with capatalized mnemonics (can
- ; you say that?) is stolen from the Mac II ROM
- ; source. Thanks to the 4th floor, DA3 (or wherever
- ; they are now╔).
- MOVEQ #1, D0 ; D0 holds the event (1 = mouse button down)
- move.b #$00,d2 ;our new MBState, assume mouse down
- move.b SwitchWord+1(a0),d1 ;get switch state
- andi.b #SwitchMask,d1 ;mask for button(s) down
- bne.s Down ;if zero, no button down
-
- MOVEQ #2, D0 ; set D0 to 2 if mouse button is up
- move.b #$80,d2 ;well, turns out the button's up
-
- Down MOVE.B MBState, D1 ; get copy of last state
- EOR.B D2, D1 ; did it change?
- BPL.S MyExit ; if it didn't, no event
-
- ; the mouse button changed, do debounce it , only generate event if it wasn't a bounce
- MOVE.L TICKS,D1 ; get current system ticks
- SUB.L MBTICKS,D1 ; and subtract ticks when the button changed
- CMP.L #1,D1 ; was it long enough?
- BLT.S MyExit ; if not, don't post an event
-
- ADD.L D1,RndSeed ; randomize our seed
- MOVE.L TICKS,MBTICKS ; since it changed, update the ticks
-
- AND.B #$80, D2 ; just store high bit
- MOVE.B D2, MBState ; also update the state
-
- ; post the mouse button event
- ;**********************************************************************************************
- ;add call to jCrsrTask!!!!!
- ;**********************************************************************************************
- MOVE.L D0, A0 ; get event number where it belongs
- MOVEQ #0, D0 ; no message
- _PostEvent ; post the event
-
- MyExit movem.l (a7)+,a0-a3/d0-d2 ;restore regs we abused
- rts
-
- DoOther
-
- move.b Myflags(a2),d2
- lsl.b #4,d2 ;move address up to hi nibble
- ori.b #TalkR1,d2 ;now we've built a Talk R1 at our address
- cmp.b d2,d0 ;so we can see if that's why we're here
- bne.s MyExit ;wasn't a Talk R0, or a Talk R1, so get out
- lea R1Count(a2),a3 ;we got a Talk R1, so point to R1 data area for move
- bsr.s MoveData ;go put the R1 data in the data area
- ori.b #FreshR1,MyFlags(a2) ;flag that says data is new
- bra.s MyExit ;all done
-
- MoveData ;A0 points to source, A3 points to destination
- movem.l a0/a3/d0,-(a7) ;save the regs
- move.w #$08,d0 ;get the count (never more than 9 bytes)
- MD1 move.b (a0)+,(a3)+ ;move a byte at a time╔
- dbra d0,MD1 ;until low word of d0 = -1
- movem.l (a7)+,a0/a3/d0 ;restore the regs
- rts
-
- ************************ My ADBReInit Procedure **********************
- ***
- *** ADBReInit Proc for deallocating memory before re-initializing
- *** the ADB Mgr
- ***
- *** On Entry: D0 = 0 for pre processing, 1 for post processing
- *** A0 = Pointer to this routine
- ***
- ***********************************************************************
-
- jProc
- cmpi.b #1,d0
- beq.s outtaHere ;only do the pre-processing
- move.b d0,d2
-
- lea MySrvcRtEnd,a2 ;get a pointer to the data area
- move.l NextjADBProc(a2),-(a7) ;push address of next guy in the chain
- move.l ADBSvRt(a2),a0
- _DisposPtr ;dispose the service routine and data area pointer
- move.b d2,d0 ;restore d0
- rts
-
- outtaHere
- move.l NextjADBProc(a2),-(a7) ;push address of next guy in the chain
- rts
-
- MySrvcRtEnd ;and begin optional data area
-
- ******************************* Installer *****************************
- *** On Entry: A0 = Pointer to this routine
- *** D0 = ADB device address (0-15)
- *** D1 = ADB Device Type
- ***********************************************************************
- ******************************** Equates ******************************
-
- DataSiz EQU EndDataArea-StartDataArea ;this is how big my optional data area is
- RoutineSiz EQU MySrvcRtEnd-MySrvcRt ;this is how big my service routine is
- NewPtrSiz EQU RoutineSiz+DataSiz
- jADBProcOffset EQU jProc-MySrvcRt ;offset from NewPtr to my jADBProc (after blockmove)
- jmpOffset EQU entry2-entry
-
- Installer
-
- movem.l a0-a3/d0-d2,-(a7) ;protect the virtue of the registers we use
- move.b d0,d2 ;save device address for later
- move.l #0,a2 ;zero our handle regs (a2 for original ADBS and a3 the new one)
- move.l #0,a3
- lea Entry,a0 ;get a handle on the ADBS
- _RecoverHandle
- move.l a0,a2 ;keep this handle around, we need to dispose is later
- cmp.b #TabltType,d1 ;see if it's our kind of device
- bne exit ;if not, quit
-
- _GetHandleSize ;this code relocates the ADBS hi in the heap, to
- ;try and cause the least amount of heap fragmentation
- bmi exit ;something's wrong, let's get outta here
- move.l d0,d1 ;we'll need the size later for BlockMove
- _NewHandle ,SYS ;get a new handle of our same size
- bne.s noChoice ;if we can't get memory, go ahead and fragment the sys heap
- move.l a0,a3 ;remember the new handle
- _MoveHHi ;move this new handle up in the heap (error shouldn't be possible)
- _Hlock ;lock it down (error shouldn't occur)
- move.l d1,d0 ;get our size
- move.l (a0),a1 ;set up destination ptr
- move.l (a2),a0 ;and source
- _BlockMove ;move entire ADBS up hi in the heap
- ;do this so that the NewPtr will be as low as
- ;possible in the heap, avoiding fragmentation due to
- ;ADBS being below NewPtr
- adda.l #jmpOffset,a1 ;a0 now points to Entry2 in the copy of this ADBS
- jmp (a1) ;now we start execution in our MoveHHi'd ADBS
-
- noChoice
- move.l #NewPtrSiz,d0 ;make a block for the driver and data area
- _NewPtr ,SYS,CLEAR ;we likes our bytes clean, we does
- bne.s exit ;abort if error
- move.l a0,a1 ;set up destination for BlockMove
- lea MySrvcRt,a0 ;and source pointer
- move.l #RoutineSiz,d0 ;and how many bytes to move
- _BlockMove ;now move the driver into our new ptr (no errors)
- move.l a1,a0 ;now create pointer to the data area
- adda.l #RoutineSiz,a0 ;a0 now points to area past the service routine
- move.l a0,ADBDtAr(a0) ;keep pointer to data area in data area
- move.l a1,ADBSvRt(a0) ;keep pointer to service routine in data area
- ;initialize the data area
- move.l #'TBLT',TabltID(a0) ;set up the drivers data area
- andi.b #$0F,d2 ;clear hi nibble of device address
- or.b d2,MyFlags(a0) ;fill in our address for the driver's sake
- move.b d2,d0 ;set the device addrs for our tablet (for _SetADBInfo)
- lsl.b #4,d2 ;now move the address into the hi nibble
- move.b d2,MyTalkR0(a0) ;Create a TalkR0 command byte for the drvr to compare with
- ori.b #TalkR0,MyTalkR0(a0) ;now we've built a Talk R0 at our address
- move.l a0,d2 ;keep pointer to data area for later
-
- lea ADBSvRt(a0),a0 ;set up for installing my stuff
- _SetADBInfo ;install it!
- tst.w d0 ;any error?
- bne.s badExit ;if so, abort
-
- move.l d2,a0 ;get pointer to data area back
- move.l jADBProc,NextjADBProc(a0) ;get the next guy's address
- lea jADBProcOffset(a1),a0 ;set up the jADBProc for _ADBReInt (Just in case╔)
- move.l a0,jADBProc ;all done
-
- exit move.l a2,a0 ;the handle of the original ADBS
- cmpa.l #0,a0 ;make sure it's a real handle
- beq.s exit2
- _DisposHandle ;nuke it!
-
- exit2 move.l a3,a0 ;enter here with handle to dispose in a3
- cmpa.l #0,a0 ;if handle is nil, don't dispose
- beq.s around
- _DisposHandle ;
- around movem.l (a7)+,a0-a3/d0-d2 ;restore the registers we use
- rts ;Return To Sender
-
- badExit ;error occured after allocating new ptr
- move.l a1,a0
- _DisposPtr ;get rid of our pointer
- bra.s exit
-
- END