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

📄 piix4smbus.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"////	SMBus support for the PIIX4//enum{	IntelVendID=	0x8086,	Piix4PMID=	0x7113,		/* PIIX4 power management function */	// SMBus configuration registers (function 3)	SMBbase=	0x90,		// 4 byte base address (bit 0 == 1, bit 3:1 == 0)	SMBconfig=	0xd2,	 SMBintrselect=	(7<<1),	  SMIenable=	(0<<1),		//  interrupts sent to SMI#	  IRQ9enable=	(4<<1),		//  intettupts sent to IRQ9	 SMBenable=	(1<<0),		//  1 enables	// SMBus IO space registers	Hoststatus=	0x0,		//  (writing 1 bits reset the interrupt bits)	 Failed=	(1<<4),	 	//  transaction terminated by KILL	 Bus_error=	(1<<3),		//  transactio collision	 Dev_error=	(1<<2),		//  device error interrupt	 Host_complete=	(1<<1),		//  host command completion interrupt 	 Host_busy=	(1<<0),		//	Slavestatus=	0x1,		//  (writing 1 bits reset)	 Alert_sts=	(1<<5),		//  someone asserted SMBALERT#	 Shdw2_sts=	(1<<4),		//  slave accessed shadow 2 port	 Shdw1_sts=	(1<<3),		//  slave accessed shadow 1 port	 Slv_sts=	(1<<2),		//  slave accessed shadow 1 port	 Slv_bsy=	(1<<0),	Hostcontrol=	0x2,	 Start=		(1<<6),		//  start execution	 Cmd_prot=	(7<<2),		//  command protocol mask	  Quick=	(0<<2),		//   address only	  Byte=		(1<<2),		//   address + cmd	  ByteData=	(2<<2),		//   address + cmd + data	  WordData=	(3<<2),		//   address + cmd + data + data	 Kill=		(1<<1),		//  abort in progress command	 Ienable=	(1<<0),		//  enable completion interrupts	Hostcommand=	0x3,	Hostaddress=	0x4,	 AddressMask=	(0x7f<<1),	//  target address	 Read=		(1<<0),		//  1 == read, 0 == write	Hostdata0=	0x5,	Hostdata1=	0x6,	Blockdata=	0x7,	Slavecontrol=	0x8,	 Alert_en=	(1<<3),		//  enable inter on SMBALERT#	 Shdw2_en=	(1<<2),		//  enable inter on external shadow 2 access	 Shdw1_en=	(1<<1),		//  enable inter on external shadow 1 access	 Slv_en=	(1<<0),		//  enable inter on access of host ctlr slave port	Shadowcommand=	0x9,	Slaveevent=	0xa,	Slavedata=	0xc,};static struct{	int	rw;	int	cmd;	int	len;	int	proto;} proto[] ={	[SMBquick]	{ 0,	0,	0,	Quick },	[SMBsend]	{ 0,	1,	0,	Byte },	[SMBbytewrite]	{ 0,	1,	1,	ByteData },	[SMBwordwrite]	{ 0,	1,	2,	WordData },	[SMBrecv]	{ Read,	0,	1, 	Byte },	[SMBbyteread]	{ Read,	1,	1,	ByteData },	[SMBwordread]	{ Read,	1,	2,	WordData },};static voidtransact(SMBus *s, int type, int addr, int cmd, uchar *data){	int tries, status;	char err[ERRLEN];	if(type < 0 || type > nelem(proto))		panic("piix4smbus: illegal transaction type %d", type);	if(waserror()){		qunlock(s);		nexterror();	}	qlock(s);	// wait a while for the host interface to be available	for(tries = 0; tries < 1000000; tries++){		if((inb(s->base+Hoststatus) & Host_busy) == 0)			break;		sched();	}	if(tries >= 1000000){		// try aborting current transaction		outb(s->base+Hostcontrol, Kill);		for(tries = 0; tries < 1000000; tries++){			if((inb(s->base+Hoststatus) & Host_busy) == 0)				break;			sched();		}		if(tries >= 1000000){			snprint(err, sizeof(err), "SMBus jammed: %2.2ux", inb(s->base+Hoststatus));			error(err);		}	}	// set up for transaction	outb(s->base+Hostaddress, (addr<<1)|proto[type].rw);	if(proto[type].cmd)		outb(s->base+Hostcommand, cmd);	if(proto[type].rw != Read){		switch(proto[type].len){		case 2:			outb(s->base+Hostdata1, data[1]);			// fall through		case 1:			outb(s->base+Hostdata0, data[0]);			break;		}	}	 	// reset the completion/error bits and start transaction	outb(s->base+Hoststatus, Failed|Bus_error|Dev_error|Host_complete);	outb(s->base+Hostcontrol, Start|proto[type].proto);	// wait for completion	status = 0;	for(tries = 0; tries < 1000000; tries++){		status = inb(s->base+Hoststatus);		if(status & (Failed|Bus_error|Dev_error|Host_complete))			break;		sched();	}	if((status & Host_complete) == 0){		snprint(err, sizeof(err), "SMBus request failed: %2.2ux", status);		error(err);	}	// get results	if(proto[type].rw == Read){		switch(proto[type].len){		case 2:			data[1] = inb(s->base+Hostdata1);			// fall through		case 1:			data[0] = inb(s->base+Hostdata0);			break;		}	}	qunlock(s);	poperror();}static SMBus smbusproto ={	.transact = transact,};////  return 0 if this is a piix4 with an smbus interface//SMBus*piix4smbus(void){	Pcidev *p;	static SMBus *s;	if(s != nil)		return s;	p = pcimatch(nil, IntelVendID, Piix4PMID);	if(p == nil)		return nil;	s = smalloc(sizeof(*s));		memmove(s, &smbusproto, sizeof(*s));	s->arg = p;	// disable the smbus	pcicfgw8(p, SMBconfig, IRQ9enable|0);	// see if bios gave us a viable port space	s->base = pcicfgr32(p, SMBbase) & ~1;print("SMB base from bios is 0x%lux\n", s->base);	if(ioalloc(s->base, 0xd, 0, "piix4smbus") < 0){		s->base = ioalloc(-1, 0xd, 2, "piix4smbus");		if(s->base < 0){			free(s);			print("piix4smbus: can't allocate io port\n");			return nil;		}print("SMB base ialloc is 0x%lux\n", s->base);		pcicfgw32(p, SMBbase, s->base|1);	}	// disable SMBus interrupts, abort any transaction in progress	outb(s->base+Hostcontrol, Kill);	outb(s->base+Slavecontrol, 0);	// enable the smbus	pcicfgw8(p, SMBconfig, IRQ9enable|SMBenable);	return s;}

⌨️ 快捷键说明

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