Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Mar 2001 06:32:46 -0800
From:      Ben Lovett <blovett@bsdguru.com>
To:        Dann Lunsford <dann@greycat.com>
Cc:        mobile@FreeBSD.ORG
Subject:   Re: Tosh 2595XDVD -- fan control?
Message-ID:  <20010314063246.A12367@bsdguru.com>
In-Reply-To: <20010313234128.A70849@greycat.com>; from dann@greycat.com on Tue, Mar 13, 2001 at 11:41:28PM -0800
References:  <20010313234128.A70849@greycat.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--xHFwDpU9dbj6ez1V
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I believe I saw Dann Lunsford (dann@greycat.com) write this:
> Have a ${SUBJECT}, running 4.2-STABLE as of Jan 5. Looking for data
> on turning on the cooling fan (as it gets a bit warm in there).  Natch, 
> Toshiba's reaction on hearing "FreeBSD" or "UNIX" is "Huh?",  Anyone got
> a clue? Ideally, I'd just like to type "fan on" or "fan off", but I'll
> take whatever I can get.  I've seen some references to Linux based
> utils of this type, but my experience has been that porting Linux 
> hardware utils is pure torture.  
> 
> Thanks!
> 
> 
> -- 
> Dann Lunsford       The only thing necessary for the triumph of evil
> dann@greycat.com    is that men of good will do nothing.  --  Cicero
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-mobile" in the body of the message
> 
Hello Dann,

I had this very same problem on my Satellite 2505CDS and 2515CDS and
someone was kind enough to port the Linux fan util to FreeBSD so it
works great ;)

I have attached the fan util and here are some instructions on how to
use it.  It *may* need to be modified slightly for a new laptop but I'm
not sure (not being a coder myself).

To start run: fan -n
to stop: fan -f (both must be done as root)

