Linux的WDT(watchdog)驱动(4)

static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
                size_t len, loff_t *ppos)
{
    /*
    * Refresh the timer.
    */
    if (len) {
        if (!nowayout) {
            size_t i;

/* In case it was set long ago */
            expect_close = 0;

for (i = 0; i != len; i++) {
                char c;

if (get_user(c, data + i))
                    return -EFAULT;
                if (c == 'V')
                    expect_close = 42;
            }
        }
        s3c2410wdt_keepalive();
    }
    return len;
}

#define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)

static const struct watchdog_info s3c2410_wdt_ident = {
    .options = OPTIONS,
    .firmware_version = 0,
    .identity = "S3C2410 Watchdog",
};


static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg)
{
    void __user *argp = (void __user *)arg;
    int __user *p = argp;
    int new_margin;

switch (cmd) {
    case WDIOC_GETSUPPORT:
        return copy_to_user(argp, &s3c2410_wdt_ident,
            sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
    case WDIOC_GETSTATUS:
    case WDIOC_GETBOOTSTATUS:
        return put_user(0, p);
    case WDIOC_KEEPALIVE:
        s3c2410wdt_keepalive();
        return 0;
    case WDIOC_SETTIMEOUT:
        if (get_user(new_margin, p))
            return -EFAULT;
        if (s3c2410wdt_set_heartbeat(new_margin))
            return -EINVAL;
        s3c2410wdt_keepalive();
        return put_user(tmr_margin, p);
    case WDIOC_GETTIMEOUT:
        return put_user(tmr_margin, p);
    default:
        return -ENOTTY;
    }
}

/* kernel interface */

static const struct file_operations s3c2410wdt_fops = {
    .owner = THIS_MODULE,
    .llseek = no_llseek,
    .write = s3c2410wdt_write,
    .unlocked_ioctl = s3c2410wdt_ioctl,
    .open = s3c2410wdt_open,
    .release = s3c2410wdt_release,
};

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

/* interrupt handler code */

static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
{
    dev_info(wdt_dev, "watchdog timer expired (irq)\n");

s3c2410wdt_keepalive();
    return IRQ_HANDLED;
}
/* device interface */

static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
{
    struct resource *res;
    struct device *dev;
    unsigned int wtcon;
    int started = 0;
    int ret;
    int size;

DBG("%s: probe=%p\n", __func__, pdev);

dev = &pdev->dev;
    wdt_dev = &pdev->dev;

/* get the memory region for the watchdog timer -- flags is IORESOURCE_MEM */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (res == NULL) {
        dev_err(dev, "no memory resource specified\n");
        return -ENOENT;
    }

size = (res->end - res->start) + 1;

//请求分配指定的I/O内存资源
    wdt_mem = request_mem_region(res->start, size, pdev->name);
    if (wdt_mem == NULL) {
        dev_err(dev, "failed to get memory region\n");
        ret = -ENOENT;
        goto err_req;
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/16180.html