Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * HIL MLC state machine and serio interface driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (c) 2001 Brian S. Julin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *    notice, this list of conditions, and the following disclaimer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *    without modification.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * 2. The name of the author may not be used to endorse or promote products
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *    derived from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * Alternatively, this software may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * GNU General Public License ("GPL").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  * References:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  *	Driver theory of operation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)  *	Some access methods and an ISR is defined by the sub-driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36)  *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)  *	few bits of logic in addition to raw access to the HIL MLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)  *	specifically, the ISR, which is entirely registered by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  *	sub-driver and invoked directly, must check for record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  *	termination or packet match, at which point a semaphore must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  *	be cleared and then the hil_mlcs_tasklet must be scheduled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43)  *	The hil_mlcs_tasklet processes the state machine for all MLCs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44)  *	each time it runs, checking each MLC's progress at the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  *	node in the state machine, and moving the MLC to subsequent nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  *	in the state machine when appropriate.  It will reschedule
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47)  *	itself if output is pending.  (This rescheduling should be replaced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  *	at some point with a sub-driver-specific mechanism.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  *	A timer task prods the tasklet once per second to prevent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  *	hangups when attached devices do not return expected data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  *	and to initiate probes of the loop for new devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #include <linux/hil_mlc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) MODULE_DESCRIPTION("HIL MLC serio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) MODULE_LICENSE("Dual BSD/GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) EXPORT_SYMBOL(hil_mlc_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) EXPORT_SYMBOL(hil_mlc_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define PREFIX "HIL MLC: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) static LIST_HEAD(hil_mlcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) static DEFINE_RWLOCK(hil_mlcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) static struct timer_list	hil_mlcs_kicker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) static int			hil_mlcs_probe, hil_mlc_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) static void hil_mlcs_process(unsigned long unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) /* #define HIL_MLC_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) /********************** Device info/instance management **********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static void hil_mlc_clear_di_map(hil_mlc *mlc, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	for (j = val; j < 7 ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 		mlc->di_map[j] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static void hil_mlc_clear_di_scratch(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) static int hil_mlc_match_di_scratch(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 		int j, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 		/* In-use slots are not eligible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 		for (j = 0; j < 7 ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 			if (mlc->di_map[j] == idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 				found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 		if (!memcmp(mlc->di + idx, &mlc->di_scratch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 				sizeof(mlc->di_scratch)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	return idx >= HIL_MLC_DEVMEM ? -1 : idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) static int hil_mlc_find_free_di(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	/* TODO: Pick all-zero slots first, failing that,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	 * randomize the slot picked among those eligible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 		int j, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		for (j = 0; j < 7 ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 			if (mlc->di_map[j] == idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 				found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 		if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	return idx; /* Note: It is guaranteed at least one above will match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) static inline void hil_mlc_clean_serio_map(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		int j, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		for (j = 0; j < 7 ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 			if (mlc->di_map[j] == idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 				found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 		if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 			mlc->serio_map[idx].di_revmap = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) static void hil_mlc_send_polls(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	int did, i, cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	struct serio_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	i = cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	drv = (serio != NULL) ? serio->drv : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	while (mlc->icount < 15 - i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		hil_packet p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		p = mlc->ipacket[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 			if (drv && drv->interrupt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 				drv->interrupt(serio, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 				drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 				drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 				drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 			did = (p & HIL_PKT_ADDR_MASK) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 			drv = (serio != NULL) ? serio->drv : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 			cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 		i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		if (drv && drv->interrupt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 			drv->interrupt(serio, (p >> 24), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 			drv->interrupt(serio, (p >> 16) & 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 			drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 			drv->interrupt(serio, p & 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) /*************************** State engine *********************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) #define HILSEN_SCHED	0x000100	/* Schedule the tasklet		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) #define HILSEN_BREAK	0x000200	/* Wait until next pass		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) #define HILSEN_UP	0x000400	/* relative node#, decrement	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) #define HILSEN_DOWN	0x000800	/* relative node#, increment	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) #define HILSEN_FOLLOW	0x001000	/* use retval as next node#	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) #define HILSEN_MASK	0x0000ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) #define HILSEN_START	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) #define HILSEN_RESTART	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) #define HILSEN_DHR	9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) #define HILSEN_DHR2	10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) #define HILSEN_IFC	14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) #define HILSEN_HEAL0	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) #define HILSEN_HEAL	18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) #define HILSEN_ACF      21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) #define HILSEN_ACF2	22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) #define HILSEN_DISC0	25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) #define HILSEN_DISC	27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) #define HILSEN_MATCH	40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) #define HILSEN_OPERATE	41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) #define HILSEN_PROBE	44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) #define HILSEN_DSR	52
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) #define HILSEN_REPOLL	55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) #define HILSEN_IFCACF	58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) #define HILSEN_END	60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) #define HILSEN_NEXT	(HILSEN_DOWN | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) #define HILSEN_SAME	(HILSEN_DOWN | 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) #define HILSEN_LAST	(HILSEN_UP | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) #define HILSEN_DOZE	(HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) #define HILSEN_SLEEP	(HILSEN_SAME | HILSEN_BREAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) static int hilse_match(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	rc = hil_mlc_match_di_scratch(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	if (rc == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		rc = hil_mlc_find_free_di(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 		if (rc == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 		hil_mlc_copy_di_scratch(mlc, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		mlc->di_map[mlc->ddi] = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 		mlc->serio_map[rc].di_revmap = mlc->ddi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 		hil_mlc_clean_serio_map(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		serio_rescan(mlc->serio[rc]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	mlc->di_map[mlc->ddi] = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	mlc->serio_map[rc].di_revmap = mlc->ddi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	hil_mlc_clean_serio_map(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)  err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) static int hilse_init_lcv(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	time64_t now = ktime_get_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	if (mlc->lcv && (now - mlc->lcv_time) < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	mlc->lcv_time = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	mlc->lcv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) static int hilse_inc_lcv(hil_mlc *mlc, int lim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	return mlc->lcv++ >= lim ? -1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) static int hilse_set_lcv(hil_mlc *mlc, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	mlc->lcv = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) /* Management of the discovered device index (zero based, -1 means no devs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) static int hilse_set_ddi(hil_mlc *mlc, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	mlc->ddi = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	hil_mlc_clear_di_map(mlc, val + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) static int hilse_dec_ddi(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	mlc->ddi--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	if (mlc->ddi <= -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		mlc->ddi = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 		hil_mlc_clear_di_map(mlc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) static int hilse_inc_ddi(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	BUG_ON(mlc->ddi >= 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	mlc->ddi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) static int hilse_take_idd(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	/* Help the state engine:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	 * Is this a real IDD response or just an echo?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	 * Real IDD response does not start with a command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	if (mlc->ipacket[0] & HIL_PKT_CMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	/* Should have the command echoed further down. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	for (i = 1; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 		     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		    (mlc->ipacket[i] & HIL_PKT_CMD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	if (i > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 		goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	/* And the rest of the packets should still be clear. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	while (++i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		if (mlc->ipacket[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	if (i < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		mlc->di_scratch.idd[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	/* Next step is to see if RSC supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 		return HILSEN_NEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 		return HILSEN_DOWN | 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376)  bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	mlc->ddi--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	return -1; /* This should send us off to ACF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) static int hilse_take_rsc(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		mlc->di_scratch.rsc[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	/* Next step is to see if EXD supported (IDD has already been read) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 		return HILSEN_NEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) static int hilse_take_exd(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		mlc->di_scratch.exd[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	/* Next step is to see if RNM supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		return HILSEN_NEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) static int hilse_take_rnm(hil_mlc *mlc, int unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		mlc->di_scratch.rnm[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	printk(KERN_INFO PREFIX "Device name gotten: %16s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 			mlc->di_scratch.rnm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) static int hilse_operate(hil_mlc *mlc, int repoll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	if (mlc->opercnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 		hil_mlcs_probe = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	mlc->opercnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	hil_mlc_send_polls(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	if (!hil_mlcs_probe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	hil_mlcs_probe = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	mlc->opercnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) #define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) { HILSE_FUNC,		{ .func = funct }, funct_arg, zero_rc, neg_rc, pos_rc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) #define OUT(pack) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) { HILSE_OUT,		{ .packet = pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) #define CTS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) { HILSE_CTS,		{ .packet = 0    }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) #define EXPECT(comp, to, got, got_wrong, timed_out) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) { HILSE_EXPECT,		{ .packet = comp }, to, got, got_wrong, timed_out },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) #define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) { HILSE_EXPECT_LAST,	{ .packet = comp }, to, got, got_wrong, timed_out },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) #define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) { HILSE_EXPECT_DISC,	{ .packet = comp }, to, got, got_wrong, timed_out },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) #define IN(to, got, got_error, timed_out) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) { HILSE_IN,		{ .packet = 0    }, to, got, got_error, timed_out },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) #define OUT_DISC(pack) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) { HILSE_OUT_DISC,	{ .packet = pack }, 0, 0, 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) #define OUT_LAST(pack) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) { HILSE_OUT_LAST,	{ .packet = pack }, 0, 0, 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) static const struct hilse_node hil_mlc_se[HILSEN_END] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	/* 0  HILSEN_START */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	/* 1  HILSEN_RESTART */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,  0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	OUT(HIL_CTRL_ONLY)			/* Disable APE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	CTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) #define TEST_PACKET(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	EXPECT(HIL_ERR_INT | TEST_PACKET(0x5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	OUT(HIL_CTRL_ONLY | 0)			/* Disable test mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	/* 9  HILSEN_DHR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	/* 10 HILSEN_DHR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	OUT(HIL_PKT_CMD | HIL_CMD_DHR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	/* 14 HILSEN_IFC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	       20000,		HILSEN_DISC,	HILSEN_DHR2,	HILSEN_NEXT )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	/* If devices are there, they weren't in PUP or other loopback mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	 * We're more concerned at this point with restoring operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	 * to devices than discovering new ones, so we try to salvage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	 * the loop configuration by closing off the loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	/* 16 HILSEN_HEAL0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	FUNC(hilse_dec_ddi, 0,	HILSEN_NEXT,	HILSEN_ACF,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	FUNC(hilse_inc_ddi, 0,	HILSEN_NEXT,	0,		0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	/* 18 HILSEN_HEAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	OUT_LAST(HIL_CMD_ELB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 		    20000,	HILSEN_REPOLL,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	FUNC(hilse_dec_ddi, 0,	HILSEN_HEAL,	HILSEN_NEXT,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	/* 21 HILSEN_ACF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_DOZE,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	/* 22 HILSEN_ACF2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	IN(20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	/* 25 HILSEN_DISC0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	/* Only enter here if response just received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	/* 27 HILSEN_DISC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	FUNC(hilse_inc_ddi,  0,	HILSEN_NEXT,	HILSEN_START,	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	FUNC(hilse_take_idd, 0,	HILSEN_MATCH,	HILSEN_IFCACF,	HILSEN_FOLLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	FUNC(hilse_take_rsc, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	FUNC(hilse_take_exd, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	FUNC(hilse_take_rnm, 0, HILSEN_MATCH,	0,		0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	/* 40 HILSEN_MATCH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	FUNC(hilse_match, 0,	HILSEN_NEXT,	HILSEN_NEXT,	/* TODO */ 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	/* 41 HILSEN_OPERATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	OUT(HIL_PKT_CMD | HIL_CMD_POL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	FUNC(hilse_operate, 0,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	/* 44 HILSEN_PROBE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	IN(10000,		HILSEN_DISC0,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	IN(10000,		HILSEN_OPERATE,	HILSEN_DSR,	HILSEN_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	/* 52 HILSEN_DSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	OUT(HIL_PKT_CMD | HIL_CMD_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	IN(20000,		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	/* 55 HILSEN_REPOLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	/* 58 HILSEN_IFCACF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	/* 60 HILSEN_END */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	switch (node->act) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	case HILSE_EXPECT_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		mlc->imatch = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	case HILSE_EXPECT_LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		mlc->imatch = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	case HILSE_EXPECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		mlc->imatch = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	case HILSE_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		mlc->imatch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	mlc->istarted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	mlc->intimeout = usecs_to_jiffies(node->arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	mlc->instart = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	mlc->icount = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	BUG_ON(down_trylock(&mlc->isem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) static int doze;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) static int seidx; /* For debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) static int hilse_donode(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	const struct hilse_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	int nextidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	int sched_long = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	if (mlc->seidx && mlc->seidx != seidx &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	    mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		doze = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	seidx = mlc->seidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	node = hil_mlc_se + mlc->seidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	switch (node->act) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		hil_packet pack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	case HILSE_FUNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		BUG_ON(node->object.func == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		rc = node->object.func(mlc, node->arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		nextidx = (rc > 0) ? node->ugly :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 			((rc < 0) ? node->bad : node->good);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		if (nextidx == HILSEN_FOLLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			nextidx = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	case HILSE_EXPECT_LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	case HILSE_EXPECT_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	case HILSE_EXPECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	case HILSE_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		/* Already set up from previous HILSE_OUT_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		rc = mlc->in(mlc, node->arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		if (rc == 2)  {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			nextidx = HILSEN_DOZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			sched_long = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 			write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		if (rc == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			nextidx = node->ugly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		else if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 			nextidx = node->good;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 			nextidx = node->bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		mlc->istarted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	case HILSE_OUT_LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		pack = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	case HILSE_OUT_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		pack = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	case HILSE_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		pack = node->object.packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		if (!mlc->istarted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 			/* Prepare to receive input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 			if ((node + 1)->act & HILSE_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 				hilse_setup_input(mlc, node + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		if (down_trylock(&mlc->osem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 			nextidx = HILSEN_DOZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		up(&mlc->osem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		if (!mlc->ostarted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			mlc->ostarted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 			mlc->opacket = pack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 			rc = mlc->out(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 			nextidx = HILSEN_DOZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 			write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 			if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 				hil_mlc_stop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		mlc->ostarted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		mlc->instart = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		nextidx = HILSEN_NEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	case HILSE_CTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		write_lock_irqsave(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		rc = mlc->cts(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		nextidx = rc ? node->bad : node->good;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		write_unlock_irqrestore(&mlc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 		if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 			hil_mlc_stop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	if (nextidx == HILSEN_DOZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		doze++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	while (nextidx & HILSEN_SCHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		unsigned long now = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		if (!sched_long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 			goto sched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		if (time_after(now, mlc->instart + mlc->intimeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 			 goto sched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		mod_timer(&hil_mlcs_kicker, mlc->instart + mlc->intimeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	sched:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		tasklet_schedule(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	if (nextidx & HILSEN_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		mlc->seidx += nextidx & HILSEN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	else if (nextidx & HILSEN_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		mlc->seidx -= nextidx & HILSEN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		mlc->seidx = nextidx & HILSEN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	if (nextidx & HILSEN_BREAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) /******************** tasklet context functions **************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) static void hil_mlcs_process(unsigned long unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	struct list_head *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	read_lock(&hil_mlcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	list_for_each(tmp, &hil_mlcs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		while (hilse_donode(mlc) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) #ifdef HIL_MLC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			if (mlc->seidx != 41 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			    mlc->seidx != 42 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			    mlc->seidx != 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 				printk(KERN_DEBUG PREFIX " + ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	read_unlock(&hil_mlcs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) /************************* Keepalive timer task *********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) static void hil_mlcs_timer(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	if (hil_mlc_stop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		/* could not send packet - stop immediately. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		pr_warn(PREFIX "HIL seems stuck - Disabling HIL MLC.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	hil_mlcs_probe = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	tasklet_schedule(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	/* Re-insert the periodic task. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	if (!timer_pending(&hil_mlcs_kicker))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		mod_timer(&hil_mlcs_kicker, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) /******************** user/kernel context functions **********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) static int hil_mlc_serio_write(struct serio *serio, unsigned char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	struct hil_mlc_serio_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	struct hil_mlc *mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	struct serio_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	uint8_t *idx, *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	map = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	BUG_ON(map == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	mlc = map->mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	BUG_ON(mlc == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	mlc->serio_opacket[map->didx] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	if (mlc->serio_oidx[map->didx] >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		/* for now only commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		case HIL_CMD_IDD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 			idx = mlc->di[map->didx].idd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 			goto emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		case HIL_CMD_RSC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 			idx = mlc->di[map->didx].rsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			goto emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		case HIL_CMD_EXD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			idx = mlc->di[map->didx].exd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 			goto emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 		case HIL_CMD_RNM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 			idx = mlc->di[map->didx].rnm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 			goto emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		mlc->serio_oidx[map->didx] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		mlc->serio_opacket[map->didx] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	mlc->serio_oidx[map->didx]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)  emu:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	drv = serio->drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	BUG_ON(drv == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	last = idx + 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	while ((last != idx) && (*last == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		last--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	while (idx != last) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		drv->interrupt(serio, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		drv->interrupt(serio, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		drv->interrupt(serio, *idx, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	drv->interrupt(serio, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	drv->interrupt(serio, *idx, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	mlc->serio_oidx[map->didx] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	mlc->serio_opacket[map->didx] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) static int hil_mlc_serio_open(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	struct hil_mlc_serio_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	struct hil_mlc *mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	if (serio_get_drvdata(serio) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	map = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	BUG_ON(map == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	mlc = map->mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	BUG_ON(mlc == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) static void hil_mlc_serio_close(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	struct hil_mlc_serio_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	struct hil_mlc *mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	map = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	BUG_ON(map == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	mlc = map->mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	BUG_ON(mlc == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	serio->drv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	/* TODO wake up interruptable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) static const struct serio_device_id hil_mlc_serio_id = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	.type = SERIO_HIL_MLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	.proto = SERIO_HIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	.extra = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	.id = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) int hil_mlc_register(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	BUG_ON(mlc == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	mlc->istarted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	mlc->ostarted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	rwlock_init(&mlc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	sema_init(&mlc->osem, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	sema_init(&mlc->isem, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	mlc->icount = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	mlc->imatch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	mlc->opercnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	sema_init(&(mlc->csem), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	hil_mlc_clear_di_scratch(mlc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	hil_mlc_clear_di_map(mlc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		struct serio *mlc_serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		hil_mlc_copy_di_scratch(mlc, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		mlc->serio[i] = mlc_serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		if (!mlc->serio[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 			for (; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 				kfree(mlc->serio[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		mlc_serio->id			= hil_mlc_serio_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		mlc_serio->id.id		= i; /* HIL port no. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		mlc_serio->write		= hil_mlc_serio_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		mlc_serio->open			= hil_mlc_serio_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		mlc_serio->close		= hil_mlc_serio_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		mlc_serio->port_data		= &(mlc->serio_map[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		mlc->serio_map[i].mlc		= mlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		mlc->serio_map[i].didx		= i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		mlc->serio_map[i].di_revmap	= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		mlc->serio_opacket[i]		= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		mlc->serio_oidx[i]		= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		serio_register_port(mlc_serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	mlc->tasklet = &hil_mlcs_tasklet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	write_lock_irqsave(&hil_mlcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	list_add_tail(&mlc->list, &hil_mlcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	mlc->seidx = HILSEN_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	write_unlock_irqrestore(&hil_mlcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	tasklet_schedule(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) int hil_mlc_unregister(hil_mlc *mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	struct list_head *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	BUG_ON(mlc == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	write_lock_irqsave(&hil_mlcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	list_for_each(tmp, &hil_mlcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		if (list_entry(tmp, hil_mlc, list) == mlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 			goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	/* not found in list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	write_unlock_irqrestore(&hil_mlcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	tasklet_schedule(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993)  found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	list_del(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	write_unlock_irqrestore(&hil_mlcs_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		serio_unregister_port(mlc->serio[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		mlc->serio[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	tasklet_schedule(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /**************************** Module interface *************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) static int __init hil_mlc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	timer_setup(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	mod_timer(&hil_mlcs_kicker, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	tasklet_enable(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static void __exit hil_mlc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	del_timer_sync(&hil_mlcs_kicker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	tasklet_kill(&hil_mlcs_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) module_init(hil_mlc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) module_exit(hil_mlc_exit);