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

📄 devlm78.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"#include "ureg.h"#include "../port/error.h"// this driver doesn't implement the management interrupts.  we// leave the LM78 interrupts set to whatever the BIOS did.  we do// allow reading and writing the the readouts and alarm values.// Read(2)ing or write(2)ing at offset 0x0-0x1f, is// equivalent to reading or writing lm78 registers 0x20-0x3f.enum{	// address of chip on serial interface	Serialaddr=	0x2d,	// parallel access registers	Rpaddr=		0x5,	 Bbusy=		 (1<<7),	Rpdata=		0x6,	// internal register addresses	Rconfig=	0x40,	 Bstart=	 (1<<0),	 Bsmiena=	 (1<<1),	 Birqena=	 (1<<2),	 Bintclr=	 (1<<3),	 Breset=	 (1<<4),	 Bnmi=		 (1<<5),	// if set, use nmi, else irq	 Bpowbypass=	 (1<<6),	 Binit=		 (1<<7),	Ristat1=	0x41,	Ristat2=	0x42,	Rsmimask1=	0x43,	Rsmimask2=	0x44,	Rnmimask1=	0x45,	Rnmimask2=	0x46,	Rvidfan=	0x47,		// set fan counter, and read voltage level	 Mvid=		 0x0f,	 Mfan=		 0xf0,	Raddr=		0x48,		// address used on serial bus	Rresetid=	0x49,		// chip reset and ID register	Rpost=		0x00,		// start of post ram	Rvalue=		0x20,		// start of value ram	VRsize=		0x20,		// size of value ram};enum{	Qdir,	Qlm78vram,};static Dirtab lm78dir[] = {	"lm78vram",		{ Qlm78vram, 0 },		0,	0444,};// interface typeenum{	None=	0,	Smbus,	Parallel,};static struct {	QLock;	int	probed;	int 	ifc;	// which interface is connected	SMBus	*smbus;	// serial interface	int	port;	// parallel interface} lm78;extern SMBus*	piix4smbus(void);// wait for device to become quiescent and then set the// register addressstatic voidsetreg(int reg){	int tries;	for(tries = 0; tries < 1000000; tries++)		if((inb(lm78.port+Rpaddr) & Bbusy) == 0){			outb(lm78.port+Rpaddr, reg);			return;		}	error("lm78 broken");}// routines that actually touch the devicestatic voidlm78wrreg(int reg, uchar val){	if(waserror()){		qunlock(&lm78);		nexterror();	}	qlock(&lm78);	switch(lm78.ifc){	case Smbus:		lm78.smbus->transact(lm78.smbus, SMBbytewrite, Serialaddr, reg, &val);		break;	case Parallel:		setreg(reg);		outb(lm78.port+Rpdata, val);		break;	default:		error(Enodev);		break;	}	qunlock(&lm78);	poperror();}static intlm78rdreg(int reg){	uchar val;	if(waserror()){		qunlock(&lm78);		nexterror();	}	qlock(&lm78);	switch(lm78.ifc){	case Smbus:		lm78.smbus->transact(lm78.smbus, SMBsend, Serialaddr, reg, nil);		lm78.smbus->transact(lm78.smbus, SMBrecv, Serialaddr, 0, &val);		break;	case Parallel:		setreg(reg);		val = inb(lm78.port+Rpdata);		break;	default:		error(Enodev);		break;	}	qunlock(&lm78);	poperror();	return val;}// start the chip monitoring but don't change any smi// interrupts and/or alarms that the BIOS may have set up.//// this isn't locked because it's thought to be idempotentstatic voidlm78enable(void){	uchar config;	if(lm78.ifc == None)		error(Enodev);	if(lm78.probed == 0){		// make sure its really there		if(lm78rdreg(Raddr) != Serialaddr){			lm78.ifc = None;			error(Enodev);		} else {			// start the sampling			config = lm78rdreg(Rconfig);			config = (config | Bstart) & ~(Bintclr|Binit);			lm78wrreg(Rconfig, config);pprint("Rvidfan %2.2ux\n", lm78rdreg(Rconfig), lm78rdreg(Rvidfan));		}		lm78.probed = 1;	}}enum{	IntelVendID=	0x8086,	PiixID=		0x122E,	Piix3ID=	0x7000,	Piix4PMID=	0x7113,		// PIIX4 power management function	PCSC=		0x78,		// programmable chip select control register	PCSC8bytes=	0x01,};// figure out what kind of interface we could havevoidlm78reset(void){	int pcs;	Pcidev *p;	lm78.ifc = None;	p = nil;	while((p = pcimatch(p, IntelVendID, 0)) != nil){		switch(p->did){		// these bridges use the PCSC to map the lm78 into port space.		// for this case the lm78's CS# select is connected to the PIIX's		// PCS# output and the bottom 3 bits of address are passed to the		// LM78's A0-A2 inputs.		case PiixID:		case Piix3ID:			pcs = pcicfgr16(p, PCSC);			if(pcs & 3) {				/* already enabled */				lm78.port = pcs & ~3;				lm78.ifc = Parallel;				return;				}			// enable the chip, use default address 0x50			pcicfgw16(p, PCSC, 0x50|PCSC8bytes);			pcs = pcicfgr16(p, PCSC);			lm78.port = pcs & ~3;			lm78.ifc = Parallel;			return;		// this bridge puts the lm78's serial interface on the smbus		case Piix4PMID:			lm78.smbus = piix4smbus();			if(lm78.smbus == nil)				continue;			print("found piix4 smbus, base %lud\n", lm78.smbus->base);			lm78.ifc = Smbus;			return;		}	}}static Chan*lm78attach(char* spec){	lm78enable();	return devattach('T', spec);}intlm78walk(Chan* c, char* name){	return devwalk(c, name, lm78dir, nelem(lm78dir), devgen);}static voidlm78stat(Chan* c, char* dp){	devstat(c, dp, lm78dir, nelem(lm78dir), devgen);}static Chan*lm78open(Chan* c, int omode){	return devopen(c, omode, lm78dir, nelem(lm78dir), devgen);}static voidlm78close(Chan*){}enum{	Linelen= 25,};static longlm78read(Chan *c, void *a, long n, vlong offset){	uchar *va = a;	int off, e;	off = offset;	switch(c->qid.path & ~CHDIR){	case Qdir:		return devdirread(c, a, n, lm78dir, nelem(lm78dir), devgen);	case Qlm78vram:		if(off >=  VRsize)			return 0;		e = off + n;		if(e > VRsize)			e = VRsize;		for(; off < e; off++)			*va++ = lm78rdreg(Rvalue+off);		return va - (uchar*)a;	}	return 0;}static longlm78write(Chan *c, void *a, long n, vlong offset){	uchar *va = a;	int off, e;	off = offset;	switch(c->qid.path){	default:		error(Eperm);	case Qlm78vram:		if(off >=  VRsize)			return 0;		e = off + n;		if(e > VRsize)			e = VRsize;		for(; off < e; off++)			lm78wrreg(Rvalue+off, *va++);		return va - (uchar*)a;	}	return 0;}Dev lm78devtab = {	'T',	"lm78",	lm78reset,	devinit,	lm78attach,	devclone,	lm78walk,	lm78stat,	lm78open,	devcreate,	lm78close,	lm78read,	devbread,	lm78write,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

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