📄 i2c.inc
字号:
;------------------------------------------------------------------------------;
; READ_I2C_DATA_BLOCK ;
;------------------------------------------------------------------------------;
; Input: AH = Slave address ;
; AL = device register index (command code) ;
; Output: ZF = 0 : fail ;
; ZF = 1 : success and CL = byte data read ;
; Modified: CL ;
;------------------------------------------------------------------------------;
public read_i2c_data_block
read_i2c_data_block proc near
pusha
sti
call ClearTCLSTS
;; Don't Destory CX
;Reset Host Status Registers
call IntelClearHostStatus
;Clock Generator Address = D3h
or dx,04h
lea si,SlaveAddress
mov al,ds:[si]
or al,01h
out dx,al
jmp short $+2
jmp short $+2
; Write 00h to Host Command Register
and dl,0f0h
or dx,03h
mov al,000h
out dx,al
jmp short $+2
jmp short $+2
; Number Of Bytes to Program (06h)
and dl,0f0h
or dx,05h
mov al,80h
out dx,al
jmp short $+2
jmp short $+2
; Start Block Write Command
and dl,0f0h
or dx,02h
mov al,54h
out dx,al
jmp short $+2
jmp short $+2
call IntelWaitByte0STS
;;; KenWang [050602] >>>>>>
lea si,CurrentVendorID
cmp dword ptr ds:[si],031471106h
jnz SkipPreReadSmbusBlockData
lea si,SmbusTempFlag
mov al,ds:[si]
cmp al,11h
jz SkipPreReadSmbusBlockData
push ax
mov al,11h
mov ds:[si],al
pop ax
lea si,SmbusAddress
mov cx,17
sub cl,al
PreReadLoop:
mov dx,ds:[si]
or dx,07h
in al,dx
loop PreReadLoop
SkipPreReadSmbusBlockData:
;;; KenWang [050602] <<<<<<
and dl,0f0h
or dx,05h
in al,dx
cmp al,0
jz skip_program_loopr
movzx ax,al
lea si,ReadDataRow
mov cl,ds:[si]
movzx cx,cl
loop_block_row:
push cx
mov cx,16
start_block_read:
push cx
lea si,SmbusAddress
mov dx,ds:[si]
or dx,07h
in al,dx
call DisplayDataAttribute
mov al,' '
call DisplayChar
jmp $+2
jmp $+2
call check_send_done
pop cx
loop start_block_read
lea si,crlf
call DisplayString
call GetCursor
mov dl,ValueStartCol
call SetCursor
pop cx
loop loop_block_row
skip_program_loopr:
popa
ret
read_i2c_data_block endp
;------------------------------------------------------------------------------;
; WRITE_I2C_DATA_BLOCK ;
;------------------------------------------------------------------------------;
; Input: AH = Slave address ;
; AL = device register index (command code) ;
; Output: ZF = 0 : fail ;
; ZF = 1 : success and CL = byte data read ;
; Modified: CL ;
;------------------------------------------------------------------------------;
public write_i2c_data_block
write_i2c_data_block proc near
call ClearTCLSTS
;Reset Host Status Registers
push cx
push si
call IntelClearHostStatus
;;; KenWang [050602] >>>>>>
lea si,SmbusTempFlag
mov al,01h
mov ds:[si],al
;;; KenWang [050602] <<<<<<
;Clock Generator Address = D2h
lea si,SmbusAddress
mov dx,ds:[si]
or dx,04h
lea si,SlaveAddress
mov al,ds:[si]
out dx,al
jmp $+2
; Write 00h to Host Command Register
and dl,0f0h
or dx,03h
mov al,000h
out dx,al
jmp short $+2
jmp short $+2
; Number Of Bytes to Program (06h)
and dl,0f0h
or dx,05h
call GetBlockSendCounts
out dx,al
jmp short $+2
jmp short $+2
; Write Byte 0 Control Register
mov dx,(ValueStartCol+ValueStartRow)
call CalaFixedCursorposn
call GetFixCursorValue
mov al,bl
lea si,SmbusAddress
mov dx,ds:[si]
and dl,0f0h
or dx,07h
out dx,al
jmp short $+2
jmp short $+2
; Start Block Write Command
and dl,0f0h
or dx,02h
mov al,54h
out dx,al
jmp short $+2
jmp short $+2
call IntelWaitByte0STS
mov cx, 12*20 ; 3ms
loop $
mov cx,WriteBlockRow
mov dx,(ValueStartCol+ValueStartRow)+0003h
post_start_block_write_row:
push cx
cmp cx,WriteBlockRow
mov cx,15
jz post_start_block_write
inc cx
post_start_block_write:
push cx
push dx
call CalaFixedCursorposn
call GetFixCursorValue
mov al,bl
lea si,SmbusAddress
mov dx,ds:[si]
and dl,0f0h
or dx,07h
out dx,al
jmp $+2
jmp $+2
call check_send_done
pop dx
add dl,3
pop cx
loop post_start_block_write
inc dh
mov dl,ValueStartCol
pop cx
loop post_start_block_write_row
post_skip_program_loop:
pop si
pop cx
ret
write_i2c_data_block endp
;------------------------------------------------------------------------------;
IntelWaitByte0STS:
mov cx,6
rdd_1:
out 0ebh,al
out 0ebh,al
jmp $+2
loop rdd_1
and dl,0f0h
mov cx,1800h
check_rbds1:
in al,dx
jmp short $+2
jmp short $+2
test al,80h
out 0ebh,al
out 0ebh,al
loopz short check_rbds1
ret
;------------------------------------------------------------------------------;
IntelClearHostStatus:
mov cx,200h
rbb1_c:
lea si,SmbusAddress
mov dx,ds:[si]
in al,dx
out dx,al
and al,not 60h
or al,al
jz status_okr
out 0ebh,al
jmp short $+2
out 0ebh,al
jmp short $+2
loop rbb1_c
status_okr:
ret
;------------------------------------------------------------------------------;
; READ_I2C_DATA_BYTE ;
;------------------------------------------------------------------------------;
; Input: AH = Slave address ;
; AL = device register index (command code) ;
; Output: ZF = 0 : fail ;
; ZF = 1 : success and CL = byte data read ;
; Modified: CL ;
;------------------------------------------------------------------------------;
public read_i2c_data_byte
read_i2c_data_byte proc near
; pushf
push ax
push dx
push bx
call ClearTCLSTS
cli
or ah,01h ; Read Command
call reset_smbus_host
mov al,48h ; byte access
call access_i2c_device
mov cl,0ffh
jnz read_i2c_byte_error
and dl,0f0h
or dl,05h ;base + 05h
in al,dx
mov cl,al
cmp sp,sp ;ZF = 1 for success
read_i2c_byte_error:
pop bx
pop dx
pop ax
; popf
ret
read_i2c_data_byte endp
;------------------------------------------------------------------------------;
; WRITE_I2C_DATA_BYTE ;
;------------------------------------------------------------------------------;
; Input: AH = Slave address ;
; AL = device register index (command code) ;
; CL = byte data to write ;
; Output: ZF = 0 : fail ;
; ZF = 1 : success ;
; Modified: nothing ;
;------------------------------------------------------------------------------;
public write_i2c_data_byte
write_i2c_data_byte proc near
; pushf
push ax
push dx
push bx
call ClearTCLSTS
cli
call reset_smbus_host
and dl,0f0h
or dl,05h ;base + 05h
mov al,cl
out dx,al
jmp $+2
jmp $+2
mov al,48h ;byte access
and ah,0feh
call access_i2c_device
jnz write_i2c_byte_error
cmp sp,sp ;ZF = 1 for success
write_i2c_byte_error:
pop bx
pop dx
pop ax
; popf
ret
write_i2c_data_byte endp
;------------------------------------------------------------------------------;
; ACCESS_I2C_DEVICE ;
;------------------------------------------------------------------------------;
; Input: AH = Slave address ;
; AL = 48h/4ch for byte/word ;
; DX = sMBUS ADDRESS
; Output: ZF = 0 : fail ;
; ZF = 1 : success ;
; Modified: AL, DX ;
;------------------------------------------------------------------------------;
access_i2c_device proc near
xchg al,ah
lea si,SmbusAddress
mov dx,ds:[si]
or dl,04h ;base + 04h
out dx,al ;Program the Address
jmp $+2
jmp $+2
xchg al,ah
and dl,0f0h
or dl,02h ;base + 02h
out dx,al
out 0ebh,al
jmp $+2
jmp $+2
push cx
xor cx,cx
mov cx,8000h
and dl,0f0h ;base + 00h
check_host_status:
in al,dx
out 0ebh,al
out 0ebh,al
jmp $+2
jmp $+2
dec cx
jz time_out
test al,00000100b ;error?
jnz access_i2c_device_error
test al,00000001b ;busy?
jnz check_host_status ;ZF = 0 for fail
test al,00000010b ;interrupt?
jz check_host_status
out dx,al ;Reset Host Status Registers
cmp sp,sp ;ZF = 1 for success
access_i2c_device_error:
pop cx
ret
time_out:
or al,0ffh
jmp short access_i2c_device_error
access_i2c_device endp
;------------------------------------------------------------------------------;
; RESET_SMBUS_HOST ;
;------------------------------------------------------------------------------;
; Input: AL = command byte ;
; Output: nothing ;
; Modified: nothing ;
;------------------------------------------------------------------------------;
reset_smbus_host proc near
push ax
push cx
lea si,SmbusAddress
mov dx,ds:[si]
call IntelClearHostStatus
; mov cx,200h
;ByteClearSTS:
; mov al,0ffh
; out dx,al ;Reset Host Status Registers
; jmp $+2
; in al,dx
; and al,not 60h
; or al,al
; jz status_okb
; loop ByteClearSTS
out dx,al ;Reset Host Status Registers
jmp $+2
out dx,al ;Reset Host Status Registers
jmp $+2
status_okb:
pop cx
pop ax
or dl,03h ;base + 03h
out dx,al ;Program the index
jmp $+2
jmp $+2
ret
reset_smbus_host endp
;------------------------------------------------------------------------------;
public check_send_done
check_send_done:
push dx
push cx
push si
; Clear Byte Done Status for Next Transmission.
lea si,SmbusAddress
mov dx,ds:[si]
mov al,0ffh
out dx,al
jmp short $+2
jmp short $+2
mov cx,100h
check_byte_done_sts_post:
push cx
mov cx,6
wait_cls_post:
in al,80h
jmp $+2
out 80h,al
jmp $+2
in al,80h
jmp $+2
loop wait_cls_post
pop cx
in al,dx
test al,80h
jnz byte_done_post
loop check_byte_done_sts_post
byte_done_post:
pop si
pop cx
pop dx
ret
;---------------------------------------------
ClearTCLSTS:
pushad
mov eax,8000f800h
mov bh,1 ;BH=0/1/2 byte/word/dword
call ReadPciReg ;eax=Value
cmp ax,8086h
jnz NotIntelChipSet
mov eax,8000f840h
mov bh,2 ;BH=0/1/2 byte/word/dword
call ReadPciReg ;eax=Value
mov dx,ax
and dx,0fffeh
add dx,66h
mov al,02h
out dx,al
NotIntelChipSet:
popad
ret
;---------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -