DMP 3300MX-A 임베디드 컴퓨터, 데비안 6.0 스크랩, 커널 3.2, BIOS 워치독 및 Harwdare 재설정

DMP 3300MX-A 임베디드 컴퓨터, 데비안 6.0 스크랩, 커널 3.2, BIOS 워치독 및 Harwdare 재설정

수많은 게시물을 읽으면서 임베디드 시스템에서 감시 장치를 올바르게 설정하는 방법을 연구해 왔지만 해결책이 없습니다. 나는 읽었다:

깊게 살펴보기도 했어요

그러나 지금 이 순간에는 후퇴가 없습니다.

따라서 먼저 내 하드웨어/소프트웨어를 설명하고 내가 무엇을 달성하려고 하는지 설명한 다음, 내가 한 일과 결과가 무엇인지 설명하겠습니다. 여러분 중 한 분이 저에게 올바른 방향을 알려 주실 수 있기를 바랍니다.

하워데일:

Vortex86DX CPU(A9111 @ 933Mhz)에 내장된 DMP는 다음 주소에서 일부 문서를 참조하십시오.

2개의 감시 타이머(16C550 직렬 포트 1, GPIO 포트 4)에 대한 강력한 지원을 제공하며 ALI(Acer Labs) M6117 감시 하드웨어, 24비트 카운터가 있는 32.768KHz 클록이 함께 제공됩니다. 타이머 범위는 30.5u초 ~ 512초이며, 분해능은 30.5u초입니다. 타이머가 만료되면 시스템 재설정이 발생하고 NMI 또는 IRQ가 발생할 수 있습니다.

바이오스:

미국 메가트렌드 AMIBIOS(62-0100-000001-00101111-110309-A9100-1ADSV000-Y2KC), BIOS 날짜 2011년 8월 3일

운영 체제:

