;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/

;/*************************************************************************
;*
;* SOURCE FILE NAME = BUS.ASM
;*
;* DESCRIPTIVE NAME = MS Bus Mouse specific code
;*
;*
;* VERSION      V2.0
;*
;* DATE         10/13/91
;*
;* DESCRIPTION  This file contains the code specific to the MS
;*              Bus mouse.
;*
;* FUNCTIONS    CheckforBUSDevice()
;*              FindBusInterrupt ()
;*              FindBusChangingLevels ()
;*              FindBusLevel          ()
;*              BusInit               ()
;*
;* NOTES        This file contains the code specific to the MS
;*              Bus mouse.
;*
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*
;*
;*
;*
;*
;*
;**************************************************************************


.xlist
       include mouse.inc
.list

.386p

;*
;*   External Mouse Module Data References
;*

       extrn DeviceData          : byte

       extrn Int_Packet          : word
       extrn ByteCount           : word
       extrn PrevEvent           : word

       extrn Device_Help         : dword

       extrn GIDC_Entry          : far

       extrn _RM_MSE_AllocPorts    :far
       extrn _RM_MSE_DeallocPorts  :far


CSEG     SEGMENT   WORD  PUBLIC  USE16 'CODE'
         ASSUME    CS:CSEG, SS:nothing, ES:nothing, DS:nothing

;*
;*    Module Procs made Public for other Mouse Modules
;*

       public  CheckforBUSDevice
       public  FindBusInterrupt
       public  FindBusChangingLevels
       public  FindBusLevel
       public  BusInit


;/***************************************************************************
;*
;* FUNCTION NAME = CheckforBUSDevice
;*
;* DESCRIPTION   = This procedure will attempt to find a bus mouse adaptor
;*                 In the system and will return the results of this search.
;*
;* INPUT         = NONE.
;*
;* OUTPUT        = NONE.
;*
;*
;* RETURN-NORMAL = NC NZ           No bus mouse adaptor was found
;*
;*                   NC ZR           A bus mouse adaptor was found
;*                   AL              Interrupt it is jumpered on
;*                   BL              Bit mask for this interrupt
;*                   DX              Address of mask register of 8259A
;*
;*                   CY NZ           Multiple interrupts were found
;*
;*                   CY ZR           No interrupts were found
;*
;* RETURN-ERROR  =  NONE.
;*
;* EFFECTS       =  AX, BX, CX, DX
;**************************************************************************/



CheckforBUSDevice  proc  near

;*
;* We determine if the bus mouse adaptor is present by attempting to
;*  program the 8255A, and then seeing if we can write a value out to
;*  Port B on the 8255A and get that value back. If we can, we assume
;*  that we have a bus mouse adaptor.
;*

        mov  dx, BUS_INIT             ; Get address of 8255A control port.

        pusha
        push es
        push dx
        call _RM_MSE_AllocPorts
        or ax, ax
        pop dx
        pop es
        popa
        jnz  PortBusClaimed

        mov  al, BUS_INIT_VALUE       ; Get proper value.
        out  dx, al                   ; Set up 8255A.
        MyIODelay                     ; Generate delay between I/O instructions
        address BUS_SIG FROM BUS_INIT ; Get address of Port B.
        mov  ax, 0a5a5h               ; Set Port B with signature.
        out  dx, al
        MyIODelay                     ; Generate delay between I/O instructions
        in      al,dx                 ; Read back Port B.
        MyIODelay                     ; Generate delay between I/O instructions

        .if <al ne ah>                ; Does it match signature byte?
           stc
           jmp short tfb_not_found    ; Nope - no bus mouse adaptor.
        .endif

        call FindBusInterrupt         ; Determine interrupt level.
        jc   short tfb_not_found      ; Leave right away if returning error.

        pushf                         ; Save return flags.
        mov     dx,MASTER_MASK_ADDR   ; Assume we are on master 8259A.
        cmp     al,2                  ; Is it IRQ 2?
        jne     short tfb_irq_mapping_done ; Nope, don't map IRQ.
        mov     al,9                  ; YES! Map IRQ 2 into IRQ 9.
        mov     bl,00000010b          ; ...
        mov     dx,SLAVE_MASK_ADDR    ; ...

tfb_irq_mapping_done:
        popf                          ; Restore return flags.
        ret

tfb_not_found:
        pusha
        push es
        call _RM_MSE_DeallocPorts
        pop es
        popa

PortBusClaimed:
        stc
        ret


CheckforBUSDevice  endp


;/***************************************************************************
;*
;* FUNCTION NAME = FindBusInterrupt
;*
;* DESCRIPTION   = This procedure determines the interrupt level that the
;*                 bus mouse adaptor is jumpered at.
;*
;* INPUT         = NONE
;*
;* ENTRY         = Bus interrupts are enabled at the adaptor.
;*                 DX              Has address of BUS_SIG
;*
;*
;* EXIT          = carry clear     Only 1 interrupt level was found
;*                 ZR
;*                 AL              IRQ # of this interrupt level
;*                 BL              Bit mask giving bus mouse interrupt level
;*
;*                 carry set       Some error occurred
;*                 NZ              Multiple interrupts were found
;*                 ZR              No interrupts were found
;*
;* OUTPUT        = NONE
;*
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR  = NONE
;*
;*
;**************************************************************************/




