/*-
* Copyright (c) 1999-2000 James E. Housley <jim@thehousleys.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: getMBinfo.c,v 1.1.1.17 2004/05/25 10:40:29 housley Exp $
*/
/************************************************
Subroutines to get Mother Board Information
assuming WinBond chips
Information related to WinBond W83781D Chip
and National Semiconductor LM78/LM79/LM75 Chips
----------------------------------------------
http://www.euronet.nl/users/darkside/mbmonitor
----------------------------------------------
by Alex van Kaam
************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
#include "methods.h"
#include "parameters.h"
#include "healthd.h"
extern struct lm_methods method_isa;
#ifdef HAVE_SMBUS
extern struct lm_methods method_smb;
#endif
static struct lm_methods *this_method;
#define OpenIO() (this_method->Open());
#define CloseIO() (this_method->Close());
#define ReadByte(addr) (this_method->Read((addr)))
#define WriteByte(addr, val) (this_method->Write((addr), (val)))
/*----------------------
Restarting Chip
----------------------*/
int
InitMBInfo(char type) {
if(type == 'I') {
this_method = &method_isa;
}
#ifdef HAVE_SMBUS
else if(type == 'S'){
this_method = &method_smb;
}
#endif
else {
return -1;
}
return OpenIO();
}
int
FiniMBInfo(void)
{
return CloseIO();
}
int
RstChip(void) {
return WriteByte(0x40,0x01);
}
unsigned int
GetVendorID(void) {
unsigned int result;
/*
* First check for WinBond chips
*/
/* changing to bank 0 */
WriteByte(0x4E, 0x00);
/* Select HBACS to get MSW of ID */
WriteByte(0x4E, 0x80);
result = ReadByte(0x4F) << 8;
/* Clear HBACS to get LSW of ID */
WriteByte(0x4E, 0x00);
result += ReadByte(0x4F) & 0x0FF;
if (result != 0)
return(result);
/*
* Try LM78/LM79
*/
result = ReadByte(0x49);
if (result != 0)
return(0xFFFF0000 | result);
/*
* Try LM80
*/
result = ReadByte(0x05); /* May be changed for work in different mainboards */
if(result != 0)
return(0xFFFFAAAA);
return(result);
}
unsigned int
GetChipID_winbond(void) {
unsigned int result;
result = ReadByte(0x58);
return(result);
}
/*-------------------------------------------
Getting Temperatures (assuming WinBond)
-------------------------------------------*/
int getTemp(double *t1, double *t2, double *t3) {
int n;
extern enum eChip MonitorType;
/* Force bank 0 */
WriteByte(0x4E, 0);
n = ReadByte(0x27);
*t1 = n;
/* changing to bank 1 */
WriteByte(0x4E, 0x01);
n = ReadByte(0x50);
if (ReadByte(0x51) == 128)
*t2 = n + 0.5;
else
*t2 = n;
/* returning to bank 0 */
WriteByte(0x4E, 0);
/* 208 if no connection to thermal chip !*/
if (n > 200)
*t2 = 0.0;
/* changing to bank 2 */
WriteByte(0x4E, 0x02);
n = ReadByte(0x50);
if (ReadByte(0x51) == 128)
*t3 = n + 0.5;
else
*t3 = n;
/* returning to bank 0 */
WriteByte(0x4E,0);
/* 208 if no connection to thermal chip !*/
if (n > 200)
*t3 = 0.0;
/*
* For LM80
*/
if( MonitorType == LM80){
*t1 = ReadByte(0x27);
*t2 = 0.0;
*t3 = 0.0;
}
return 0;
}
/*-------------------------------------------
Getting Voltages (assuming WinBond)
-------------------------------------------*/
int getVolt(double *vc0, double *vc1, double *v33,\
double *v50p, double *v50n,\
double *v12p, double *v12n) {
unsigned char n;
extern enum eChip MonitorType;
extern int UseVbat;
/*
* Each step in the A/D is 16mV
*/
/*
* Vcore0
*/
if (MonitorType == LM80) {
/*
* LM80
*/
*vc0 = ReadByte(0x21) * 1.316 / 100;
} else {
*vc0 = (double)ReadByte(0x20) * 0.016;
}
/*
* Vcore1
*/
if (UseVbat) {
/*
* Some systems seem to like using Vbat for Vcore1
*/
/* changing to bank 5 */
WriteByte(0x4E, 0x05);
*vc1 = (double)ReadByte(0x51) * 0.016;
/* changing to bank 0 */
WriteByte(0x4E, 0x00);
}
else if (MonitorType == LM80) {
/*
* LM80
*/
*vc1 = ReadByte(0x23) * 1.316 / 100;
} else {
*vc1 = (double)ReadByte(0x21) * 0.016;
}
/*
* 3.3Volt
*/
if (MonitorType == LM80) {
/*
* LM80
*/
*v33 = ReadByte(0x20) * 1.740 / 100;
} else {
*v33 = (double)ReadByte(0x22) * 0.016;
}
/*
* +5Volt
*/
n=ReadByte(0x23);
if (MonitorType == LM80) {
/*
* LM80
*/
*v50p = ReadByte(0x22) * 2.633 / 100;
} else {
*v50p = (double)n * 0.016 * 1.68;
}
/*
* +12Volt
*/
n=ReadByte(0x24);
if ((MonitorType == LM78) || (MonitorType == LM79) || (MonitorType == AS99127F)) {
/*
* LM78 & LM79
*/
*v12p = n * 6.316 / 100;
}
else if (MonitorType == LM80) {
/*
* LM80
*/
*v12n = (n * 5.482) / 100 - 22.41;
} else {
/*
* Winbond W83781D or W83782D
*/
*v12p = (double)n * 0.016 * 3.80;
}
/*
* -12Volt
*/
n=ReadByte(0x25) ;
if ((MonitorType == LM78) || (MonitorType == LM79) || (MonitorType == AS99127F)) {
/*
* LM78 & LM79
*/
*v12n = - n * 0.016 * 4.00;
}
else if (MonitorType == LM80) {
/*
* LM80
*/
*v12n = (n * 5.482) / 100 - 22.41;
}
else if ((MonitorType == W83781D)) {
/*
* Winbond W83781D ONLY
*/
*v12n = - n * 0.016 * 3.47;
} else {
/*
* Winbond W83782D
*/
*v12n = n * 0.016 * 5.143 - 14.914;
}
/*
* -5Volt
*/
n=ReadByte(0x26);
if ((MonitorType == LM78) || (MonitorType == LM79)) {
/*
* LM78 & LM79
*/
*v50n = - n * 0.016 * 1.6666667;
}
else if (MonitorType == LM80) {
/*
* LM80
*/
*v50n = 0;
}
else if ((MonitorType == W83781D) || (MonitorType == AS99127F)) {
/*
* Winbond W83781D ONLY
*/
*v50n = - n * 0.016 * 1.50;
} else {
/*
* Winbond W83782D
*/
*v50n = n * 0.016 * 3.143 - 7.714;
}
return 0;
}
/*----------------------
Getting Fan Speed
----------------------*/
int getFanSp(int *r1, int *r2, int *r3) {
/*
FanType = 1 for a normal fan
FanType = 2 for a fan which gives 2 pulses per rotation
*/
int FanType1 = 1, FanType2 = 1, FanType3 = 1;
int div1, div2, div3 = 2;
unsigned char n;
extern enum eChip MonitorType;
/*
* For LM80
*/
if( MonitorType == LM80) {
switch (ReadByte(0x05)&0x0c){
case 0x00:
div1 = 1;
break;
case 0x04:
div1 = 2;
break;
case 0x08:
div1 = 4;
break;
case 0x0c:
div1 = 8;
break;
default:
;
}
div1 = 2;
*r3 = 0;
if (ReadByte(0x28) < 240)
*r1 = 1350000 / (div1 * ReadByte(0x28));
else
*r1=0;
if (ReadByte(0x29) < 240)
*r2 = 1350000 / (div1 * ReadByte(0x29));
else
*r2=0;
} else {
n = ReadByte(0x47);
div1 = 1 << ((n & 0x30) >> 4);
div2 = 1 << ((n & 0xC0) >> 6);
n = ReadByte(0x28);
if ((n == 255) || (n == 0) || (div1 == 0))
*r1 = 0;
else
*r1 = 1350000 / (n * div1 * FanType1);
n=ReadByte(0x29);
if ((n == 255) || (n == 0) || (div2 == 0))
*r2 = 0;
else
*r2 = 1350000 / (n * div2 * FanType2);
n=ReadByte(0x2A);
if ((n == 255) || (n == 0))
*r3 = 0;
else
*r3 = 1350000 / (n * div3 * FanType3);
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1