⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2cport.cpp

📁 ati driver
💻 CPP
字号:
/******************************************************************************//	File:			I2C.cpp//	Description:	ATI Radeon I2C Serial Bus interface.//	Copyright 2001, Carlos Hasan/*******************************************************************************/#include <Debug.h>#include "I2CPort.h"CI2CPort::CI2CPort(CRadeon & radeon, int rate)	:	fRadeon(radeon),		fNfactor(0),		fMfactor(0),		fTimeLimit(0){	PRINT(("CI2CPort::CI2CPort()\n"));		if( fRadeon.InitCheck() == B_OK ) {		int refFreq, refDiv, minFreq, maxFreq, xclock;		fRadeon.GetPLLParameters(refFreq, refDiv, minFreq, maxFreq, xclock);			double n = (xclock * 10000.0) / (4.0 * rate);		for (fNfactor = 1; fNfactor < 255; fNfactor++) {			if (fNfactor * (fNfactor - 1) > n)				break;		}		fMfactor = fNfactor - 1;		fTimeLimit = 2 * fNfactor;			// enable I2C bus		fRadeon.SetRegister(C_RADEON_I2C_CNTL_1, 0x00ff0000,			C_RADEON_I2C_SEL | C_RADEON_I2C_EN);				fRadeon.SetRegister(C_RADEON_I2C_CNTL_0, 0x000000ff,			C_RADEON_I2C_DONE | C_RADEON_I2C_NACK |			C_RADEON_I2C_HALT | C_RADEON_I2C_SOFT_RST |			C_RADEON_I2C_DRIVE_EN | C_RADEON_I2C_DRIVE_SEL);			#if DEBUG		PRINT(("CI2CPort::CI2CPort() - I2C devices found at ports: "));		for (int address = 0x80; address <= 0xff; address += 0x02) {			if (Probe(address))				PRINT(("0x%02x ", address));		}		PRINT(("\n"));#endif	}}CI2CPort::~CI2CPort(){	PRINT(("CI2CPort::~CI2CPort()\n"));	if( fRadeon.InitCheck() == B_OK ) {		// disable I2C bus		fRadeon.SetRegister(C_RADEON_I2C_CNTL_1, 0);	}}status_t CI2CPort::InitCheck() const{	return fRadeon.InitCheck();}CRadeon & CI2CPort::Radeon() const{	return fRadeon;}bool CI2CPort::Probe(int address){	char buffer[1];		return Read(address, buffer, sizeof(buffer));}bool CI2CPort::Write(int address, const char * buffer, int length){	if (Send(address, buffer, length, true, true) == length)		return true;	return false;}bool CI2CPort::Read(int address, char * buffer, int length){	if (Receive(address, buffer, length, true, true) == length)		return true;	return false;}bool CI2CPort::Write(int address, const char * buffer, int length, char * result, int reslen){	if (Send(address, buffer, length, true, false) == length)		if (Receive(address, result, reslen, true, true) == reslen)			return true;	return false;}int CI2CPort::Register(int address, int index){	char value = index;	if (Send(address, &value, sizeof(value), true, false) == sizeof(value)) {		if (Receive(address, &value, sizeof(value), true, true) == sizeof(value))			return value & 0xff;	}	PRINT(("CI2CPort::Register() - error\n"));	return -1;}void CI2CPort::SetRegister(int address, int index, int value){	char buffer[2];		buffer[0] = index;	buffer[1] = value;		if (Send(address, buffer, sizeof(buffer), true, true) != sizeof(buffer))		PRINT(("CI2CPort::SetRegister() - error\n"));}int CI2CPort::Send(int address, const char * buffer, int length, bool start, bool stop){	//fRadeon.WaitForFifo(4 + length);		// clear status bit	fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		C_RADEON_I2C_DONE |	C_RADEON_I2C_NACK |		C_RADEON_I2C_HALT |	C_RADEON_I2C_SOFT_RST);	// write address	fRadeon.SetRegister(C_RADEON_I2C_DATA, address & 0xfffffffe);	// write data	for (int offset = 0; offset < length; offset++)		fRadeon.SetRegister(C_RADEON_I2C_DATA, buffer[offset]);	//	fRadeon.SetRegister(C_RADEON_I2C_CNTL_1,		(fTimeLimit << 24) | length |		C_RADEON_I2C_EN | C_RADEON_I2C_SEL | 0x100);		fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		(fNfactor << 24) | (fMfactor << 16) |		C_RADEON_I2C_GO | C_RADEON_I2C_DRIVE_EN |		(start ? C_RADEON_I2C_START : 0) | (stop ? C_RADEON_I2C_STOP : 0));			for (int wait = 0; wait < 100; wait++) {		if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)			break;	}	if (WaitAck() != C_RADEON_I2C_DONE) {		Stop();		return 0;	}		return length;}int CI2CPort::Receive(int address, char * buffer, int length, bool start, bool stop){	//fRadeon.WaitForFifo(length + 4);		fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		C_RADEON_I2C_DONE | C_RADEON_I2C_NACK |		C_RADEON_I2C_HALT | C_RADEON_I2C_SOFT_RST);		fRadeon.SetRegister(C_RADEON_I2C_DATA, address | 0x00000001);		fRadeon.SetRegister(C_RADEON_I2C_CNTL_1,		(fTimeLimit << 24) | C_RADEON_I2C_EN | //C_RADEON_I2C_SEL |		length | 0x100);			fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		(fNfactor << 24) | (fMfactor << 16) | C_RADEON_I2C_GO |		(start ? C_RADEON_I2C_START : 0) | (stop ? C_RADEON_I2C_STOP : 0) |		C_RADEON_I2C_DRIVE_EN | C_RADEON_I2C_RECEIVE);			for (int wait = 0; wait < 100; wait++) {		if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)			break;	}	if (WaitAck() != C_RADEON_I2C_DONE)		return 0;	snooze(1000);		for (int offset = 0; offset < length; offset++) {		//fRadeon.WaitForFifo(1);		buffer[offset] = fRadeon.Register(C_RADEON_I2C_DATA) & 0xff;	}	return length;}int CI2CPort::WaitAck(){	for (int wait = 0; wait < 100; wait++) {		int control = fRadeon.Register(C_RADEON_I2C_CNTL_0);		if ((control & C_RADEON_I2C_HALT) != 0)			return C_RADEON_I2C_HALT;		if ((control & C_RADEON_I2C_NACK) != 0)			return C_RADEON_I2C_NACK;		if ((control & C_RADEON_I2C_DONE) != 0)			return C_RADEON_I2C_DONE;		snooze(1000);	}	PRINT(("CI2CPort::WaitAck() - Time out!\n"));	return C_RADEON_I2C_HALT;		}void CI2CPort::Stop(){	// reset status flags	fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		C_RADEON_I2C_DONE | C_RADEON_I2C_NACK | C_RADEON_I2C_HALT, 0);	// issue abort call	fRadeon.SetRegister(C_RADEON_I2C_CNTL_0,		C_RADEON_I2C_ABORT | C_RADEON_I2C_GO, C_RADEON_I2C_ABORT | C_RADEON_I2C_GO);		// wait GO bit to go low	for (int wait = 0; wait < 100; wait++) {		if ((fRadeon.Register(C_RADEON_I2C_CNTL_0) & C_RADEON_I2C_GO) == 0)		snooze(1000);	}	PRINT(("CI2CPort::Stop() - Time out!\n"));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -