Home | History | Annotate | Line # | Download | only in scmdctl
      1  1.1  brad /*	$NetBSD: common.c,v 1.1 2021/12/07 17:39:55 brad Exp $	*/
      2  1.1  brad 
      3  1.1  brad /*
      4  1.1  brad  * Copyright (c) 2021 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: common.c,v 1.1 2021/12/07 17:39:55 brad Exp $");
     21  1.1  brad #endif
     22  1.1  brad 
     23  1.1  brad /* Common functions dealing with the SCMD devices.  This does not
     24  1.1  brad  * know how to talk to anything in particular, it calls out to the
     25  1.1  brad  * functions defined in the function blocks for that.
     26  1.1  brad  */
     27  1.1  brad 
     28  1.1  brad #include <inttypes.h>
     29  1.1  brad #include <stdbool.h>
     30  1.1  brad #include <stdio.h>
     31  1.1  brad #include <stdlib.h>
     32  1.1  brad #include <unistd.h>
     33  1.1  brad #include <err.h>
     34  1.1  brad #include <fcntl.h>
     35  1.1  brad #include <string.h>
     36  1.1  brad #include <limits.h>
     37  1.1  brad #include <errno.h>
     38  1.1  brad 
     39  1.1  brad #include <dev/ic/scmdreg.h>
     40  1.1  brad 
     41  1.1  brad #define EXTERN
     42  1.1  brad #include "common.h"
     43  1.1  brad #include "responses.h"
     44  1.1  brad #include "scmdctl.h"
     45  1.1  brad 
     46  1.1  brad 
     47  1.1  brad int
     48  1.1  brad decode_motor_level(int raw)
     49  1.1  brad {
     50  1.1  brad 	int r;
     51  1.1  brad 
     52  1.1  brad 	r = abs(128 - raw);
     53  1.1  brad 	if (raw < 128)
     54  1.1  brad 		r = r * -1;
     55  1.1  brad 
     56  1.1  brad 	return r;
     57  1.1  brad }
     58  1.1  brad 
     59  1.1  brad int common_clear(struct function_block *fb, int fd, bool debug)
     60  1.1  brad {
     61  1.1  brad 	return (*(fb->func_clear))(fd, debug);
     62  1.1  brad }
     63  1.1  brad 
     64  1.1  brad int
     65  1.1  brad common_identify(struct function_block *fb, int fd, bool debug, int a_module, struct scmd_identify_response *r)
     66  1.1  brad {
     67  1.1  brad 	uint8_t b;
     68  1.1  brad 	int err;
     69  1.1  brad 
     70  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
     71  1.1  brad 	if (! err) {
     72  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, a_module, SCMD_REG_ID, SCMD_REG_ID, &b);
     73  1.1  brad 		if (! err)
     74  1.1  brad 			r->id = b;
     75  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, a_module, SCMD_REG_FID, SCMD_REG_FID, &b);
     76  1.1  brad 		if (! err)
     77  1.1  brad 			r->fwversion = b;
     78  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, a_module, SCMD_REG_CONFIG_BITS, SCMD_REG_CONFIG_BITS, &b);
     79  1.1  brad 		if (! err)
     80  1.1  brad 			r->config_bits = b;
     81  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, a_module, SCMD_REG_SLAVE_ADDR, SCMD_REG_SLAVE_ADDR, &b);
     82  1.1  brad 		if (! err)
     83  1.1  brad 			r->slv_i2c_address = b;
     84  1.1  brad 	}
     85  1.1  brad 
     86  1.1  brad 	return err;
     87  1.1  brad }
     88  1.1  brad 
     89  1.1  brad int common_diag(struct function_block *fb, int fd, bool debug, int a_module, struct scmd_diag_response *r)
     90  1.1  brad {
     91  1.1  brad 	uint8_t b;
     92  1.1  brad 	int err, m;
     93  1.1  brad 
     94  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
     95  1.1  brad 	if (! err) {
     96  1.1  brad 		m = 0;
     97  1.1  brad 		for(uint8_t n = SCMD_REG_U_I2C_RD_ERR; n <= SCMD_REG_GEN_TEST_WORD; n++) {
     98  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, a_module, n, n, &b);
     99  1.1  brad 			if (! err) {
    100  1.1  brad 				r->diags[m] = b;
    101  1.1  brad 			}
    102  1.1  brad 			m++;
    103  1.1  brad 		}
    104  1.1  brad 	}
    105  1.1  brad 
    106  1.1  brad 	return err;
    107  1.1  brad }
    108  1.1  brad 
    109  1.1  brad /* This tries to avoid reading just every register if only one
    110  1.1  brad  * motor is asked about.
    111  1.1  brad  */
    112  1.1  brad int
    113  1.1  brad common_get_motor(struct function_block *fb, int fd, bool debug, int a_module, struct scmd_motor_response *r)
    114  1.1  brad {
    115  1.1  brad 	uint8_t b;
    116  1.1  brad 	int err = 0,m;
    117  1.1  brad 
    118  1.1  brad 	if (a_module != SCMD_ANY_MODULE &&
    119  1.1  brad 	    (a_module < 0 || a_module > 16))
    120  1.1  brad 		return EINVAL;
    121  1.1  brad 
    122  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    123  1.1  brad 	if (! err) {
    124  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_DRIVER_ENABLE, SCMD_REG_DRIVER_ENABLE, &b);
    125  1.1  brad 		if (! err)
    126  1.1  brad 			r->driver = b;
    127  1.1  brad 
    128  1.1  brad 		m = 0;
    129  1.1  brad 		for(uint8_t n = SCMD_REG_MA_DRIVE; n <= SCMD_REG_S16B_DRIVE; n++) {
    130  1.1  brad 			r->motorlevels[m] = SCMD_NO_MOTOR;
    131  1.1  brad 			if (a_module != SCMD_ANY_MODULE &&
    132  1.1  brad 			    (m / 2) != a_module)
    133  1.1  brad 				goto skip;
    134  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, n, n, &b);
    135  1.1  brad 			if (! err)
    136  1.1  brad 				r->motorlevels[m] = b;
    137  1.1  brad  skip:
    138  1.1  brad 			m++;
    139  1.1  brad 		}
    140  1.1  brad 
    141  1.1  brad 		if (a_module == SCMD_ANY_MODULE ||
    142  1.1  brad 		    a_module == 0) {
    143  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_MOTOR_A_INVERT, SCMD_REG_MOTOR_A_INVERT, &b);
    144  1.1  brad 			if (!err)
    145  1.1  brad 				r->invert[0] = (b & 0x01);
    146  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_MOTOR_B_INVERT, SCMD_REG_MOTOR_B_INVERT, &b);
    147  1.1  brad 			if (!err)
    148  1.1  brad 				r->invert[1] = (b & 0x01);
    149  1.1  brad 		}
    150  1.1  brad 
    151  1.1  brad 		if (a_module != 0) {
    152  1.1  brad 			m = 2;
    153  1.1  brad 			for(uint8_t n = SCMD_REG_INV_2_9; n <= SCMD_REG_INV_26_33; n++) {
    154  1.1  brad 				err = (*(fb->func_phy_read))(fd, debug, 0, n, n, &b);
    155  1.1  brad 				if (!err) {
    156  1.1  brad 					for(uint8_t j = 0; j < 8;j++) {
    157  1.1  brad 						r->invert[m] = (b & (1 << j));
    158  1.1  brad 						m++;
    159  1.1  brad 					}
    160  1.1  brad 				}
    161  1.1  brad 			}
    162  1.1  brad 		}
    163  1.1  brad 
    164  1.1  brad 		if (a_module == SCMD_ANY_MODULE ||
    165  1.1  brad 		    a_module == 0) {
    166  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_BRIDGE, SCMD_REG_BRIDGE, &b);
    167  1.1  brad 			if (!err)
    168  1.1  brad 				r->bridge[0] = (b & 0x01);
    169  1.1  brad 		}
    170  1.1  brad 
    171  1.1  brad 		if (a_module != 0) {
    172  1.1  brad 			m = 1;
    173  1.1  brad 			for(uint8_t n = SCMD_REG_BRIDGE_SLV_L; n <= SCMD_REG_BRIDGE_SLV_H; n++) {
    174  1.1  brad 				err = (*(fb->func_phy_read))(fd, debug, 0, n, n, &b);
    175  1.1  brad 				if (!err) {
    176  1.1  brad 					for(uint8_t j = 0; j < 8;j++) {
    177  1.1  brad 						r->bridge[m] = (b & (1 << j));
    178  1.1  brad 						m++;
    179  1.1  brad 					}
    180  1.1  brad 				}
    181  1.1  brad 			}
    182  1.1  brad 		}
    183  1.1  brad 	}
    184  1.1  brad 
    185  1.1  brad 	return err;
    186  1.1  brad }
    187  1.1  brad 
    188  1.1  brad int
    189  1.1  brad common_set_motor(struct function_block *fb, int fd, bool debug, int a_module, char a_motor, int8_t reg_v)
    190  1.1  brad {
    191  1.1  brad 	uint8_t reg;
    192  1.1  brad 	int err;
    193  1.1  brad 	int reg_index;
    194  1.1  brad 
    195  1.1  brad 	if (a_module < 0 || a_module > 16)
    196  1.1  brad 		return EINVAL;
    197  1.1  brad 
    198  1.1  brad 	if (!(a_motor == 'A' || a_motor == 'B'))
    199  1.1  brad 		return EINVAL;
    200  1.1  brad 
    201  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    202  1.1  brad 	if (! err) {
    203  1.1  brad 		reg_index = a_module * 2;
    204  1.1  brad 		if (a_motor == 'B')
    205  1.1  brad 			reg_index++;
    206  1.1  brad 		reg = SCMD_REG_MA_DRIVE + reg_index;
    207  1.1  brad 		reg_v = reg_v + 128;
    208  1.1  brad 		if (debug)
    209  1.1  brad 			fprintf(stderr,"common_set_motor: reg_index: %d ; reg: %02X ; reg_v: %d\n",reg_index,reg,reg_v);
    210  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, reg, reg_v);
    211  1.1  brad 	}
    212  1.1  brad 
    213  1.1  brad 	return err;
    214  1.1  brad }
    215  1.1  brad 
    216  1.1  brad int
    217  1.1  brad common_invert_motor(struct function_block *fb, int fd, bool debug, int a_module, char a_motor)
    218  1.1  brad {
    219  1.1  brad 	uint8_t b;
    220  1.1  brad 	int err;
    221  1.1  brad 	uint8_t reg, reg_index = 0, reg_offset = 0;
    222  1.1  brad 	int motor_index;
    223  1.1  brad 
    224  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    225  1.1  brad 	if (! err) {
    226  1.1  brad 		if (a_module == 0) {
    227  1.1  brad 			if (a_motor == 'A') {
    228  1.1  brad 				reg = SCMD_REG_MOTOR_A_INVERT;
    229  1.1  brad 			} else {
    230  1.1  brad 				reg = SCMD_REG_MOTOR_B_INVERT;
    231  1.1  brad 			}
    232  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, reg, reg, &b);
    233  1.1  brad 			if (!err) {
    234  1.1  brad 				b = b ^ 0x01;
    235  1.1  brad 				err = (*(fb->func_phy_write))(fd, debug, 0, reg, b);
    236  1.1  brad 			}
    237  1.1  brad 		} else {
    238  1.1  brad 			motor_index = (a_module * 2) - 2;
    239  1.1  brad 			if (a_motor == 'B')
    240  1.1  brad 				motor_index++;
    241  1.1  brad 			reg_offset = motor_index / 8;
    242  1.1  brad 			motor_index = motor_index % 8;
    243  1.1  brad 			reg_index = 1 << motor_index;
    244  1.1  brad 			reg = SCMD_REG_INV_2_9 + reg_offset;
    245  1.1  brad 			if (debug)
    246  1.1  brad 				fprintf(stderr,"common_invert_motor: remote invert: motor_index: %d ; reg_offset: %d ; reg_index: %02X ; reg: %02X\n",motor_index,reg_offset,reg_index,reg);
    247  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, reg, reg, &b);
    248  1.1  brad 			if (!err) {
    249  1.1  brad 				b = b ^ reg_index;
    250  1.1  brad 				err = (*(fb->func_phy_write))(fd, debug, 0, reg, b);
    251  1.1  brad 			}
    252  1.1  brad 		}
    253  1.1  brad 	}
    254  1.1  brad 
    255  1.1  brad 	return err;
    256  1.1  brad }
    257  1.1  brad 
    258  1.1  brad int
    259  1.1  brad common_bridge_motor(struct function_block *fb, int fd, bool debug, int a_module)
    260  1.1  brad {
    261  1.1  brad 	uint8_t b;
    262  1.1  brad 	int err = 0;
    263  1.1  brad 	uint8_t reg, reg_index = 0, reg_offset = 0;
    264  1.1  brad 	int module_index;
    265  1.1  brad 
    266  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    267  1.1  brad 	if (! err) {
    268  1.1  brad 		if (a_module == 0) {
    269  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_BRIDGE, SCMD_REG_BRIDGE, &b);
    270  1.1  brad 			if (!err) {
    271  1.1  brad 				b = b ^ 0x01;
    272  1.1  brad 				err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_BRIDGE, b);
    273  1.1  brad 			}
    274  1.1  brad 		} else {
    275  1.1  brad 			module_index = a_module - 1;
    276  1.1  brad 			reg_offset = module_index / 8;
    277  1.1  brad 			module_index = module_index % 8;
    278  1.1  brad 			reg_index = 1 << module_index;
    279  1.1  brad 			reg = SCMD_REG_BRIDGE_SLV_L + reg_offset;
    280  1.1  brad 			if (debug)
    281  1.1  brad 				fprintf(stderr,"common_bridge_motor: remote bridge: module_index: %d ; reg_offset: %d ; reg_index: %02X ; reg: %02X\n",module_index,reg_offset,reg_index,reg);
    282  1.1  brad 			err = (*(fb->func_phy_read))(fd, debug, 0, reg, reg, &b);
    283  1.1  brad 			if (!err) {
    284  1.1  brad 				b = b ^ reg_index;
    285  1.1  brad 				err = (*(fb->func_phy_write))(fd, debug, 0, reg, b);
    286  1.1  brad 			}
    287  1.1  brad 		}
    288  1.1  brad 	}
    289  1.1  brad 
    290  1.1  brad 	return err;
    291  1.1  brad }
    292  1.1  brad 
    293  1.1  brad int
    294  1.1  brad common_enable_disable(struct function_block *fb, int fd, bool debug, int subcmd)
    295  1.1  brad {
    296  1.1  brad 	int err;
    297  1.1  brad 	uint8_t reg_v;
    298  1.1  brad 
    299  1.1  brad 	if (!(subcmd == SCMD_ENABLE || subcmd == SCMD_DISABLE))
    300  1.1  brad 		return EINVAL;
    301  1.1  brad 
    302  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    303  1.1  brad 	if (! err) {
    304  1.1  brad 		switch (subcmd) {
    305  1.1  brad 		case SCMD_ENABLE:
    306  1.1  brad 			reg_v = SCMD_DRIVER_ENABLE;
    307  1.1  brad 			break;
    308  1.1  brad 		case SCMD_DISABLE:
    309  1.1  brad 			reg_v = SCMD_DRIVER_DISABLE;
    310  1.1  brad 			break;
    311  1.1  brad 		default:
    312  1.1  brad 			return EINVAL;
    313  1.1  brad 		}
    314  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_DRIVER_ENABLE, reg_v);
    315  1.1  brad 	}
    316  1.1  brad 
    317  1.1  brad 	return err;
    318  1.1  brad }
    319  1.1  brad 
    320  1.1  brad /* These control commands can take a very long time and the restart
    321  1.1  brad  * make cause the device to become unresponsive for a bit.
    322  1.1  brad  */
    323  1.1  brad int
    324  1.1  brad common_control_1(struct function_block *fb, int fd, bool debug, int subcmd)
    325  1.1  brad {
    326  1.1  brad 	int err;
    327  1.1  brad 	uint8_t reg_v;
    328  1.1  brad 
    329  1.1  brad 	if (!(subcmd == SCMD_RESTART || subcmd == SCMD_ENUMERATE))
    330  1.1  brad 		return EINVAL;
    331  1.1  brad 
    332  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    333  1.1  brad 	if (! err) {
    334  1.1  brad 		switch (subcmd) {
    335  1.1  brad 		case SCMD_RESTART:
    336  1.1  brad 			reg_v = SCMD_CONTROL_1_RESTART;
    337  1.1  brad 			break;
    338  1.1  brad 		case SCMD_ENUMERATE:
    339  1.1  brad 			reg_v = SCMD_CONTROL_1_REENUMERATE;
    340  1.1  brad 			break;
    341  1.1  brad 		default:
    342  1.1  brad 			return EINVAL;
    343  1.1  brad 		}
    344  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_CONTROL_1, reg_v);
    345  1.1  brad 	}
    346  1.1  brad 
    347  1.1  brad 	return err;
    348  1.1  brad }
    349  1.1  brad 
    350  1.1  brad int
    351  1.1  brad common_get_update_rate(struct function_block *fb, int fd, bool debug, uint8_t *rate)
    352  1.1  brad {
    353  1.1  brad 	uint8_t b;
    354  1.1  brad 	int err;
    355  1.1  brad 
    356  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    357  1.1  brad 	if (! err) {
    358  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_UPDATE_RATE, SCMD_REG_UPDATE_RATE, &b);
    359  1.1  brad 		if (!err)
    360  1.1  brad 			*rate = b;
    361  1.1  brad 	}
    362  1.1  brad 
    363  1.1  brad 	return err;
    364  1.1  brad }
    365  1.1  brad 
    366  1.1  brad int
    367  1.1  brad common_set_update_rate(struct function_block *fb, int fd, bool debug, uint8_t rate)
    368  1.1  brad {
    369  1.1  brad 	int err;
    370  1.1  brad 
    371  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    372  1.1  brad 	if (! err) {
    373  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_UPDATE_RATE, rate);
    374  1.1  brad 	}
    375  1.1  brad 
    376  1.1  brad 	return err;
    377  1.1  brad }
    378  1.1  brad 
    379  1.1  brad int
    380  1.1  brad common_force_update(struct function_block *fb, int fd, bool debug)
    381  1.1  brad {
    382  1.1  brad 	int err;
    383  1.1  brad 
    384  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    385  1.1  brad 	if (! err) {
    386  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_FORCE_UPDATE, 0x01);
    387  1.1  brad 	}
    388  1.1  brad 
    389  1.1  brad 	return err;
    390  1.1  brad }
    391  1.1  brad 
    392  1.1  brad int
    393  1.1  brad common_get_ebus_speed(struct function_block *fb, int fd, bool debug, uint8_t *speed)
    394  1.1  brad {
    395  1.1  brad 	uint8_t b;
    396  1.1  brad 	int err;
    397  1.1  brad 
    398  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    399  1.1  brad 	if (! err) {
    400  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, 0, SCMD_REG_E_BUS_SPEED, SCMD_REG_E_BUS_SPEED, &b);
    401  1.1  brad 		if (!err)
    402  1.1  brad 			*speed = b;
    403  1.1  brad 	}
    404  1.1  brad 
    405  1.1  brad 	return err;
    406  1.1  brad }
    407  1.1  brad 
    408  1.1  brad int
    409  1.1  brad common_set_ebus_speed(struct function_block *fb, int fd, bool debug, uint8_t speed)
    410  1.1  brad {
    411  1.1  brad 	int err;
    412  1.1  brad 
    413  1.1  brad 	if (speed > 0x03)
    414  1.1  brad 		return EINVAL;
    415  1.1  brad 
    416  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    417  1.1  brad 	if (! err) {
    418  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, SCMD_REG_E_BUS_SPEED, speed);
    419  1.1  brad 	}
    420  1.1  brad 
    421  1.1  brad 	return err;
    422  1.1  brad }
    423  1.1  brad 
    424  1.1  brad int
    425  1.1  brad common_get_lock_state(struct function_block *fb, int fd, bool debug, int ltype, uint8_t *lstate)
    426  1.1  brad {
    427  1.1  brad 	uint8_t b;
    428  1.1  brad 	uint8_t reg;
    429  1.1  brad 	int err;
    430  1.1  brad 
    431  1.1  brad 	switch (ltype) {
    432  1.1  brad 	case SCMD_LOCAL_USER_LOCK:
    433  1.1  brad 		reg = SCMD_REG_LOCAL_USER_LOCK;
    434  1.1  brad 		break;
    435  1.1  brad 	case SCMD_LOCAL_MASTER_LOCK:
    436  1.1  brad 		reg = SCMD_REG_LOCAL_MASTER_LOCK;
    437  1.1  brad 		break;
    438  1.1  brad 	case SCMD_GLOBAL_USER_LOCK:
    439  1.1  brad 		reg = SCMD_REG_USER_LOCK;
    440  1.1  brad 		break;
    441  1.1  brad 	case SCMD_GLOBAL_MASTER_LOCK:
    442  1.1  brad 		reg = SCMD_REG_MASTER_LOCK;
    443  1.1  brad 		break;
    444  1.1  brad 	default:
    445  1.1  brad 		return EINVAL;
    446  1.1  brad 	}
    447  1.1  brad 
    448  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    449  1.1  brad 	if (! err) {
    450  1.1  brad 		err = (*(fb->func_phy_read))(fd, debug, 0, reg, reg, &b);
    451  1.1  brad 		if (!err)
    452  1.1  brad 			*lstate = b;
    453  1.1  brad 	}
    454  1.1  brad 
    455  1.1  brad 	return err;
    456  1.1  brad }
    457  1.1  brad 
    458  1.1  brad int
    459  1.1  brad common_set_lock_state(struct function_block *fb, int fd, bool debug, int ltype, uint8_t lstate)
    460  1.1  brad {
    461  1.1  brad 	uint8_t reg;
    462  1.1  brad 	uint8_t state;
    463  1.1  brad 	int err;
    464  1.1  brad 
    465  1.1  brad 	switch (ltype) {
    466  1.1  brad 	case SCMD_LOCAL_USER_LOCK:
    467  1.1  brad 		reg = SCMD_REG_LOCAL_USER_LOCK;
    468  1.1  brad 		break;
    469  1.1  brad 	case SCMD_LOCAL_MASTER_LOCK:
    470  1.1  brad 		reg = SCMD_REG_LOCAL_MASTER_LOCK;
    471  1.1  brad 		break;
    472  1.1  brad 	case SCMD_GLOBAL_USER_LOCK:
    473  1.1  brad 		reg = SCMD_REG_USER_LOCK;
    474  1.1  brad 		break;
    475  1.1  brad 	case SCMD_GLOBAL_MASTER_LOCK:
    476  1.1  brad 		reg = SCMD_REG_MASTER_LOCK;
    477  1.1  brad 		break;
    478  1.1  brad 	default:
    479  1.1  brad 		return EINVAL;
    480  1.1  brad 	}
    481  1.1  brad 
    482  1.1  brad 	switch (lstate) {
    483  1.1  brad 	case SCMD_LOCK_LOCKED:
    484  1.1  brad 		state = SCMD_ANY_LOCK_LOCKED;
    485  1.1  brad 		break;
    486  1.1  brad 	case SCMD_LOCK_UNLOCK:
    487  1.1  brad 		state = SCMD_MASTER_LOCK_UNLOCKED;
    488  1.1  brad 		if (ltype == SCMD_LOCAL_USER_LOCK ||
    489  1.1  brad 		    ltype == SCMD_GLOBAL_USER_LOCK)
    490  1.1  brad 			state = SCMD_USER_LOCK_UNLOCKED;
    491  1.1  brad 		break;
    492  1.1  brad 	default:
    493  1.1  brad 		return EINVAL;
    494  1.1  brad 	}
    495  1.1  brad 
    496  1.1  brad 	err = (*(fb->func_clear))(fd, debug);
    497  1.1  brad 	if (! err) {
    498  1.1  brad 		err = (*(fb->func_phy_write))(fd, debug, 0, reg, state);
    499  1.1  brad 	}
    500  1.1  brad 
    501  1.1  brad 	return err;
    502  1.1  brad }
    503