|
My Programming Page - VCAND
|
VCAND
Contents of this page
- VCAND.ASM, Main module of Virtual Device Driver
VCAND.ASM
;****************************************************************************
;* *
;* Name: VCAND.ASM - CAN VxD *
;* *
;* Version: 1.00 *
;* *
;* Date: 20.11.95 *
;* *
;* Author: Tom Wellige *
;* *
;* Copyright (c) in 1995 by Dubin Institute of Technology. *
;* *
;* All rights reserved. *
;* *
;* Description: Virtual Controller Area Network (CAN) Device Driver *
;* *
;*--------------------------------------------------------------------------*
;* *
;* Change log: *
;* *
;* DATE REV DESCRIPTION *
;* ----------- --- --------------------------------------------------------*
;* *
;****************************************************************************
PAGE 58,132 ; memorypage setting
TITLE VCAND ; name of this VxD
.386p ; generate 386 code
;****************************************************************************
;* I N C L U D E S *
;****************************************************************************
.XLIST
INCLUDE VMM.INC ; VM Manager
INCLUDE VPICD.INC ; IRQ Manager
INCLUDE VSD.INC ; Sound
INCLUDE DEBUG.INC ; Debug Stuff
INCLUDE VCAND.INC ; own definitions
.LIST
;****************************************************************************
;* V I R T U A L D E V I C E D E C L A R A T I O N *
;****************************************************************************
Declare_Virtual_Device VXD, VCAND_VERMAJ, VCAND_VERMIN, VCAND_Control, \
VCAND_DEV_ID,, VCAND_API_Proc, VCAND_API_Proc
;****************************************************************************
;* D A T A *
;****************************************************************************
VxD_IDATA_SEG
; Initialization data here - discarded after Init_Complete
;****************************************************************************
;* I N T E R R U P T D E S C R I P T O R T A B L E *
;****************************************************************************
VCAND_IRQ_Desc VPICD_IRQ_Descriptor ,,\
OFFSET32 VCAND_Hw_Int_Proc,,,,,>
VxD_IDATA_ENDS
VxD_DATA_SEG
; Normal Data here
;****************************************************************************
;* A P I J U M P T A B L E *
;****************************************************************************
VCAND_API_Table label DWORD ; Function No.:
dd offset32 VCAND_Get_Version ; 00h
dd offset32 VCAND_Set_Filter ; 01h
dd offset32 VCAND_Get_Filter ; 02h
dd offset32 VCAND_Reset_Filter ; 03h
dd offset32 VCAND_Set_CONT_REG ; 04h
dd offset32 VCAND_Set_COMM_REG ; 05h
dd offset32 VCAND_Set_ACC_REG ; 06h
dd offset32 VCAND_Set_ACM_REG ; 07h
dd offset32 VCAND_Set_BT0_REG ; 08h
dd offset32 VCAND_Set_BT1_REG ; 09h
dd offset32 VCAND_Set_OUTP_REG ; 0Ah
dd offset32 VCAND_Set_CLKD_REG ; 0Bh
dd offset32 VCAND_Get_CONT_REG ; 0Ch
dd offset32 VCAND_Get_STAT_REG ; 0Dh
dd offset32 VCAND_Get_INT_REG ; 0Eh
dd offset32 VCAND_Get_ACC_REG ; 0Fh
dd offset32 VCAND_Get_ACM_REG ; 10h
dd offset32 VCAND_Get_BT0_REG ; 11h
dd offset32 VCAND_Get_BT1_REG ; 12h
dd offset32 VCAND_Get_OUTP_REG ; 13h
dd offset32 VCAND_Get_CLKD_REG ; 14h
dd offset32 VCAND_Get_Counter ; 15h
dd offset32 VCAND_Reset_Counter ; 16h
dd offset32 VCAND_Allocate_Buffer ; 17h
dd offset32 VCAND_Free_Buffer ; 18h
dd offset32 VCAND_Mask_IRQ ; 19h
dd offset32 VCAND_Unmask_IRQ ; 1Ah
dd offset32 VCAND_Get_Status ; 1Bh
dd offset32 VCAND_Reset ; 1Ch
dd offset32 VCAND_Update_Timebase ; 1Dh
dd offset32 VCAND_Receive_Messages ; 1Eh
dd offset32 VCAND_Transmit_Messages ; 1Fh
dd offset32 VCAND_Set_RX_HWND ; 20h
dd offset32 VCAND_Set_TX_HWND ; 21h
dd offset32 VCAND_Register_Callback ; 22h
VCAND_Max_API = ($ - VCAND_API_Table) / 4 - 1
VxD_DATA_ENDS
VxD_LOCKED_DATA_SEG
; Pagelocked data here - try to keep this to a minimum.
VCAND_Node1 dd 0 ; handle to VCAND_Data for CAN 1
VCAND_Node2 dd 0 ; handle to VCAND_Data for CAN 2
VCAND_Node3 dd 0 ; handle to VCAND_Data for CAN 3
VCAND_Node4 dd 0 ; handle to VCAND_Data for CAN 4
VCAND_Node5 dd 0 ; handle to VCAND_Data for CAN 5
VCAND_Node6 dd 0 ; handle to VCAND_Data for CAN 6
VCAND_Node7 dd 0 ; handle to VCAND_Data for CAN 7
VCAND_Node8 dd 0 ; handle to VCAND_Data for CAN 8
VCAND_Node9 dd 0 ; handle to VCAND_Data for CAN 9
VCAND_Node dd 0 ; handle to the actual VCAND_Data
VCAND_Node_Ptr dd ? ; points to actual VCAND_Node variable
VCAND_Num_Of_Nodes dw 0 ; number of nodes
VCAND_Dummy1 dd 0 ; push/pop variable in API functions
VCAND_Dummy2 dd 0 ; push/pop variable in API functions
VCAND_Ini_Str_Ptr dd 0 ; points actual VCAND_Ini_ string
VCAND_Ini_Reg_Ptr dd 0 ; points actual Register in VCAND_Data
VCAND_Sys_VM dd 0 ; System VM handle
VCAND_Cur_VM dd 0 ; the current VM
VCAND_PostMsg_Off32 dd 0 ; CAN.DLL's post message addr
VCAND_PostMsg_Seg dw 0
VxD_LOCKED_DATA_ENDS
;****************************************************************************
;* I N I T I A L I Z A T I O N C O D E *
;* ------------------------------------------------------------------------ *
;* Code in the initialization segment is discarded after Init_Complete *
;****************************************************************************
VxD_ICODE_SEG
;****************************************************************************
;* *
;* VMM: VCAND_Device_Init *
;* *
;* DESCRIPTION: *
;* This function inits the driver. *
;* *
;* ENTRY: *
;* EBX = System VM handle *
;* *
;* EXIT: *
;* Carry clear to indicate load success *
;* Carry set to abort loading this VxD *
;* *
;* USES: *
;* flags *
;* *
;****************************************************************************
BeginProc VCAND_Device_Init
mov [VCAND_Sys_VM], ebx ; save Sys_VM
mov [VCAND_Ini_Str_Ptr], OFFSET32 VCAND_Ini_1_IRQ
; pointer to first Ini string
mov [VCAND_Node_Ptr], OFFSET32 VCAND_Node1
; points to Node1 var
Init_Node:
inc [VCAND_Num_Of_Nodes] ; a new node !
VMMCall _HeapAllocate, <[VCAND_Data_Size], HeapZeroInit>
cmp eax, 0
jnz short Init_Node_Save
jmp Init_Failed
Init_Node_Save:
mov [VCAND_Node], eax
mov bx, [VCAND_Num_Of_Nodes]
mov [eax.VCAND_Data.CAN], bx ; save CAN ID number
mov ebx, [VCAND_Node_Ptr]
mov [ebx], eax ; save Node in Node"x" var
add [VCAND_Node_Ptr], 4 ; points to Node"x+1" var
Init_Filter:
mov ebx, [VCAND_Node]
VMMCall _HeapAllocate, <[VCAND_Filter_Size], HeapZeroInit>
cmp eax, 0 ; success ?
jnz short Init_Filter_Save
bts [ebx.VCAND_Data.Status], ST_ERROR ; set ERROR status
jmp short Init_IRQ
Init_Filter_Save:
mov [ebx.VCAND_Data.Filter], eax ; save pointer to filter
Init_IRQ:
mov eax, -1
mov esi, OFFSET32 VCAND_Ini_Profile
mov edi, [VCAND_Ini_Str_Ptr] ; points on VCAND_Ini_x_IRQ
VMMCall Get_Profile_Hex_Int ; get defined IRQ
cmp eax, -1
jnz short Init_IRQ_Save ; not found or no value
mov eax, DEFAULT_IRQ ; use default value
Init_IRQ_Save:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.IRQ], ax ; save it
Init_BTR0:
add [VCAND_Ini_Str_Ptr], 15 ; points on VCAND_Ini_x_BTR0
mov eax, -1
mov edi, [VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Hex_Int ; get defined BTR0 value
cmp eax, -1
jnz short Init_BTR0_Save ; not found or no value
mov eax, DEFAULT_BTR0 ; use default value
Init_BTR0_Save:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.BTR0], ax ; save it
Init_BTR1:
add [VCAND_Ini_Str_Ptr], 15 ; points on VCAND_Ini_x_BTR1
mov eax, -1
mov edi, [VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Hex_Int ; get defined BTR1 value
cmp eax, -1
jnz short Init_BTR1_Save ; not found or no value
mov eax, DEFAULT_BTR1 ; use default value
Init_BTR1_Save:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.BTR1], ax ; save it
Init_OCR:
add [VCAND_Ini_Str_Ptr], 15 ; points on VCAND_Ini_x_OCR
mov eax, -1
mov edi, [VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Hex_Int ; get defined OCR value
cmp eax, -1
jnz short Init_OCR_Save ; not found or no value
mov eax, DEFAULT_OCR ; use default value
Init_OCR_Save:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.OCR], ax ; save it
Init_BufSize:
add [VCAND_Ini_Str_Ptr], 15 ; ptr to VCAND_Ini_x_BufSize
mov eax, -1
mov edi,[VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Decimal_Int ; get defined BufSize
cmp eax, -1
jnz short Init_BufSize_Save ; not found or no value
mov eax, DEFAULT_BufSize ; use default value
Init_BufSize_Save:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.BufSize], eax ; save it
Init_Port:
add [VCAND_Ini_Str_Ptr], 15 ; points on VCAND_Ini_x_Port
mov eax, -1
mov edi, [VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Hex_Int ; get defined Port
cmp eax, -1
jnz short Init_Reg_Vars ; not found or no value
mov eax, DEFAULT_Port ; use default value
Init_Reg_Vars:
mov ebx, [VCAND_Node]
mov cx, 30 ; fill up to RXB8 Register
Init_Set_Reg_Var:
mov [ebx], ax ; save address in reg var
add ebx, 2 ; set ptr to next reg var
inc ax ; set next address
dec cx
jnz short Init_Set_Reg_Var ; ready ?
inc ax
mov [ebx], ax ; 1 byte gap RXB8 - CLKD_REG
Init_Controller:
mov ebx, [VCAND_Node]
mov dx, [ebx.VCAND_Data.CONT_REG]
mov cx, 01h ; set RESET-REQUEST to
call VCAND_Set_Reg ; configure the controller
mov dx, [ebx.VCAND_Data.ACC_REG]
mov cx, 0FFh ; acceptance register
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.ACM_REG]
mov cx, 0FFh ; all messages accepted
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.BT0_REG]
mov cx, [ebx.VCAND_Data.BTR0] ; bus timing register 0
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.BT1_REG]
mov cx, [ebx.VCAND_Data.BTR1] ; bus timing register 1
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.OUTP_REG]
mov cx, [ebx.VCAND_Data.OCR] ; output control register
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.CONT_REG] ; release reset, all
mov cx, 00h ; interrupts disabled
call VCAND_Set_Reg
mov dx, [ebx.VCAND_Data.INT_REG]
call VCAND_Get_Reg
cmp ax, 0E0h ; card installed ?
jz short Init_Virt_IRQ
bts [ebx.VCAND_Data.Status], ST_ERROR ; set ERROR status
Init_Virt_IRQ:
mov ebx, [VCAND_Node]
xor eax, eax
mov ax, [ebx.VCAND_Data.IRQ] ; copy IRQ num in ax
mov cx, [VCAND_Num_Of_Nodes]
cmp cx, 01h ; is this the first card ?
jz short Init_Virt_IRQ_Virtualize ; yes - virtualize IRQ!
; no - so check if this
call VCAND_Check_If_IRQ_Is_Used ; IRQ already used ?
jc short Init_Virt_IRQ_Is_Used
Init_Virt_IRQ_Virtualize:
mov edi, OFFSET32 VCAND_IRQ_Desc ; point to vpicd struct
mov [edi.VID_IRQ_Number], ax ; save IRQ Number here
VxDCall VPICD_Virtualize_IRQ ; set up callbacks
jc short Init_Virt_IRQ_Error ; error ?
mov [ebx.VCAND_Data.IRQ_Handle],eax ; save handle
VxDCall VPICD_Physically_Mask ; mask interrupt
jmp short Init_Error_Check
Init_Virt_IRQ_Is_Used:
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.IRQ_Handle],eax ; save the IRQ handle
jmp short Init_Error_Check
Init_Virt_IRQ_Error:
bts [ebx.VCAND_Data.Status], ST_ERROR ; set ERROR status
Init_Error_Check:
bt [ebx.VCAND_Data.Status], ST_ERROR ; ERROR status ?
jc short Init_Test_Next_Card
bts [ebx.VCAND_Data.Status], ST_INIT ; set INIT status
Init_Test_Next_Card:
mov ax, [VCAND_Num_Of_Nodes]
cmp ax, 9 ; is this the 9th card ?
jz short Init_All_Done
add [VCAND_Ini_Str_Ptr], 15 ; points on VCAND_Ini_x+1_IRQ
mov eax, -1
mov edi,[VCAND_Ini_Str_Ptr]
VMMCall Get_Profile_Hex_Int
cmp eax, -1
jnz Init_Node ; get data for next card
Init_Idle_Callback:
mov esi, OFFSET32 VCAND_Idle_Handler
VMMCall Call_When_Idle
jnc short Init_All_Done
bts [ebx.VCAND_Data.Status], ST_ERROR
Init_All_Done:
mov ax, [ebx.VCAND_Data.Status]
Mono_Out "VCAND_Device_Init: all done, status of last card #AX, Node #EBX"
Mono_Out " "
clc ; no errors - load VxD
jmp short Init_Exit
Init_Failed:
Mono_Out "VCAND_Device_Init: failed !"
Mono_Out " "
stc ; errors - don't load VxD
Init_Exit:
ret
EndProc VCAND_Device_Init
;****************************************************************************
;* *
;* VCAND_Check_If_IRQ_Is_Used *
;* *
;* DESCRIPTION: *
;* This function checks, if the given IRQ is already used from another *
;* CAN card (node) or not. This information is needed because an IRQ *
;* whih is already used by a CAN card is also already virtualized. *
;* *
;* ENTRY: *
;* AX : IRQ *
;* *
;* EXIT: *
;* EAX : IRQ_Handle or zero. *
;* Carry Flag : set if IRQ is already used *
;* *
;* USES: *
;* EAX, BX, ECX, Flags *
;* *
;****************************************************************************
BeginProc VCAND_Check_If_IRQ_Is_Used
mov edx, [VCAND_Node_Ptr] ; save current VCAND_Node_Ptr
push edx
mov [VCAND_Node_Ptr], OFFSET32 VCAND_Node1
mov bx, 1h
Check_Node:
mov ecx, [VCAND_Node_Ptr]
mov dx, [ecx.VCAND_Data.IRQ]
cmp dx, ax ; this IRQ = given IRQ ?
jz short Check_Used_IRQ ; yes, this IRQ is used
add [VCAND_Node_Ptr], 4 ; points to Node"x+1" var
inc bx
cmp bx, [VCAND_Num_Of_Nodes] ; current node ?
jnz short Check_Node
Check_Not_Used_IRQ:
clc ; clear carry flag
jmp short Check_Exit
Check_Used_IRQ:
mov eax, [ecx.VCAND_Data.IRQ_Handle]; return IRQ handle
stc ; set carry flag
Check_Exit:
pop edx
mov [VCAND_Node_Ptr], edx ; restore VCAND_Node_Ptr
ret
EndProc VCAND_Check_If_IRQ_Is_Used
VxD_ICODE_ENDS
;****************************************************************************
;* P A G E L O C K E D C O D E *
;****************************************************************************
VxD_LOCKED_CODE_SEG
;****************************************************************************
;* *
;* VMM: VCAND_Control *
;* *
;* DESCRIPTION: *
;* This is a call-back routine to handle the messages that are sent *
;* to VxD's to control system operation. *
;* *
;* ENTRY: *
;* EAX = Message number *
;* EBX = VM Handle *
;* *
;****************************************************************************
BeginProc VCAND_Control
Control_Dispatch Device_Init, VCAND_Device_Init
clc
ret
EndProc VCAND_Control
;****************************************************************************
;* *
;* VMM: VCAND_Idle_Handler *
;* *
;* DESCRIPTION: *
;* This is a call-back routine the VMM calls when Windows is in *
;* idle mode. VCAND uses this callback to inform an application *
;* if a message to this application has been lost. This can happen *
;* when Windows wasn't fast enough to handle a previous message. *
;* *
;* ENTRY: *
;* EBX = System VM handle *
;* EBP = Client register structure. Return with carry set to pass the *
;* call to the next handler. Return with carry clear to "eat" *
;* the call-back and indicate the System VM is not idle. *
;* *
;****************************************************************************
BeginProc VCAND_Idle_Handler
mov cx, [VCAND_Num_Of_Nodes]
mov dx, 1
Idle_Get_Node:
mov bx, dx
call VCAND_Get_Node_By_ID ; node handle in eax
jc short Idle_Exit
bt [eax.VCAND_Data.Status], ST_INIT
jnc short Idle_Check_Node
bt [eax.VCAND_Data.Status], ST_POST_MESSAGES
jnc short Idle_Check_Node ; post message callback ?
Idle_Check_Lost:
bt [eax.VCAND_Data.Status], ST_MESSAGE_LOST
jnc short Idle_Check_Node
btr [eax.VCAND_Data.Status], ST_MESSAGE_LOST
mov ebx, eax
mov [ebx.VCAND_Data.Message], can_MESSAGE_LOST
call VCAND_Post_Message ; post WM_CAN message
Idle_Check_Node:
cmp cx, dx ; current node = last node ?
je short Idle_Exit
inc dx
jmp short Idle_Get_Node ; get next node
Idle_Exit:
or [ebp.Client_Flags], CF_Mask ; set the client carry flag
ret
EndProc VCAND_Idle_Handler
;****************************************************************************
;* IRQ: VCAND_Hw_Int_Proc *
;* *
;* DESCRIPTION: *
;* Hardware interrupt handler. Called by VPICD. This is the so called *
;* Interrupt Service Routine ISR. *
;* *
;* ENTRY: *
;* EAX : IRQ handle *
;* EBX : current VM handle *
;* *
;* EXIT: *
;* Carry Flag : clc if IRQ successful processed *
;* stc if IRQ unsuccessful processed *
;* *
;****************************************************************************
BeginProc VCAND_Hw_Int_Proc
pushad ; save 32 bit registers
mov ecx, eax ; save IRQ handle
mov [VCAND_Cur_VM], ebx
call VCAND_Get_Node_By_IRQ_Handle ; get first node
ISR_Node_Check:
mov ebx, [VCAND_Node]
mov dx, [ebx.VCAND_Data.INT_REG] ; get address of INT_REG
in al, dx ; read INT_REG
test ax, 1Fh ; is an INT bit set ?
jnz short ISR_Node_Found ; yes, this is the node which
; caused the interrupt
mov ebx, ecx ; no, look for next node
call VCAND_Get_Next_Node_By_IRQ_Handle
cmp eax, 0 ; is there a next node ?
jz ISR_Exit ; no -> "phantom-IRQ"
jmp short ISR_Node_Check ; yes -> check this node
ISR_Node_Found:
mov ebx, [VCAND_Node]
bt [ebx.VCAND_Data.Status], ST_IRQ ; IRQ status ?
jnc ISR_Exit
test ax, 04h ; error interrupt ?
jnz ISR_Error
test ax, 08h ; overrun interrupt ?
jnz ISR_Overrun
test ax, 01h ; receive interrupt ?
jnz short ISR_Receive
test ax, 02h ; transmit interrupt ?
jnz ISR_Transmit
test ax, 10h ; wake up interrupt ?
jnz ISR_Wake_Up
ISR_Receive:
ISR_Receive_Get_ID:
mov dx, [ebx.VCAND_Data.RRTR_REG]
xor ecx, ecx
xor ax, ax
in al, dx ; ID bits 0..2 in RRTR_REG
shr ax, 5 ; shift to correct position
mov cx, ax ; save ID bits 0..2 in cx
xor ax, ax
mov dx, [ebx.VCAND_Data.RXID_REG]
in al, dx ; ID bits 3..10 in RXID_REG
shl ax, 3 ; shift to correct position
or cx, ax ; complete ID in CX !
ISR_Receive_Filter_Check:
mov eax, [ebx.VCAND_Data.Filter]
bt [eax], ecx ; is msg in filter ?
jnc short ISR_Receive_RX_Check
inc [ebx.VCAND_Data.Num_Filtered]
jmp ISR_Receive_Ready
ISR_Receive_RX_Check:
mov eax, [ebx.VCAND_Data.BufSize]
cmp [ebx.VCAND_Data.Num_RX], eax
jge short ISR_Receive_Check_Number
inc [ebx.VCAND_Data.Num_RX]
ISR_Receive_Check_Number:
mov eax, [ebx.VCAND_Data.Num_RX]
cmp ax, [ebx.VCAND_Data.RX_HWND_Num]
jng short ISR_Receive_Save_Message ; RX_HWND_Num msgs available?
bt [ebx.VCAND_Data.Status], ST_REQUEST_SEND
jc short ISR_Receive_Save_Message ; CM_REQUEST_MESSAGES send ?
bts [ebx.VCAND_Data.Status], ST_REQUEST_SEND
mov [ebx.VCAND_Data.Message], can_REQUEST_MESSAGES
call VCAND_Post_Message ; post WM_CAN message
ISR_Receive_Save_Message:
mov edx, [ebx.VCAND_Data.RX_Write] ; pointer to recv buffer
mov [edx.VCAND_Message.ID], cx ; save message id
mov ecx, edx ; save RX_Write in ecx
xor ax, ax
mov dx, [ebx.VCAND_Data.RRTR_REG]
in al, dx ; read RXID buffer
mov edx, ecx ; restore RW_Write
xor cl, cl
bt al, 4 ; rtr bit = 1 ?
rcl cl, 1 ; copy carry to cl.0
mov [edx.VCAND_Message.RTR], cl ; save message rtr
and ax, 0Fh ; mask out id and rtr
mov [edx.VCAND_Message.DLC], al ; save message dlc
VMMCall Get_System_Time ; get system time
mov ecx, [ebx.VCAND_Data.Time_Base] ; get time base
sub eax, ecx ; system time - time base
mov [edx.VCAND_Message.Time], eax ; save message time
mov ecx, edx ; save RX_Write in ecx
lea edi, [ecx] + 4 ; save b1..b4 here
mov dx, [ebx.VCAND_Data.RXB1] ; port address of RXB1
insd ; read and save b1..b4
lea edi, [ecx] + 8 ; save b5..b8 here
mov dx, [ebx.VCAND_Data.RXB5] ; port address of RXB5
insd ; read and save b5..b8
ISR_Receive_Inc_RX_Write:
add ecx, [VCAND_Message_Size] ; inc RX_Write
cmp ecx, [ebx.VCAND_Data.RX_Top] ; RX_Write = RX_Top ?
jne short ISR_Receive_Overrun_Check
mov ecx, [ebx.VCAND_Data.RX_Bottom] ; set RX_Write = RX_Bottom
ISR_Receive_Overrun_Check:
cmp ecx, [ebx.VCAND_Data.RX_LastMsg] ; RX_Write = RX_LastMsg ?
jne short ISR_Receive_No_Overrun
mov [ebx.VCAND_Data.Message], can_OVERRUN
call VCAND_Post_Message ; post WM_CAN message
inc [ebx.VCAND_Data.Num_Overrun]
ISR_Receive_No_Overrun:
mov [ebx.VCAND_Data.RX_Write], ecx ; save new RX_Write pointer
ISR_Receive_Ready:
jmp short ISR_Clear_Buffer
ISR_Transmit:
call VCAND_Send_Message ; send one message
jmp short ISR_Exit
ISR_Error:
inc [ebx.VCAND_Data.Num_Error]
mov [ebx.VCAND_Data.Message], can_ERROR
call VCAND_Post_Message ; post WM_CAN message
jmp short ISR_Exit
ISR_Overrun:
inc [ebx.VCAND_Data.Num_Overrun]
mov [ebx.VCAND_Data.Message], can_OVERRUN
call VCAND_Post_Message ; post WM_CAN message
jmp short ISR_Clear_Buffer
ISR_Wake_Up:
inc [ebx.VCAND_Data.Num_Wake_Up]
mov [ebx.VCAND_Data.Message], can_WAKEUP
call VCAND_Post_Message ; post WM_CAN message
jmp short ISR_Exit
ISR_Clear_Buffer:
mov ax, 0Ch
mov dx, [ebx.VCAND_Data.COMM_REG]
out dx, al ; release receive buffer
mov dx, [ebx.VCAND_Data.STAT_REG]
in al, dx
test al, 01h ; message in 2nd buffer ?
jnz ISR_Receive
ISR_Exit:
mov dx, [ebx.VCAND_Data.INT_REG]
in al, dx ; clear interrupt register
popad ; restore 32 bit register
VxDCall VPICD_Phys_EOI ; unmask IRQ in VPICD
clc ; IRQ successful handled
ret
EndProc VCAND_Hw_Int_Proc
;****************************************************************************
;* *
;* VCAND_Get_Node_By_IRQ_Handle *
;* *
;* DESCRIPTION: *
;* Returns in EAX and VCAND_Node variable the handle to the node which *
;* IRQ_Handle is given in EBX. Returns zero and Carry flag set if no *
;* Node with this IRQ_Handle found. *
;* *
;* ENTRY: *
;* EAX : IRQ Handle. *
;* *
;* EXIT: *
;* VCAND_Node : Handle to Node or zero. *
;* EAX : Handle to Node or zero. *
;* Carry Flag : Set if no Node with this IRQ_Handle found. *
;* *
;* USES: *
;* EAX, EBX *
;* *
;****************************************************************************
BeginProc VCAND_Get_Node_By_IRQ_Handle
push ecx
push edx
mov [VCAND_Node_Ptr], OFFSET32 VCAND_Node1
; points to Node1 var
Get_Node_IRQ_Compare:
mov edx, [VCAND_Node_Ptr]
mov ebx, [edx]
test ebx, 0FFFFFFFFh ; exist Node ?
jz short Get_Node_IRQ_Failed
mov ecx, [ebx.VCAND_Data.IRQ_Handle]
cmp ecx, eax ; current IRQ = searched IRQ ?
jz short Get_Node_IRQ_Success
add [VCAND_Node_Ptr], 4 ; get next node
jmp short Get_Node_IRQ_Compare
Get_Node_IRQ_Failed:
stc ; set carry flag - error!
jmp short Get_Node_IRQ_Exit
Get_Node_IRQ_Success:
clc ; clear carry flag - success!
Get_Node_IRQ_Exit:
mov [VCAND_Node], ebx ; save handle in VCAND_Node
mov eax, ebx
pop edx
pop ecx
ret
EndProc VCAND_Get_Node_By_IRQ_Handle
;****************************************************************************
;* *
;* VCAND_Get_Next_Node_By_IRQ_Handle *
;* *
;* DESCRIPTION: *
;* Returns in EAX and VCAND_Node variable the handle to the node which *
;* IRQ_Handle is given in EBX. Also VCAND_Node_Ptr points not to *
;* VCAND_Node1. Returns zero and Carry flag set if there is no more *
;* Node with this IRQ_Handle. This function should only used directly *
;* after a VCAND_Get_Node_By_IRQ_Handle call since there is no search *
;* initialization. *
;* *
;* ENTRY: *
;* EBX : IRQ Handle. *
;* *
;* EXIT: *
;* VCAND_Node : Handle to Node or zero. *
;* EAX : Handle to Node or zero. *
;* Carry Flag : Set on error. *
;* *
;* USES: *
;* EAX, EBX *
;* *
;****************************************************************************
BeginProc VCAND_Get_Next_Node_By_IRQ_Handle
push ecx
push edx
Get_Next_Node_IRQ_Compare:
mov edx, [VCAND_Node_Ptr]
mov eax, [edx]
test eax, 0FFFFFFFFh ; exist Node ?
jz short Get_Next_Node_IRQ_Failed
mov ecx, [eax.VCAND_Data.IRQ_Handle]
cmp ecx, ebx ; current IRQ = searched IRQ ?
jz short Get_Next_Node_IRQ_Success
add [VCAND_Node_Ptr], 4 ; get next node
jmp short Get_Next_Node_IRQ_Compare
Get_Next_Node_IRQ_Failed:
stc ; set carry flag - error!
jmp short Get_Next_Node_IRQ_Exit
Get_Next_Node_IRQ_Success:
clc ; clear carry flag - success!
Get_Next_Node_IRQ_Exit:
mov [VCAND_Node], eax ; save handle in VCAND_Node
pop edx
pop ecx
ret
EndProc VCAND_Get_Next_Node_By_IRQ_Handle
;****************************************************************************
;* *
;* VCAND_Send_Message *
;* *
;* DESCRIPTION: *
;* Copy the message in TX_Buffer at TX_Read position to the controller *
;* transmit buffer and forces the chip to transmit this message. If *
;* no messages to send, the function reset the ST_SEND status bit. *
;* *
;* ENTRY: *
;* EBX : VCAND_Data *
;* *
;* EXIT: *
;* Carry clear : Success *
;* ST_SEND : 1 if more messages to send, 0 if not *
;* *
;****************************************************************************
BeginProc VCAND_Send_Message
cmp [ebx.VCAND_Data.Num_TX], 0 ; messages to send ?
jne short Send_Message_Copy
btr [ebx.VCAND_Data.Status], ST_SEND ; clear ST_SEND flag
mov ecx, [ebx.VCAND_Data.TX_LastMsg]
mov [ebx.VCAND_Data.TX_Read], ecx
mov [ebx.VCAND_Data.Message], can_SEND_MESSAGES
call VCAND_Post_Message ; post WM_CAN message
jmp short Send_Message_Exit
Send_Message_Copy:
dec [ebx.VCAND_Data.Num_TX]
mov ecx, [ebx.VCAND_Data.TX_Read] ; ptr to message in ebx
mov dx, [ebx.VCAND_Data.TXID_REG]
mov ax, [ecx.VCAND_Message.ID]
shr ax, 3 ; ID.3-ID.10
out dx, al ; write to TXID_REG
mov ax, [ecx.VCAND_Message.ID]
and ax, 07h ; delete ID.3-ID.10
shl ax, 1 ; shift left for RTR
or al, [ecx.VCAND_Message.RTR] ; copy RTR
shl ax, 4 ; shift left for DLC
or al, [ecx.VCAND_Message.DLC] ; copy DLC
mov dx, [ebx.VCAND_Data.TRTR_REG]
out dx, al ; write TRTR_REG
add ecx, 4 ; points to first data
mov dx, [ebx.VCAND_Data.TXB1] ; port address of TXB1
mov eax, [ecx]
out dx, eax ; TXB1...TXB4
add ecx, 4 ; points to fifth data
mov dx, [ebx.VCAND_Data.TXB5] ; port address of TXB1
mov eax, [ecx]
out dx, eax ; TXB5...TXB8
mov dx, [ebx.VCAND_Data.COMM_REG]
mov ax, 01 ; transmission request
out dx, al
add ecx, 8 ; increment read ptr
cmp ecx, [ebx.VCAND_Data.TX_Top] ; is read ptr at the top ?
jne short Send_Message_Exit
mov ecx, [ebx.VCAND_Data.TX_Bottom]
Send_Message_Exit:
mov [ebx.VCAND_Data.TX_Read], ecx
clc
ret
EndProc VCAND_Send_Message
;****************************************************************************
;* *
;* VCAND_Post_Message *
;* *
;* DESCRIPTION: *
;* This function register the VCAND_Post_Message_Now function in the *
;* VMM which calls the CAN_Callback function in CAN.DLL. *
;* *
;* ENTRY: *
;* EBX : VCAND_Data *
;* *
;* EXIT: *
;* Carry clear : Success *
;* *
;****************************************************************************
BeginProc VCAND_Post_Message
pushad
bt [ebx.VCAND_Data.Status], ST_CALLBACK_PENDING
jc short Post_Message_Exit_Error
bt [ebx.VCAND_Data.Status], ST_POST_MESSAGES
jnc short Post_Message_Exit
bts [edx.VCAND_Data.Status], ST_CALLBACK_PENDING
mov dx, [ebx.VCAND_Data.Message]
mov [ebx.VCAND_Data.Msg_To_Send],dx ; this is the msg to send!
mov edx, ebx ; Node as ref.dat. for callb.
VMMcall Get_Sys_VM_Handle
mov eax, Low_Pri_Device_Boost
mov ecx, PEF_Wait_For_STI or PEF_Wait_Not_Crit
mov esi, OFFSET32 VCAND_Post_Message_Now
VMMcall Call_Priority_VM_Event
jmp short Post_Message_Exit
Post_Message_Exit_Error:
bts [ebx.VCAND_Data.Status], ST_MESSAGE_LOST
Post_Message_Exit:
popad
clc
ret
EndProc VCAND_Post_Message
;****************************************************************************
;* *
;* VCAND_Post_Message_Now *
;* *
;* DESCRIPTION: *
;* This function is called by the VMM. It takes the current *
;* message in VCAND_Node data and "sends" it to a windows appl. by *
;* calling CAN_Callback in CAN.DLL . *
;* *
;* ENTRY: *
;* EDX : VCAND_Data of calling Node *
;* *
;* EXIT: *
;* *
;****************************************************************************
BeginProc VCAND_Post_Message_Now
Push_Client_State
movzx eax, [VCAND_PostMsg_Seg] ; is callback addr NULL?
or eax, [VCAND_PostMsg_Off32]
jz short Post_Message_Now_Exit
VMMcall Begin_Nest_Exec ; prepare to call VM
;; The callback in the CAN.DLL is prototyped as follows:
;; void FAR PASCAL CAN_Callback( WORD ID, WORD wParam )
xor eax, eax
mov ax, [edx.VCAND_Data.CAN] ; push CAN ID
VMMcall Simulate_Push
xor eax, eax
mov ax, [edx.VCAND_Data.Msg_To_Send] ; push message type
VMMcall Simulate_Push
mov cx, [VCAND_PostMsg_Seg] ; CX:EDX -> ...CAN_Callback
mov edx, [VCAND_PostMsg_Off32]
VMMcall Simulate_Far_Call ; set stuff up for call
VMMcall Resume_Exec ; finally! call it (immediate)
VMMcall End_Nest_Exec ; done with that
Post_Message_Now_Exit:
Pop_Client_State
btr [edx.VCAND_Data.Status], ST_CALLBACK_PENDING
ret
EndProc VCAND_Post_Message_Now
VxD_LOCKED_CODE_ENDS
;****************************************************************************
;* C O D E *
;****************************************************************************
VxD_CODE_SEG
;****************************************************************************
;* *
;* VCAND_Get_Node_By_ID *
;* *
;* DESCRIPTION: *
;* Returns in EAX and VCAND_Node variable the handle to the node which *
;* CAN ID is given in EBX. Returns zero and Carry flag set is CAN ID *
;* is not valid. *
;* *
;* ENTRY: *
;* EBX : CAN ID of the node. *
;* *
;* EXIT: *
;* VCAND_Node : Handle to Node or zero. *
;* EAX : Handle to Node or zero. *
;* Carry Flag : Set on error. *
;* *
;* USES: *
;* EAX, EBX *
;* *
;****************************************************************************
BeginProc VCAND_Get_Node_By_ID
push ecx
push edx
cmp bx, [VCAND_Num_Of_Nodes] ; valid CAN ID number ?
ja short Get_Node_ID_Failed
mov [VCAND_Node_Ptr], OFFSET32 VCAND_Node1
; points to Node1 var
Get_Node_ID_Compare:
mov edx, [VCAND_Node_Ptr]
mov eax, [edx]
mov cx, [eax.VCAND_Data.CAN]
cmp cx, bx ; current CAN = searched CAN ?
jz short Get_Node_ID_Success
add [VCAND_Node_Ptr], 4 ; get next node
jmp short Get_Node_ID_Compare
Get_Node_ID_Failed:
mov eax, 0 ; return zero handle
stc ; set carry flag - error!
jmp short Get_Node_ID_Exit
Get_Node_ID_Success:
clc ; clear carry flag - success!
Get_Node_ID_Exit:
mov [VCAND_Node], eax ; save handle in VCAND_Node
pop edx
pop ecx
ret
EndProc VCAND_Get_Node_By_ID
;****************************************************************************
;* *
;* VCAND_Get_Reg *
;* *
;* DESCRIPTION: *
;* Returns the value of the Register specified in EDX *
;* *
;* ENTRY: *
;* EDX : Port address of the Register *
;* *
;* EXIT: *
;* AX : value of the Register *
;* *
;****************************************************************************
BeginProc VCAND_Get_Reg
xor ax, ax
in al, dx
ret
EndProc VCAND_Get_Reg
;****************************************************************************
;* *
;* VCAND_Get_Reg_With_Reset *
;* *
;* DESCRIPTION: *
;* Returns the value of the Register specified in EDX.While requesting *
;* the value the Controller Chip is switched into its reset mode. *
;* *
;* ENTRY: *
;* [VCAND_Node] : VCAND_Data *
;* EDX : Port address of the Register *
;* *
;* EXIT: *
;* AX : value of the Register *
;* *
;****************************************************************************
BeginProc VCAND_Get_Reg_With_Reset
push ebx
push edx
mov ebx, edx ; save Port addres
mov eax, [VCAND_Node]
mov dx, [eax.VCAND_Data.CONT_REG]
in al, dx
push eax ; save current COMM_REG
mov ax, 01h
out dx, al ; set RESET-REQUEST
mov edx, ebx ; restore port addres
xor ax, ax
in al, dx
mov bx, ax ; save register value
mov eax, [VCAND_Node]
mov dx, [eax.VCAND_Data.CONT_REG]
pop eax
out dx, al ; restore old COMM_REG
mov ax, bx ; restore register value
pop edx
pop ebx
ret
EndProc VCAND_Get_Reg_With_Reset
;****************************************************************************
;* *
;* VCAND_Set_Reg *
;* *
;* DESCRIPTION: *
;* Set the new value given in AX to the register given in EDX. *
;* *
;* ENTRY: *
;* CX : New value for the register *
;* EDX : Port address of the Register *
;* *
;****************************************************************************
BeginProc VCAND_Set_Reg
push eax
mov eax, ecx
out dx, al ; set the new value
pop eax
ret
EndProc VCAND_Set_Reg
;****************************************************************************
;* *
;* VCAND_Set_Reg_With_Reset *
;* *
;* DESCRIPTION: *
;* Set the new value given in AX to the register given in EDX. While *
;* setting the value the Controller Chip is switched into its reset *
;* mode. *
;* *
;* ENTRY: *
;* [VCAND_Node] : VCAND_Data *
;* CX : New value for the register *
;* EDX : Port address of the Register *
;* *
;****************************************************************************
BeginProc VCAND_Set_Reg_With_Reset
push ebx
push edx
mov bx, dx ; save Port addres
mov eax, [VCAND_Node]
mov dx, [eax.VCAND_Data.CONT_REG]
in al, dx
push eax ; save current COMM_REG
mov ax, 01h
out dx, al ; set RESET-REQUEST
mov dx, bx ; restore Port address
mov ax, cx
out dx, al ; set new value
mov eax, [VCAND_Node]
mov dx, [eax.VCAND_Data.CONT_REG]
pop eax
out dx, al ; restore old COMM_REG
mov ax, bx ; restore register value
pop edx
pop ebx
ret
EndProc VCAND_Set_Reg_With_Reset
;****************************************************************************
;* *
;* API: VCAND_API_Proc *
;* *
;* DESCRIPTION: *
;* This is the exported API procedure that is callable from VM's. *
;* An application needs only to use INT 2Fh, AX=1684h, BX=device ID *
;* and a call back address is returned. Then, when the address is *
;* called, eventually it ends up here. *
;* *
;* *
;* ENTRY: *
;* EBX : VM Handle. *
;* EBP : Client register structure. *
;* Client_CS:IP : Instruction following API call. *
;* Client_AX : Function number. *
;* Client_BX : CAN ID *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : success *
;* Carry set : hosed *
;* *
;****************************************************************************
BeginProc VCAND_API_Proc
mov [VCAND_Cur_VM], ebx ; save current VM handle
movzx eax, [ebp.Client_AX] ; function #
movzx ebx, [ebp.Client_BX] ; CAN ID in ebx
movzx ecx, [ebp.Client_CX] ; Message ID in ecx
mov edx, [VCAND_Max_API]
cmp ax, VCAND_Max_API ; a valid service?
ja short VCAND_API_Failed ; function > VCAND_Max_API
jmp VCAND_API_Table[ eax * 4 ]
VCAND_API_Success:
mov ax, [ebp.Client_AX]
and [ebp.Client_EFlags], NOT CF_Mask
jmp short VCAND_API_Exit
VCAND_API_Failed:
mov [ebp.Client_AX], 0 ; FALSE return value
or [ebp.Client_EFlags], CF_Mask
VCAND_API_Exit:
ret
EndProc VCAND_API_Proc
;****************************************************************************
;* *
;* API: 00h VCAND_Get_Version *
;* *
;* DESCRIPTION: *
;* This service gets the version number of this VxD. The major *
;* version number is loaded into AH; the minor version number is *
;* stuffed into AL. *
;* *
;* ENTRY: *
;* EBX : VM Handle. *
;* EBP : Client register structure. *
;* Client_CS:IP : Instruction following API call. *
;* *
;* EXIT: *
;* Client: *
;* EAX : Major and minor version number. *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_Version
mov [ebp.Client_AX], (VCAND_VERMAJ shl 8) + VCAND_VERMIN
jmp VCAND_API_Success
EndProc VCAND_Get_Version
;****************************************************************************
;* *
;* API: 01h VCAND_Set_Filter *
;* *
;* DESCRIPTION: *
;* Sets the bit belonging to the Message ID in the buffer belonging to *
;* CAN ID so that this message is in the filter and will NOT be *
;* noticed. It also clears the receive buffer. *
;* *
;* ENTRY: *
;* EBX : CAN ID *
;* ECX : Message ID *
;* EDX : 1 = set filter and reset RX buffer *
;* everything else = only set filter *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* EAX : 1 => Success, 0 => failed *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_Filter
mov [VCAND_Dummy1], edx ; save reset buffer info
cmp cx, 7FFh ; Message ID > 2047 ?
jg VCAND_API_Failed
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
mov eax, [ebx.VCAND_Data.Filter]
bts [eax], ecx
mov ecx, [VCAND_Dummy1] ; restore reset buffer info
cmp ecx, 1 ; reset RX buffer ?
jne short Set_Filter_Exit
bt [ebx.VCAND_Data.Status], ST_BUFFER
jnc short Set_Filter_Exit
bt [ebx.VCAND_Data.Status], ST_IRQ
jnc short Set_Filter_Exit
bts [ebx.VCAND_Data.Status], ST_FILTER ; set ST_FILTER status
mov eax, [ebx.VCAND_Data.IRQ_Handle]
VxDCall VPICD_Physically_Mask ; disable IRQ
mov [ebx.VCAND_Data.Num_RX], 0 ; reset RX_Num
mov edx, [ebx.VCAND_Data.RX_Bottom]
mov [ebx.VCAND_Data.RX_Write], edx
mov [ebx.VCAND_Data.RX_LastMsg], edx
VxDCall VPICD_Physically_Unmask ; enable IRQ
Set_Filter_Exit:
jmp VCAND_API_Success
EndProc VCAND_Set_Filter
;****************************************************************************
;* *
;* API: 02h VCAND_Get_Filter *
;* *
;* DESCRIPTION: *
;* Checks, if the bit belonging to the Message ID in the filter buffer *
;* belonging to CAN ID is set or not. So it checks, if this messages *
;* is in the filter or not. Returns Client_AX = 1 if the Message ID is *
;* in the filter and Client_AX = 0 if not. *
;* *
;* ENTRY: *
;* EBX : CAN ID *
;* ECX : Message ID *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : 0 = Msg not in filter, 1 = Msg in filter *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_Filter
cmp cx, 7FFh ; Message ID > 2047 ?
jg VCAND_API_Failed
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
mov eax, [ebx.VCAND_Data.Filter]
bt [eax], ecx
jc short Get_Filter_Found ; it is !
mov [ebp.Client_AX], 0 ; Message NOT in Filter
jmp short Get_Filter_Exit
Get_Filter_Found:
mov [ebp.Client_AX], 1 ; Message in Filter
Get_Filter_Exit:
jmp VCAND_API_Success
EndProc VCAND_Get_Filter
;****************************************************************************
;* *
;* API: 03h VCAND_Reset_Filter *
;* *
;* DESCRIPTION: *
;* Reset the filter buffer of CAN ID so that all messages will be *
;* noticed and clears the receive buffer. *
;* *
;* ENTRY: *
;* EBX : CAN ID *
;* ECX : Message ID to be resetted. *
;* 2048 = reset complete filter. *
;* EDX : 1 = reset filter and reset RX buffer *
;* everything else = only reset filter *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* EAX : 1 => Success, 0 => failed *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Reset_Filter
mov [VCAND_Dummy1], edx ; save reset buffer info
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov edx, eax
mov ebx, [edx.VCAND_Data.Filter] ; pointer to filter in ebx
cmp cx, 2048
je short Reset_Filter_Complete
Reset_Filter_Single:
btr [ebx], ecx ; reset single message
jmp short Reset_Filter_Check
Reset_Filter_Complete: ; reset complete filter
mov eax, [VCAND_Filter_Size]
mov ecx, 0 ; fill data
Fill_Data:
mov [ebx], ecx ; "0" in buffer
inc ebx ; next byte in buffer
dec eax ; buffer full ?
jnz short Fill_Data
Reset_Filter_Check:
mov ecx, [VCAND_Dummy1] ; restore reset buffer info
cmp ecx, 1 ; reset RX buffer ?
jne short Reset_Filter_Exit
bt [edx.VCAND_Data.Status], ST_BUFFER ; Buffers allocated ?
jnc short Reset_Filter_Exit
bt [edx.VCAND_Data.Status], ST_IRQ ; IRQ enabled ?
jnc short Reset_Filter_Exit
mov eax, [edx.VCAND_Data.IRQ_Handle]
VxDCall VPICD_Physically_Mask ; disable IRQ
mov [edx.VCAND_Data.Num_RX], 0 ; reset RX_Num
mov ebx, [edx.VCAND_Data.RX_Bottom]
mov [edx.VCAND_Data.RX_Write], ebx
mov [edx.VCAND_Data.RX_LastMsg], ebx
VxDCall VPICD_Physically_Unmask ; enable IRQ
Reset_Filter_Exit:
jmp VCAND_API_Success
EndProc VCAND_Reset_Filter
;****************************************************************************
;* *
;* API: 04h VCAND_Set_CONT_REG *
;* *
;* DESCRIPTION: *
;* Set the Control Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Control Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_CONT_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.CONT_REG] ; get port address
call VCAND_Set_Reg ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_CONT_REG
;****************************************************************************
;* *
;* API: 05h VCAND_Set_COMM_REG *
;* *
;* DESCRIPTION: *
;* Set the Command Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Command Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_COMM_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.COMM_REG] ; get port address
call VCAND_Set_Reg ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_COMM_REG
;****************************************************************************
;* *
;* API: 06h VCAND_Set_ACC_REG *
;* *
;* DESCRIPTION: *
;* Set the Acceptance Code Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Acceptance Code Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_ACC_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.ACC_REG] ; get port address
call VCAND_Set_Reg_With_Reset ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_ACC_REG
;****************************************************************************
;* *
;* API: 07h VCAND_Set_ACM_REG *
;* *
;* DESCRIPTION: *
;* Set the Acceptance Mask Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Acceptance Mask Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_ACM_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.ACM_REG] ; get port address
call VCAND_Set_Reg_With_Reset ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_ACM_REG
;****************************************************************************
;* *
;* API: 08h VCAND_Set_BT0_REG *
;* *
;* DESCRIPTION: *
;* Set the Bus Timing Register 0 in the 80C200 controller chip. This *
;* function should be used together witch VCAND_Set_BT1_REG to set a *
;* new Bitrate per second. *
;* *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for BTR0 *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_BT0_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.BT0_REG] ; get port address
call VCAND_Set_Reg_With_Reset ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_BT0_REG
;****************************************************************************
;* *
;* API: 09h VCAND_Set_BT1_REG *
;* *
;* DESCRIPTION: *
;* Set the Bus Timing Register 1 in the 80C200 controller chip. This *
;* function should be used together witch VCAND_Set_BT0_REG to set a *
;* new Bitrate per second. *
;* *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for BTR1 *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_BT1_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.BT1_REG] ; get port address
call VCAND_Set_Reg_With_Reset ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_BT1_REG
;****************************************************************************
;* *
;* API: 0Ah VCAND_Set_OUTP_REG *
;* *
;* DESCRIPTION: *
;* Set the Output Control Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Output Control Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_OUTP_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.OUTP_REG] ; get port address
call VCAND_Set_Reg_With_Reset ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_OUTP_REG
;****************************************************************************
;* *
;* API: 0Bh VCAND_Set_CLKD_REG *
;* *
;* DESCRIPTION: *
;* Set the Clock Divider Register in the 80C200 controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : new value for the Clock Divider Register *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Set_CLKD_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.CLKD_REG] ; get port address
call VCAND_Set_Reg ; set new value to register
jmp VCAND_API_Success
EndProc VCAND_Set_CLKD_REG
;****************************************************************************
;* *
;* API: 0Ch VCAND_Get_CONT_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Control Register in the 80C200 *
;* controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Control Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_CONT_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.CONT_REG] ; get port address
call VCAND_Get_Reg ; get register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_CONT_REG
;****************************************************************************
;* *
;* API: 0Dh VCAND_Get_STAT_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Status Register in the 80C200 *
;* controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Status Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_STAT_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.STAT_REG] ; get port address
call VCAND_Get_Reg ; get register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_STAT_REG
;****************************************************************************
;* *
;* API: 0Eh VCAND_Get_INT_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Interrupt Register in the 80C200 *
;* controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Interrupt Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_INT_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.INT_REG] ; get port address
call VCAND_Get_Reg ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_INT_REG
;****************************************************************************
;* *
;* API: 0Fh VCAND_Get_ACC_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Acceptance Code Register in the 80C200 *
;* controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Acceptance Code Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_ACC_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.ACC_REG] ; get port address
call VCAND_Get_Reg_With_Reset ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_ACC_REG
;****************************************************************************
;* *
;* API: 10h VCAND_Get_ACM_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Acceptance Mask Register in the 80C200 *
;* controller chip. To do this the chip is switched into reset mode. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Acceptance Mask Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_ACM_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.ACM_REG] ; get port address
call VCAND_Get_Reg_With_Reset ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_ACM_REG
;****************************************************************************
;* *
;* API: 11h VCAND_Get_BT0_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Bus Timing 0 Register in the 80C200 *
;* controller chip. To do this the chip is switched into reset mode. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Bus Timing 0 Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_BT0_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.BT0_REG] ; get port address
call VCAND_Get_Reg_With_Reset ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_BT0_REG
;****************************************************************************
;* *
;* API: 12h VCAND_Get_BT1_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Bus Timing 1 Register in the 80C200 *
;* controller chip. To do this the chip is switched into reset mode. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Bus Timing 1 Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_BT1_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.BT1_REG] ; get port address
call VCAND_Get_Reg_With_Reset ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_BT1_REG
;****************************************************************************
;* *
;* API: 13h VCAND_Get_OUTP_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Output Control Register in the 80C200 *
;* controller chip. To do this the chip is switched into reset mode. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Output Control Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_OUTP_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.OUTP_REG] ; get port address
call VCAND_Get_Reg_With_Reset ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_OUTP_REG
;****************************************************************************
;* *
;* API: 14h VCAND_Get_CLKD_REG *
;* *
;* DESCRIPTION: *
;* Returns the value of the Clock Divider Register in the 80C200 *
;* controller chip. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : value of the Clock Divider Register *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_CLKD_REG
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov dx, [eax.VCAND_Data.CLKD_REG] ; get port address
call VCAND_Get_Reg ; get the register value
mov [ebp.Client_AX], ax ; return value in AX
jmp VCAND_API_Success
EndProc VCAND_Get_CLKD_REG
;****************************************************************************
;* *
;* API: 15h VCAND_Get_Counter *
;* *
;* DESCRIPTION: *
;* Return the actual values of all internal counters *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : Received Counter *
;* BX : Transmit Counter *
;* CX : Error Counter *
;* DX : Overrun Counter *
;* SI : Wake Up Counter *
;* DI : Filtered Counter *
;* *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_Counter
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, [eax.VCAND_Data.Num_RX]
mov [ebp.Client_AX], bx
mov ebx, [eax.VCAND_Data.Num_TX]
mov [ebp.Client_BX], bx
mov ebx, [eax.VCAND_Data.Num_Error]
mov [ebp.Client_CX], bx
mov ebx, [eax.VCAND_Data.Num_Overrun]
mov [ebp.Client_DX], bx
mov ebx, [eax.VCAND_Data.Num_Wake_Up]
mov [ebp.Client_SI], bx
mov ebx, [eax.VCAND_Data.Num_Filtered]
mov [ebp.Client_DI], bx
jmp VCAND_API_Success
EndProc VCAND_Get_Counter
;****************************************************************************
;* *
;* API: 16h VCAND_Reset_Counter *
;* *
;* DESCRIPTION: *
;* Reset all or one specific counter. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* ECX : 0 - reset all Counters *
;* 1 - reset Num_Error *
;* 2 - reset Num_Overrun *
;* 3 - reset Num_Wake_Up *
;* 4 - reset Num_Filtered *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Reset_Counter
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
cmp cx, 0
jz short Reset_Counter_All
cmp cx, 1
jz short Reset_Counter_Error
cmp cx, 2
jz short Reset_Counter_Overrun
cmp cx, 3
jz short Reset_Counter_Wake_Up
cmp cx, 4
jz short Reset_Counter_Filtered
jmp VCAND_API_Failed
Reset_Counter_All:
mov [eax.VCAND_Data.Num_Error], 0
mov [eax.VCAND_Data.Num_Overrun], 0
mov [eax.VCAND_Data.Num_Wake_Up], 0
mov [eax.VCAND_Data.Num_Filtered], 0
jmp short Reset_Counter_Exit
Reset_Counter_Error:
mov [eax.VCAND_Data.Num_Error], 0
jmp short Reset_Counter_Exit
Reset_Counter_Overrun:
mov [eax.VCAND_Data.Num_Overrun], 0
jmp short Reset_Counter_Exit
Reset_Counter_Wake_Up:
mov [eax.VCAND_Data.Num_Wake_Up], 0
jmp short Reset_Counter_Exit
Reset_Counter_Filtered:
mov [eax.VCAND_Data.Num_Filtered], 0
Reset_Counter_Exit:
jmp VCAND_API_Success
EndProc VCAND_Reset_Counter
;****************************************************************************
;* *
;* API: 17h VCAND_Allocate_Buffer *
;* *
;* DESCRIPTION: *
;* Allocates the memory for the send and receive buffer and init the *
;* pointer RX_xxx and TX_xxx. *
;* Usually this function is called while an application opens the *
;* CAN driver. The function checks, if the ST_INIT bit, the ST_BUFFER *
;* bit and the ST_IRQ bit in the Status variable is set. This *
;* function must be called BEFORE unmasking the IRQ. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Allocate_Buffer
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
bt [ebx.VCAND_Data.Status], ST_INIT ; INIT status ?
jnc VCAND_API_Failed
bt [ebx.VCAND_Data.Status], ST_BUFFER ; BUFFER status ?
jc VCAND_API_Failed
bt [ebx.VCAND_Data.Status], ST_IRQ ; IRQ status ?
jc VCAND_API_Failed
xor ecx, ecx
xor edx, edx
mov eax, [ebx.VCAND_Data.BufSize]
mov ecx, [VCAND_Message_Size]
mul ecx ; calculating buffer size
push eax ; save size of 1 buffer
mov ecx, 2
mul ecx
jc short Allocate_Buffer_Error2
jz short Allocate_Buffer_Error2
mov ecx, eax ; size of 2 buffers in ecx
VMMCall _HeapAllocate,
cmp eax, 0
jz short Allocate_Buffer_Error2
mov ebx, eax ; save base pointer in ebx
shr eax, 12
VMMCall _LinPageLock,
cmp eax, 0
jz short Allocate_Buffer_Error1
pop edx ; restore size of 1 buffeer
mov eax, ebx ; restore base pointer
mov ebx, [VCAND_Node]
mov [ebx.VCAND_Data.RX_Bottom], eax ; RX_Bottom
mov [ebx.VCAND_Data.RX_Write], eax ; RX_Write
mov [ebx.VCAND_Data.RX_LastMsg],eax ; RX_LastMsg
add eax, edx
mov [ebx.VCAND_Data.RX_Top], eax ; RX_Top
mov [ebx.VCAND_Data.TX_Bottom], eax ; TX_Bottom
mov [ebx.VCAND_Data.TX_Read], eax ; TX_Read
mov [ebx.VCAND_Data.TX_LastMsg],eax ; TX_LastMsg
add eax, edx
mov [ebx.VCAND_Data.TX_Top], eax ; TX_Top
jmp short Allocate_Buffer_Exit
Allocate_Buffer_Error1:
VMMCall _HeapFree, ; free memory
Allocate_Buffer_Error2:
mov [ebx.VCAND_Data.RX_Bottom], 0 ; clear pointers
mov [ebx.VCAND_Data.RX_Top], 0
mov [ebx.VCAND_Data.RX_Write], 0
mov [ebx.VCAND_Data.RX_LastMsg], 0
mov [ebx.VCAND_Data.TX_Bottom], 0
mov [ebx.VCAND_Data.TX_Top], 0
mov [ebx.VCAND_Data.TX_Read], 0
mov [ebx.VCAND_Data.TX_LastMsg], 0
btr [ebx.VCAND_Data.Status], ST_BUFFER ; reset BUFFER status
jmp VCAND_API_Failed
Allocate_Buffer_Exit:
mov [ebx.VCAND_Data.Num_RX], 0 ; empty receive buffer
mov [ebx.VCAND_Data.Num_TX], 0 ; empty transmit buffer
bts [ebx.VCAND_Data.Status], ST_BUFFER ; set BUFFER status
jmp VCAND_API_Success
EndProc VCAND_Allocate_Buffer
;****************************************************************************
;* *
;* API: 18h VCAND_Free_Buffer *
;* *
;* DESCRIPTION: *
;* Free the memory of send and receive buffer and set the RX_xxx and *
;* TX_xxx pointer to zero. Usually this function is called while an *
;* application opens the CAN driver. This function checks if the *
;* ST_INIT bit, the ST_BUFFER bit and the ST_IRQ bit in the Status *
;* variable is set. This function can only be called AFTER masking *
;* the interrupt ! *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Free_Buffer
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
bt [ebx.VCAND_Data.Status], ST_INIT ; INIT status ?
jnc VCAND_API_Failed
bt [ebx.VCAND_Data.Status], ST_BUFFER ; BUFFER status ?
jnc VCAND_API_Failed
bt [ebx.VCAND_Data.Status], ST_IRQ ; IRQ status ?
jc VCAND_API_Failed
mov eax, [ebx.VCAND_Data.RX_Bottom] ; base pointer to buffers
VMMCall _HeapFree, ; free both buffers
cmp eax, 0
jz VCAND_API_Failed
mov [ebx.VCAND_Data.RX_Bottom], 0 ; clear pointers
mov [ebx.VCAND_Data.RX_Top], 0
mov [ebx.VCAND_Data.RX_Write], 0
mov [ebx.VCAND_Data.RX_LastMsg], 0
mov [ebx.VCAND_Data.TX_Bottom], 0
mov [ebx.VCAND_Data.TX_Top], 0
mov [ebx.VCAND_Data.TX_Read], 0
mov [ebx.VCAND_Data.TX_LastMsg], 0
btr [ebx.VCAND_Data.Status], ST_BUFFER ; reset BUFFER status
jmp VCAND_API_Success
EndProc VCAND_Free_Buffer
;****************************************************************************
;* *
;* API: 19h VCAND_Mask_IRQ *
;* *
;* DESCRIPTION: *
;* Mask physically the interrupt for the given CAN ID. *
;* Usually this function is called while an application closes the *
;* CAN driver. To mask an IRQ the ST_INIT bit and the ST_BUFFER bit *
;* in the Status variable must be set. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Mask_IRQ
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
bt [eax.VCAND_Data.Status], ST_INIT ; INIT status ?
jnc VCAND_API_Failed
bt [eax.VCAND_Data.Status], ST_BUFFER ; BUFFER status ?
jnc VCAND_API_Failed
btr [eax.VCAND_Data.Status], ST_IRQ ; reset IRQ status
mov ebx, [eax.VCAND_Data.IRQ_Handle]
mov eax, ebx
VxDCall VPICD_Physically_Mask
jmp VCAND_API_Success
EndProc VCAND_Mask_IRQ
;****************************************************************************
;* *
;* API: 1Ah VCAND_Unmask_IRQ *
;* *
;* DESCRIPTION: *
;* Unmask physically the interrupt for the given CAN ID. *
;* Usually this function is called while an application opens the *
;* CAN driver. To unmask an IRQ the ST_INIT bit and the ST_BUFFER bit *
;* in the Status variable must be set. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Unmask_IRQ
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
bt [ebx.VCAND_Data.Status], ST_INIT ; INIT status ?
jnc VCAND_API_Failed
bt [ebx.VCAND_Data.Status], ST_BUFFER ; BUFFER status ?
jnc VCAND_API_Failed
bts [ebx.VCAND_Data.Status], ST_IRQ ; set IRQ status
VMMCall Get_System_Time
mov [ebx.VCAND_Data.Time_Base], eax
mov eax, [ebx.VCAND_Data.IRQ_Handle]
VxDCall VPICD_Physically_Unmask
jmp VCAND_API_Success
EndProc VCAND_Unmask_IRQ
;****************************************************************************
;* *
;* API: 1Bh VCAND_Get_Status *
;* *
;* DESCRIPTION: *
;* Returns the actual value of the status word of the driver. *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* AX : actual status of CAN (ID) driver *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Get_Status
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov bx, [eax.VCAND_Data.Status] ; actual status word
mov [ebp.Client_AX], bx ; return status in ax
jmp VCAND_API_Success
EndProc VCAND_Get_Status
;****************************************************************************
;* *
;* API: 1Ch VCAND_Reset *
;* *
;* DESCRIPTION: *
;* Unmask IRQ, free all buffers, reset counters, reset status word *
;* (accept ST_INIT and ST_ERROR), reset controller, reset all window *
;* handles (HWND). *
;* *
;* This function does *NOT* reset the message filter ! *
;* *
;* ENTRY: *
;* EBX : CAN ID; *
;* EBP : Client register structure. *
;* *
;* EXIT: *
;* Client: *
;* Carry clear : Success. *
;* *
;****************************************************************************
BeginProc VCAND_Reset
call VCAND_Get_Node_By_ID ; node handle in eax
jc VCAND_API_Failed
mov ebx, eax
Reset_IRQ:
bt [ebx.VCAND_Data.Status], ST_IRQ
jnc short Reset_Buffer
mov eax, [ebx.VCAND_Data.IRQ_Handle]
VxDCall VPICD_Physically_Mask | |