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