xref: /linux-6.15/include/linux/hil_mlc.h (revision 6188e10d)
16ab0f5cdSMatthew Wilcox /*
26ab0f5cdSMatthew Wilcox  * HP Human Interface Loop Master Link Controller driver.
36ab0f5cdSMatthew Wilcox  *
46ab0f5cdSMatthew Wilcox  * Copyright (c) 2001 Brian S. Julin
56ab0f5cdSMatthew Wilcox  * All rights reserved.
66ab0f5cdSMatthew Wilcox  *
76ab0f5cdSMatthew Wilcox  * Redistribution and use in source and binary forms, with or without
86ab0f5cdSMatthew Wilcox  * modification, are permitted provided that the following conditions
96ab0f5cdSMatthew Wilcox  * are met:
106ab0f5cdSMatthew Wilcox  * 1. Redistributions of source code must retain the above copyright
116ab0f5cdSMatthew Wilcox  *    notice, this list of conditions, and the following disclaimer,
126ab0f5cdSMatthew Wilcox  *    without modification.
136ab0f5cdSMatthew Wilcox  * 2. The name of the author may not be used to endorse or promote products
146ab0f5cdSMatthew Wilcox  *    derived from this software without specific prior written permission.
156ab0f5cdSMatthew Wilcox  *
166ab0f5cdSMatthew Wilcox  * Alternatively, this software may be distributed under the terms of the
176ab0f5cdSMatthew Wilcox  * GNU General Public License ("GPL").
186ab0f5cdSMatthew Wilcox  *
196ab0f5cdSMatthew Wilcox  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
206ab0f5cdSMatthew Wilcox  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
216ab0f5cdSMatthew Wilcox  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
226ab0f5cdSMatthew Wilcox  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
236ab0f5cdSMatthew Wilcox  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
246ab0f5cdSMatthew Wilcox  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
256ab0f5cdSMatthew Wilcox  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
266ab0f5cdSMatthew Wilcox  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
276ab0f5cdSMatthew Wilcox  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
286ab0f5cdSMatthew Wilcox  *
296ab0f5cdSMatthew Wilcox  * References:
306ab0f5cdSMatthew Wilcox  * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
316ab0f5cdSMatthew Wilcox  *
326ab0f5cdSMatthew Wilcox  */
336ab0f5cdSMatthew Wilcox 
346ab0f5cdSMatthew Wilcox #include <linux/hil.h>
356ab0f5cdSMatthew Wilcox #include <linux/time.h>
366ab0f5cdSMatthew Wilcox #include <linux/interrupt.h>
37*6188e10dSMatthew Wilcox #include <linux/semaphore.h>
386ab0f5cdSMatthew Wilcox #include <linux/serio.h>
396ab0f5cdSMatthew Wilcox #include <linux/list.h>
406ab0f5cdSMatthew Wilcox 
416ab0f5cdSMatthew Wilcox typedef struct hil_mlc hil_mlc;
426ab0f5cdSMatthew Wilcox 
436ab0f5cdSMatthew Wilcox /* The HIL has a complicated state engine.
446ab0f5cdSMatthew Wilcox  * We define the structure of nodes in the state engine here.
456ab0f5cdSMatthew Wilcox  */
466ab0f5cdSMatthew Wilcox enum hilse_act {
476ab0f5cdSMatthew Wilcox   	/* HILSE_OUT prepares to receive input if the next node
486ab0f5cdSMatthew Wilcox 	 * is an IN or EXPECT, and then sends the given packet.
496ab0f5cdSMatthew Wilcox 	 */
506ab0f5cdSMatthew Wilcox 	HILSE_OUT = 0,
516ab0f5cdSMatthew Wilcox 
526ab0f5cdSMatthew Wilcox   	/* HILSE_CTS checks if the loop is busy. */
536ab0f5cdSMatthew Wilcox 	HILSE_CTS,
546ab0f5cdSMatthew Wilcox 
556ab0f5cdSMatthew Wilcox 	/* HILSE_OUT_LAST sends the given command packet to
566ab0f5cdSMatthew Wilcox 	 * the last configured/running device on the loop.
576ab0f5cdSMatthew Wilcox 	 */
586ab0f5cdSMatthew Wilcox 	HILSE_OUT_LAST,
596ab0f5cdSMatthew Wilcox 
606ab0f5cdSMatthew Wilcox 	/* HILSE_OUT_DISC sends the given command packet to
616ab0f5cdSMatthew Wilcox 	 * the next device past the last configured/running one.
626ab0f5cdSMatthew Wilcox 	 */
636ab0f5cdSMatthew Wilcox 	HILSE_OUT_DISC,
646ab0f5cdSMatthew Wilcox 
656ab0f5cdSMatthew Wilcox 	/* HILSE_FUNC runs a callback function with given arguments.
666ab0f5cdSMatthew Wilcox 	 * a positive return value causes the "ugly" branch to be taken.
676ab0f5cdSMatthew Wilcox 	 */
686ab0f5cdSMatthew Wilcox 	HILSE_FUNC,
696ab0f5cdSMatthew Wilcox 
706ab0f5cdSMatthew Wilcox   	/* HILSE_IN simply expects any non-errored packet to arrive
716ab0f5cdSMatthew Wilcox 	 * within arg usecs.
726ab0f5cdSMatthew Wilcox 	 */
736ab0f5cdSMatthew Wilcox 	HILSE_IN		= 0x100,
746ab0f5cdSMatthew Wilcox 
756ab0f5cdSMatthew Wilcox   	/* HILSE_EXPECT expects a particular packet to arrive
766ab0f5cdSMatthew Wilcox 	 * within arg usecs, any other packet is considered an error.
776ab0f5cdSMatthew Wilcox 	 */
786ab0f5cdSMatthew Wilcox 	HILSE_EXPECT,
796ab0f5cdSMatthew Wilcox 
806ab0f5cdSMatthew Wilcox   	/* HILSE_EXPECT_LAST as above but dev field should be last
816ab0f5cdSMatthew Wilcox 	 * discovered/operational device.
826ab0f5cdSMatthew Wilcox 	 */
836ab0f5cdSMatthew Wilcox 	HILSE_EXPECT_LAST,
846ab0f5cdSMatthew Wilcox 
856ab0f5cdSMatthew Wilcox   	/* HILSE_EXPECT_LAST as above but dev field should be first
866ab0f5cdSMatthew Wilcox 	 * undiscovered/inoperational device.
876ab0f5cdSMatthew Wilcox 	 */
886ab0f5cdSMatthew Wilcox 	HILSE_EXPECT_DISC
896ab0f5cdSMatthew Wilcox };
906ab0f5cdSMatthew Wilcox 
916ab0f5cdSMatthew Wilcox typedef int	(hilse_func) (hil_mlc *mlc, int arg);
926ab0f5cdSMatthew Wilcox struct hilse_node {
936ab0f5cdSMatthew Wilcox 	enum hilse_act		act;	/* How to process this node         */
946ab0f5cdSMatthew Wilcox 	union {
956ab0f5cdSMatthew Wilcox 		hilse_func	*func;	/* Function to call if HILSE_FUNC   */
966ab0f5cdSMatthew Wilcox 		hil_packet	packet;	/* Packet to send or to compare     */
976ab0f5cdSMatthew Wilcox 	} object;
986ab0f5cdSMatthew Wilcox 	int			arg;	/* Timeout in usec or parm for func */
996ab0f5cdSMatthew Wilcox 	int			good;	/* Node to jump to on success       */
1006ab0f5cdSMatthew Wilcox 	int			bad;	/* Node to jump to on error         */
1016ab0f5cdSMatthew Wilcox 	int			ugly;	/* Node to jump to on timeout       */
1026ab0f5cdSMatthew Wilcox };
1036ab0f5cdSMatthew Wilcox 
1046ab0f5cdSMatthew Wilcox /* Methods for back-end drivers, e.g. hp_sdc_mlc */
1056ab0f5cdSMatthew Wilcox typedef int	(hil_mlc_cts) (hil_mlc *mlc);
1066ab0f5cdSMatthew Wilcox typedef void	(hil_mlc_out) (hil_mlc *mlc);
1076ab0f5cdSMatthew Wilcox typedef int	(hil_mlc_in)  (hil_mlc *mlc, suseconds_t timeout);
1086ab0f5cdSMatthew Wilcox 
1096ab0f5cdSMatthew Wilcox struct hil_mlc_devinfo {
1106ab0f5cdSMatthew Wilcox 	uint8_t	idd[16];	/* Device ID Byte and Describe Record */
1116ab0f5cdSMatthew Wilcox 	uint8_t	rsc[16];	/* Security Code Header and Record */
1126ab0f5cdSMatthew Wilcox 	uint8_t	exd[16];	/* Extended Describe Record */
1136ab0f5cdSMatthew Wilcox 	uint8_t	rnm[16];	/* Device name as returned by RNM command */
1146ab0f5cdSMatthew Wilcox };
1156ab0f5cdSMatthew Wilcox 
1166ab0f5cdSMatthew Wilcox struct hil_mlc_serio_map {
1176ab0f5cdSMatthew Wilcox 	hil_mlc *mlc;
1186ab0f5cdSMatthew Wilcox 	int di_revmap;
1196ab0f5cdSMatthew Wilcox 	int didx;
1206ab0f5cdSMatthew Wilcox };
1216ab0f5cdSMatthew Wilcox 
1226ab0f5cdSMatthew Wilcox /* How many (possibly old/detached) devices the we try to keep track of */
1236ab0f5cdSMatthew Wilcox #define HIL_MLC_DEVMEM 16
1246ab0f5cdSMatthew Wilcox 
1256ab0f5cdSMatthew Wilcox struct hil_mlc {
1266ab0f5cdSMatthew Wilcox 	struct list_head	list;	/* hil_mlc is organized as linked list */
1276ab0f5cdSMatthew Wilcox 
1286ab0f5cdSMatthew Wilcox 	rwlock_t		lock;
1296ab0f5cdSMatthew Wilcox 
1306ab0f5cdSMatthew Wilcox 	void *priv; /* Data specific to a particular type of MLC */
1316ab0f5cdSMatthew Wilcox 
1326ab0f5cdSMatthew Wilcox 	int 			seidx;	/* Current node in state engine */
1336ab0f5cdSMatthew Wilcox 	int			istarted, ostarted;
1346ab0f5cdSMatthew Wilcox 
1356ab0f5cdSMatthew Wilcox 	hil_mlc_cts		*cts;
1366ab0f5cdSMatthew Wilcox 	struct semaphore	csem;   /* Raised when loop idle */
1376ab0f5cdSMatthew Wilcox 
1386ab0f5cdSMatthew Wilcox 	hil_mlc_out		*out;
1396ab0f5cdSMatthew Wilcox 	struct semaphore	osem;   /* Raised when outpacket dispatched */
1406ab0f5cdSMatthew Wilcox 	hil_packet		opacket;
1416ab0f5cdSMatthew Wilcox 
1426ab0f5cdSMatthew Wilcox 	hil_mlc_in		*in;
1436ab0f5cdSMatthew Wilcox 	struct semaphore	isem;   /* Raised when a packet arrives */
1446ab0f5cdSMatthew Wilcox 	hil_packet		ipacket[16];
1456ab0f5cdSMatthew Wilcox 	hil_packet		imatch;
1466ab0f5cdSMatthew Wilcox 	int			icount;
1476ab0f5cdSMatthew Wilcox 	struct timeval		instart;
1486ab0f5cdSMatthew Wilcox 	suseconds_t		intimeout;
1496ab0f5cdSMatthew Wilcox 
1506ab0f5cdSMatthew Wilcox 	int			ddi;	/* Last operational device id */
1516ab0f5cdSMatthew Wilcox 	int			lcv;	/* LCV to throttle loops */
1526ab0f5cdSMatthew Wilcox 	struct timeval		lcv_tv; /* Time loop was started */
1536ab0f5cdSMatthew Wilcox 
1546ab0f5cdSMatthew Wilcox 	int			di_map[7]; /* Maps below items to live devs */
1556ab0f5cdSMatthew Wilcox 	struct hil_mlc_devinfo	di[HIL_MLC_DEVMEM];
1566ab0f5cdSMatthew Wilcox 	struct serio		*serio[HIL_MLC_DEVMEM];
1576ab0f5cdSMatthew Wilcox 	struct hil_mlc_serio_map serio_map[HIL_MLC_DEVMEM];
1586ab0f5cdSMatthew Wilcox 	hil_packet		serio_opacket[HIL_MLC_DEVMEM];
1596ab0f5cdSMatthew Wilcox 	int			serio_oidx[HIL_MLC_DEVMEM];
1606ab0f5cdSMatthew Wilcox 	struct hil_mlc_devinfo	di_scratch; /* Temporary area */
1616ab0f5cdSMatthew Wilcox 
1626ab0f5cdSMatthew Wilcox 	int			opercnt;
1636ab0f5cdSMatthew Wilcox 
1646ab0f5cdSMatthew Wilcox 	struct tasklet_struct	*tasklet;
1656ab0f5cdSMatthew Wilcox };
1666ab0f5cdSMatthew Wilcox 
1676ab0f5cdSMatthew Wilcox int hil_mlc_register(hil_mlc *mlc);
1686ab0f5cdSMatthew Wilcox int hil_mlc_unregister(hil_mlc *mlc);
169