/*
 * Copyright (c) 1999
 *         Chris D. Faulhaber <jedgar@fxp.org>.  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 as
 *    the first lines of this file unmodified.
 * 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 CHRIS D. FAULHABER ``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 CHRIS D. FAULHABER 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.
 *
 * Portions of this software derived from examples (c) 1998 Takanori Watanabe.
 *
 * Addition of an output format (-m) suitable for the UCD SNMP Agent
 *   Kevin Walton, <kevinw@demon.net>, March 2000
 *
 *      $Id: lmmon.c,v 1.31 2000/03/08 17:41:28 jedgar Exp $
 */
              
#include <curses.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <machine/cpufunc.h>

#ifdef HAVE_CONFIG_H
  #include "config.h"
#endif
#ifdef HAVE_SMB
  #include <dev/smbus/smb.h>
#endif

#include "lmmon.h"

void
usage()
{
	(void)fprintf(stderr, "%s%s\n%s\n",
		      "lmmon v", LMMON_VERSION,
		      "usage: lmmon [-hipsvm] [-r delay]");
	exit(1);
}

u_char
get_data(int iodev, u_char command, int interface)
{
	u_char return_val;

	return_val = 0;

#ifdef HAVE_SMB
	if (interface == INTERFACE_SMB) {
		struct smbcmd cmd;
		u_char byte;
 
		byte = 0;

		/* Initialize the struct */
		bzero(&cmd, sizeof(cmd));
		cmd.data.byte_ptr = &byte;
		cmd.slave         = 0x5a;
		cmd.cmd           = command;
 
		/* Send the command */
		if (ioctl(iodev, SMB_READB, (caddr_t)&cmd) == -1) {
			perror("IOCTL");
			exit(1);
		}
 
		/* Return the value */
		return_val = byte;
	} else if (interface == INTERFACE_IO) {
#endif /* HAVE_SMB */
		outb(WBIO1, command);
		return_val = inb(WBIO2);
#ifdef HAVE_SMB
	}
#endif

	return return_val;
}

int
main(int argc, char *argv[])
{
	double voltage;
	int i, iodev, interface, byte;
	int ch, delay, cflag, fflag, kflag, nocurses, mflag;
	int fandiv[3], fanspeed, temperature[3];
	char *device_name;

	const char *Vname[] = {
		"Vcore1", "Vcore2", "+ 3.3V", "+ 5.0V", "+12.0V", "-12.0V", "- 5.0V"
	};

	/* Get command-line options */
	cflag = 0;
	fflag = 0;
	kflag = 0;
	mflag = 0;
	delay = DELAY;
	interface = INTERFACE_SMB;
	nocurses = 0;
	while ((ch = getopt(argc, argv, "hipmr:sv")) != -1)
		switch(ch) {
		case 'i':
			interface = INTERFACE_IO;
			break;
		case 'p':
			nocurses = 1;
			break;
		case 'r':
			delay = atoi(optarg);
			break;
		case 's':
			delay = -1;
			break;
		case 'm':
			mflag = 1;
			nocurses = 1;
			delay = -1;
			break;
		default:
			usage();
			break;
		}
	argc -= optind;
	argv += optind;

	if (delay < 1)
		delay = -1;

#ifndef HAVE_SMB
	interface = INTERFACE_IO;
#endif

	/* Open the device */
	switch(interface) {
	case INTERFACE_SMB:
		device_name = SMB_DEV;
		break;
	default:
		device_name = IO_DEV;
		break;
	}

	if ((iodev = open(device_name, O_RDWR)) == -1) {
		fprintf(stderr, "Failed to open device %s.\n", device_name);
		if (!strncmp(device_name, "/dev/smb", 8)) {
			fprintf(stderr, "If your system does not support intpm(4),\n");
			fprintf(stderr, "try to use /dev/io (-i flag) or check\n");
		} else {
			fprintf(stderr, "Check ");
		}
		fprintf(stderr, "the permissions of %s.\n", device_name);
		exit(1);
	}

	/* Get fan divisors */
	byte      = get_data(iodev, LM78_FANDIV, interface);
	fandiv[0] = LM78_DIV_FROM_DATA((byte >> 4) & 0x03);
	fandiv[1] = LM78_DIV_FROM_DATA(byte >> 6);
	fandiv[2] = LM78_DIV_FROM_DATA(1);

	/* Initialize curses environment */
	if (!nocurses) {
		initscr();
		noecho();
		move(1, 1);
		printw("%s", "Motherboard Temp");
		move(5, 4);
		printw("%s", "Fan Speeds");
		for (i = 1; i < 4; i++) {
			move(i + 6, 4);
			printw("%i:      rpm", i);
		}
		move(1, 32);
		printw("%s", "Voltages");
		for (i = 0; i < 7; i++) {
			move(i + 3, 27);
			printw("%s:         V", Vname[i]);
		}
	}

	/* Start our loop (if applicable) */
	do {
		/* Get motherboard temp */
		if (nocurses && !mflag)
			printf("MB temp:\n");
		for (i = 0; i < 3; i++)
			temperature[i] = LM78_TEMP_FROM_DATA(get_data(iodev, LM78_TEMP, interface), i);
		if (mflag)
			printf("%i\n", temperature[0]);
		else if (nocurses)
			printf("%iC / %iF / %iK\n", temperature[0], temperature[1], temperature[2]);
		else {
			move(3, 1);
			printw("%iC / %iF / %iK", temperature[0], temperature[1], temperature[2]);
		}

		/* Get fan speeds */
		if (nocurses && !mflag)
			printf("Fans:\n");
		for (i = 0; i < 3; i++) {
			fanspeed = LM78_FAN_FROM_DATA(get_data(iodev, LM78_FAN(i), interface),
						      fandiv[i]);
			if (mflag)
				 printf("%i\n", fanspeed);
			else if (nocurses)
				printf("  %i : %4d rpm\n", i + 1, fanspeed);
			else {
				move(i + 7, 7);
				printw("%4i", fanspeed);
			}
		}

		/* Get voltages */
		if (nocurses && !mflag)
			printf("Voltages:\n");
		for (i = 0; i < 7; i++) {
			voltage = LM78_VOLT_FROM_DATA(get_data(iodev, LM78_VOLT(i), interface), i);
			if (mflag)
				printf("%-8.3f\n", voltage);
			else if (nocurses)
				printf("  %s :%+8.3fV\n", Vname[i], voltage);
			else {
				move(i + 3, 35);
				printw("%+8.3f", voltage);
			}
		}

		if (!nocurses) {
			move(11, 0);
			refresh();
		} else if (!mflag)
			printf("\n");

		delay > 0 ? sleep(delay) : 0;

	} while (delay != -1);

	if (!nocurses) {
		echo();
		endwin();
	}

	/* Close the file */
	close(iodev);

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1