linux/drivers/watchdog/wdt_pci.c

// SPDX-License-Identifier: GPL-2.0+
/*
 *	Industrial Computer Source PCI-WDT500/501 driver
 *
 *	(c) Copyright 1996-1997 Alan Cox <[email protected]>,
 *						All Rights Reserved.
 *
 *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
 *	warranty for any of this software. This material is provided
 *	"AS-IS" and at no charge.
 *
 *	(c) Copyright 1995    Alan Cox <[email protected]>
 *
 *	Release 0.10.
 *
 *	Fixes
 *		Dave Gregorich	:	Modularisation and minor bugs
 *		Alan Cox	:	Added the watchdog ioctl() stuff
 *		Alan Cox	:	Fixed the reboot problem (as noted by
 *					Matt Crocker).
 *		Alan Cox	:	Added wdt= boot option
 *		Alan Cox	:	Cleaned up copy/user stuff
 *		Tim Hockin	:	Added insmod parameters, comment cleanup
 *					Parameterized timeout
 *		JP Nollmann	:	Added support for PCI wdt501p
 *		Alan Cox	:	Split ISA and PCI cards into two drivers
 *		Jeff Garzik	:	PCI cleanups
 *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle
 *					failures
 *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
 *		Zwane Mwaikambo	:	Magic char closing, locking changes,
 *					cleanups
 *		Matt Domsch	:	nowayout module option
 */

#define pr_fmt(fmt)

#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/fs.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/uaccess.h>


#define WDT_IS_PCI
#include "wd501p.h"

/* We can only use 1 card due to the /dev/watchdog restriction */
static int dev_count;

static unsigned long open_lock;
static DEFINE_SPINLOCK(wdtpci_lock);
static char expect_close;

static resource_size_t io;
static int irq;

/* Default timeout */
#define WD_TIMO

static int heartbeat =;
static int wd_heartbeat;
module_param(heartbeat, int, 0);
MODULE_PARM_DESC();

static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC();

/* Support for the Fan Tachometer on the PCI-WDT501 */
static int tachometer;
module_param(tachometer, int, 0);
MODULE_PARM_DESC();

static int type =;
module_param(type, int, 0);
MODULE_PARM_DESC();

/*
 *	Programming support
 */

static void wdtpci_ctr_mode(int ctr, int mode)
{}

static void wdtpci_ctr_load(int ctr, int val)
{}

/**
 *	wdtpci_start:
 *
 *	Start the watchdog driver.
 */

static int wdtpci_start(void)
{}

/**
 *	wdtpci_stop:
 *
 *	Stop the watchdog driver.
 */

static int wdtpci_stop(void)
{}

/**
 *	wdtpci_ping:
 *
 *	Reload counter one with the watchdog heartbeat. We don't bother
 *	reloading the cascade counter.
 */

static int wdtpci_ping(void)
{}

/**
 *	wdtpci_set_heartbeat:
 *	@t:		the new heartbeat value that needs to be set.
 *
 *	Set a new heartbeat value for the watchdog device. If the heartbeat
 *	value is incorrect we keep the old value and return -EINVAL.
 *	If successful we return 0.
 */
static int wdtpci_set_heartbeat(int t)
{}

/**
 *	wdtpci_get_status:
 *	@status:		the new status.
 *
 *	Extract the status information from a WDT watchdog device. There are
 *	several board variants so we have to know which bits are valid. Some
 *	bits default to one and some to zero in order to be maximally painful.
 *
 *	we then map the bits onto the status ioctl flags.
 */

static int wdtpci_get_status(int *status)
{}

/**
 *	wdtpci_get_temperature:
 *
 *	Reports the temperature in degrees Fahrenheit. The API is in
 *	farenheit. It was designed by an imperial measurement luddite.
 */

static int wdtpci_get_temperature(int *temperature)
{}

/**
 *	wdtpci_interrupt:
 *	@irq:		Interrupt number
 *	@dev_id:	Unused as we don't allow multiple devices.
 *
 *	Handle an interrupt from the board. These are raised when the status
 *	map changes in what the board considers an interesting way. That means
 *	a failure condition occurring.
 */

static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
{}


/**
 *	wdtpci_write:
 *	@file: file handle to the watchdog
 *	@buf: buffer to write (unused as data does not matter here
 *	@count: count of bytes
 *	@ppos: pointer to the position to write. No seeks allowed
 *
 *	A write to a watchdog device is defined as a keepalive signal. Any
 *	write of data will do, as we we don't define content meaning.
 */

static ssize_t wdtpci_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
{}

/**
 *	wdtpci_ioctl:
 *	@file: file handle to the device
 *	@cmd: watchdog command
 *	@arg: argument pointer
 *
 *	The watchdog API defines a common set of functions for all watchdogs
 *	according to their available features. We only actually usefully support
 *	querying capabilities and current status.
 */

static long wdtpci_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{}

/**
 *	wdtpci_open:
 *	@inode: inode of device
 *	@file: file handle to device
 *
 *	The watchdog device has been opened. The watchdog device is single
 *	open and on opening we load the counters. Counter zero is a 100Hz
 *	cascade, into counter 1 which downcounts to reboot. When the counter
 *	triggers counter 2 downcounts the length of the reset pulse which
 *	set set to be as long as possible.
 */

static int wdtpci_open(struct inode *inode, struct file *file)
{}

/**
 *	wdtpci_release:
 *	@inode: inode to board
 *	@file: file handle to board
 *
 *	The watchdog has a configurable API. There is a religious dispute
 *	between people who want their watchdog to be able to shut down and
 *	those who want to be sure if the watchdog manager dies the machine
 *	reboots. In the former case we disable the counters, in the latter
 *	case you have to open it again very soon.
 */

static int wdtpci_release(struct inode *inode, struct file *file)
{}

/**
 *	wdtpci_temp_read:
 *	@file: file handle to the watchdog board
 *	@buf: buffer to write 1 byte into
 *	@count: length of buffer
 *	@ptr: offset (no seek allowed)
 *
 *	Read reports the temperature in degrees Fahrenheit. The API is in
 *	fahrenheit. It was designed by an imperial measurement luddite.
 */

static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
						size_t count, loff_t *ptr)
{}

/**
 *	wdtpci_temp_open:
 *	@inode: inode of device
 *	@file: file handle to device
 *
 *	The temperature device has been opened.
 */

static int wdtpci_temp_open(struct inode *inode, struct file *file)
{}

/**
 *	wdtpci_temp_release:
 *	@inode: inode to board
 *	@file: file handle to board
 *
 *	The temperature device has been closed.
 */

static int wdtpci_temp_release(struct inode *inode, struct file *file)
{}

/**
 *	wdtpci_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 card
 *	off at reboot otherwise the machine will reboot again during memory
 *	test or worse yet during the following fsck. This would suck, in fact
 *	trust me - if it happens it does suck.
 */

static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
							void *unused)
{}

/*
 *	Kernel Interfaces
 */


static const struct file_operations wdtpci_fops =;

static struct miscdevice wdtpci_miscdev =;

static const struct file_operations wdtpci_temp_fops =;

static struct miscdevice temp_miscdev =;

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

static struct notifier_block wdtpci_notifier =;


static int wdtpci_init_one(struct pci_dev *dev,
					const struct pci_device_id *ent)
{}


static void wdtpci_remove_one(struct pci_dev *pdev)
{}


static const struct pci_device_id wdtpci_pci_tbl[] =;
MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);


static struct pci_driver wdtpci_driver =;

module_pci_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();