Merge branch 'uninit-var' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / include / linux / hil_mlc.h
1 /*
2  * HP Human Interface Loop Master Link Controller driver.
3  *
4  * Copyright (c) 2001 Brian S. Julin
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * Alternatively, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL").
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  *
29  * References:
30  * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
31  *
32  */
33
34 #include <linux/hil.h>
35 #include <linux/time.h>
36 #include <linux/interrupt.h>
37 #include <asm/semaphore.h>
38 #include <linux/serio.h>
39 #include <linux/list.h>
40
41 typedef struct hil_mlc hil_mlc;
42
43 /* The HIL has a complicated state engine.
44  * We define the structure of nodes in the state engine here.
45  */
46 enum hilse_act {
47         /* HILSE_OUT prepares to receive input if the next node
48          * is an IN or EXPECT, and then sends the given packet.
49          */
50         HILSE_OUT = 0,
51
52         /* HILSE_CTS checks if the loop is busy. */
53         HILSE_CTS,
54
55         /* HILSE_OUT_LAST sends the given command packet to 
56          * the last configured/running device on the loop.
57          */
58         HILSE_OUT_LAST,
59
60         /* HILSE_OUT_DISC sends the given command packet to
61          * the next device past the last configured/running one.
62          */
63         HILSE_OUT_DISC,
64
65         /* HILSE_FUNC runs a callback function with given arguments.
66          * a positive return value causes the "ugly" branch to be taken.
67          */
68         HILSE_FUNC,
69
70         /* HILSE_IN simply expects any non-errored packet to arrive 
71          * within arg usecs.
72          */
73         HILSE_IN                = 0x100,
74
75         /* HILSE_EXPECT expects a particular packet to arrive 
76          * within arg usecs, any other packet is considered an error.
77          */
78         HILSE_EXPECT,
79
80         /* HILSE_EXPECT_LAST as above but dev field should be last 
81          * discovered/operational device.
82          */
83         HILSE_EXPECT_LAST,
84
85         /* HILSE_EXPECT_LAST as above but dev field should be first 
86          * undiscovered/inoperational device.
87          */
88         HILSE_EXPECT_DISC
89 };
90
91 typedef int     (hilse_func) (hil_mlc *mlc, int arg);
92 struct hilse_node {
93         enum hilse_act          act;    /* How to process this node         */
94         union {
95                 hilse_func      *func;  /* Function to call if HILSE_FUNC   */
96                 hil_packet      packet; /* Packet to send or to compare     */
97         } object;
98         int                     arg;    /* Timeout in usec or parm for func */
99         int                     good;   /* Node to jump to on success       */
100         int                     bad;    /* Node to jump to on error         */
101         int                     ugly;   /* Node to jump to on timeout       */
102 };
103
104 /* Methods for back-end drivers, e.g. hp_sdc_mlc */
105 typedef int     (hil_mlc_cts) (hil_mlc *mlc);
106 typedef void    (hil_mlc_out) (hil_mlc *mlc);
107 typedef int     (hil_mlc_in)  (hil_mlc *mlc, suseconds_t timeout);
108
109 struct hil_mlc_devinfo {
110         uint8_t idd[16];        /* Device ID Byte and Describe Record */
111         uint8_t rsc[16];        /* Security Code Header and Record */
112         uint8_t exd[16];        /* Extended Describe Record */
113         uint8_t rnm[16];        /* Device name as returned by RNM command */
114 };
115
116 struct hil_mlc_serio_map {
117         hil_mlc *mlc;
118         int di_revmap;
119         int didx;
120 };
121
122 /* How many (possibly old/detached) devices the we try to keep track of */
123 #define HIL_MLC_DEVMEM 16
124
125 struct hil_mlc {
126         struct list_head        list;   /* hil_mlc is organized as linked list */
127
128         rwlock_t                lock;
129
130         void *priv; /* Data specific to a particular type of MLC */
131
132         int                     seidx;  /* Current node in state engine */
133         int                     istarted, ostarted;
134
135         hil_mlc_cts             *cts;
136         struct semaphore        csem;   /* Raised when loop idle */
137
138         hil_mlc_out             *out;
139         struct semaphore        osem;   /* Raised when outpacket dispatched */
140         hil_packet              opacket;
141
142         hil_mlc_in              *in;
143         struct semaphore        isem;   /* Raised when a packet arrives */
144         hil_packet              ipacket[16];
145         hil_packet              imatch;
146         int                     icount;
147         struct timeval          instart;
148         suseconds_t             intimeout;
149
150         int                     ddi;    /* Last operational device id */
151         int                     lcv;    /* LCV to throttle loops */
152         struct timeval          lcv_tv; /* Time loop was started */
153
154         int                     di_map[7]; /* Maps below items to live devs */
155         struct hil_mlc_devinfo  di[HIL_MLC_DEVMEM];
156         struct serio            *serio[HIL_MLC_DEVMEM];
157         struct hil_mlc_serio_map serio_map[HIL_MLC_DEVMEM];
158         hil_packet              serio_opacket[HIL_MLC_DEVMEM];
159         int                     serio_oidx[HIL_MLC_DEVMEM];
160         struct hil_mlc_devinfo  di_scratch; /* Temporary area */
161
162         int                     opercnt;
163
164         struct tasklet_struct   *tasklet;
165 };
166
167 int hil_mlc_register(hil_mlc *mlc);
168 int hil_mlc_unregister(hil_mlc *mlc);