AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 484673
Accepted
Thorbjørn E. K. Christensen
Thorbjørn E. K. Christensen
Asked: 2018-11-29 06:13:23 +0800 CST2018-11-29 06:13:23 +0800 CST 2018-11-29 06:13:23 +0800 CST

Clevo N141WU 风扇冷却时的噪音

  • 772

我刚从丹麦 PC 商店买了一台Clevo N141WU(在系统 76 上它被称为 galago pro)。

它主要工作得非常好,但是当风扇旋转时(在繁重的工作量之后)它开始发出非常高的音调并且风扇停止(听起来风扇没有获得旋转所需的电压)。

我打电话给商店,他们的解决方案是一些 Windows 软件,但 PC 没有 Windows,我买它是为了运行 Linux(因为它与 galago pro 相同,我认为它会工作)。

由于笔记本电脑从 system76 运行 Linux,我认为它应该是可行的。

我应该安装什么让它运行得更好,或者有人知道让粉丝开心的 BIOS 技巧吗?

我正在运行 Solus 3.X,其中 x 是您想花时间插入的许多九;-)

使用键盘快捷键Fn+ 1(在有关 system76 galago pro 的大声风扇的线程中找到)两次将打开和关闭风扇。这将消除声音,直到下一个硬负载消失。

自最初发布以来,我发现了两件事:

  • system76 有一些固件更新,但谁知道他们是否愿意将其发送给其他经销商的笔记本电脑(我会很好地问他们)
  • System76 在 ubuntu 中有一个名为 system76-dkms 的软件包,它可能提供风扇控制,但它不在 Solus 存储库中。(今晚我可能会在 Solus irc 中询问包装的工作原理。)
bios laptop
  • 1 1 个回答
  • 1104 Views

