drivers/watchdog/pcwd.c
Source file repositories/reference/linux-study-clean/drivers/watchdog/pcwd.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/watchdog/pcwd.c- Extension
.c- Size
- 26508 bytes
- Lines
- 997
- Domain
- Driver Families
- Bucket
- drivers/watchdog
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/moduleparam.hlinux/types.hlinux/errno.hlinux/kernel.hlinux/delay.hlinux/timer.hlinux/jiffies.hlinux/miscdevice.hlinux/watchdog.hlinux/reboot.hlinux/init.hlinux/fs.hlinux/isa.hlinux/ioport.hlinux/spinlock.hlinux/uaccess.hlinux/io.h
Detected Declarations
function send_isa_commandfunction set_command_modefunction unset_command_modefunction pcwd_check_temperature_supportfunction pcwd_get_firmwarefunction pcwd_get_option_switchesfunction pcwd_show_card_infofunction pcwd_timer_pingfunction pcwd_startfunction pcwd_stopfunction pcwd_keepalivefunction pcwd_set_heartbeatfunction pcwd_get_statusfunction pcwd_clear_statusfunction pcwd_get_temperaturefunction pcwd_ioctlfunction pcwd_writefunction pcwd_openfunction pcwd_closefunction pcwd_temp_readfunction pcwd_temp_openfunction pcwd_temp_closefunction get_revisionfunction pcwd_isa_matchfunction pcwd_isa_probefunction pcwd_isa_removefunction pcwd_isa_shutdown
Annotated Snippet
static const struct file_operations pcwd_fops = {
.owner = THIS_MODULE,
.write = pcwd_write,
.unlocked_ioctl = pcwd_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.open = pcwd_open,
.release = pcwd_close,
};
static struct miscdevice pcwd_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &pcwd_fops,
};
static const struct file_operations pcwd_temp_fops = {
.owner = THIS_MODULE,
.read = pcwd_temp_read,
.open = pcwd_temp_open,
.release = pcwd_temp_close,
};
static struct miscdevice temp_miscdev = {
.minor = TEMP_MINOR,
.name = "temperature",
.fops = &pcwd_temp_fops,
};
/*
* Init & exit routines
*/
static inline int get_revision(void)
{
int r = PCWD_REVISION_C;
spin_lock(&pcwd_private.io_lock);
/* REV A cards use only 2 io ports; test
* presumes a floating bus reads as 0xff. */
if ((inb(pcwd_private.io_addr + 2) == 0xFF) ||
(inb(pcwd_private.io_addr + 3) == 0xFF))
r = PCWD_REVISION_A;
spin_unlock(&pcwd_private.io_lock);
return r;
}
/*
* The ISA cards have a heartbeat bit in one of the registers, which
* register is card dependent. The heartbeat bit is monitored, and if
* found, is considered proof that a Berkshire card has been found.
* The initial rate is once per second at board start up, then twice
* per second for normal operation.
*/
static int pcwd_isa_match(struct device *dev, unsigned int id)
{
int base_addr = pcwd_ioports[id];
int port0, last_port0; /* Reg 0, in case it's REV A */
int port1, last_port1; /* Register 1 for REV C cards */
int i;
int retval;
if (debug >= DEBUG)
pr_debug("pcwd_isa_match id=%d\n", id);
if (!request_region(base_addr, 4, "PCWD")) {
pr_info("Port 0x%04x unavailable\n", base_addr);
return 0;
}
retval = 0;
port0 = inb_p(base_addr); /* For REV A boards */
port1 = inb_p(base_addr + 1); /* For REV C boards */
if (port0 != 0xff || port1 != 0xff) {
/* Not an 'ff' from a floating bus, so must be a card! */
for (i = 0; i < 4; ++i) {
msleep(500);
last_port0 = port0;
last_port1 = port1;
port0 = inb_p(base_addr);
port1 = inb_p(base_addr + 1);
/* Has either heartbeat bit changed? */
if ((port0 ^ last_port0) & WD_HRTBT ||
(port1 ^ last_port1) & WD_REVC_HRBT) {
retval = 1;
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleparam.h`, `linux/types.h`, `linux/errno.h`, `linux/kernel.h`, `linux/delay.h`, `linux/timer.h`, `linux/jiffies.h`.
- Detected declarations: `function send_isa_command`, `function set_command_mode`, `function unset_command_mode`, `function pcwd_check_temperature_support`, `function pcwd_get_firmware`, `function pcwd_get_option_switches`, `function pcwd_show_card_info`, `function pcwd_timer_ping`, `function pcwd_start`, `function pcwd_stop`.
- Atlas domain: Driver Families / drivers/watchdog.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.