drivers/hwmon/fschmd.c
Source file repositories/reference/linux-study-clean/drivers/hwmon/fschmd.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/hwmon/fschmd.c- Extension
.c- Size
- 39650 bytes
- Lines
- 1370
- Domain
- Driver Families
- Bucket
- drivers/hwmon
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/init.hlinux/slab.hlinux/jiffies.hlinux/i2c.hlinux/hwmon.hlinux/hwmon-sysfs.hlinux/err.hlinux/mutex.hlinux/sysfs.hlinux/dmi.hlinux/fs.hlinux/watchdog.hlinux/miscdevice.hlinux/uaccess.hlinux/kref.h
Detected Declarations
struct fschmd_dataenum chipsfunction fschmd_release_resourcesfunction in_value_showfunction temp_value_showfunction temp_max_showfunction temp_max_storefunction temp_fault_showfunction temp_alarm_showfunction fan_value_showfunction fan_div_showfunction fan_div_storefunction fan_alarm_showfunction fan_fault_showfunction pwm_auto_point1_pwm_showfunction pwm_auto_point1_pwm_storefunction alert_led_showfunction alert_led_storefunction watchdog_set_timeoutfunction watchdog_get_timeoutfunction watchdog_triggerfunction watchdog_stopfunction watchdog_openfunction watchdog_releasefunction watchdog_writefunction watchdog_ioctlfunction fschmd_dmi_decodefunction fschmd_detectfunction fschmd_probefunction fschmd_remove
Annotated Snippet
static const struct file_operations watchdog_fops = {
.owner = THIS_MODULE,
.open = watchdog_open,
.release = watchdog_release,
.write = watchdog_write,
.unlocked_ioctl = watchdog_ioctl,
.compat_ioctl = compat_ptr_ioctl,
};
/*
* Detect, register, unregister and update device functions
*/
/*
* DMI decode routine to read voltage scaling factors from special DMI tables,
* which are available on FSC machines with an fscher or later chip.
*/
static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
{
int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0;
/*
* dmi code ugliness, we get passed the address of the contents of
* a complete DMI record, but in the form of a dmi_header pointer, in
* reality this address holds header->length bytes of which the header
* are the first 4 bytes
*/
u8 *dmi_data = (u8 *)header;
/* We are looking for OEM-specific type 185 */
if (header->type != 185)
return;
/*
* we are looking for what Siemens calls "subtype" 19, the subtype
* is stored in byte 5 of the dmi block
*/
if (header->length < 5 || dmi_data[4] != 19)
return;
/*
* After the subtype comes 1 unknown byte and then blocks of 5 bytes,
* consisting of what Siemens calls an "Entity" number, followed by
* 2 16-bit words in LSB first order
*/
for (i = 6; (i + 4) < header->length; i += 5) {
/* entity 1 - 3: voltage multiplier and offset */
if (dmi_data[i] >= 1 && dmi_data[i] <= 3) {
/* Our in sensors order and the DMI order differ */
const int shuffle[3] = { 1, 0, 2 };
int in = shuffle[dmi_data[i] - 1];
/* Check for twice the same entity */
if (found & (1 << in))
return;
mult[in] = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
offset[in] = dmi_data[i + 3] | (dmi_data[i + 4] << 8);
found |= 1 << in;
}
/* entity 7: reference voltage */
if (dmi_data[i] == 7) {
/* Check for twice the same entity */
if (found & 0x08)
return;
vref = dmi_data[i + 1] | (dmi_data[i + 2] << 8);
found |= 0x08;
}
}
if (found == 0x0F) {
for (i = 0; i < 3; i++) {
dmi_mult[i] = mult[i] * 10;
dmi_offset[i] = offset[i] * 10;
}
/*
* According to the docs there should be separate dmi entries
* for the mult's and offsets of in3-5 of the syl, but on
* my test machine these are not present
*/
dmi_mult[3] = dmi_mult[2];
dmi_mult[4] = dmi_mult[1];
dmi_mult[5] = dmi_mult[2];
dmi_offset[3] = dmi_offset[2];
dmi_offset[4] = dmi_offset[1];
Annotation
- Immediate include surface: `linux/module.h`, `linux/init.h`, `linux/slab.h`, `linux/jiffies.h`, `linux/i2c.h`, `linux/hwmon.h`, `linux/hwmon-sysfs.h`, `linux/err.h`.
- Detected declarations: `struct fschmd_data`, `enum chips`, `function fschmd_release_resources`, `function in_value_show`, `function temp_value_show`, `function temp_max_show`, `function temp_max_store`, `function temp_fault_show`, `function temp_alarm_show`, `function fan_value_show`.
- Atlas domain: Driver Families / drivers/hwmon.
- 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.