Linux 커널 3.2.0-0.bpo.4-486을 사용하는 Debian 6.0 squeeze(#uname -r)

운전사:

ALI M6117 Watchdog v0.2는 내 커널에서 작동하며 Federico Bareilles의 원래 Linux 2.4.x 드라이버를 기반으로 한다고 제조업체에서 직접 나에게 제공했습니다(http://www.iar.unlp.edu.ar/~fede/ali_m6117.html)

내 목표:

제가 사는 곳에서 멀리 떨어진 곳에 기계가 설치되어 있어서 가끔 멈춰서 하드웨어 재설정을 위해 강제로 그곳으로 운전해서 가야 했습니다.

시스템이 정지되면 기기가 자동으로 재설정되도록 설정하고 싶습니다.

내가 뭘 한거지:

위의 드라이버를 컴파일(make clean, make)하고 설치(make install)했습니다. 모듈은 커널 경로 아래의 "extra" 폴더에서 올바르게 찾을 수 있습니다.

/etc/watchdog.conf파일을 편집 하고 /dev/watchdog워치독을 활성화하기 위해 해당 행의 주석 처리를 제거했습니다(다른 것은 없습니다. 주석 처리를 제거하거나 추가 행을 추가하지 않습니다).

/lib/modules/3.2.0-0.bpo.4-486/extra 폴더로 이동하고 모듈을 로드했습니다.insmod alim6117_wdt.ko

모듈이 로드되었는지 확인 lsmod하면

Module alim6117_wdt, size 12565, used by 0 

(BIOS에서 watchdog을 활성화하면 값이 1이 됩니다)

머신을 다시 시작하고 BIOS로 들어가서 watchdog 0, watchdog 0 타이머 512초, watchdog 0 신호를 활성화하고 "Reset"을 선택하세요.

나한테는 무엇이 있나요:

시스템이 정상적으로 부팅되고 watchdog 활성화/로드에 대한 메시지가 표시되지만 잠시 후 다음 메시지와 함께 재부팅됩니다. alim6117_wdt unexpected close, not stopping watchdog

실행하면 dmesg | watchdog얻을 수 있지만 [0.017827] NMI watchdog disabled (cpu0): hardware events not enabled필요한 것은 하드웨어 재설정뿐이므로 중요하지 않다고 생각합니다.

/etc/watchdog.conf성공하지 못한 채 파일에 다음 줄을 추가하여 추가 테스트를 수행했습니다.

ping            = 127.00.0.1
interface       = lan0 

lan0ifconfig명령을 통해 얻은 이더넷 인터페이스의 올바른 이름입니다 . 아니면 인터페이스를 loping하려고 하므로 인터페이스로 사용해야 합니까 ?loopback

혹시라도 시스템 부팅이 완료되면 표시되는 마지막 메시지는 다음과 같습니다.

stopping watchdog keepalive daemon....
stargint watchdog daemon....
startpar: service(s) returnet failure: rc.local ... failed!

시작 시퀀스 중 어느 시점에서 watchdog keepalive 데몬이 시작되었다가 watchdog 데몬을 시작한 직후에 중지됩니다. 이게 이상한 일인가요? 아니면 정상인가요? wd_keepalive는 항상 켜져 있어야 합니까, 아니면 감시 데몬이 시작될 때 꺼야 합니까? (이것에 대해 조사를 좀 해보니 이해하면 정상인 것 같아서 좀 헷갈립니다.)

이것이 내 옆구리에 가시가 되고 있다. 내가 뭘 잘못했나요? 누구든지 올바른 방향으로 나를 가리킬 수 있습니까?

다음은 드라이버의 소스 코드입니다.

 /** 
 *   ALi M6117 Watchdog timer driver.
 *
 *   (c) Copyright 2003 Federico Bareilles <[email protected]>,
 *   Instituto Argentino de Radio Astronomia (IAR).
 *
 *   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 of
 *   the License, or (at your option) any later version.
 *     
 *   The author does NOT admit liability nor provide warranty for any
 *   of this software. This material is provided "AS-IS" in the hope
 *   that it may be useful for others.
 *
 *   Based on alim1535_wdt.c by Alan Cox and other WDT by several
 *   authors...
 *
 *   ALi (Acer Labs) M6117 is an i386 that has the watchdog timer
 *   built in.  Watchdog uses a 32.768KHz clock with a 24 bits
 *   counter. The timer ranges is from 30.5u sec to 512 sec with
 *   resolution 30.5u sec. When the timer times out; a system reset,
 *   NMI or IRQ may happen. This can be decided by the user's
 *   programming.
 **/

#define ALI_WDT_VERSION "0.2.0"

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/proc_fs.h>

#define OUR_NAME "alim6117_wdt"

/* Port definitions: */
#define M6117_PORT_INDEX 0x22
#define M6117_PORT_DATA  0x23
/* YES, the two unused ports of 8259:
 * 0020-003f : pic1 
 *
 * The 8259 Interrup Controller uses four port addresses (0x20 through
 * 0x23). Although IBM documentation indicates that these four port
 * addresses are reserved for the 8259, only the two lower ports (0x20
 * and 0x21) ar documented as usable by programers. The two ports
 * (0x22 and 0x23) are used only when reprogramming the 8259 for
 * special dedicated systems that operate in modes which are not
 * compatible with normal IBM PC operation (this case).
 **/

/* Index for ALI M6117: */
#define ALI_LOCK_REGISTER 0x13
#define ALI_WDT           0x37
#define ALI_WDT_SELECT    0x38
#define ALI_WDT_DATA0     0x39
#define ALI_WDT_DATA1     0x3a
#define ALI_WDT_DATA2     0x3b
#define ALI_WDT_CTRL      0x3c

/* Time out generates signal select: */
#define WDT_SIGNAL_IRQ3  0x10
#define WDT_SIGNAL_IRQ4  0x20
#define WDT_SIGNAL_IRQ5  0x30
#define WDT_SIGNAL_IRQ6  0x40
#define WDT_SIGNAL_IRQ7  0x50
#define WDT_SIGNAL_IRQ9  0x60
#define WDT_SIGNAL_IRQ10 0x70
#define WDT_SIGNAL_IRQ11 0x80
#define WDT_SIGNAL_IRQ12 0x90
#define WDT_SIGNAL_IRQ14 0xa0
#define WDT_SIGNAL_IRQ15 0xb0
#define WDT_SIGNAL_NMI   0xc0
#define WDT_SIGNAL_SRSET 0xd0
/* set signal to use: */
#define WDT_SIGNAL       WDT_SIGNAL_SRSET

/* ALI_WD_TIME_FACTOR is 1000000/30.5 */
#define ALI_WD_TIME_FACTOR 32787    /* (from seconds to ALi counter) */

static unsigned long wdt_is_open;
static char ali_expect_close;
static int wdt_run = 0;


static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
    "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

static unsigned wdt_timeout = 60;
module_param(wdt_timeout, int, 0);
MODULE_PARM_DESC(wdt_timeout, "initial watchdog timeout (in seconds)");


static int alim6117_read(int index)
{
    outb(index, M6117_PORT_INDEX);
    return inb(M6117_PORT_DATA);
}

static void alim6117_write(int index, int data)
{
    outb(index, M6117_PORT_INDEX);
    outb(data, M6117_PORT_DATA);
}

static void alim6117_ulock_conf_register(void)
{
    alim6117_write(ALI_LOCK_REGISTER, 0xc5);
}

static void alim6117_lock_conf_register(void)
{
    alim6117_write(ALI_LOCK_REGISTER, 0x00);
}

static void alim6117_set_timeout(int time)
{
    u32 timeout_bits;

    timeout_bits = time * ALI_WD_TIME_FACTOR;
    alim6117_write(ALI_WDT_DATA0, timeout_bits & 0xff);
    alim6117_write(ALI_WDT_DATA1, (timeout_bits & 0xff00) >> 8);
    alim6117_write(ALI_WDT_DATA2, (timeout_bits & 0xff0000) >> 16);

    return;
}

static void alim6117_wdt_disable(void)
{
    int val = alim6117_read(ALI_WDT);

    val &= 0xbf;        /* 1011|1111 */
    alim6117_write(ALI_WDT, val);
}

static void alim6117_wdt_enable(void)
{
    int val = alim6117_read(ALI_WDT);

    val |= 0x40;        /* 0100|0000 */
    alim6117_write(ALI_WDT, val);
}

static void alim6117_wdt_signal_select(int signal)
{
    int val = alim6117_read(ALI_WDT_SELECT);

    val &= 0xf0;
    val |= signal;
    alim6117_write(ALI_WDT_SELECT, val);
}

static void ali_wdt_ping(void)
{
    int val;

    /* if no run, no ping; wdt start when ping it. */ 
    if (wdt_run) {
        alim6117_ulock_conf_register();
        val = alim6117_read(ALI_WDT);
        val &= ~0x40; /* 0100|0000 */
        alim6117_write(ALI_WDT, val);
        val |= 0x40;  /* 0100|0000 */
        alim6117_write(ALI_WDT, val);
        alim6117_lock_conf_register();
        /*
        printk(KERN_INFO OUR_NAME ": WDT ping...\n");
        */
    } else { 
        printk(KERN_WARNING OUR_NAME ": WDT is stopped\n");
    }
}

static void ali_wdt_start(void)
{
    alim6117_ulock_conf_register();
    alim6117_wdt_disable();
    alim6117_set_timeout(wdt_timeout);
    alim6117_wdt_signal_select(WDT_SIGNAL);
    alim6117_wdt_enable();
    alim6117_lock_conf_register();
    wdt_run = 1;
}

static void ali_wdt_stop(void)
{
    int val;
    if ( wdt_run ) {
        alim6117_ulock_conf_register();
        val = alim6117_read(ALI_WDT);
        val &= ~0x40;  /* 0100|0000 */
        alim6117_write(ALI_WDT, val);
        alim6117_lock_conf_register();
        wdt_run = 0;
        /*
        printk(KERN_INFO OUR_NAME ": WDT stop...\n");
        */
    }
}

/**
 *      ali_wdt_notify_sys:
 *      @this: our notifier block
 *      @code: the event being reported
 *      @unused: unused
 *
 *      Our notifier is called on system shutdowns. We want to turn the timer
 *      off at reboot otherwise the machine will reboot again during memory
 *      test or worse yet during the following fsck.
 *
 */

static int ali_wdt_notify_sys(struct notifier_block *this,
                  unsigned long code, void *unused)
{
    if (code == SYS_DOWN || code == SYS_HALT) {
        /* Turn the timer off */
        ali_wdt_stop();
    }
    return NOTIFY_DONE;
}

/**
 *      ali_write       -       writes to ALi watchdog
 *      @file: file handle to the watchdog
 *      @data: user address of data
 *      @len: length of data
 *      @ppos: pointer to the file offset
 *
 *      Handle a write to the ALi watchdog. Writing to the file pings
 *      the watchdog and resets it. Writing the magic 'V' sequence allows
 *      the next close to turn off the watchdog.
 */

static ssize_t ali_write(struct file *file, const char *data,
             size_t len, loff_t * ppos)
{
    /*  Can't seek (pwrite) on this device  */
    if (ppos != &file->f_pos)
        return -ESPIPE;

    /* Check if we've got the magic character 'V' and reload the timer */
    if (len) {
        size_t i;

        ali_expect_close = 0;

        /* scan to see whether or not we got the magic character */
        for (i = 0; i != len; i++) {
            u8 c;
            if (get_user(c, data + i))
                return -EFAULT;
            if (c == 'V')
                ali_expect_close = 42;
        }
        ali_wdt_ping();
        return 1;
    }
    return 0;
}

/**
 *      ali_ioctl       -       handle watchdog ioctls
 *      @inode: inode of the device
 *      @file: file handle to the device
 *      @cmd: watchdog command
 *      @arg: argument pointer
 *
 *      Handle the watchdog ioctls supported by the ALi driver.
 */

static long ali_ioctl(struct file *file,
             unsigned int cmd, unsigned long arg)
{
    int options;

    static struct watchdog_info ident = {
        .options          = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
        .firmware_version = 0,
        .identity         = "ALi M6117 WDT",
    };

    switch (cmd) {
    case WDIOC_KEEPALIVE:
        ali_wdt_ping();
        return 0;
    case WDIOC_SETTIMEOUT:
        if (get_user(options, (int *) arg))
            return -EFAULT;
        if (options < 1 || options > 512)
            return -EFAULT;
        wdt_timeout = options;
        ali_wdt_start();
    case WDIOC_GETTIMEOUT:
        return put_user(wdt_timeout, (int *) arg);
    case WDIOC_GETSUPPORT:
        if (copy_to_user
            ((struct watchdog_info *) arg, &ident, sizeof(ident)))
            return -EFAULT;
        return 0;
    case WDIOC_GETSTATUS:
    case WDIOC_GETBOOTSTATUS:
        return put_user(0, (int *) arg);
    case WDIOC_SETOPTIONS:
        if (get_user(options, (int *) arg))
            return -EFAULT;
        if (options & WDIOS_DISABLECARD) {
            ali_wdt_stop();
            return 0;
        }
        if (options & WDIOS_ENABLECARD) {
            ali_wdt_start();
            return 0;
        }
        return -EINVAL;

    default:
        return -ENOTTY;

    }
}

/**
 *      ali_open        -       handle open of ali watchdog
 *      @inode: inode of device
 *      @file: file handle to device
 *
 *      Open the ALi watchdog device. Ensure only one person opens it
 *      at a time. Also start the watchdog running.
 */

static int ali_open(struct inode *inode, struct file *file)
{
    if(test_and_set_bit(0, &wdt_is_open))
                return -EBUSY;
    ali_wdt_start();

    return 0;
}

/**
 *      ali_release     -       close an ALi watchdog
 *      @inode: inode from VFS
 *      @file: file from VFS
 *
 *      Close the ALi watchdog device. Actual shutdown of the timer
 *      only occurs if the magic sequence has been set or nowayout is 
 *      disabled.
 */

static int ali_release(struct inode *inode, struct file *file)
{
    if (ali_expect_close == 42 && !nowayout) {
        ali_wdt_stop();
    } else {
        printk(KERN_CRIT OUR_NAME
               ": Unexpected close, not stopping watchdog!\n");
    }
    ali_expect_close = 0;
    clear_bit(0, &wdt_is_open);

    return 0;
}

static struct file_operations ali_fops = {
    .owner          = THIS_MODULE,
    .write          = ali_write,
    .unlocked_ioctl = ali_ioctl,
    .open           = ali_open,
    .release        = ali_release,
};

static struct miscdevice ali_miscdev = {
    .minor          = WATCHDOG_MINOR,
    .name           = "watchdog",
    .fops           = &ali_fops,
};

/*
 *   The WDT needs to learn about soft shutdowns in order to turn the
 *   timebomb registers off.
 */

static struct notifier_block ali_notifier = {
    .notifier_call = ali_wdt_notify_sys,
    .next          = NULL,
    .priority      = 0
};

static int __init alim6117_init(void)
{
    if (wdt_timeout < 1 || wdt_timeout > 512){
        printk(KERN_ERR OUR_NAME
               ": Timeout out of range (0 < wdt_timeout <= 512)\n");
        return -EIO;
    }

    if (misc_register(&ali_miscdev) != 0) {
        printk(KERN_ERR OUR_NAME
               ": cannot register watchdog device node.\n");
        return -EIO;
    }

    register_reboot_notifier(&ali_notifier);

    printk(KERN_INFO "WDT driver for ALi M6117 v(" 
           ALI_WDT_VERSION ") initialising.\n");

    return 0;
}

static void __exit alim6117_exit(void)
{
    misc_deregister(&ali_miscdev);
    unregister_reboot_notifier(&ali_notifier);

    ali_wdt_stop();     /* Stop the timer */
}

module_init(alim6117_init);
module_exit(alim6117_exit);

MODULE_AUTHOR("Federico Bareilles <[email protected]>");
MODULE_DESCRIPTION("Driver for watchdog timer in ALi M6117 chip.");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("watchdog");

관련 정보