1 /* $OpenBSD: hil.c,v 1.29 2022/01/09 05:42:37 jsg Exp $ */
2 /*
3 * Copyright (c) 2003, 2004, Miodrag Vallat.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29 /*
30 * Copyright (c) 1988 University of Utah.
31 * Copyright (c) 1990, 1993
32 * The Regents of the University of California. All rights reserved.
33 *
34 * This code is derived from software contributed to Berkeley by
35 * the Systems Programming Group of the University of Utah Computer
36 * Science Department.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 * from: Utah $Hdr: hil.c 1.38 92/01/21$
63 *
64 * @(#)hil.c 8.2 (Berkeley) 1/12/94
65 */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/conf.h>
70 #include <sys/device.h>
71 #include <sys/ioctl.h>
72 #include <sys/kernel.h>
73 #include <sys/proc.h>
74 #include <sys/kthread.h>
75
76 #include <machine/autoconf.h>
77 #include <machine/bus.h>
78 #include <machine/cpu.h>
79
80 #include <dev/hil/hilreg.h>
81 #include <dev/hil/hilvar.h>
82 #include <dev/hil/hildevs.h>
83 #include <dev/hil/hildevs_data.h>
84
85 #include "hilkbd.h"
86
87 /*
88 * splhigh is extremely conservative but insures atomic operation,
89 * splvm (clock only interrupts) seems to be good enough in practice.
90 */
91 #define splhil splvm
92
93 struct cfdriver hil_cd = {
94 NULL, "hil", DV_DULL
95 };
96
97 void hilconfig(struct hil_softc *, u_int);
98 void hilempty(struct hil_softc *);
99 int hilsubmatch(struct device *, void *, void *);
100 void hil_process_int(struct hil_softc *, u_int8_t, u_int8_t);
101 int hil_process_poll(struct hil_softc *, u_int8_t, u_int8_t);
102 void hil_thread(void *);
103 int send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd);
104 void polloff(struct hil_softc *);
105 void pollon(struct hil_softc *);
106
107 static int hilwait(struct hil_softc *);
108 static int hildatawait(struct hil_softc *);
109
110 #define hil_process_pending(sc) wakeup(&(sc)->sc_pending)
111
112 static __inline int
hilwait(struct hil_softc * sc)113 hilwait(struct hil_softc *sc)
114 {
115 int cnt;
116
117 for (cnt = 50000; cnt != 0; cnt--) {
118 DELAY(1);
119 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
120 HIL_BUSY) == 0)
121 break;
122 }
123
124 return (cnt);
125 }
126
127 static __inline int
hildatawait(struct hil_softc * sc)128 hildatawait(struct hil_softc *sc)
129 {
130 int cnt;
131
132 for (cnt = 50000; cnt != 0; cnt--) {
133 DELAY(1);
134 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
135 HIL_DATA_RDY) != 0)
136 break;
137 }
138
139 return (cnt);
140 }
141
142 /*
143 * Common HIL bus attachment
144 */
145
146 void
hil_attach(struct hil_softc * sc,int * hil_is_console)147 hil_attach(struct hil_softc *sc, int *hil_is_console)
148 {
149 printf("\n");
150
151 /*
152 * Initialize loop information
153 */
154 sc->sc_cmdending = 0;
155 sc->sc_actdev = sc->sc_cmddev = 0;
156 sc->sc_cmddone = 0;
157 sc->sc_cmdbp = sc->sc_cmdbuf;
158 sc->sc_pollbp = sc->sc_pollbuf;
159 sc->sc_console = hil_is_console;
160 }
161
162 /*
163 * HIL subdevice attachment
164 */
165
166 int
hildevprint(void * aux,const char * pnp)167 hildevprint(void *aux, const char *pnp)
168 {
169 struct hil_attach_args *ha = aux;
170
171 if (pnp != NULL) {
172 printf("\"%s\" at %s id %x",
173 ha->ha_descr, pnp, ha->ha_id);
174 }
175 printf(" code %d", ha->ha_code);
176 if (pnp == NULL) {
177 printf(": %s", ha->ha_descr);
178 }
179
180 return (UNCONF);
181 }
182
183 int
hilsubmatch(struct device * parent,void * vcf,void * aux)184 hilsubmatch(struct device *parent, void *vcf, void *aux)
185 {
186 struct hil_attach_args *ha = aux;
187 struct cfdata *cf = vcf;
188
189 if (cf->cf_loc[0] != -1 &&
190 cf->cf_loc[0] != ha->ha_code)
191 return (0);
192
193 return ((*cf->cf_attach->ca_match)(parent, vcf, aux));
194 }
195
196 void
hil_attach_deferred(void * v)197 hil_attach_deferred(void *v)
198 {
199 struct hil_softc *sc = v;
200 int tries;
201 u_int8_t db;
202
203 sc->sc_status = HIL_STATUS_BUSY;
204
205 /*
206 * Initialize the loop: reconfigure, don't report errors,
207 * put keyboard in cooked mode, and enable autopolling.
208 */
209 db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
210 send_hil_cmd(sc, HIL_WRITELPCTRL, &db, 1, NULL);
211
212 /*
213 * Delay one second for reconfiguration and then read the
214 * data to clear the interrupt (if the loop reconfigured).
215 */
216 DELAY(1000000);
217 if (bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
218 HIL_DATA_RDY) {
219 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
220 DELAY(1);
221 }
222
223 /*
224 * The HIL loop may have reconfigured. If so we proceed on,
225 * if not we loop a few times until a successful reconfiguration
226 * is reported back to us. If the HIL loop is still lost after a
227 * few seconds, give up.
228 */
229 for (tries = 10; tries != 0; tries--) {
230 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) {
231 if (db & (LPS_CONFFAIL | LPS_CONFGOOD))
232 break;
233 }
234
235 #ifdef HILDEBUG
236 printf("%s: loop not ready, retrying...\n",
237 sc->sc_dev.dv_xname);
238 #endif
239
240 DELAY(1000000);
241 }
242
243 if (tries == 0 || (db & LPS_CONFFAIL)) {
244 printf("%s: no devices\n", sc->sc_dev.dv_xname);
245 sc->sc_pending = 0;
246 if (tries == 0)
247 return;
248 }
249
250 /*
251 * Create asynchronous loop event handler thread.
252 */
253 if (kthread_create(hil_thread, sc, &sc->sc_thread,
254 sc->sc_dev.dv_xname) != 0) {
255 printf("%s: unable to create event thread\n",
256 sc->sc_dev.dv_xname);
257 return;
258 }
259
260 /*
261 * Enable loop interrupts.
262 */
263 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
264
265 /*
266 * Reconfigure if necessary
267 */
268 sc->sc_status = HIL_STATUS_READY;
269 hil_process_pending(sc);
270 }
271
272 /*
273 * Asynchronous event processing
274 */
275
276 int
hil_intr(void * v)277 hil_intr(void *v)
278 {
279 struct hil_softc *sc = v;
280 u_int8_t c, stat;
281
282 if (cold)
283 return (0);
284
285 stat = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
286
287 /*
288 * This should never happen if the interrupt comes from the
289 * loop.
290 */
291 if ((stat & HIL_DATA_RDY) == 0)
292 return (0); /* not for us */
293
294 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
295 HILP_DATA); /* clears interrupt */
296 DELAY(1);
297
298 hil_process_int(sc, stat, c);
299
300 if (sc->sc_status != HIL_STATUS_BUSY)
301 hil_process_pending(sc);
302
303 return (1);
304 }
305
306 void
hil_process_int(struct hil_softc * sc,u_int8_t stat,u_int8_t c)307 hil_process_int(struct hil_softc *sc, u_int8_t stat, u_int8_t c)
308 {
309 struct hildev_softc *dev;
310
311 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
312 case HIL_STATUS:
313 if (c & HIL_ERROR) {
314 sc->sc_cmddone = 1;
315 switch (c) {
316 case HIL_RECONFIG:
317 sc->sc_pending = HIL_PENDING_RECONFIG;
318 break;
319 case HIL_UNPLUGGED:
320 sc->sc_pending = HIL_PENDING_UNPLUGGED;
321 break;
322 }
323 break;
324 }
325 if (c & HIL_COMMAND) {
326 if (c & HIL_POLLDATA) { /* End of data */
327 dev = sc->sc_devices[sc->sc_actdev];
328 if (dev != NULL && dev->sc_fn != NULL)
329 dev->sc_fn(dev,
330 sc->sc_pollbp - sc->sc_pollbuf,
331 sc->sc_pollbuf);
332 } else { /* End of command */
333 sc->sc_cmdending = 1;
334 }
335 sc->sc_actdev = 0;
336 } else {
337 if (c & HIL_POLLDATA) { /* Start of polled data */
338 sc->sc_actdev = (c & HIL_DEVMASK);
339 sc->sc_pollbp = sc->sc_pollbuf;
340 } else { /* Start of command */
341 if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
342 sc->sc_cmdbp = sc->sc_cmdbuf;
343 sc->sc_actdev = 0;
344 }
345 }
346 }
347 break;
348 case HIL_DATA:
349 if (sc->sc_actdev != 0) /* Collecting poll data */
350 *sc->sc_pollbp++ = c;
351 else {
352 if (sc->sc_cmddev != 0) { /* Collecting cmd data */
353 if (sc->sc_cmdending) {
354 sc->sc_cmddone = 1;
355 sc->sc_cmdending = 0;
356 } else
357 *sc->sc_cmdbp++ = c;
358 }
359 }
360 break;
361 }
362 }
363
364 /*
365 * Same as above, but in polled mode: return data as it gets seen, instead
366 * of buffering it.
367 */
368 int
hil_process_poll(struct hil_softc * sc,u_int8_t stat,u_int8_t c)369 hil_process_poll(struct hil_softc *sc, u_int8_t stat, u_int8_t c)
370 {
371 u_int8_t db;
372
373 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
374 case HIL_STATUS:
375 if (c & HIL_ERROR) {
376 sc->sc_cmddone = 1;
377 switch (c) {
378 case HIL_RECONFIG:
379 /*
380 * Remember that a configuration event
381 * occurred; it will be processed upon
382 * leaving polled mode...
383 */
384 sc->sc_pending = HIL_PENDING_RECONFIG;
385 /*
386 * However, the keyboard will come back as
387 * cooked, and we rely on it being in raw
388 * mode. So, put it back in raw mode right
389 * now.
390 */
391 db = 0;
392 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db,
393 1, NULL);
394 break;
395 case HIL_UNPLUGGED:
396 /*
397 * Remember that an unplugged event
398 * occurred; it will be processed upon
399 * leaving polled mode...
400 */
401 sc->sc_pending = HIL_PENDING_UNPLUGGED;
402 break;
403 }
404 break;
405 }
406 if (c & HIL_COMMAND) {
407 if (!(c & HIL_POLLDATA)) {
408 /* End of command */
409 sc->sc_cmdending = 1;
410 }
411 sc->sc_actdev = 0;
412 } else {
413 if (c & HIL_POLLDATA) {
414 /* Start of polled data */
415 sc->sc_actdev = (c & HIL_DEVMASK);
416 sc->sc_pollbp = sc->sc_pollbuf;
417 } else {
418 /* Start of command - should not happen */
419 if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
420 sc->sc_cmdbp = sc->sc_cmdbuf;
421 sc->sc_actdev = 0;
422 }
423 }
424 }
425 break;
426 case HIL_DATA:
427 if (sc->sc_actdev != 0) /* Collecting poll data */
428 return 1;
429 else {
430 if (sc->sc_cmddev != 0) { /* Discarding cmd data */
431 if (sc->sc_cmdending) {
432 sc->sc_cmddone = 1;
433 sc->sc_cmdending = 0;
434 }
435 }
436 }
437 break;
438 }
439
440 return 0;
441 }
442
443 void
hil_thread(void * arg)444 hil_thread(void *arg)
445 {
446 struct hil_softc *sc = arg;
447 int s;
448
449 for (;;) {
450 s = splhil();
451 if (sc->sc_pending == 0) {
452 splx(s);
453 tsleep_nsec(&sc->sc_pending, PWAIT, "hil_event",
454 INFSLP);
455 continue;
456 }
457
458 switch (sc->sc_pending) {
459 case HIL_PENDING_RECONFIG:
460 sc->sc_pending = 0;
461 hilconfig(sc, sc->sc_maxdev);
462 break;
463 case HIL_PENDING_UNPLUGGED:
464 sc->sc_pending = 0;
465 hilempty(sc);
466 break;
467 }
468 splx(s);
469 }
470 }
471
472 /*
473 * Called after the loop has reconfigured. Here we need to:
474 * - determine how many devices are on the loop
475 * (some may have been added or removed)
476 * - make sure all keyboards are in raw mode
477 *
478 * Note that our device state is now potentially invalid as
479 * devices may no longer be where they were. What we should
480 * do here is either track where the devices went and move
481 * state around accordingly...
482 *
483 * Note that it is necessary that we operate the loop with the keyboards
484 * in raw mode: they won't cause the loop to generate an NMI if the
485 * ``reset'' key combination is pressed, and we do not handle the hil
486 * NMI interrupt...
487 */
488 void
hilconfig(struct hil_softc * sc,u_int knowndevs)489 hilconfig(struct hil_softc *sc, u_int knowndevs)
490 {
491 struct hil_attach_args ha;
492 u_int8_t db;
493 int id, s;
494
495 s = splhil();
496
497 /*
498 * Determine how many devices are on the loop.
499 */
500 db = 0;
501 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db);
502 sc->sc_maxdev = db & LPS_DEVMASK;
503 #ifdef HILDEBUG
504 printf("%s: %d device(s)\n", sc->sc_dev.dv_xname, sc->sc_maxdev);
505 #endif
506
507 /*
508 * Put all keyboards in raw mode now.
509 */
510 db = 0;
511 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 1, NULL);
512
513 /*
514 * If the loop grew, attach new devices.
515 */
516 for (id = knowndevs + 1; id <= sc->sc_maxdev; id++) {
517 int len;
518 const struct hildevice *hd;
519
520 if (send_device_cmd(sc, id, HIL_IDENTIFY) != 0) {
521 printf("%s: no answer from device %d\n",
522 sc->sc_dev.dv_xname, id);
523 continue;
524 }
525
526 len = sc->sc_cmdbp - sc->sc_cmdbuf;
527 if (len == 0) {
528 #ifdef HILDEBUG
529 printf("%s: no device at code %d\n",
530 sc->sc_dev.dv_xname, id);
531 #endif
532 continue;
533 }
534
535 /* Identify and attach device */
536 for (hd = hildevs; hd->minid >= 0; hd++)
537 if (sc->sc_cmdbuf[0] >= hd->minid &&
538 sc->sc_cmdbuf[0] <= hd->maxid) {
539
540 ha.ha_console = *sc->sc_console;
541 ha.ha_code = id;
542 ha.ha_type = hd->type;
543 ha.ha_descr = hd->descr;
544 ha.ha_infolen = len;
545 bcopy(sc->sc_cmdbuf, ha.ha_info, len);
546
547 sc->sc_devices[id] = (struct hildev_softc *)
548 config_found_sm(&sc->sc_dev, &ha, hildevprint,
549 hilsubmatch);
550
551 #if NHILKBD > 0
552 /*
553 * If we just attached a keyboard as console,
554 * console choice is not indeterminate anymore.
555 */
556 if (sc->sc_devices[id] != NULL &&
557 ha.ha_type == HIL_DEVICE_KEYBOARD &&
558 ha.ha_console != 0)
559 *sc->sc_console = 1;
560 #endif
561 }
562 }
563
564 /*
565 * Detach remaining devices, if the loop has shrunk.
566 */
567 for (id = sc->sc_maxdev + 1; id < NHILD; id++) {
568 if (sc->sc_devices[id] != NULL)
569 config_detach((struct device *)sc->sc_devices[id],
570 DETACH_FORCE);
571 sc->sc_devices[id] = NULL;
572 }
573
574 sc->sc_cmdbp = sc->sc_cmdbuf;
575
576 splx(s);
577 }
578
579 /*
580 * Called after the loop has been unplugged. We simply force detach of
581 * all our children.
582 */
583 void
hilempty(struct hil_softc * sc)584 hilempty(struct hil_softc *sc)
585 {
586 u_int8_t db;
587 int id, s;
588 u_int oldmaxdev;
589
590 s = splhil();
591
592 /*
593 * Wait for the loop to be stable.
594 */
595 for (;;) {
596 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) {
597 if (db & (LPS_CONFFAIL | LPS_CONFGOOD))
598 break;
599 } else {
600 db = LPS_CONFFAIL;
601 break;
602 }
603 }
604
605 if (db & LPS_CONFFAIL) {
606 sc->sc_maxdev = 0;
607 } else {
608 db = 0;
609 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db);
610 oldmaxdev = sc->sc_maxdev;
611 sc->sc_maxdev = db & LPS_DEVMASK;
612
613 if (sc->sc_maxdev != 0) {
614 /*
615 * The loop was not unplugged after all, but its
616 * configuration has changed.
617 */
618 hilconfig(sc, oldmaxdev);
619 splx(s);
620 return;
621 }
622 }
623
624 /*
625 * Now detach all hil devices.
626 */
627 for (id = sc->sc_maxdev + 1; id < NHILD; id++) {
628 if (sc->sc_devices[id] != NULL)
629 config_detach((struct device *)sc->sc_devices[id],
630 DETACH_FORCE);
631 sc->sc_devices[id] = NULL;
632 }
633
634 sc->sc_cmdbp = sc->sc_cmdbuf;
635
636 splx(s);
637 }
638
639 /*
640 * Low level routines which actually talk to the 8042 chip.
641 */
642
643 /*
644 * Send a command to the 8042 with zero or more bytes of data.
645 * If rdata is non-null, wait for and return a byte of data.
646 */
647 int
send_hil_cmd(struct hil_softc * sc,u_int cmd,u_int8_t * data,u_int dlen,u_int8_t * rdata)648 send_hil_cmd(struct hil_softc *sc, u_int cmd, u_int8_t *data, u_int dlen,
649 u_int8_t *rdata)
650 {
651 u_int8_t status;
652 int s;
653
654 s = splhil();
655
656 if (hilwait(sc) == 0) {
657 #ifdef HILDEBUG
658 printf("%s: no answer from the loop\n", sc->sc_dev.dv_xname);
659 #endif
660 splx(s);
661 return (EBUSY);
662 }
663
664 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, cmd);
665 while (dlen--) {
666 hilwait(sc);
667 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, *data++);
668 DELAY(1);
669 }
670 if (rdata) {
671 do {
672 if (hildatawait(sc) == 0) {
673 #ifdef HILDEBUG
674 printf("%s: no answer from the loop\n",
675 sc->sc_dev.dv_xname);
676 #endif
677 break;
678 }
679 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
680 HILP_STAT);
681 *rdata = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
682 HILP_DATA);
683 DELAY(1);
684 } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
685 }
686 splx(s);
687 return (0);
688 }
689
690 /*
691 * Send a command to a device on the loop.
692 * Since only one command can be active on the loop at any time,
693 * we must ensure that we are not interrupted during this process.
694 * Hence we mask interrupts to prevent potential access from most
695 * interrupt routines and turn off auto-polling to disable the
696 * internally generated poll commands.
697 * Needs to be called at splhil().
698 */
699 int
send_device_cmd(struct hil_softc * sc,u_int device,u_int cmd)700 send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd)
701 {
702 u_int8_t status, c;
703 int rc = 0;
704
705 polloff(sc);
706
707 sc->sc_cmdbp = sc->sc_cmdbuf;
708 sc->sc_cmddev = device;
709
710 if (hilwait(sc) == 0) {
711 #ifdef HILDEBUG
712 printf("%s: no answer from device %d\n",
713 sc->sc_dev.dv_xname, device);
714 #endif
715 rc = EBUSY;
716 goto out;
717 }
718
719 /*
720 * Transfer the command and device info to the chip
721 */
722 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_STARTCMD);
723 hilwait(sc);
724 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 8 + device);
725 hilwait(sc);
726 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, cmd);
727 hilwait(sc);
728 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, HIL_TIMEOUT);
729
730 /*
731 * Trigger the command and wait for completion
732 */
733 hilwait(sc);
734 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_TRIGGER);
735 sc->sc_cmddone = 0;
736 do {
737 if (hildatawait(sc) == 0) {
738 #ifdef HILDEBUG
739 printf("%s: no answer from device %d\n",
740 sc->sc_dev.dv_xname, device);
741 #endif
742 rc = EBUSY;
743 break;
744 }
745 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
746 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
747 DELAY(1);
748 hil_process_int(sc, status, c);
749 } while (sc->sc_cmddone == 0);
750 out:
751 sc->sc_cmddev = 0;
752
753 pollon(sc);
754 return (rc);
755 }
756
757 int
send_hildev_cmd(struct hildev_softc * dev,u_int cmd,u_int8_t * outbuf,u_int * outlen)758 send_hildev_cmd(struct hildev_softc *dev, u_int cmd,
759 u_int8_t *outbuf, u_int *outlen)
760 {
761 struct hil_softc *sc = (struct hil_softc *)dev->sc_dev.dv_parent;
762 int s, rc;
763
764 s = splhil();
765
766 if ((rc = send_device_cmd(sc, dev->sc_code, cmd)) == 0) {
767 /*
768 * Return the command response in the buffer if necessary
769 */
770 if (outbuf != NULL && outlen != NULL) {
771 *outlen = min(*outlen, sc->sc_cmdbp - sc->sc_cmdbuf);
772 bcopy(sc->sc_cmdbuf, outbuf, *outlen);
773 }
774 }
775
776 splx(s);
777 return (rc);
778 }
779
780 /*
781 * Turn auto-polling off and on.
782 */
783 void
polloff(struct hil_softc * sc)784 polloff(struct hil_softc *sc)
785 {
786 u_int8_t db;
787
788 if (hilwait(sc) == 0)
789 return;
790
791 /*
792 * Turn off auto repeat
793 */
794 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
795 hilwait(sc);
796 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
797
798 /*
799 * Turn off auto-polling
800 */
801 hilwait(sc);
802 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
803 hildatawait(sc);
804 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
805 db &= ~LPC_AUTOPOLL;
806 hilwait(sc);
807 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
808 hilwait(sc);
809 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
810
811 /*
812 * Must wait until polling is really stopped
813 */
814 do {
815 hilwait(sc);
816 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READBUSY);
817 hildatawait(sc);
818 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
819 } while (db & BSY_LOOPBUSY);
820
821 sc->sc_cmddone = 0;
822 sc->sc_cmddev = 0;
823 }
824
825 void
pollon(struct hil_softc * sc)826 pollon(struct hil_softc *sc)
827 {
828 u_int8_t db;
829
830 if (hilwait(sc) == 0)
831 return;
832
833 /*
834 * Turn on auto polling
835 */
836 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
837 hildatawait(sc);
838 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
839 db |= LPC_AUTOPOLL;
840 hilwait(sc);
841 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
842 hilwait(sc);
843 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
844
845 /*
846 * Turn off auto repeat - we emulate this through wscons
847 */
848 hilwait(sc);
849 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
850 hilwait(sc);
851 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
852 DELAY(1);
853 }
854
855 void
hil_set_poll(struct hil_softc * sc,int on)856 hil_set_poll(struct hil_softc *sc, int on)
857 {
858 if (on) {
859 pollon(sc);
860 } else {
861 hil_process_pending(sc);
862 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
863 }
864 }
865
866 int
hil_poll_data(struct hildev_softc * dev,u_int8_t * stat,u_int8_t * data)867 hil_poll_data(struct hildev_softc *dev, u_int8_t *stat, u_int8_t *data)
868 {
869 struct hil_softc *sc = (struct hil_softc *)dev->sc_dev.dv_parent;
870 u_int8_t s, c;
871
872 s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
873 if ((s & HIL_DATA_RDY) == 0)
874 return -1;
875
876 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
877 DELAY(1);
878
879 if (hil_process_poll(sc, s, c)) {
880 /* Discard any data not for us */
881 if (sc->sc_actdev == dev->sc_code) {
882 *stat = s;
883 *data = c;
884 return 0;
885 }
886 }
887
888 return -1;
889 }
890