FindBusInterrupt  proc  near

        address BUS_CONTROL FROM BUS_SIG; Get address of mouse control port.
        mov     cx,5                  ; Only try to get rid of multiple

fbi_loop:
        mov     bh,0FFh               ; All interrupt levels still valid.
                                      ;  interrupts 5 times.
        mov     al,10010000b          ; Value to disable bus interrupts.
        out     dx,al                 ; DISABLE BUS INTERRUPTS
        MyIODelay                  ; Generate delay between I/O instructions
        call    FindBusChangingLevels ; Determine which levels are changing.
        not     ah                    ; Remove from consideration those
        and     bh,ah                 ;  levels which are changing now.
        mov     al,10000000b          ; Value to enable bus interrupts.
        out     dx,al                 ; ENABLE BUS INTERRUPTS
        MyIODelay                     ; Generate delay between I/O instructions
        call    FindBusChangingLevels ; Determine which levels are changing.
        .if <bit ah z bh>             ; If no levels were changing
           stc                        ; No levels were responding!!!!
           jmp  fbi_again
        .endif

        call    FindBusLevel          ; Determine interrupt level and mask.
        jnc     short fbi_leave       ; Found it! Leave.

fbi_again:
        loop    fbi_loop              ; Found multiple interrupts. Try again.


fbi_leave:                            ; All return codes set correctly.
        push    ax                    ; Save IRQ level.
        mov     al,10010000b          ; Value to disable bus interrupts.
        out     dx,al                 ; DISABLE BUS INTERRUPTS.
        pop     ax                    ; Restore IRQ level.
        ret

FindBusInterrupt  endp


;/***************************************************************************
;*
;* FUNCTION NAME = FindBusChangingLevels
;*
;* DESCRIPTION   = This procedure will return back a bit mask indicating which
;*                 of the possible bus mouse interrupt levels are changing.
;*
;* INPUT         =  NONE
;*
;* OUTPUT        =  NONE
;*
;* ENTRY         =  DX         Has address of BUS_CONTROL
;*
;* EXIT          =  AH         Mask giving levels that were changing
;*
;*
;* OUTPUT        =  NONE
;*
;*
;* RETURN-NORMAL =  NONE
;*
;*
;* RETURN-ERROR  =  NONE
;*
;*
;**************************************************************************/




FindBusChangingLevels  proc  near

        push cx                   ; Save environment.
        in   al,dx                ; Get current interrupt state.
        MyIODelay                 ; Generate delay between I/O instructions
        mov  bl,al                ; Save as last state.
        xor  ah,ah                ; No levels are currently changing.
        mov  cx, 0ffffh
fbcl_inner:
        in   al,dx                ; Get current state.
        MyIODelay                 ; Generate delay between I/O instructions
        xor  bl,al                ; Determine levels which changed from
        or   ah,bl                ;  last state and save them.
        mov  bl,al                ; Save current state as last state.
        loop fbcl_inner
        and  ah,0fh               ; Keep only valid bits.
        pop  cx                   ; Restore environment.
        ret

FindBusChangingLevels  endp



;/***************************************************************************
;*
;* FUNCTION NAME = FindBusLevel
;*
;* DESCRIPTION   = This procedure accepts the mask giving possible bus
;*                 interrupts abd will return back the interrupt mask and
;*                 the interrupt number for it.
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* ENTRY         = AH         Mask of possible levels.
;*                            Bit 0 == IRQ 5 through Bit 3 == IRQ
;*
;* EXIT          = NC              Only 1 possible level.
;*                 AL              Interrupt number.
;*                 BL              Interrupt mask
;*
;*                 CY              Multiple levels were possible.
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR  = NONE
;*
;*
;**************************************************************************/

FindBusLevel  proc  near

        mov     al,5                 ; Start with IRQ 5.
        mov     bl,00100000b         ; Bit mask for IRQ 5.

fbl_loop:
        shr     ah,1                 ; Test next possible interrupt level.
        jc      short fbl_got_it     ; Branch if possible level found.
        dec     ax                   ; If not a possible level, move on to
        shr     bl,1                 ;  the next possible level
        jmp     short fbl_loop

fbl_got_it:
        jnz     short fbl_leave      ; If more levels still possible, error.
        clc                          ; Show only 1 level was possible.

fbl_leave:                           ; Return codes set correctly.
        ret

FindBusLevel  endp



;/***************************************************************************
;*
;* FUNCTION NAME =
;*                  BusInit
;* DESCRIPTION   =
;*                  This procedure is called at the end of the initialization
;*                  process in order to finish the initialization of the
;*                  bus mouse. It has to perform whatever actions that are
;*                  necessary in order to put the bus mouse into the state it
;*                  needs to be in.
;*
;* INPUT         =  NONE
;*
;* OUTPUT        =  NONE
;*
;* ENTRY         =  NONE
;*
;* EXIT          =  Carry clear        Init was successful.
;*
;*
;*
;*
;*
;* RETURN-NORMAL =  NONE
;*
;*
;* RETURN-ERROR  =  NONE
;*
;*
;**************************************************************************/



BusInit PROC    NEAR

        mov     dx,BUS_CONTROL       ; Get address of the control port.
        xor     al,al                ; Write out the value that enables the
        out     dx,al                ;  counters and interrupts.
        ret                          ; Leave with carry clear.

BusInit ENDP


CSEG     ENDS
         END