HTH
-- 
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Ben Lovett                                  printf("Hello world!);
blovett@bsdguru.com                         return 0;
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
            The dark ages were caused by the Y1K problem.

--xHFwDpU9dbj6ez1V
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fan.c"

/* fan.c -- turn the internal fan on/off in a Toshiba Pentium(tm) laptop.
 *
 * Copyright (c) 1996/98  Jonathan A. Buzzard (jonathan@buzzard.org.uk)
 *
 * $Log: fan.c,v $
 * Revision 3.1  1999/07/24 13:52:37  jab
 * updates for glibc
 *
 * Revision 3.0  1998/07/11 14:01:38  jab
 * New selective switching method based on the return from GetMachineID,
 * should work on all known models
 *
 * Revision 2.2  1998/05/30 22:50:03  jab
 * hopefully fixed problems with reporting of fan status
 *
 * Revision 2.1  1998/05/08 22:52:17  jab
 * now drop root priveleges as soon as permision on the ports granted
 *
 * Revision 2.0  1998/01/31 16:00:23  jab
 * Changed to new method of turning the fan on/off, which should
 * work on a wider range of Toshiba laptops
 *
 * Revision 1.5  1997/05/23 13:17:25  jab
 * change the command line option processing to only deal with the first
 *
 * Revision 1.4  1997/04/29 21:26:11  jab
 * changed the name of the port variables to reflect their real status
 *
 * Revision 1.3  1996/08/01 14:25:36  jab
 * Added logging of changes in fan status via syslogd(8)
 *
 * Revision 1.2  1996/07/30 18:11:16  jab
 * fixed reporting of unknown command line options
 *
 * Revision 1.1  1996/06/25 21:47:42  jab
 * Initial revision
 *
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

static const char rcsid[]="$Id: fan.c,v 3.1 1999/07/24 13:52:37 jab Exp jab $";


#include<unistd.h>
#include<syslog.h>
#include<pwd.h>
/* #include<features.h> */
#ifdef __GLIBC__
#include<sys/perm.h>
#endif
#include<stdio.h>
#include<stdlib.h>
#include<machine/sysarch.h>


#define DEFAULT 0
#define PORTAGE 1
#define TECRA   2

int GetMachineID(int *id)
{
	unsigned short lsb,msb;
	unsigned char fl1,fl2;

	return 0;

	asm ("movw $0xfe00,%%ax\n\t" \
		"movw $0x0070,%%bx\n\t" \
		"movl $0x000ffffa,%%edx\n\t" \
		"inb $0xb2,%%al\n\t" \
		"movw %%cx,%0\n\t" \
		"lahf\n\t" \
		"movb %%ah,%1\n\t" \
		"movw $0xfe00,%%ax\n\t" \
		"movw $0x0070,%%bx\n\t" \
		"movl $0x000ffffe,%%edx\n\t" \
		"inb $0xb2,%%al\n\t" \
		"movw %%cx,%2\n\t" \
		"lahf\n\t" \
		"movb %%ah,%3\n"
		:"=m" (lsb), "=m" (fl1), "=m" (msb), "=m" (fl2) \
		: \
		: "memory" );

		*id = (lsb & 0xff) + 0x100*(msb & 0xff);

		return ((fl1 & 0x01)==1) || ((fl2 & 0x01)==1);
}



void FanOn(int method)
{
	switch (method) {
		case PORTAGE:
			asm("cli\n\t" \
				"movb $0xbe,%al\n\t" \
				"outb %al,$0xe4\n\t" \
				"inb $0xe5,%al\n\t" \
				"andb $0xfe,%al\n\t" \
				"movb %al,%ah\n\t" \
				"movb $0xbe,%al\n\t" \
				"outb %al,$0xe4\n\t" \
				"movb %ah,%al\n\t" \
				"outb %al,$0xe5\n\t" \
				"sti");
			break;
		case TECRA:
			asm("cli\n\t" \
				"movw $0x00e4,%dx\n\t" \
				"movb $0xe0,%al\n\t" \
				"outb %al,%dx\n\t" \
				"incw %dx\n\t" \
				"inb %dx,%al\n\t" \
				"orw $0x0001,%ax\n\t" \
				"decw %dx\n\t" \
				"movb %al,%ah\n\t" \
				"movb $0xe0,%al\n\t" \
				"outw %ax,%dx\n\t" \
				"sti");
			break;
		default:
			asm ("movw $0xffff,%ax\n\t" \
				"movw $0x0004,%bx\n\t" \
				"movw $0x0001,%cx\n\t" \
				"inb $0xb2,%al");
			break;
		}

	return;
}

void FanOff(int method)
{
	switch (method) {
		case PORTAGE:
			asm("cli\n\t" \
				"movb $0xbe,%al\n\t" \
				"outb %al,$0xe4\n\t" \
				"inb $0xe5,%al\n\t" \
				"orb $0x01,%al\n\t" \
				"movb %al,%ah\n\t" \
				"movb $0xbe,%al\n\t" \
				"outb %al,$0xe4\n\t" \
				"movb %ah,%al\n\t" \
				"outb %al,$0xe5\n\t" \
				"sti");
			break;
		case TECRA:
			asm("cli\n\t" \
				"movw $0x00e4,%dx\n\t" \
				"movb $0xe0,%al\n\t" \
				"outb %al,%dx\n\t" \
				"incw %dx\n\t" \
				"inb %dx,%al\n\t" \
				"andw $0xfffe,%ax\n\t" \
				"decw %dx\n\t" \
				"movb %al,%ah\n\t" \
				"movb $0xe0,%al\n\t" \
				"outw %ax,%dx\n\t" \
				"sti");
			break;
		default:
			asm ("movw $0xffff,%ax\n\t" \
				"movw $0x0004,%bx\n\t" \
				"movw $0x0000,%cx\n\t" \
				"inb $0xb2,%al");
			break;
		}

	return;
}

int FanStatus(int method)
{
	unsigned short status;

	switch(method) {
		case PORTAGE:
			asm("cli\n\t" \
				"movb $0xbe,%%al\n\t" \
				"outb %%al,$0xe4\n\t" \
				"inb $0xe5,%%al\n\t" \
				"andw $0x0001,%%ax\n\t" \
				"movw %%ax,%0\n\t" \
				"sti\n"
 				:"=m" (status) : : "memory" );
				status = (status==0x00) ? 0x01:0x00;
			break;
		case TECRA:
			asm("cli\n\t" \
				"movw $0x00e4,%%dx\n\t" \
				"movb $0xe0,%%al\n\t" \
				"outb %%al,%%dx\n\t" \
				"incw %%dx\n\t" \
				"inb %%dx,%%al\n\t" \
				"andw $0x0001,%%ax\n\t"
				"movw %%ax,%0\n\t" \
				"sti\n"
				:"=m" (status) : : "memory" );
			break;
		default:
			asm ("pushl %%eax\n\t" \
				"pushl %%ebx\n\t" \
				"pushl %%ecx\n\t" \
				"movw $0xfefe,%%ax\n\t" \
				"movw $0x0004,%%bx\n\t" \
				"movw $0x0000,%%cx\n\t" \
				"inb $0xb2,%%al\n\t" \
				"andw $0x0001,%%cx\n\t" \
				"movw %%cx,%0\n\t" \
				"popl %%ecx\n\t" \
				"popl %%ebx\n\t" \
				"popl %%eax\n"
 				:"=m" (status) : : "memory" );
			break;
		}

	return (int) status;
}


int main(int argc, char *argv[])
{
	int method,id;
	struct passwd *pw;
	char *name;

	/* get the necessary I/O permissions */

#ifdef NONONO
	if (iopl(3)) {
		printf("fan: can't get I/O permissions.\n");
		exit (1);
		}
#endif	/* NONONO */
	if ( i386_set_ioperm( 0xb2, 4, 1) )
		perror("ioperm()");


	/* drop root priveleges to minimize security risk of running suid root */

/*	seteuid(getuid());
	setegid(getgid()); */

	/* open connection to system logger */

	openlog("fan", LOG_PID | LOG_CONS, LOG_USER);

	/* get user name */

	pw = getpwuid(getuid());
	name = pw ? pw->pw_name : getenv("LOGNAME");

	/* select a method based on the model we are running on */

	method = DEFAULT;
	if (GetMachineID(&id)==0x00) {
		if (id==0xfccb)
			method = PORTAGE;
		else if (id==0xfccc)
			method = TECRA;
		}

	/* process command line arguments */

	if ((--argc>0) && ((*++argv)[0]=='-'))
		switch (*++argv[0]) {
			case 'n':      /* turn the fan on */
				FanOn(method);
				syslog(LOG_INFO, "cooling fan turned on by %s", name);
				break;

			case 'f':     /* turn the fan off */
				FanOff(method);
				syslog(LOG_INFO, "cooling fan turned off by %s", name);
				break;

			default:
				printf("fan: illegal option %s\nUsage: fan [-n|f]\n", argv[0]);
				exit(1);
			}

	/* Toshiba's fan.exe waits here for 0.1 seconds, so we do the same */
	
	usleep(100000);

	/* print the current status of the fan */

	if (FanStatus(method)==0x00)
		printf("Fan is off.\n");
	else
		printf("Fan is on.\n");

	return 0;
}

--xHFwDpU9dbj6ez1V--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010314063246.A12367>