1 // Partial implementation for PCI IDE ISA Xcelerator.
3 use std
::time
::Duration
;
5 use crate::{timer
, winring0
};
7 pub const I2C_BLOCK_MAX
: usize = 32;
10 #[derive(Clone, Copy, Debug)]
11 enum TransactionType
{
17 I2cSmbusBlockData
= 5,
18 I2cSmbusI2cBlockBroken
= 6,
19 I2cSmbusBlockProcCall
= 7, /* SMBus 2.0 */
20 I2cSmbusI2cBlockData
= 8,
24 #[derive(Clone, Copy, Debug)]
25 enum Piix4TransactionType
{
30 Piix4BlockData
= 0x14,
33 // PIIX4 SMBus address offsets
36 #[derive(Clone, Copy, Debug)]
37 enum SMBusAddressOffsets
{
53 #[derive(Clone, Copy)]
77 pub fn new(base_address
: u16) -> Self {
81 pub fn write_block_data(&self, addr
: u8, command
: u8, data
: &[u8]) {
85 "Data length must not exceed {}",
88 let mut data_block
= [0u8; I2C_BLOCK_MAX
+ 2];
89 data_block
[0] = l
as u8;
90 data_block
[1..l
+ 1].copy_from_slice(&data
);
93 match self.i2c_smbus_xfer(
97 TransactionType
::I2cSmbusBlockData
,
100 Err(error
) => println!("Error when writing block (I2c): {error:?}"),
106 pub fn i2c_smbus_write_quick(&self, addr
: u8, value
: u8) {
112 TransactionType
::I2cSmbusQuick
,
119 unsafe fn i2c_smbus_xfer(
122 access_type
: AccessType
,
124 transaction_type
: TransactionType
, // Called 'size' in 'i2c_smbus\i2c_smbus_piix4.cpp'.
126 ) -> Result
<XferResult
, Error
> {
127 let piix4_transaction_type
= match transaction_type
{
128 TransactionType
::I2cSmbusQuick
=> {
129 self.write_io_port_byte(
130 SMBusAddressOffsets
::Smbhstadd
,
131 addr
<< 1 | access_type
as u8,
133 Piix4TransactionType
::Piix4Quick
135 TransactionType
::I2cSmbusByte
=> todo!(),
136 TransactionType
::I2cSmbusByteData
=> todo!(), // Here 'data' should be a byte, maybe using a enum?.
137 TransactionType
::I2cSmbusWordData
=> todo!(), // Here 'data' should be a u16, maybe using a enum?.
138 TransactionType
::I2cSmbusBlockData
=> {
139 self.write_io_port_byte(
140 SMBusAddressOffsets
::Smbhstadd
,
141 addr
<< 1 | access_type
as u8,
143 self.write_io_port_byte(SMBusAddressOffsets
::Smbhstcmd
, command
);
144 if let AccessType
::Write
= access_type
{
145 let len
= data
.unwrap()[0];
146 if len
== 0 || len
> I2C_BLOCK_MAX
as u8 {
147 panic!("Invalid len value: {}", len
);
150 self.write_io_port_byte(SMBusAddressOffsets
::Smbhstdat0
, len
);
151 self.read_io_port_byte(SMBusAddressOffsets
::Smbhstcnt
); // TODO: do something of the result!?
153 self.write_io_port_byte(
154 SMBusAddressOffsets
::Smbblkdat
,
155 data
.unwrap()[i
as usize],
159 Piix4TransactionType
::Piix4BlockData
161 _
=> panic!("Not supported: {:?}", transaction_type
),
164 self.write_io_port_byte(
165 SMBusAddressOffsets
::Smbhstcnt
,
166 piix4_transaction_type
as u8 & 0x1C,
169 self.piix4_transaction()?
;
171 // if let (AccessType::Write, Piix4TransactionType::Piix4Quick) = (access_type, piix4_transaction_type) {
175 match piix4_transaction_type
{
176 Piix4TransactionType
::Piix4Quick
=> Ok(XferResult
::Ok
),
177 Piix4TransactionType
::Piix4Byte
=> todo!(),
178 Piix4TransactionType
::Piix4ByteData
=> todo!(),
179 Piix4TransactionType
::Piix4WordData
=> todo!(),
180 Piix4TransactionType
::Piix4BlockData
=> {
181 let l
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhstdat0
) as usize;
182 if l
== 0 || l
> I2C_BLOCK_MAX
{
183 return Err(Error
::Data
);
185 self.read_io_port_byte(SMBusAddressOffsets
::Smbhstcnt
);
186 let mut data
= vec
![0; l
+ 1];
188 data
[i
] = self.read_io_port_byte(SMBusAddressOffsets
::Smbblkdat
);
190 return Ok(XferResult
::BlockData(data
));
195 unsafe fn piix4_transaction(&self) -> Result
<(), Error
> {
196 let timer
= timer
::Sleep
::new();
198 // Make sure the SMBus is ready to start transmitting.
199 let mut res
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhststs
);
201 self.write_io_port_byte(SMBusAddressOffsets
::Smbhststs
, res
);
202 res
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhststs
);
204 return Err(Error
::Busy
);
208 // Start the transaction by setting bit 6.
209 res
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhstcnt
);
210 self.write_io_port_byte(SMBusAddressOffsets
::Smbhstcnt
, res
| 0x40);
212 // let duration: i64 = -2_500; // 250 us.
215 timer
.wait(Duration
::from_micros(250));
217 res
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhststs
);
218 // println!("Res: {}", res);
224 return Err(Error
::Timeout
);
228 // println!("-----");
230 if res
& 0x10 != 0x00 || res
& 0x08 != 0x0 || res
& 0x04 != 0x0 {
231 return Err(Error
::IO
);
234 res
= self.read_io_port_byte(SMBusAddressOffsets
::Smbhststs
);
236 self.write_io_port_byte(SMBusAddressOffsets
::Smbhststs
, res
);
242 unsafe fn write_io_port_byte(&self, op
: SMBusAddressOffsets
, value
: u8) {
243 winring0
::WriteIoPortByte(self.base_address
+ op
as u16, value
);
246 unsafe fn read_io_port_byte(&self, op
: SMBusAddressOffsets
) -> u8 {
247 winring0
::ReadIoPortByte(self.base_address
+ op
as u16)
252 type ADL_MAIN_MALLOC_CALLBACK = unsafe fn(c_int) -> *mut c_void;
253 type ADL_CONTEXT_HANDLE = *mut c_void;
255 type ADL2_MAIN_CONTROL_CREATE = unsafe extern "C" fn(ADL_MAIN_MALLOC_CALLBACK, c_int, *mut ADL_CONTEXT_HANDLE) -> c_int;
256 type ADL2_MAIN_CONTROL_DESTROY = unsafe extern "C" fn(ADL_CONTEXT_HANDLE) -> c_int;
257 type ADL2_ADAPTER_NUMBEROFADAPTERS_GET = unsafe extern "C" fn(ADL_CONTEXT_HANDLE, *mut c_int) -> c_int;
261 let hDLL = LoadLibraryW(w!("atiadlxx.dll")).unwrap();
262 println!("{:?}", hDLL);
264 let ADL2_Main_Control_Create: ADL2_MAIN_CONTROL_CREATE = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Create")).unwrap());
265 let ADL2_Main_Control_Destroy: ADL2_MAIN_CONTROL_DESTROY = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Destroy")).unwrap());
266 let ADL2_Adapter_NumberOfAdapters_Get: ADL2_ADAPTER_NUMBEROFADAPTERS_GET = transmute(&GetProcAddress(hDLL, s!("ADL2_Adapter_NumberOfAdapters_Get")).unwrap());
269 let m: *mut c_void = libc::malloc(4);