^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);