Home | History | Annotate | Line # | Download | only in emcfanctl
      1  1.1  brad /*	$NetBSD: emcfanctlutil.c,v 1.1 2025/03/11 13:56:48 brad Exp $	*/
      2  1.1  brad 
      3  1.1  brad /*
      4  1.1  brad  * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org>
      5  1.1  brad  *
      6  1.1  brad  * Permission to use, copy, modify, and distribute this software for any
      7  1.1  brad  * purpose with or without fee is hereby granted, provided that the above
      8  1.1  brad  * copyright notice and this permission notice appear in all copies.
      9  1.1  brad  *
     10  1.1  brad  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  1.1  brad  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  1.1  brad  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  1.1  brad  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  1.1  brad  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  1.1  brad  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  1.1  brad  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  1.1  brad  */
     18  1.1  brad 
     19  1.1  brad #ifdef __RCSID
     20  1.1  brad __RCSID("$NetBSD: emcfanctlutil.c,v 1.1 2025/03/11 13:56:48 brad Exp $");
     21  1.1  brad #endif
     22  1.1  brad 
     23  1.1  brad #include <inttypes.h>
     24  1.1  brad #include <stdbool.h>
     25  1.1  brad #include <stdio.h>
     26  1.1  brad #include <stdlib.h>
     27  1.1  brad #include <unistd.h>
     28  1.1  brad #include <err.h>
     29  1.1  brad #include <fcntl.h>
     30  1.1  brad #include <string.h>
     31  1.1  brad #include <limits.h>
     32  1.1  brad #include <errno.h>
     33  1.1  brad 
     34  1.1  brad #include <dev/i2c/emcfanreg.h>
     35  1.1  brad #include <dev/i2c/emcfaninfo.h>
     36  1.1  brad 
     37  1.1  brad #define EXTERN
     38  1.1  brad #include "emcfanctl.h"
     39  1.1  brad #include "emcfanctlconst.h"
     40  1.1  brad #include "emcfanctlutil.h"
     41  1.1  brad 
     42  1.1  brad int
     43  1.1  brad emcfan_read_register(int fd, uint8_t reg, uint8_t *res, bool debug)
     44  1.1  brad {
     45  1.1  brad 	int err;
     46  1.1  brad 
     47  1.1  brad 	err = lseek(fd, reg, SEEK_SET);
     48  1.1  brad 	if (err != -1) {
     49  1.1  brad 		err = read(fd, res, 1);
     50  1.1  brad 		if (err == -1)
     51  1.1  brad 			err = errno;
     52  1.1  brad 		else
     53  1.1  brad 			err = 0;
     54  1.1  brad 	} else {
     55  1.1  brad 		err = errno;
     56  1.1  brad 	}
     57  1.1  brad 
     58  1.1  brad 	if (debug)
     59  1.1  brad 		fprintf(stderr,"emcfan_read_register: reg=0x%02X, res=0x%02x, return err: %d\n",reg, *res, err);
     60  1.1  brad 
     61  1.1  brad 	return err;
     62  1.1  brad }
     63  1.1  brad 
     64  1.1  brad int
     65  1.1  brad emcfan_write_register(int fd, uint8_t reg, uint8_t value, bool debug)
     66  1.1  brad {
     67  1.1  brad 	int err;
     68  1.1  brad 
     69  1.1  brad 	err = lseek(fd, reg, SEEK_SET);
     70  1.1  brad 	if (err != -1) {
     71  1.1  brad 		err = write(fd, &value, 1);
     72  1.1  brad 		if (err == -1)
     73  1.1  brad 			err = errno;
     74  1.1  brad 		else
     75  1.1  brad 			err = 0;
     76  1.1  brad 	} else {
     77  1.1  brad 		err = errno;
     78  1.1  brad 	}
     79  1.1  brad 
     80  1.1  brad 	if (debug)
     81  1.1  brad 		fprintf(stderr,"emcfan_write_register: reg=0x%02X, value=0x%02X, return err: %d\n",reg, value, err);
     82  1.1  brad 
     83  1.1  brad 	return err;
     84  1.1  brad }
     85  1.1  brad 
     86  1.1  brad int
     87  1.1  brad emcfan_rmw_register(int fd, uint8_t reg, uint8_t value,
     88  1.1  brad     const struct emcfan_bits_translate translation[],
     89  1.1  brad     long unsigned int translation_size,
     90  1.1  brad     int tindex,
     91  1.1  brad     bool debug)
     92  1.1  brad {
     93  1.1  brad 	int err = 0;
     94  1.1  brad 	uint8_t current, oldcurrent;
     95  1.1  brad 
     96  1.1  brad 	err = emcfan_read_register(fd, reg, &oldcurrent, debug);
     97  1.1  brad 	if (err != 0)
     98  1.1  brad 		return(err);
     99  1.1  brad 
    100  1.1  brad 
    101  1.1  brad 	current = oldcurrent & ~translation[tindex].clear_mask;
    102  1.1  brad 	current = current | translation[tindex].bit_mask;
    103  1.1  brad 
    104  1.1  brad 	if (debug)
    105  1.1  brad 		fprintf(stderr,"tindex=%d, clear_mask=0x%02X 0x%02X, value=%d (0x%02X), bit_mask=0x%02X 0x%02X, oldcurrent=%d (0x%02X), new current=%d (0x%02X)\n",tindex,
    106  1.1  brad 		    translation[tindex].clear_mask,
    107  1.1  brad 		    (uint8_t)~translation[tindex].clear_mask,
    108  1.1  brad 		    value,value,
    109  1.1  brad 		    translation[tindex].bit_mask,
    110  1.1  brad 		    (uint8_t)~translation[tindex].bit_mask,
    111  1.1  brad 		    oldcurrent,oldcurrent,current,current);
    112  1.1  brad 
    113  1.1  brad 	err = emcfan_write_register(fd, reg, current, debug);
    114  1.1  brad 
    115  1.1  brad 	return(err);
    116  1.1  brad }
    117  1.1  brad 
    118  1.1  brad char *
    119  1.1  brad emcfan_product_to_name(uint8_t product_id)
    120  1.1  brad {
    121  1.1  brad 	for(long unsigned int i = 0;i < __arraycount(emcfan_chip_infos); i++)
    122  1.1  brad 		if (product_id == emcfan_chip_infos[i].product_id)
    123  1.1  brad 			return(__UNCONST(emcfan_chip_infos[i].name));
    124  1.1  brad 	return(NULL);
    125  1.1  brad }
    126  1.1  brad 
    127  1.1  brad void
    128  1.1  brad emcfan_family_to_name(int family, char *name, int len)
    129  1.1  brad {
    130  1.1  brad 	switch(family) {
    131  1.1  brad 	case EMCFAN_FAMILY_210X:
    132  1.1  brad 		snprintf(name, len, "%s", "EMC210x");
    133  1.1  brad 		break;
    134  1.1  brad 	case EMCFAN_FAMILY_230X:
    135  1.1  brad 		snprintf(name, len, "%s", "EMC230x");
    136  1.1  brad 		break;
    137  1.1  brad 	case EMCFAN_FAMILY_UNKNOWN:
    138  1.1  brad 	default:
    139  1.1  brad 		snprintf(name, len, "%s", "UNKNOWN");
    140  1.1  brad 		break;
    141  1.1  brad 	}
    142  1.1  brad 
    143  1.1  brad 	return;
    144  1.1  brad }
    145  1.1  brad 
    146  1.1  brad int
    147  1.1  brad emcfan_find_info(uint8_t product)
    148  1.1  brad {
    149  1.1  brad 	for(long unsigned int i = 0;i < __arraycount(emcfan_chip_infos); i++)
    150  1.1  brad 		if (product == emcfan_chip_infos[i].product_id)
    151  1.1  brad 			return(i);
    152  1.1  brad 
    153  1.1  brad 	return(-1);
    154  1.1  brad }
    155  1.1  brad 
    156  1.1  brad bool
    157  1.1  brad emcfan_reg_is_real(int iindex, uint8_t reg)
    158  1.1  brad {
    159  1.1  brad 	int segment;
    160  1.1  brad 	uint64_t index;
    161  1.1  brad 
    162  1.1  brad 	segment = reg / 64;
    163  1.1  brad 	index = reg % 64;
    164  1.1  brad 
    165  1.1  brad 	return(emcfan_chip_infos[iindex].register_void[segment] & ((uint64_t)1 << index));
    166  1.1  brad }
    167  1.1  brad 
    168  1.1  brad static int
    169  1.1  brad emcfan_hunt_by_name(const struct emcfan_registers the_registers[], long unsigned int the_registers_size, char *the_name)
    170  1.1  brad {
    171  1.1  brad 	int r = -1;
    172  1.1  brad 
    173  1.1  brad 	for(long unsigned int i = 0;i < the_registers_size;i++) {
    174  1.1  brad 		if (strcmp(the_name, the_registers[i].name) == 0) {
    175  1.1  brad 			r = the_registers[i].reg;
    176  1.1  brad 			break;
    177  1.1  brad 		}
    178  1.1  brad 	}
    179  1.1  brad 
    180  1.1  brad 	return(r);
    181  1.1  brad }
    182  1.1  brad 
    183  1.1  brad int
    184  1.1  brad emcfan_reg_by_name(uint8_t product_id, int product_family, char *name)
    185  1.1  brad {
    186  1.1  brad 	int r = -1;
    187  1.1  brad 
    188  1.1  brad 	switch(product_family) {
    189  1.1  brad 	case EMCFAN_FAMILY_210X:
    190  1.1  brad 		switch(product_id) {
    191  1.1  brad 		case EMCFAN_PRODUCT_2101:
    192  1.1  brad 		case EMCFAN_PRODUCT_2101R:
    193  1.1  brad 			r = emcfan_hunt_by_name(emcfanctl_2101_registers,__arraycount(emcfanctl_2101_registers),name);
    194  1.1  brad 			break;
    195  1.1  brad 		case EMCFAN_PRODUCT_2103_1:
    196  1.1  brad 			r = emcfan_hunt_by_name(emcfanctl_2103_1_registers,__arraycount(emcfanctl_2103_1_registers),name);
    197  1.1  brad 			break;
    198  1.1  brad 		case EMCFAN_PRODUCT_2103_24:
    199  1.1  brad 			r = emcfan_hunt_by_name(emcfanctl_2103_24_registers,__arraycount(emcfanctl_2103_24_registers),name);
    200  1.1  brad 			break;
    201  1.1  brad 		case EMCFAN_PRODUCT_2104:
    202  1.1  brad 			r = emcfan_hunt_by_name(emcfanctl_2104_registers,__arraycount(emcfanctl_2104_registers),name);
    203  1.1  brad 			break;
    204  1.1  brad 		case EMCFAN_PRODUCT_2106:
    205  1.1  brad 			r = emcfan_hunt_by_name(emcfanctl_2106_registers,__arraycount(emcfanctl_2106_registers),name);
    206  1.1  brad 			break;
    207  1.1  brad 		default:
    208  1.1  brad 			printf("UNSUPPORTED YET %d\n",product_id);
    209  1.1  brad 			exit(99);
    210  1.1  brad 			break;
    211  1.1  brad 		};
    212  1.1  brad 		break;
    213  1.1  brad 	case EMCFAN_FAMILY_230X:
    214  1.1  brad 		r = emcfan_hunt_by_name(emcfanctl_230x_registers,__arraycount(emcfanctl_230x_registers),name);
    215  1.1  brad 		break;
    216  1.1  brad 	};
    217  1.1  brad 
    218  1.1  brad 	return(r);
    219  1.1  brad }
    220  1.1  brad 
    221  1.1  brad static const char *
    222  1.1  brad emcfan_hunt_by_reg(const struct emcfan_registers the_registers[], long unsigned int the_registers_size, uint8_t the_reg)
    223  1.1  brad {
    224  1.1  brad 	const char *r = NULL;
    225  1.1  brad 
    226  1.1  brad 	for(long unsigned int i = 0;i < the_registers_size;i++) {
    227  1.1  brad 		if (the_reg == the_registers[i].reg) {
    228  1.1  brad 			r = the_registers[i].name;
    229  1.1  brad 			break;
    230  1.1  brad 		}
    231  1.1  brad 	}
    232  1.1  brad 
    233  1.1  brad 	return(r);
    234  1.1  brad }
    235  1.1  brad 
    236  1.1  brad const char *
    237  1.1  brad emcfan_regname_by_reg(uint8_t product_id, int product_family, uint8_t reg)
    238  1.1  brad {
    239  1.1  brad 	const char *r = NULL;
    240  1.1  brad 
    241  1.1  brad 	switch(product_family) {
    242  1.1  brad 	case EMCFAN_FAMILY_210X:
    243  1.1  brad 		switch(product_id) {
    244  1.1  brad 		case EMCFAN_PRODUCT_2101:
    245  1.1  brad 		case EMCFAN_PRODUCT_2101R:
    246  1.1  brad 			r = emcfan_hunt_by_reg(emcfanctl_2101_registers,__arraycount(emcfanctl_2101_registers),reg);
    247  1.1  brad 			break;
    248  1.1  brad 		case EMCFAN_PRODUCT_2103_1:
    249  1.1  brad 			r = emcfan_hunt_by_reg(emcfanctl_2103_1_registers,__arraycount(emcfanctl_2103_1_registers),reg);
    250  1.1  brad 			break;
    251  1.1  brad 		case EMCFAN_PRODUCT_2103_24:
    252  1.1  brad 			r = emcfan_hunt_by_reg(emcfanctl_2103_24_registers,__arraycount(emcfanctl_2103_24_registers),reg);
    253  1.1  brad 			break;
    254  1.1  brad 		case EMCFAN_PRODUCT_2104:
    255  1.1  brad 			r = emcfan_hunt_by_reg(emcfanctl_2104_registers,__arraycount(emcfanctl_2104_registers),reg);
    256  1.1  brad 			break;
    257  1.1  brad 		case EMCFAN_PRODUCT_2106:
    258  1.1  brad 			r = emcfan_hunt_by_reg(emcfanctl_2106_registers,__arraycount(emcfanctl_2106_registers),reg);
    259  1.1  brad 			break;
    260  1.1  brad 		default:
    261  1.1  brad 			printf("UNSUPPORTED YET %d\n",product_id);
    262  1.1  brad 			exit(99);
    263  1.1  brad 			break;
    264  1.1  brad 		};
    265  1.1  brad 		break;
    266  1.1  brad 	case EMCFAN_FAMILY_230X:
    267  1.1  brad 		r = emcfan_hunt_by_reg(emcfanctl_230x_registers,__arraycount(emcfanctl_230x_registers),reg);
    268  1.1  brad 		break;
    269  1.1  brad 	};
    270  1.1  brad 
    271  1.1  brad 	return(r);
    272  1.1  brad }
    273  1.1  brad 
    274  1.1  brad int
    275  1.1  brad find_translated_blob_by_bits_instance(const struct emcfan_bits_translate translation[],
    276  1.1  brad     long unsigned int translation_size,
    277  1.1  brad     uint8_t bits, int instance)
    278  1.1  brad {
    279  1.1  brad 	int r = -10191;
    280  1.1  brad 	uint8_t clear_mask;
    281  1.1  brad 	uint8_t b;
    282  1.1  brad 
    283  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    284  1.1  brad 		if (instance == translation[i].instance) {
    285  1.1  brad 			clear_mask = translation[i].clear_mask;
    286  1.1  brad 			b = bits & clear_mask;
    287  1.1  brad 			if (b == translation[i].bit_mask) {
    288  1.1  brad 				r = i;
    289  1.1  brad 				break;
    290  1.1  brad 			}
    291  1.1  brad 		}
    292  1.1  brad 
    293  1.1  brad 	}
    294  1.1  brad 
    295  1.1  brad 	return(r);
    296  1.1  brad }
    297  1.1  brad 
    298  1.1  brad int
    299  1.1  brad find_translated_bits_by_hint_instance(const struct emcfan_bits_translate translation[],
    300  1.1  brad     long unsigned int translation_size,
    301  1.1  brad     int human_value, int instance)
    302  1.1  brad {
    303  1.1  brad 	int r = -10191;
    304  1.1  brad 
    305  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    306  1.1  brad 		if (instance == translation[i].instance &&
    307  1.1  brad 		    human_value == translation[i].human_int) {
    308  1.1  brad 			r = i;
    309  1.1  brad 			break;
    310  1.1  brad 		}
    311  1.1  brad 	}
    312  1.1  brad 
    313  1.1  brad 	return(r);
    314  1.1  brad }
    315  1.1  brad 
    316  1.1  brad int
    317  1.1  brad find_translated_bits_by_hint(const struct emcfan_bits_translate translation[],
    318  1.1  brad     long unsigned int translation_size,
    319  1.1  brad     int human_value)
    320  1.1  brad {
    321  1.1  brad 	int r = -10191;
    322  1.1  brad 
    323  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    324  1.1  brad 		if (human_value == translation[i].human_int) {
    325  1.1  brad 			r = i;
    326  1.1  brad 			break;
    327  1.1  brad 		}
    328  1.1  brad 	}
    329  1.1  brad 
    330  1.1  brad 	return(r);
    331  1.1  brad }
    332  1.1  brad 
    333  1.1  brad int
    334  1.1  brad find_translated_bits_by_str(const struct emcfan_bits_translate translation[],
    335  1.1  brad     long unsigned int translation_size,
    336  1.1  brad     char *human_str)
    337  1.1  brad {
    338  1.1  brad 	int r = -10191;
    339  1.1  brad 
    340  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    341  1.1  brad 		if (strcmp(human_str,translation[i].human_str) == 0) {
    342  1.1  brad 			r = i;
    343  1.1  brad 			break;
    344  1.1  brad 		}
    345  1.1  brad 	}
    346  1.1  brad 
    347  1.1  brad 	return(r);
    348  1.1  brad }
    349  1.1  brad 
    350  1.1  brad int
    351  1.1  brad find_translated_bits_by_str_instance(const struct emcfan_bits_translate translation[],
    352  1.1  brad     long unsigned int translation_size,
    353  1.1  brad     char *human_str, int instance)
    354  1.1  brad {
    355  1.1  brad 	int r = -10191;
    356  1.1  brad 
    357  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    358  1.1  brad 		if (instance == translation[i].instance &&
    359  1.1  brad 		    strcmp(human_str,translation[i].human_str) == 0) {
    360  1.1  brad 			r = i;
    361  1.1  brad 			break;
    362  1.1  brad 		}
    363  1.1  brad 	}
    364  1.1  brad 
    365  1.1  brad 	return(r);
    366  1.1  brad }
    367  1.1  brad 
    368  1.1  brad int
    369  1.1  brad find_human_int(const struct emcfan_bits_translate translation[],
    370  1.1  brad     long unsigned int translation_size,
    371  1.1  brad     uint8_t bits)
    372  1.1  brad {
    373  1.1  brad 	int r = -10191;
    374  1.1  brad 
    375  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    376  1.1  brad 		if (bits == translation[i].bit_mask) {
    377  1.1  brad 			r = translation[i].human_int;
    378  1.1  brad 			break;
    379  1.1  brad 		}
    380  1.1  brad 	}
    381  1.1  brad 
    382  1.1  brad 	return(r);
    383  1.1  brad }
    384  1.1  brad 
    385  1.1  brad char *
    386  1.1  brad find_human_str(const struct emcfan_bits_translate translation[],
    387  1.1  brad     long unsigned int translation_size,
    388  1.1  brad     uint8_t bits)
    389  1.1  brad {
    390  1.1  brad 	char *r = NULL;
    391  1.1  brad 
    392  1.1  brad 	for(long unsigned int i = 0;i < translation_size;i++) {
    393  1.1  brad 		if (bits == translation[i].bit_mask) {
    394  1.1  brad 			r = __UNCONST(translation[i].human_str);
    395  1.1  brad 			break;
    396  1.1  brad 		}
    397  1.1  brad 	}
    398  1.1  brad 
    399  1.1  brad 	return(r);
    400  1.1  brad }
    401