56 #include <linux/errno.h>
57 #include <linux/kernel.h>
58 #include <linux/module.h>
61 #include <linux/slab.h>
63 #include <linux/list.h>
72 #define PREFIX "HIL MLC: "
77 static int hil_mlcs_probe;
79 static void hil_mlcs_process(
unsigned long unused);
87 static void hil_mlc_clear_di_map(
hil_mlc *mlc,
int val)
91 for (j = val; j < 7 ; j++)
95 static void hil_mlc_clear_di_scratch(
hil_mlc *mlc)
100 static void hil_mlc_copy_di_scratch(
hil_mlc *mlc,
int idx)
105 static int hil_mlc_match_di_scratch(
hil_mlc *mlc)
113 for (j = 0; j < 7 ; j++)
114 if (mlc->
di_map[j] == idx)
124 return idx >= HIL_MLC_DEVMEM ? -1 :
idx;
127 static int hil_mlc_find_free_di(
hil_mlc *mlc)
137 for (j = 0; j < 7 ; j++)
138 if (mlc->
di_map[j] == idx)
148 static inline void hil_mlc_clean_serio_map(
hil_mlc *mlc)
155 for (j = 0; j < 7 ; j++)
156 if (mlc->
di_map[j] == idx)
164 static void hil_mlc_send_polls(
hil_mlc *mlc)
175 while (mlc->
icount < 15 - i) {
198 drv->
interrupt(serio, (p >> 16) & 0xff, 0);
199 drv->
interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
207 #define HILSEN_SCHED 0x000100
208 #define HILSEN_BREAK 0x000200
209 #define HILSEN_UP 0x000400
210 #define HILSEN_DOWN 0x000800
211 #define HILSEN_FOLLOW 0x001000
213 #define HILSEN_MASK 0x0000ff
214 #define HILSEN_START 0
215 #define HILSEN_RESTART 1
217 #define HILSEN_DHR2 10
218 #define HILSEN_IFC 14
219 #define HILSEN_HEAL0 16
220 #define HILSEN_HEAL 18
221 #define HILSEN_ACF 21
222 #define HILSEN_ACF2 22
223 #define HILSEN_DISC0 25
224 #define HILSEN_DISC 27
225 #define HILSEN_MATCH 40
226 #define HILSEN_OPERATE 41
227 #define HILSEN_PROBE 44
228 #define HILSEN_DSR 52
229 #define HILSEN_REPOLL 55
230 #define HILSEN_IFCACF 58
231 #define HILSEN_END 60
233 #define HILSEN_NEXT (HILSEN_DOWN | 1)
234 #define HILSEN_SAME (HILSEN_DOWN | 0)
235 #define HILSEN_LAST (HILSEN_UP | 1)
237 #define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
238 #define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK)
244 rc = hil_mlc_match_di_scratch(mlc);
246 rc = hil_mlc_find_free_di(mlc);
253 hil_mlc_copy_di_scratch(mlc, rc);
256 hil_mlc_clean_serio_map(mlc);
266 hil_mlc_clean_serio_map(mlc);
270 printk(
KERN_ERR PREFIX
"Residual device slots exhausted, close some serios!\n");
281 if (mlc->
lcv && (tv.tv_sec - mlc->
lcv_tv.tv_sec) < 5)
290 static int hilse_inc_lcv(
hil_mlc *mlc,
int lim)
292 return mlc->
lcv++ >= lim ? -1 : 0;
296 static int hilse_set_lcv(
hil_mlc *mlc,
int val)
305 static int hilse_set_ddi(
hil_mlc *mlc,
int val)
308 hil_mlc_clear_di_map(mlc, val + 1);
313 static int hilse_dec_ddi(
hil_mlc *mlc,
int unused)
316 if (mlc->
ddi <= -1) {
318 hil_mlc_clear_di_map(mlc, 0);
321 hil_mlc_clear_di_map(mlc, mlc->
ddi + 1);
326 static int hilse_inc_ddi(
hil_mlc *mlc,
int unused)
334 static int hilse_take_idd(
hil_mlc *mlc,
int unused)
347 for (i = 1; i < 16; i++) {
348 if (((mlc->
ipacket[i] & HIL_PKT_ADDR_MASK) ==
349 (mlc->
ipacket[0] & HIL_PKT_ADDR_MASK)) &&
365 for (i = 0; i < 16; i++)
384 static int hilse_take_rsc(
hil_mlc *mlc,
int unused)
388 for (i = 0; i < 16; i++)
399 static int hilse_take_exd(
hil_mlc *mlc,
int unused)
403 for (i = 0; i < 16; i++)
414 static int hilse_take_rnm(
hil_mlc *mlc,
int unused)
418 for (i = 0; i < 16; i++)
428 static int hilse_operate(
hil_mlc *mlc,
int repoll)
435 hil_mlc_send_polls(mlc);
444 #define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
445 { HILSE_FUNC, { .func = funct }, funct_arg, zero_rc, neg_rc, pos_rc },
447 { HILSE_OUT, { .packet = pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
449 { HILSE_CTS, { .packet = 0 }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
450 #define EXPECT(comp, to, got, got_wrong, timed_out) \
451 { HILSE_EXPECT, { .packet = comp }, to, got, got_wrong, timed_out },
452 #define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
453 { HILSE_EXPECT_LAST, { .packet = comp }, to, got, got_wrong, timed_out },
454 #define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
455 { HILSE_EXPECT_DISC, { .packet = comp }, to, got, got_wrong, timed_out },
456 #define IN(to, got, got_error, timed_out) \
457 { HILSE_IN, { .packet = 0 }, to, got, got_error, timed_out },
458 #define OUT_DISC(pack) \
459 { HILSE_OUT_DISC, { .packet = pack }, 0, 0, 0, 0 },
460 #define OUT_LAST(pack) \
461 { HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 },
473 #define TEST_PACKET(x) \
474 (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
619 static int hilse_donode(
hil_mlc *mlc)
635 node = hil_mlc_se + mlc->
seidx;
644 nextidx = (rc > 0) ? node->
ugly :
645 ((rc < 0) ? node->
bad : node->
good);
656 rc = mlc->
in(mlc, node->
arg);
664 nextidx = node->
ugly;
666 nextidx = node->
good;
693 hilse_setup_input(mlc, node + 1);
721 nextidx = mlc->
cts(mlc) ? node->
bad : node->
good;
742 tv.tv_usec -= mlc->
instart.tv_usec;
745 if (!tv.tv_usec)
goto sched;
746 mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
749 tasklet_schedule(&hil_mlcs_tasklet);
767 static void hil_mlcs_process(
unsigned long unused)
774 while (hilse_donode(mlc) == 0) {
776 if (mlc->
seidx != 41 &&
788 static void hil_mlcs_timer(
unsigned long data)
791 tasklet_schedule(&hil_mlcs_tasklet);
793 if (!timer_pending(&hil_mlcs_kicker))
799 static int hil_mlc_serio_write(
struct serio *serio,
unsigned char c)
821 idx = mlc->
di[map->
didx].idd;
824 idx = mlc->
di[map->
didx].rsc;
827 idx = mlc->
di[map->
didx].exd;
830 idx = mlc->
di[map->
didx].rnm;
846 while ((last != idx) && (*last == 0))
849 while (idx != last) {
867 static int hil_mlc_serio_open(
struct serio *serio)
872 if (serio_get_drvdata(serio) !=
NULL)
884 static void hil_mlc_serio_close(
struct serio *serio)
895 serio_set_drvdata(serio,
NULL);
918 sema_init(&mlc->
osem, 1);
920 sema_init(&mlc->
isem, 1);
926 sema_init(&(mlc->
csem), 0);
928 hil_mlc_clear_di_scratch(mlc);
929 hil_mlc_clear_di_map(mlc, 0);
931 struct serio *mlc_serio;
932 hil_mlc_copy_di_scratch(mlc, i);
933 mlc_serio = kzalloc(
sizeof(*mlc_serio),
GFP_KERNEL);
934 mlc->
serio[
i] = mlc_serio;
935 if (!mlc->
serio[i]) {
942 mlc_serio->
id = hil_mlc_serio_id;
943 mlc_serio->
id.id =
i;
944 mlc_serio->
write = hil_mlc_serio_write;
945 mlc_serio->
open = hil_mlc_serio_open;
946 mlc_serio->
close = hil_mlc_serio_close;
956 mlc->
tasklet = &hil_mlcs_tasklet;
963 tasklet_schedule(&hil_mlcs_tasklet);
982 tasklet_schedule(&hil_mlcs_tasklet);
994 tasklet_schedule(&hil_mlcs_tasklet);
1000 static int __init hil_mlc_init(
void)
1002 setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
1005 tasklet_enable(&hil_mlcs_tasklet);
1010 static void __exit hil_mlc_exit(
void)
1014 tasklet_disable(&hil_mlcs_tasklet);