SleepyTami
Cadet
- Joined
- Aug 25, 2021
- Messages
- 2
Hey Guys,
Just thought this simple app might help a few of you. Unfortunately, I don't have time to create a plugin for Truenas Core but it would be nice if someone else did.
Enjoy!!
Just thought this simple app might help a few of you. Unfortunately, I don't have time to create a plugin for Truenas Core but it would be nice if someone else did.
Enjoy!!
Code:
/* * Broadcom/Avago/LSI HBA/RAID cards are made to be used in servers where there's plenty of airflow (minimum of 200 linear feet per minute (LFM)). * These conditions are not always attainable in Desktop PCs without generating a considerable amount of noise. * In this scenario, there's a need of constantly monitoring the IOC core temperature to dynamically regulate fan speed. * * Unfortunately, those idiotic devs at Broadcom couldn't be bothered to add this feature to "sas3ircu" so a DIY approach had to be followed. * * The IOC has internal sensors that measure the temperature of each core. * * This very simple PoC displays the IOC core temperature (MAX(Sensor[0->N-1])) for Broadcom/Avago/LSI HBA cards. No kernel mods required. * * Tested against: * * Broadcom/Avago/LSI 9305-16i 12Gb/s HBA * * Tested on: * * FreeBSD 13.0-RELEASE * * Compile with: * * gcc lsi_temp.c -o lsi_temp * * Output: * * ./lsi_temp /dev/mpr0 * IOC Temp: 43 (C) * Board Temp: 0 (N/A) * * tami@ombra.org.uk */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/ioctl.h> #include <fcntl.h> #define MPI2_IOCSTATUS_MASK (0x7FFF) #define MPI2_IOCSTATUS_SUCCESS (0x0000) #define MPRIO_READ_CFG_PAGE _IOWR('M', 201, struct mpr_cfg_page_req) #define MPRIO_READ_CFG_HEADER _IOWR('M', 200, struct mpr_cfg_page_req) #define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) #define MPI2_IOUNITPAGE7_PAGEVERSION (0x05) #define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) #define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) #define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02) typedef struct _MPI2_CONFIG_PAGE_HEADER { uint8_t PageVersion; uint8_t PageLength; uint8_t PageNumber; uint8_t PageType; } MPI2_CONFIG_PAGE_HEADER, Mpi2ConfigPageHeader_t; struct mpr_cfg_page_req { MPI2_CONFIG_PAGE_HEADER header; uint32_t page_address; void *buf; int len; uint16_t ioc_status; }; typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { MPI2_CONFIG_PAGE_HEADER Header; uint8_t CurrentPowerMode; uint8_t PreviousPowerMode; uint8_t PCIeWidth; uint8_t PCIeSpeed; uint32_t ProcessorState; uint32_t PowerManagementCapabilities; uint16_t IOCTemperature; uint8_t IOCTemperatureUnits; uint8_t IOCSpeed; uint16_t BoardTemperature; uint8_t BoardTemperatureUnits; uint8_t Reserved3; uint32_t BoardPowerRequirement; uint32_t PCISlotPowerAllocation; uint8_t Flags; uint8_t Reserved6; uint16_t Reserved7; uint32_t Reserved8; } MPI2_CONFIG_PAGE_IO_UNIT_7, Mpi2IOUnitPage7_t; /* Application specific methods */ char *utos (uint8_t unit) { switch (unit) { case MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT: return "F"; case MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS: return "C"; default: return "N/A"; } } int main (int argc, char **argv) { int fd = 0, ret = 0; struct mpr_cfg_page_req req; Mpi2IOUnitPage7_t pg7; if (argc != 2) { printf("%s: </dev/mpr0>\n", argv[0]); return 1; } if(geteuid() != 0) { printf("Error: Not root!!\n"); return 1; } fd = open(argv[1], O_RDWR); if(fd == 0) { printf("Error: Could not open device file!!\n"); return 1; } /* Initialize structs */ memset(&req, 0x00, sizeof(struct mpr_cfg_page_req)); memset(&pg7, 0x00, sizeof(Mpi2IOUnitPage7_t)); /* Get config page 7 header */ req.header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; req.header.PageNumber = 7; req.header.PageVersion = MPI2_IOUNITPAGE7_PAGEVERSION; req.buf = (Mpi2IOUnitPage7_t *) & pg7; req.len = sizeof (Mpi2IOUnitPage7_t); if(req.buf == NULL) { printf("Error: Out of memory!!\n"); close(fd); return 1; } pg7.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; pg7.Header.PageNumber = 7; pg7.Header.PageVersion = MPI2_IOUNITPAGE7_PAGEVERSION; ret = ioctl(fd, MPRIO_READ_CFG_HEADER, &req); if(ret != 0) { printf("Error: MPRIO_READ_CFG_HEADER: IOCTL request failed with error num %d!!\n", ret); close (fd); return 1; } if((req.ioc_status & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { printf("Error: MPRIO_READ_CFG_HEADER: Reply ioc_status != 0x0000 (%x)!!\n", req.ioc_status); close(fd); return 1; } /* Get config page 7 content */ memcpy(req.buf, &req.header, sizeof(MPI2_CONFIG_PAGE_HEADER)); ret = ioctl(fd, MPRIO_READ_CFG_PAGE, &req); if(ret != 0) { printf("Error: MPRIO_READ_CFG_PAGE: IOCTL request failed with error num %d!!\n", ret); close(fd); return 1; } if((req.ioc_status & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { printf("Error: MPRIO_READ_CFG_PAGE: Reply ioc_status != 0x0000 (%x)!!\n", req.ioc_status); close(fd); return 1; } /* Display info */ printf("IOC Temp: %hu (%s)\n", pg7.IOCTemperature, utos(pg7.IOCTemperatureUnits)); printf("Board Temp: %hu (%s)\n", pg7.BoardTemperature, utos(pg7.BoardTemperatureUnits)); /* Exit */ close(fd); return 0; }