]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/wbwd/wbwd.c
Import Amazon Elastic Network Adapter (ENA) HAL to sys/contrib/
[FreeBSD/FreeBSD.git] / sys / dev / wbwd / wbwd.c
1 /*-
2  * Copyright (c) 2011 Sandvine Incorporated ULC.
3  * Copyright (c) 2012 iXsystems, Inc.
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 AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 /*
28  * Support for Winbond watchdog.
29  *
30  * With minor abstractions it might be possible to add support for other
31  * different Winbond Super I/O chips as well.  Winbond seems to have four
32  * different types of chips, four different ways to get into extended config
33  * mode.
34  *
35  * Note: there is no serialization between the debugging sysctl handlers and
36  * the watchdog functions and possibly others poking the registers at the same
37  * time.  For that at least possibly interfering sysctls are hidden by default.
38  */
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/systm.h>
46 #include <sys/bus.h>
47 #include <sys/eventhandler.h>
48 #include <sys/lock.h>
49 #include <sys/module.h>
50 #include <sys/rman.h>
51 #include <sys/sbuf.h>
52 #include <sys/sysctl.h>
53 #include <sys/watchdog.h>
54
55 #include <isa/isavar.h>
56
57 #include <machine/bus.h>
58 #include <machine/resource.h>
59
60 /*
61  * Global registers.
62  */
63 #define WB_DEVICE_ID_REG        0x20    /* Device ID */
64 #define WB_DEVICE_REV_REG       0x21    /* Device revision */
65 #define WB_CR26                 0x26    /* Bit6: HEFRAS (base port selector) */
66
67 /* LDN selection. */
68 #define WB_LDN_REG              0x07
69 #define WB_LDN_REG_LDN8         0x08    /* GPIO 2, Watchdog */
70
71 /*
72  * LDN8 (GPIO 2, Watchdog) specific registers and options.
73  */
74 /* CR30: LDN8 activation control. */
75 #define WB_LDN8_CR30            0x30
76 #define WB_LDN8_CR30_ACTIVE     0x01    /* 1: LD active */
77
78 /* CRF5: Watchdog scale, P20. Mapped to reg_1. */
79 #define WB_LDN8_CRF5            0xF5
80 #define WB_LDN8_CRF5_SCALE      0x08    /* 0: 1s, 1: 60s */
81 #define WB_LDN8_CRF5_KEYB_P20   0x04    /* 1: keyb P20 forces timeout */
82 #define WB_LDN8_CRF5_KBRST      0x02    /* 1: timeout causes pin60 kbd reset */
83
84 /* CRF6: Watchdog Timeout (0 == off). Mapped to reg_timeout. */
85 #define WB_LDN8_CRF6            0xF6
86
87 /* CRF7: Watchdog mouse, keyb, force, .. Mapped to reg_2. */
88 #define WB_LDN8_CRF7            0xF7
89 #define WB_LDN8_CRF7_MOUSE      0x80    /* 1: mouse irq resets wd timer */
90 #define WB_LDN8_CRF7_KEYB       0x40    /* 1: keyb irq resets wd timer */
91 #define WB_LDN8_CRF7_FORCE      0x20    /* 1: force timeout (self-clear) */
92 #define WB_LDN8_CRF7_TS         0x10    /* 0: counting, 1: fired */
93 #define WB_LDN8_CRF7_IRQS       0x0f    /* irq source for watchdog, 2 == SMI */
94
95 enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
96              w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg,
97              w83627dhg_p, w83667hg_b, nct6775, nct6776, nct6779, nct6791,
98              nct6792, nct6102 };
99
100 struct wb_softc {
101         device_t                dev;
102         struct resource         *portres;
103         bus_space_tag_t         bst;
104         bus_space_handle_t      bsh;
105         int                     rid;
106         eventhandler_tag        ev_tag;
107         int                     (*ext_cfg_enter_f)(struct wb_softc *, u_short);
108         void                    (*ext_cfg_exit_f)(struct wb_softc *, u_short);
109         enum chips              chip;
110         uint8_t                 ctl_reg;
111         uint8_t                 time_reg;
112         uint8_t                 csr_reg;
113         int                     debug_verbose;
114
115         /*
116          * Special feature to let the watchdog fire at a different
117          * timeout as set by watchdog(4) but still use that API to
118          * re-load it periodically.
119          */
120         unsigned int            timeout_override;
121
122         /*
123          * Space to save current state temporary and for sysctls.
124          * We want to know the timeout value and usually need two
125          * additional registers for options. Do not name them by
126          * register as these might be different by chip.
127          */
128         uint8_t                 reg_timeout;
129         uint8_t                 reg_1;
130         uint8_t                 reg_2;
131 };
132
133 static int      ext_cfg_enter_0x87_0x87(struct wb_softc *, u_short);
134 static void     ext_cfg_exit_0xaa(struct wb_softc *, u_short);
135
136 struct winbond_superio_cfg {
137         uint8_t                 efer;   /* and efir */
138         int                     (*ext_cfg_enter_f)(struct wb_softc *, u_short);
139         void                    (*ext_cfg_exit_f)(struct wb_softc *, u_short);
140 } probe_addrs[] = {
141         {
142                 .efer                   = 0x2e,
143                 .ext_cfg_enter_f        = ext_cfg_enter_0x87_0x87,
144                 .ext_cfg_exit_f         = ext_cfg_exit_0xaa,
145         },
146         {
147                 .efer                   = 0x4e,
148                 .ext_cfg_enter_f        = ext_cfg_enter_0x87_0x87,
149                 .ext_cfg_exit_f         = ext_cfg_exit_0xaa,
150         },
151 };
152
153 struct winbond_vendor_device_id {
154         uint8_t                 device_id;
155         enum chips              chip;
156         const char *            descr;
157 } wb_devs[] = {
158         {
159                 .device_id      = 0x52,
160                 .chip           = w83627hf,
161                 .descr          = "Winbond 83627HF/F/HG/G",
162         },
163         {
164                 .device_id      = 0x59,
165                 .chip           = w83627s,
166                 .descr          = "Winbond 83627S",
167         },
168         {
169                 .device_id      = 0x60,
170                 .chip           = w83697hf,
171                 .descr          = "Winbond 83697HF",
172         },
173         {
174                 .device_id      = 0x68,
175                 .chip           = w83697ug,
176                 .descr          = "Winbond 83697UG",
177         },
178         {
179                 .device_id      = 0x70,
180                 .chip           = w83637hf,
181                 .descr          = "Winbond 83637HF",
182         },
183         {
184                 .device_id      = 0x82,
185                 .chip           = w83627thf,
186                 .descr          = "Winbond 83627THF",
187         },
188         {
189                 .device_id      = 0x85,
190                 .chip           = w83687thf,
191                 .descr          = "Winbond 83687THF",
192         },
193         {
194                 .device_id      = 0x88,
195                 .chip           = w83627ehf,
196                 .descr          = "Winbond 83627EHF",
197         },
198         {
199                 .device_id      = 0xa0,
200                 .chip           = w83627dhg,
201                 .descr          = "Winbond 83627DHG",
202         },
203         {
204                 .device_id      = 0xa2,
205                 .chip           = w83627uhg,
206                 .descr          = "Winbond 83627UHG",
207         },
208         {
209                 .device_id      = 0xa5,
210                 .chip           = w83667hg,
211                 .descr          = "Winbond 83667HG",
212         },
213         {
214                 .device_id      = 0xb0,
215                 .chip           = w83627dhg_p,
216                 .descr          = "Winbond 83627DHG-P",
217         },
218         {
219                 .device_id      = 0xb3,
220                 .chip           = w83667hg_b,
221                 .descr          = "Winbond 83667HG-B",
222         },
223         {
224                 .device_id      = 0xb4,
225                 .chip           = nct6775,
226                 .descr          = "Nuvoton NCT6775",
227         },
228         {
229                 .device_id      = 0xc3,
230                 .chip           = nct6776,
231                 .descr          = "Nuvoton NCT6776",
232         },
233         {
234                 .device_id      = 0xc4,
235                 .chip           = nct6102,
236                 .descr          = "Nuvoton NCT6102",
237         },
238         {
239                 .device_id      = 0xc5,
240                 .chip           = nct6779,
241                 .descr          = "Nuvoton NCT6779",
242         },
243         {
244                 .device_id      = 0xc8,
245                 .chip           = nct6791,
246                 .descr          = "Nuvoton NCT6791",
247         },
248         {
249                 .device_id      = 0xc9,
250                 .chip           = nct6792,
251                 .descr          = "Nuvoton NCT6792",
252         },
253 };
254
255 static void
256 write_efir_1(struct wb_softc *sc, u_short baseport, uint8_t value)
257 {
258
259         MPASS(sc != NULL || baseport != 0);
260         if (sc != NULL)
261                 bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value));
262         else
263                 outb(baseport, value);
264 }
265
266 static uint8_t __unused
267 read_efir_1(struct wb_softc *sc, u_short baseport)
268 {
269
270         MPASS(sc != NULL || baseport != 0);
271         if (sc != NULL)
272                 return (bus_space_read_1((sc)->bst, (sc)->bsh, 0));
273         else
274                 return (inb(baseport));
275 }
276
277 static void
278 write_efdr_1(struct wb_softc *sc, u_short baseport, uint8_t value)
279 {
280
281         MPASS(sc != NULL || baseport != 0);
282         if (sc != NULL)
283                 bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value));
284         else
285                 outb(baseport + 1, value);
286 }
287
288 static uint8_t
289 read_efdr_1(struct wb_softc *sc, u_short baseport)
290 {
291
292         MPASS(sc != NULL || baseport != 0);
293         if (sc != NULL)
294                 return (bus_space_read_1((sc)->bst, (sc)->bsh, 1));
295         else
296                 return (inb(baseport + 1));
297 }
298
299 static void
300 write_reg(struct wb_softc *sc, uint8_t reg, uint8_t value)
301 {
302
303         write_efir_1(sc, 0, reg);
304         write_efdr_1(sc, 0, value);
305 }
306
307 static uint8_t
308 read_reg(struct wb_softc *sc, uint8_t reg)
309 {
310
311         write_efir_1(sc, 0, reg);
312         return (read_efdr_1(sc, 0));
313 }
314
315 /*
316  * Return the watchdog related registers as we last read them.  This will
317  * usually not give the current timeout or state on whether the watchdog
318  * fired.
319  */
320 static int
321 sysctl_wb_debug(SYSCTL_HANDLER_ARGS)
322 {
323         struct wb_softc *sc;
324         struct sbuf sb;
325         int error;
326
327         sc = arg1;
328
329         sbuf_new_for_sysctl(&sb, NULL, 64, req);
330
331         sbuf_printf(&sb, "LDN8 (GPIO2, Watchdog): ");
332         sbuf_printf(&sb, "CR%02X 0x%02x ", sc->ctl_reg, sc->reg_1);
333         sbuf_printf(&sb, "CR%02X 0x%02x ", sc->time_reg, sc->reg_timeout);
334         sbuf_printf(&sb, "CR%02X 0x%02x", sc->csr_reg, sc->reg_2);
335
336         error = sbuf_finish(&sb);
337         sbuf_delete(&sb);
338         return (error);
339 }
340
341 /*
342  * Read the current values before returning them.  Given this might poke
343  * the registers the same time as the watchdog, this sysctl handler should
344  * be marked CTLFLAG_SKIP to not show up by default.
345  */
346 static int
347 sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS)
348 {
349         struct wb_softc *sc;
350
351         sc = arg1;
352
353         if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
354                 return (ENXIO);
355
356         /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
357         write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
358
359         sc->reg_1 = read_reg(sc, sc->ctl_reg);
360         sc->reg_timeout = read_reg(sc, sc->time_reg);
361         sc->reg_2 = read_reg(sc, sc->csr_reg);
362
363         (*sc->ext_cfg_exit_f)(sc, 0);
364
365         return (sysctl_wb_debug(oidp, arg1, arg2, req));
366 }
367
368 /*
369  * Sysctl handlers to force a watchdog timeout or to test the NMI functionality
370  * works as expetced.
371  * For testing we could set a test_nmi flag in the softc that, in case of NMI, a
372  * callback function from trap.c could check whether we fired and not report the
373  * timeout but clear the flag for the sysctl again.  This is interesting given a
374  * lot of boards have jumpers to change the action on watchdog timeout or
375  * disable the watchdog completely.
376  * XXX-BZ notyet: currently no general infrastructure exists to do this.
377  */
378 static int
379 sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS)
380 {
381         struct wb_softc *sc;
382         int error, test, val;
383
384         sc = arg1;
385         test = arg2;
386
387 #ifdef notyet
388         val = sc->test_nmi;
389 #else
390         val = 0;
391 #endif
392         error = sysctl_handle_int(oidp, &val, 0, req);
393         if (error || !req->newptr)
394                 return (error);
395
396 #ifdef notyet
397         /* Manually clear the test for a value of 0 and do nothing else. */
398         if (test && val == 0) {
399                 sc->test_nmi = 0;
400                 return (0);
401         }
402 #endif
403
404         if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
405                 return (ENXIO);
406
407 #ifdef notyet
408         /*
409          * If we are testing the NMI functionality, set the flag before
410          * forcing the timeout.
411          */
412         if (test)
413                 sc->test_nmi = 1;
414 #endif
415
416         /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
417         write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
418
419         /* Force watchdog to fire. */
420         sc->reg_2 = read_reg(sc, sc->csr_reg);
421         sc->reg_2 |= WB_LDN8_CRF7_FORCE;
422         write_reg(sc, sc->csr_reg, sc->reg_2);
423
424         (*sc->ext_cfg_exit_f)(sc, 0);
425
426         return (0);
427 }
428
429 /*
430  * Print current watchdog state.
431  *
432  * Note: it is the responsibility of the caller to update the registers
433  * upfront.
434  */
435 static void
436 wb_print_state(struct wb_softc *sc, const char *msg)
437 {
438
439         device_printf(sc->dev, "%s%sWatchdog %sabled. %s"
440             "Scaling by %ds, timer at %d (%s=%ds%s). "
441             "CRF5 0x%02x CRF7 0x%02x\n",
442             (msg != NULL) ? msg : "", (msg != NULL) ? ": " : "",
443             (sc->reg_timeout > 0x00) ? "en" : "dis",
444             (sc->reg_2 & WB_LDN8_CRF7_TS) ? "Watchdog fired. " : "",
445             (sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1,
446             sc->reg_timeout,
447             (sc->reg_timeout > 0x00) ? "<" : "",
448             sc->reg_timeout * ((sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1),
449             (sc->reg_timeout > 0x00) ? " left" : "",
450             sc->reg_1, sc->reg_2);
451 }
452
453 /*
454  * Functions to enter and exit extended function mode.  Possibly shared
455  * between different chips.
456  */
457 static int
458 ext_cfg_enter_0x87_0x87(struct wb_softc *sc, u_short baseport)
459 {
460
461         /*
462          * Enable extended function mode.
463          * Winbond does not allow us to validate so always return success.
464          */
465         write_efir_1(sc, baseport, 0x87);
466         write_efir_1(sc, baseport, 0x87);
467
468         return (0);
469 }
470
471 static void
472 ext_cfg_exit_0xaa(struct wb_softc *sc, u_short baseport)
473 {
474
475         write_efir_1(sc, baseport, 0xaa);
476 }
477
478 /*
479  * (Re)load the watchdog counter depending on timeout.  A timeout of 0 will
480  * disable the watchdog.
481  */
482 static int
483 wb_set_watchdog(struct wb_softc *sc, unsigned int timeout)
484 {
485
486         if (timeout != 0) {
487                 /*
488                  * In case an override is set, let it override.  It may lead
489                  * to strange results as we do not check the input of the sysctl.
490                  */
491                 if (sc->timeout_override > 0)
492                         timeout = sc->timeout_override;
493
494                 /* Make sure we support the requested timeout. */
495                 if (timeout > 255 * 60)
496                         return (EINVAL);
497         }
498
499         if (sc->debug_verbose)
500                 wb_print_state(sc, "Before watchdog counter (re)load");
501
502         if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
503                 return (ENXIO);
504
505         /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */
506         write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
507
508         if (timeout == 0) {
509                 /* Disable watchdog. */
510                 sc->reg_timeout = 0;
511                 write_reg(sc, sc->time_reg, sc->reg_timeout);
512
513         } else {
514                 /* Read current scaling factor. */
515                 sc->reg_1 = read_reg(sc, sc->ctl_reg);
516
517                 if (timeout > 255) {
518                         /* Set scaling factor to 60s. */
519                         sc->reg_1 |= WB_LDN8_CRF5_SCALE;
520                         sc->reg_timeout = (timeout / 60);
521                         if (timeout % 60)
522                                 sc->reg_timeout++;
523                 } else {
524                         /* Set scaling factor to 1s. */
525                         sc->reg_1 &= ~WB_LDN8_CRF5_SCALE;
526                         sc->reg_timeout = timeout;
527                 }
528
529                 /* In case we fired before we need to clear to fire again. */
530                 sc->reg_2 = read_reg(sc, sc->csr_reg);
531                 if (sc->reg_2 & WB_LDN8_CRF7_TS) {
532                         sc->reg_2 &= ~WB_LDN8_CRF7_TS;
533                         write_reg(sc, sc->csr_reg, sc->reg_2);
534                 }
535
536                 /* Write back scaling factor. */
537                 write_reg(sc, sc->ctl_reg, sc->reg_1);
538
539                 /* Set timer and arm/reset the watchdog. */
540                 write_reg(sc, sc->time_reg, sc->reg_timeout);
541         }
542
543         (*sc->ext_cfg_exit_f)(sc, 0);
544
545         if (sc->debug_verbose)
546                 wb_print_state(sc, "After watchdog counter (re)load");
547         return (0);
548 }
549
550 /*
551  * watchdog(9) EVENTHANDLER function implementation to (re)load the counter
552  * with the given timeout or disable the watchdog.
553  */
554 static void
555 wb_watchdog_fn(void *private, u_int cmd, int *error)
556 {
557         struct wb_softc *sc;
558         unsigned int timeout;
559         int e;
560
561         sc = private;
562         KASSERT(sc != NULL, ("%s: watchdog handler function called without "
563             "softc.", __func__));
564
565         cmd &= WD_INTERVAL;
566         if (cmd > 0 && cmd <= 63) {
567                 /* Reset (and arm) watchdog. */
568                 timeout = ((uint64_t)1 << cmd) / 1000000000;
569                 if (timeout == 0)
570                         timeout = 1;
571                 e = wb_set_watchdog(sc, timeout);
572                 if (e == 0) {
573                         if (error != NULL)
574                                 *error = 0;
575                 } else {
576                         /* On error, try to make sure the WD is disabled. */
577                         wb_set_watchdog(sc, 0);
578                 }
579
580         } else {
581                 /* Disable watchdog. */
582                 e = wb_set_watchdog(sc, 0);
583                 if (e != 0 && cmd == 0 && error != NULL) {
584                         /* Failed to disable watchdog. */
585                         *error = EOPNOTSUPP;
586                 }
587         }
588 }
589
590 /*
591  * Probe/attach the Winbond Super I/O chip.
592  *
593  * Initial abstraction to possibly support more chips:
594  * - Iterate over the well known base ports, try to enable extended function
595  *   mode and read and match the device ID and device revision.  Unfortunately
596  *   the Vendor ID is in the hardware monitoring section accessible by different
597  *   base ports only.
598  * - Also HEFRAS, which would tell use the base port, is only accessible after
599  *   entering extended function mode, for which the base port is needed.
600  *   At least check HEFRAS to match the current base port we are probing.
601  * - On match set the description, remember functions to enter/exit extended
602  *   function mode as well as the base port.
603  */
604 static int
605 wb_probe_enable(device_t dev, int probe)
606 {
607         struct wb_softc *sc;
608         int error, found, i, j;
609         uint8_t dev_id, dev_rev, cr26;
610         char buf[128];
611
612         if (dev == NULL)
613                 sc = NULL;
614         else {
615                 sc = device_get_softc(dev);
616                 bzero(sc, sizeof(*sc));
617                 sc->dev = dev;
618         }
619
620         error = ENXIO;
621         found = 0;
622         for (i = 0; i < nitems(probe_addrs); i++) {
623
624                 if (sc != NULL) {
625                         /* Allocate bus resources for IO index/data register access. */
626                         sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
627                             probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE);
628                         if (sc->portres == NULL)
629                                 continue;
630                         sc->bst = rman_get_bustag(sc->portres);
631                         sc->bsh = rman_get_bushandle(sc->portres);
632                 }
633
634                 error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer);
635                 if (error != 0)
636                         goto cleanup;
637
638                 /* Identify the SuperIO chip. */
639                 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_ID_REG);
640                 dev_id = read_efdr_1(sc, probe_addrs[i].efer);
641                 write_efir_1(sc, probe_addrs[i].efer, WB_DEVICE_REV_REG);
642                 dev_rev = read_efdr_1(sc, probe_addrs[i].efer);
643                 write_efir_1(sc, probe_addrs[i].efer, WB_CR26);
644                 cr26 = read_efdr_1(sc, probe_addrs[i].efer);
645
646                 if (dev_id == 0xff && dev_rev == 0xff)
647                         goto cleanup;
648
649                 /* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */
650                 if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) ||
651                     ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) {
652                         if (dev != NULL)
653                                 device_printf(dev, "HEFRAS and EFER do not "
654                                     "align: EFER 0x%02x DevID 0x%02x DevRev "
655                                     "0x%02x CR26 0x%02x\n",
656                                     probe_addrs[i].efer, dev_id, dev_rev, cr26);
657                         goto cleanup;
658                 }
659
660                 for (j = 0; j < nitems(wb_devs); j++) {
661                         if (wb_devs[j].device_id == dev_id) {
662                                 found = 1;
663                                 break;
664                         }
665                 }
666
667                 if (probe && dev != NULL) {
668                         snprintf(buf, sizeof(buf),
669                             "%s (0x%02x/0x%02x) Watchdog Timer",
670                             found ? wb_devs[j].descr :
671                              "Unknown Winbond/Nuvoton", dev_id, dev_rev);
672                         device_set_desc_copy(dev, buf);
673                 }
674
675                 /* If this is hinted attach, try to guess the model. */
676                 if (dev != NULL && !found) {
677                         found = 1;
678                         j = 0;
679                 }
680
681 cleanup:
682                 if (probe || !found) {
683                         (*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer);
684                         if (sc != NULL)
685                                 (void) bus_release_resource(dev, SYS_RES_IOPORT,
686                                     sc->rid, sc->portres);
687                 }
688
689                 /*
690                  * Stop probing if have successfully identified the SuperIO.
691                  * Remember the extended function mode enter/exit functions
692                  * for operations.
693                  */
694                 if (found) {
695                         if (sc != NULL) {
696                                 sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f;
697                                 sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f;
698                                 sc->chip = wb_devs[j].chip;
699                                 sc->ctl_reg = 0xf5;
700                                 sc->time_reg = 0xf6;
701                                 sc->csr_reg = 0xf7;
702                                 if (sc->chip == w83697hf ||
703                                     sc->chip == w83697ug) {
704                                         sc->ctl_reg = 0xf3;
705                                         sc->time_reg = 0xf4;
706                                 } else if (sc->chip == nct6102) {
707                                         sc->ctl_reg = 0xf0;
708                                         sc->time_reg = 0xf1;
709                                         sc->csr_reg = 0xf2;
710                                 }
711                         }
712                         return (BUS_PROBE_SPECIFIC);
713                 } else
714                         error = ENXIO;
715         }
716
717         return (error);
718 }
719
720 static void
721 wb_identify(driver_t *driver, device_t parent)
722 {
723
724         if (device_find_child(parent, driver->name, 0) == NULL) {
725                 if (wb_probe_enable(NULL, 1) <= 0)
726                         BUS_ADD_CHILD(parent, 0, driver->name, 0);
727         }
728 }
729
730 static int
731 wb_probe(device_t dev)
732 {
733
734         /* Make sure we do not claim some ISA PNP device. */
735         if (isa_get_logicalid(dev) != 0)
736                 return (ENXIO);
737
738         return (wb_probe_enable(dev, 1));
739 }
740
741 static int
742 wb_attach(device_t dev)
743 {
744         struct wb_softc *sc;
745         struct sysctl_ctx_list *sctx;
746         struct sysctl_oid *soid;
747         unsigned long timeout;
748         int error;
749         uint8_t t;
750
751         error = wb_probe_enable(dev, 0);
752         if (error > 0)
753                 return (ENXIO);
754
755         sc = device_get_softc(dev);
756         KASSERT(sc->ext_cfg_enter_f != NULL && sc->ext_cfg_exit_f != NULL,
757             ("%s: successful probe result but not setup correctly", __func__));
758
759         /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
760         write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
761
762         /* Make sure WDT is enabled. */
763         write_reg(sc, WB_LDN8_CR30,
764             read_reg(sc, WB_LDN8_CR30) | WB_LDN8_CR30_ACTIVE);
765
766         switch (sc->chip) {
767         case w83627hf:
768         case w83627s:
769                 t = read_reg(sc, 0x2B) & ~0x10;
770                 write_reg(sc, 0x2B, t); /* set GPIO24 to WDT0 */
771                 break;
772         case w83697hf:
773                 /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
774                 t = read_reg(sc, 0x29) & ~0x60;
775                 t |= 0x20;
776                 write_reg(sc, 0x29, t);
777                 break;
778         case w83697ug:
779                 /* Set pin 118 to WDTO# mode */
780                 t = read_reg(sc, 0x2b) & ~0x04;
781                 write_reg(sc, 0x2b, t);
782                 break;
783         case w83627thf:
784                 t = (read_reg(sc, 0x2B) & ~0x08) | 0x04;
785                 write_reg(sc, 0x2B, t); /* set GPIO3 to WDT0 */
786                 break;
787         case w83627dhg:
788         case w83627dhg_p:
789                 t = read_reg(sc, 0x2D) & ~0x01; /* PIN77 -> WDT0# */
790                 write_reg(sc, 0x2D, t); /* set GPIO5 to WDT0 */
791                 t = read_reg(sc, sc->ctl_reg);
792                 t |= 0x02;      /* enable the WDTO# output low pulse
793                                  * to the KBRST# pin */
794                 write_reg(sc, sc->ctl_reg, t);
795                 break;
796         case w83637hf:
797                 break;
798         case w83687thf:
799                 t = read_reg(sc, 0x2C) & ~0x80; /* PIN47 -> WDT0# */
800                 write_reg(sc, 0x2C, t);
801                 break;
802         case w83627ehf:
803         case w83627uhg:
804         case w83667hg:
805         case w83667hg_b:
806         case nct6775:
807         case nct6776:
808         case nct6779:
809         case nct6791:
810         case nct6792:
811         case nct6102:
812                 /*
813                  * These chips have a fixed WDTO# output pin (W83627UHG),
814                  * or support more than one WDTO# output pin.
815                  * Don't touch its configuration, and hope the BIOS
816                  * does the right thing.
817                  */
818                 t = read_reg(sc, sc->ctl_reg);
819                 t |= 0x02;      /* enable the WDTO# output low pulse
820                                  * to the KBRST# pin */
821                 write_reg(sc, sc->ctl_reg, t);
822                 break;
823         default:
824                 break;
825         }
826
827         /* Read the current watchdog configuration. */
828         sc->reg_1 = read_reg(sc, sc->ctl_reg);
829         sc->reg_timeout = read_reg(sc, sc->time_reg);
830         sc->reg_2 = read_reg(sc, sc->csr_reg);
831
832         /* Print current state if bootverbose or watchdog already enabled. */
833         if (bootverbose || (sc->reg_timeout > 0x00))
834                 wb_print_state(sc, "Before watchdog attach");
835
836         sc->reg_1 &= ~WB_LDN8_CRF5_KEYB_P20;
837         sc->reg_1 |= WB_LDN8_CRF5_KBRST;
838         write_reg(sc, sc->ctl_reg, sc->reg_1);
839
840         /*
841          * Clear a previous watchdog timeout event (if still set).
842          * Disable timer reset on mouse interrupts.  Leave reset on keyboard,
843          * since one of my boards is getting stuck in reboot without it.
844          */
845         sc->reg_2 &= ~(WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_TS);
846         write_reg(sc, sc->csr_reg, sc->reg_2);
847
848         (*sc->ext_cfg_exit_f)(sc, 0);
849
850         /* Read global timeout override tunable, Add per device sysctls. */
851         if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) {
852                 if (timeout > 0)
853                         sc->timeout_override = timeout;
854         }
855         sctx = device_get_sysctl_ctx(dev);
856         soid = device_get_sysctl_tree(dev);
857         SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
858             "timeout_override", CTLFLAG_RW, &sc->timeout_override, 0,
859             "Timeout in seconds overriding default watchdog timeout");
860         SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
861             "debug_verbose", CTLFLAG_RW, &sc->debug_verbose, 0,
862             "Enables extra debugging information");
863         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
864             CTLTYPE_STRING|CTLFLAG_RD, sc, 0, sysctl_wb_debug, "A",
865             "Selected register information from last change by driver");
866         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug_current",
867             CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_SKIP, sc, 0,
868              sysctl_wb_debug_current, "A",
869              "Selected register information (may interfere)");
870         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "force_timeout",
871             CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_SKIP, sc, 0,
872             sysctl_wb_force_test_nmi, "I", "Enable to force watchdog to fire.");
873
874         /* Register watchdog. */
875         sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, wb_watchdog_fn, sc,
876             0);
877
878         if (bootverbose)
879                 wb_print_state(sc, "After watchdog attach");
880
881         return (0);
882 }
883
884 static int
885 wb_detach(device_t dev)
886 {
887         struct wb_softc *sc;
888
889         sc = device_get_softc(dev);
890
891         /* Unregister and stop the watchdog if running. */
892         if (sc->ev_tag)
893                 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag);
894         wb_set_watchdog(sc, 0);
895
896         /* Disable extended function mode. */
897         (*sc->ext_cfg_exit_f)(sc, 0);
898
899         /* Cleanup resources. */
900         (void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
901
902         /* Bus subroutines take care of sysctls already. */
903
904         return (0);
905 }
906
907 static device_method_t wb_methods[] = {
908         /* Device interface */
909         DEVMETHOD(device_identify,      wb_identify),
910         DEVMETHOD(device_probe,         wb_probe),
911         DEVMETHOD(device_attach,        wb_attach),
912         DEVMETHOD(device_detach,        wb_detach),
913
914         DEVMETHOD_END
915 };
916
917 static driver_t wb_isa_driver = {
918         "wbwd",
919         wb_methods,
920         sizeof(struct wb_softc)
921 };
922
923 static devclass_t wb_devclass;
924
925 DRIVER_MODULE(wb, isa, wb_isa_driver, wb_devclass, NULL, NULL);