smbus.as [SMBusモジュール]
;*******************************************************************************
; SMBus module Ver1.0a [2007.09.23]
; Programmed in HSP Ver3.1 ONION software (http://hsp.tv/)
; Copyright (C) 2007 by abo, all rights reserved.
;*******************************************************************************
#ifdef __hsp30__
#ifndef __SMBUS__
#define global __SMBUS__
#module "smbus"
;/SiS
;--------+---------+---------+---------+---------+---------+---------+---------+
#deffunc ResetSMBusSiS int SMBadr
if Io_inp(SMBAdr+2)&3 {
io_out SMBAdr+3,0x20
repeat 0xFFFF
if (Io_inp(SMBAdr+2)&1)=0 : break
loop
}
return
;/SMBusのバイト
;--------+---------+---------+---------+---------+---------+---------+---------+
; アドレス : Adr
; ホストコマンド : Hst
; データ : Data
;--------+---------+---------+---------+---------+---------+---------+---------+
#define global ctype GetByteRTM(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,0)
#define global ctype SetByteRTM(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,1)
#define global ctype GetAsusSel(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,2)
#define global ctype SetAsusSel(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,3)
#define global ctype GetByteICS(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,2)
#define global ctype SetByteICS(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,3)
#define global ctype GetAsusSelSiS(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,4)
#define global ctype SetAsusSelSiS(%1,%2,%3,%4,%5) BytePll(%1,%2,%3,%4,%5,5)
#defcfunc BytePll var Data, int SMBusCtl, int SMBadr, int Adr, int Hst, int fMode
do
;/SMBusの準備確認
; SMBadr : 0 準備ok
; 0以外はSMBus Errorとして処理
switch fMode
case 4 ;GetAsusSelSiS
case 5 ;SetAsusSelSiS
ResetSMBusSiS SMBadr
swbreak
swend
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp) : io_out SMBadr,0xFF : else : break
loop
if CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp) : _break ;SMBus Error
switch fMode
case 0 ;/RTMバイトリード
io_out SMBadr+4,Adr|1 ;アドレス,ライトをセット
io_out SMBadr+3,Hst ;ホストコマンドセット
io_out SMBadr+2,0x4C ;バイトモードスタート
swbreak
case 1 ;/RTMバイトライト
io_out SMBadr+4,Adr ;アドレス,ライトをセット
io_out SMBadr+3,Hst ;ホストコマンドセット
io_out SMBadr+6,Data ;ライトデータ
io_out SMBadr+2,0x4C ;バイトモードスタート
swbreak
case 2 ;/AsusSelリード
io_out SMBadr+4,Adr|1 ;アドレス,ライトをセット
io_out SMBadr+3,Hst ;ホストコマンドセット
io_out SMBadr+2,0x48 ;バイトモードスタート
swbreak
case 3 ;/AsusSelライト
io_out SMBadr+4,Adr ;アドレス,ライトをセット
io_out SMBadr+3,Hst ;ホストコマンドセット
io_out SMBadr+5,Data ;ライトデータ
io_out SMBadr+2,0x48 ;バイトモードスタート
swbreak
case 4 ;/AsusSelSiSリード
io_out SMBadr+4,Adr|1 ;アドレス,ライトをセット
io_out SMBadr+5,Hst ;ホストコマンドセット
io_out SMBadr,0 ;
io_out SMBadr+3,0x12 ;バイトモードスタート
swbreak
case 5 ;/AsusSelSiSライト
io_out SMBadr+4,Adr ;アドレス,ライトをセット
io_out SMBadr+5,Hst ;ホストコマンドセット
io_out SMBadr+8,Data ;ライトデータ
io_out SMBadr,0 ;
io_out SMBadr+3,0x12 ;バイトモードスタート
swbreak
swend
;/完了確認
; SMBadr : bit0 1=Host Busy
; : bit1 1=全バイト完了 , ライト1でリセット
; : bit2 1=デバイスエラー
switch fMode
case 0 ;/RTMバイトリード
case 1 ;/RTMバイトライト
case 2 ;/AsusSelリード
case 3 ;/AsusSelライト
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&1 : continue ;20b8
if ((tmp&3)=2) | (tmp&4) : break
loop
if (tmp&4)=0 & (tmp&3)=2 {
switch fMode
case 0 ;/RTMバイトリード
Data=Io_inp(SMBadr+6)
swbreak
case 2 ;/AsusSelリード
Data=Io_inp(SMBadr+5)
swbreak
swend
io_out SMBadr,2 ;完了フラグのリセット
io_out SMBadr,0xFF : tmp=Io_inp(SMBadr)
}
swbreak
case 4 ;/AsusSelSiSリード
case 5 ;/AsusSelSiSライト
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x0E : break
loop
if (tmp&6)=0 & (tmp&8)!0 {
switch fMode
case 4 ;/AsusSelリード
Data=Io_inp(SMBadr+8)
swbreak
swend
io_out SMBadr,tmp : tmp=Io_inp(SMBadr) ;完了フラグのリセット
}
swbreak
swend
until
return CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp)
;/SMBusの切替
;--------+---------+---------+---------+---------+---------+---------+---------+
; Asusのお呪い
; *SMBus_pll : SMBusをPLL-ICにセット
; *SMBus_rtn : SMBusを元に戻す
;--------+---------+---------+---------+---------+---------+---------+---------+
#defcfunc SMBusP4T533C int SmbPort
io_out 0x2E,0x87
io_out 0x2E,0x87
io_out 0x2E,0x07
io_out 0x2F,0x09
io_out 0x2E,0x30
io_out 0x2F,0x03
io_out 0x2E,0xF5
RtnSmbPort=Io_inp(0x2F) ;現在値を保存
io_out 0x2E,0xF5
io_out 0x2F,RtnSmbPort&0xFC|SmbPort ;Port値をセット
io_out 0x2E,0xAA
return 0
#defcfunc SMBusP4T533 int SMBusCtl, int SMBadr, int SmbPort
if GetAsusSel(Rtniodt,SMBusCtl,SMBadr,0x5A,0x4E) : return stat ;SMBus error
iodt=Rtniodt&0xF8|3
if SetAsusSel(iodt,SMBusCtl,SMBadr,0x5A,0x4E) : return stat ;SMBus error
if GetAsusSel(RtnSmbPort,SMBusCtl,SMBadr,0x5A,0x84) : return stat ;SMBus error
iodt=RtnSmbPort&0xFC|SmbPort
if SetAsusSel(iodt,SMBusCtl,SMBadr,0x5A,0x84) : return stat ;SMBus error
if SetAsusSel(Rtniodt,SMBusCtl,SMBadr,0x5A,0x4E) : return stat ;SMBus error
return 0
#defcfunc SMBusP4S333 int SMBusCtl, int SMBadr, int SmbPort
if GetAsusSelSiS(Rtniodt,SMBusCtl,SMBadr,0x5A,0x4E) : return stat ;SMBus error
iodt=Rtniodt&0xF8|3
if GetAsusSelSiS(RtnSmbPort,SMBusCtl,SMBadr,0x5A,0x84) : return stat ;SMBus error
iodt=RtnSmbPort&0xFC|SmbPort
if SetAsusSelSiS(Rtniodt,SMBusCtl,SMBadr,0x5A,0x4E) : return stat ;SMBus error
return 0
#defcfunc SMBusA7M266 int SmbPort
RtnSmbPort=Io_inp(iGpoAdr@+0x4D)
io_out iGpoAdr@+0x4D,RtnSmbPort&0xF6|SmbPort
return 0
#defcfunc SMBusA7S333 int SmbPort
return 0
#defcfunc SMBusPll int SMBusCtl, int SMBadr, int Asus
switch Asus
case 1 ;P4T533
return SMBusP4T533(SMBusCtl,SMBadr,1) ;PLL-ICにセレクト
swbreak
case 2 ;A7M266
return SMBusA7M266(8) ;PLL-ICにセレクト
swbreak
case 3 ;A7V333
return SMBusP4T533(SMBusCtl,SMBadr,2) ;PLL-ICにセレクト
swbreak
case 4 ;P4S533(/333/8X)
return SMBusP4S333(SMBusCtl,SMBadr,1) ;PLL-ICにセレクト
swbreak
case 5 ;A7S333
swbreak
swend
return 0
#defcfunc SMBusRtn int SMBusCtl, int SMBadr, int Asus
switch Asus
case 1 ;P4T533
case 3 ;A7V333
return SMBusP4T533(SMBusCtl,SMBadr,RtnSmbPort&3) ;前回値にセレクト
swbreak
case 2 ;A7M266
return SMBusA7M266(RtnSmbPort&9) ;前回値にセレクト
swbreak
case 4 ;P4S533(/333/8X)
return SMBusP4S333(SMBusCtl,SMBadr,RtnSmbPort&3) ;前回値にセレクト
swbreak
case 5 ;A7S333
swbreak
swend
return 0
;/PLL-ICデータのブロック
;--------+---------+---------+---------+---------+---------+---------+---------+
; PLL-IC ブロック
; ※tmpが0x40でないときはSMBus Error
;--------+---------+---------+---------+---------+---------+---------+---------+
#define global ctype GetBlockPll(%1,%2,%3,%4) BlockPll(%1,%2,%3,%4,0)
#define global ctype SetBlockPll(%1,%2,%3,%4) BlockPll(%1,%2,%3,%4,1)
#defcfunc BlockPll array CR, int SMBusCtl, int SMBadr, var byte, int fMode
do
;/SMBusの準備確認
; SMBadr : 0 準備ok
; 0以外はSMBus Errorとして処理
switch SMBusCtl&0xFFFF
case VidIntel
AuxCtl=Io_inp(SMBadr+0x0D) : io_out SMBadr+0x0D,AuxCtl&0xFD
swbreak
case VidSiS
io_outd CONFIG_ADDRESS,0x80001048 : io_out CONFIG_DATA,Io_inp(CONFIG_DATA)|0x80
ResetSMBusSiS SMBadr
swbreak
swend
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp) : io_out SMBadr,0xFF : else : break
loop
if CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp) : _break ;SMBus Error
switch fMode
case 0 ;/ブロックリード
switch SMBusCtl&0xFFFF
case VidIntel
switch SMBusCtl
case IntelPIIX4SMB
gosub *GetBlockPIIX4
swbreak
default
gosub *GetBlockICH2
swbreak
swend
swbreak
case VidVia
case VidAti
gosub *GetBlockPIIX4
swbreak
case VidSiS
gosub *GetBlockSiS
swbreak
swend
swbreak
case 1 ;/ブロックライト
switch SMBusCtl&0xFFFF
case VidIntel
switch SMBusCtl
case IntelPIIX4SMB
gosub *SetBlockPIIX4
swbreak
default
gosub *SetBlockICH2
swbreak
swend
swbreak
case VidVia
case VidAti
gosub *SetBlockPIIX4
swbreak
case VidSiS
gosub *SetBlockSiS
swbreak
swend
swbreak
swend
switch SMBusCtl&0xFFFF
case VidIntel
case VidVia
case VidAti
;/ブロックリードの完了確認
; SMBadrを0x40 準備ok , Depthを設定
; SMBadr : bit1=1 全バイト完了 , ライト1でリセット
if (tmp&4)=0 {
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if (tmp&3)=2 : break
if tmp&0x80 : io_out SMBadr,0x80 ; (DQ965GF)
loop
if (tmp&3)!2 : : _break ;Devエラー
io_out SMBadr,0x82 ;完了フラグのリセット
io_out SMBadr,0xFF : tmp=Io_inp(SMBadr)
}
swbreak
case VidSiS
if (tmp&6)=0 & (tmp&0x18)!0 : io_out SMBadr,tmp : tmp=Io_inp(SMBadr)
swbreak
swend
switch SMBusCtl&0xFFFF
case VidIntel
io_out SMBadr+0x0D,AuxCtl
swbreak
case VidSiS
io_outd CONFIG_ADDRESS,0x80001048 : io_out CONFIG_DATA,Io_inp(CONFIG_DATA)&0x7F
swbreak
swend
until
return CND((SMBusCtl&0xFFFF)=VidSiS,tmp&0x7F,tmp)
*GetBlockSiS
io_out SMBadr+4,0xD3 ;アドレス,リードをセット
io_out SMBadr+5,0 ;ホストコマンドセット
io_out SMBadr+3,0x15 ;ブロックモードスタート
; SMBadr : bit0 1=Host Busy
; : bit1 1=全バイト完了 , ライト1でリセット
; : bit2 1=デバイスエラー
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x1E : break
loop
; device error - 0x02
; bus collision - 0x04
if (tmp&6)=0 & (tmp&0x18)!0 { ;正常
byte=Io_inp(SMBadr+7) ;カウント
repeat byte
CR(cnt)=Io_inp(SMBadr+8+(cnt&7)) ;cntバイトをリード
if (cnt&7)=7 {
io_out SMBadr,Io_inp(SMBadr)
if cnt=0x1F | byte=8 : break
if cnt=0x0F & byte=0x10 : break
if cnt=0x17 & byte=0x18 : break
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x1E : break
loop
if tmp&6 : break ;異常
}
loop
}
return
*SetBlockSiS
repeat byte
if (cnt&7)=0 {
repeat 8,cnt
io_out SMBadr+8+(cnt&7),CR(cnt) ;cntバイトをライト
loop
if cnt {
io_out SMBadr,Io_inp(SMBadr)
} else {
io_out SMBadr+4,0xD2 ;アドレス,ライトをセット
io_out SMBadr+7,byte ;カウントをセット
io_out SMBadr+5,0 ;ホストコマンドセット
io_out SMBadr+3,0x15 ;ブロックモードスタート
}
; SMBadr : bit0 1=Host Busy
; : bit1 1=全バイト完了 , ライト1でリセット
; : bit2 1=デバイスエラー
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x1E : break
loop
; device error - 0x02
; bus collision - 0x04
if tmp&6 : break ;異常
}
loop
return
*GetBlockPIIX4
io_out SMBadr+4,0xD3 ;アドレス,リードをセット
io_out SMBadr+3,0 ;ホストコマンドセット
io_out SMBadr+2,0x54 ;ブロックモードスタート
; SMBadr : bit0 1=Host Busy
; : bit1 1=全バイト完了 , ライト1でリセット
; : bit2 1=デバイスエラー
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&1 : continue ;20b8
if tmp&0x0E : break
loop
if (tmp&0x0D)=0 { ;正常
byte=Io_inp(SMBadr+5) ;カウント
reg=Io_inp(SMBadr+2) ;内部カウント=0
repeat byte
CR(cnt)=Io_inp(SMBadr+7) ;cntバイトをリード,内部カウント+1
loop
}
return
*GetBlockICH2
repeat
if cnt=0 {
; SMBadr+4 : bit7-1 SH6アドレス=1101001
; (0xD3) bit0 リード=1
; SMBadr+3 : ホストコマンド 0x00にする
; SMBadr+2 : bit6 スタート=1
; (0x54) bit4-2 ブロック=101
io_out SMBadr+4,0xD3 ;アドレス,リードをセット
io_out SMBadr+3,0 ;ホストコマンドセット
io_out SMBadr+2,0x54 ;ブロックモードスタート
} else {
; SMBus : bit7 ライト1で次バイトのリクエスト
io_out SMBadr,0x80
}
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x84 : break
loop
if tmp&4 : break ;Devエラー
if cnt=0 : byte=Io_inp(SMBadr+5)
CR(cnt)=Io_inp(SMBadr+7) ;cntバイトをリード
if cnt=(byte-1) : break
loop
return
*SetBlockPIIX4
reg=Io_inp(SMBadr+2) ;内部カウント=0
repeat byte
io_out SMBadr+7,CR(cnt) ;cntバイトをライト
loop
io_out SMBadr+4,0xd2 ;アドレス,ライトをセット
io_out SMBadr+3,0 ;ホストコマンドセット
io_out SMBadr+5,byte ;カウントセット
io_out SMBadr+2,0x54 ;ブロックモードスタート
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&1 : continue ;20b8
if tmp&0x0E : break
loop
return
*SetBlockICH2
repeat byte
io_out SMBadr+7,CR(cnt) ;cntバイトをセット
if cnt=0 {
; SMBadr+4 : bit7-1 SH6アドレス=1101001
; (0xD2) bit0 ライト=0
; SMBadr+3 : ホストコマンド 0x00にする
; SMBadr+7 : ライトデータ
; SMBadr+2 : bit6 スタート=1
; (0x54) bit4-2 ブロック=101
io_out SMBadr+4,0xD2 ;アドレス,ライトをセット
io_out SMBadr+3,0 ;ホストコマンドセット
io_out SMBadr+5,byte ;カウントセット
io_out SMBadr+2,0x54 ;ブロックモードスタート
} else {
; SMBus : bit7 ライト1で次バイトのリクエスト
io_out SMBadr,0x80
}
; SMBus : bit7 1=バイド送信完了 , ライト1でリセット
repeat 0xFFFF
tmp=Io_inp(SMBadr)
if tmp&0x84 : break
loop
if tmp&4 : break ;Devエラー
loop
return
#global
#endif ; __SMBUS__
#endif ; __hsp30__
;--------------------------------------------------------------- (EOF) ---------