1 个回答

  • Voted
  1. Best Answer
    user2464424
    2019-01-13T10:03:37+08:002019-01-13T10:03:37+08:00

    我使用下面的代码在 Windows 10 中取得了成功。它处理风扇可能出现的两种故障,即:“风扇突然停止,风扇占空比=0”和“风扇突然停止,rpm > 10000,并且可以听到来自风扇的电噪声”。它需要一个加载 Winring0 的程序,例如在后台运行的 ThrottleStop。我没有在安装了 Clevo Control Center 的情况下对其进行测试。它与 MinGW-w64 一起编译\yourmingwpath\i686-w64-mingw32-gcc.exe \yoursourcepath\main.c -o \yourexepath\main.exe -Wall -mwindows

    #define UNICODE 1
    #define _UNICODE 1
    
    #include <windows.h>
    #include <winioctl.h>
    #include <stdio.h>
    #include <stddef.h>
    
    #define OLS_TYPE 40000
    #define IOCTL_OLS_READ_IO_PORT_BYTE CTL_CODE(OLS_TYPE, 0x833, METHOD_BUFFERED, FILE_READ_ACCESS)
    #define IOCTL_OLS_WRITE_IO_PORT_BYTE CTL_CODE(OLS_TYPE, 0x836, METHOD_BUFFERED, FILE_WRITE_ACCESS)
    
    #define EC_SC 0x66
    #define EC_DATA 0x62
    
    #define IBF 1
    #define OBF 0
    #define EC_SC_READ_CMD 0x80
    
    typedef struct _OLS_WRITE_IO_PORT_INPUT {
        ULONG   PortNumber; 
        union {
            ULONG   LongData;
            USHORT  ShortData;
            UCHAR   CharData;
        };
    }   OLS_WRITE_IO_PORT_INPUT;
    
    HANDLE hDevice = INVALID_HANDLE_VALUE;
    char filename[1024] = {0};
    
    WORD WInp(WORD port) {
        FILE *outlog;
        unsigned int error = 0;
    
        DWORD   returnedLength = 0;
        WORD    value = 0;
        BOOL    bResult = FALSE;
        bResult = DeviceIoControl(hDevice,
                                IOCTL_OLS_READ_IO_PORT_BYTE,
                                &port, sizeof(port),
                                &value, sizeof(value),
                                &returnedLength,
                                NULL );
        if (bResult) {
            /*outlog = fopen(filename, "ab");
            fprintf(outlog, "port=%d, value=%d, retlength=%d\n", port, value, (int)returnedLength);
            fclose(outlog);*/
            return value;
        } else {
            error = GetLastError();
            outlog = fopen(filename, "ab");
            fprintf(outlog, "DeviceIoControl (read) failed. Error %d.\n", error);
            fclose(outlog);
            CloseHandle(hDevice);
            return 0;
        }
    }
    
    WORD WOutp(WORD port, BYTE value) {
        FILE *outlog;
        unsigned int error = 0;
    
        DWORD   returnedLength = 0;
        BOOL    bResult = FALSE;
        DWORD   length = 0;
        OLS_WRITE_IO_PORT_INPUT inBuf;
        inBuf.CharData = value;
        inBuf.PortNumber = port;
        length = offsetof(OLS_WRITE_IO_PORT_INPUT, CharData) + sizeof(inBuf.CharData);
        bResult = DeviceIoControl(hDevice,
                                IOCTL_OLS_WRITE_IO_PORT_BYTE,
                                &inBuf, length,
                                NULL, 0,
                                &returnedLength,
                                NULL);
        if (bResult) {
            /*outlog = fopen(filename, "ab");
            fprintf(outlog, "port=%d, value=%d, retlength=%d\n", port, value, (int)returnedLength);
            fclose(outlog);*/
            return value;
        } else {
            error = GetLastError();
            outlog = fopen(filename, "ab");
            fprintf(outlog, "DeviceIoControl (write) failed. Error %d.\n", error);
            fclose(outlog);
            CloseHandle(hDevice);
            return 0;
        }
    }
    
    int wait_ec(const unsigned int port, const unsigned int flag, const char value) {
        int i = 0;
        unsigned char data = WInp(port);
    
        while (((data >> flag)&0x1)!=value) {
            Sleep(1);
            if (i>10) {
                //printf( "Still waiting on port 0x%x, data=0x%x, flag=0x%x, value=0x%x, i=%d\n", port, data, flag, value, i);
                return 0;
            }
            i++;
            data = WInp(port);
        }
        //printf( "Succeeded port 0x%x, data=0x%x, flag=0x%x, value=0x%x, i=%d\n", port, data, flag, value, i);
        return 0;
    }
    
    unsigned char read_ec(const unsigned int port) {
        wait_ec(EC_SC, IBF, 0);
        WOutp(EC_SC, EC_SC_READ_CMD);
        wait_ec(EC_SC, IBF, 0);
        WOutp(EC_DATA, port);
        wait_ec(EC_SC, OBF, 1);
        return WInp(EC_DATA);
    }
    
    void do_ec(const unsigned int cmd, const unsigned int port, const unsigned char value) {
        wait_ec(EC_SC, IBF, 0);
        WOutp(EC_SC, cmd);
        wait_ec(EC_SC, IBF, 0);
        WOutp(EC_DATA, port);
        wait_ec(EC_SC, IBF, 0);
        WOutp(EC_DATA, value);
        wait_ec(EC_SC, IBF, 0);
        return;
    }
    
    void write_fan_duty(int duty_percentage) {
        do_ec(0x99, 0x01, (int)(((double) duty_percentage) / 100.0 * 255.0));
        //FILE *outlog = fopen(filename, "ab");
        //fprintf(outlog, "Fan set to %d\n", duty_percentage);
        //fclose(outlog);
        return;
    }
    
    int main(){
        // get the path of this executable and append "stdout.txt\0" to it for the log file.
        int i = GetModuleFileNameA(NULL, filename, 1024);
        for (;i>0 && filename[i] != '\\';i--) {}
        char *dest=&filename[i+1], *src="stdout.txt\0";
        for (i=0;i<11;i++) dest[i]=src[i];
    
        FILE *outlog;
        outlog = fopen(filename, "wb"); // clear the log at every start
        fclose(outlog);
        unsigned int error = 0;
    
        // I could loop CreateFile until a valid handle is returned (which means that WinRing0_1_2_0 got started by throttlestop)
        // but windows defender blocks the program at start for a few seconds with 100% core usage if i do that.
    
        Sleep(3000); // ... so this is what i have to do instead. Disgusting.
    
        hDevice = CreateFile(L"\\\\.\\WinRing0_1_2_0",
                            GENERIC_READ | GENERIC_WRITE,
                            0,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
    
        if (hDevice == INVALID_HANDLE_VALUE) {
            error = GetLastError();
            if (error == ERROR_ACCESS_DENIED) {
                outlog = fopen(filename, "ab");
                fprintf(outlog, "CreateFile failed. Please retry as administrator.\n");
                fclose(outlog);
            } else if (error == ERROR_FILE_NOT_FOUND) {
                outlog = fopen(filename, "ab");
                fprintf(outlog, "CreateFile failed. The WinRing0 driver is probably not loaded yet.\n");
                fclose(outlog);
            } else {
                outlog = fopen(filename, "ab");
                fprintf(outlog, "CreateFile failed. Error %d.\n", error);
                fclose(outlog);
            }
            return 0;
        }
    
        int val_duty, raw_rpm, val_rpm, temp, last_valid_duty=50;
        while (1) {
            val_duty = (int) ((double) (read_ec(0xCE)) / 255.0 * 100.0);
            raw_rpm = (read_ec(0xD0) << 8) + (read_ec(0xD1));
            if (raw_rpm == 0)
                val_rpm = 0;
            else
                val_rpm = 2156220 / raw_rpm;
            temp = read_ec(0x07);
    
            //outlog = fopen(filename, "ab");
            //fprintf(outlog, "FAN Duty: %d%%, FAN RPMs: %d RPM, CPU Temp: %d°C\n", val_duty, val_rpm, temp);
            //fclose(outlog);
    
            if (val_rpm > 10000 || val_duty == 0) {
                // there are two malfunctions that can happen:
                // - fan stops suddenly with fan duty=0
                // - fan stops suddenly with rpm > 10000 with a electric noise that can be heard coming from the fan.
                outlog = fopen(filename, "ab");
                fprintf(outlog, "MALFUNCTION DETECTED: val_rpm=%d, val_duty=%d\n", val_rpm, val_duty);
                fclose(outlog);
                // Panic :O
                if (last_valid_duty<80) {
                    write_fan_duty(last_valid_duty+20);
                } else {
                    write_fan_duty(last_valid_duty-20);
                }
            } else {
                // This is the custom fan curve code. Can be adjusted to your liking.
                // It's required because i don't know to to set the fan back to "automatic" without manual intervention.
                // Can definitely conflict with other fan speed programs, so be careful.
                // Writes to fan speed are limited to only if the target fan duty changes.
                if (temp<55) {
                    if (last_valid_duty > 32 || last_valid_duty < 29) write_fan_duty(31);
                } else if (temp<60) {
                    if (last_valid_duty > 42 || last_valid_duty < 39) write_fan_duty(41);
                } else if (temp<65) {
                    if (last_valid_duty > 52 || last_valid_duty < 49) write_fan_duty(51);
                } else if (temp<70) {
                    if (last_valid_duty > 62 || last_valid_duty < 59) write_fan_duty(61);
                } else if (temp<75) {
                    if (last_valid_duty > 72 || last_valid_duty < 69) write_fan_duty(71);
                } else if (temp<80) {
                    if (last_valid_duty > 82 || last_valid_duty < 79) write_fan_duty(81);
                } else if (temp<85) {
                    if (last_valid_duty > 92 || last_valid_duty < 89) write_fan_duty(91);
                } else {
                    if (last_valid_duty < 98) write_fan_duty(100);
                }
                last_valid_duty = val_duty;
            }
            Sleep(200);
        }
        return 0;
    }
    

    我还没有移植代码以在基于 linux 的 oses 中使用。这样做需要:

    • 用and替换WInp(port)andWOutp(port, value)函数,inb(port)outb(value, port)
    • 在此代码片段ioperm的开头添加,
    • 替换Sleep(milliseconds)为usleep(microseconds),
    • 清理所有现在无用的包含、定义、结构和句柄,
    • 替换GetModuleFileNameA为等效功能。
    • 1

相关问题

  • Ubuntu 16.04 上的双显示器冻结问题

  • 从 BIOS/EFI 进行网络引导 (PXE)

  • Nvidia GPU + Supermicro + Xeon + Ubuntu 16.04 = 不工作

  • 带有 AMD Radeon 530 的 Bumblebee(带有 Debian 的笔记本电脑)

  • HP 笔记本电脑上的 Manjaro - 关闭电源时电池耗尽

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve