1 /*- 2 * Copyright (c) 2011 Sandvine Incorporated ULC. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 /* 27 * Support for Winbond watchdog. 28 * 29 * With minor abstractions it might be possible to add support for other 30 * different Winbond Super I/O chips as well. Winbond seems to have four 31 * different types of chips, four different ways to get into extended config 32 * mode. 33 * 34 * Note: there is no serialization between the debugging sysctl handlers and 35 * the watchdog functions and possibly others poking the registers at the same 36 * time. For that at least possibly interfering sysctls are hidden by default. 37 */ 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include <sys/param.h> 43 #include <sys/kernel.h> 44 #include <sys/systm.h> 45 #include <sys/bus.h> 46 #include <sys/eventhandler.h> 47 #include <sys/lock.h> 48 #include <sys/module.h> 49 #include <sys/rman.h> 50 #include <sys/sbuf.h> 51 #include <sys/sysctl.h> 52 #include <sys/watchdog.h> 53 54 #include <isa/isavar.h> 55 56 #include <machine/bus.h> 57 #include <machine/resource.h> 58 59 /* 60 * Global registers. 61 */ 62 #define WB_DEVICE_ID_REG 0x20 /* Device ID */ 63 #define WB_DEVICE_REV_REG 0x21 /* Device revision */ 64 #define WB_CR26 0x26 /* Bit6: HEFRAS (base port selector) */ 65 66 /* LDN selection. */ 67 #define WB_LDN_REG 0x07 68 #define WB_LDN_REG_LDN8 0x08 /* GPIO 2, Watchdog */ 69 70 /* 71 * LDN8 (GPIO 2, Watchdog) specific registers and options. 72 */ 73 /* CR30: LDN8 activation control. */ 74 #define WB_LDN8_CR30 0x30 75 #define WB_LDN8_CR30_ACTIVE 0x01 /* 1: LD active */ 76 77 /* CRF5: Watchdog scale, P20. Mapped to reg_1. */ 78 #define WB_LDN8_CRF5 0xF5 79 #define WB_LDN8_CRF5_SCALE 0x08 /* 0: 1s, 1: 60s */ 80 #define WB_LDN8_CRF5_KEYB_P20 0x04 /* 1: keyb P20 forces timeout */ 81 #define WB_LDN8_CRF5_KBRST 0x02 /* 1: timeout causes pin60 kbd reset */ 82 83 /* CRF6: Watchdog Timeout (0 == off). Mapped to reg_timeout. */ 84 #define WB_LDN8_CRF6 0xF6 85 86 /* CRF7: Watchdog mouse, keyb, force, .. Mapped to reg_2. */ 87 #define WB_LDN8_CRF7 0xF7 88 #define WB_LDN8_CRF7_MOUSE 0x80 /* 1: mouse irq resets wd timer */ 89 #define WB_LDN8_CRF7_KEYB 0x40 /* 1: keyb irq resets wd timer */ 90 #define WB_LDN8_CRF7_FORCE 0x20 /* 1: force timeout (self-clear) */ 91 #define WB_LDN8_CRF7_TS 0x10 /* 0: counting, 1: fired */ 92 #define WB_LDN8_CRF7_IRQS 0x0f /* irq source for watchdog, 2 == SMI */ 93 #define WB_LDN8_CRF7_CLEAR_MASK \ 94 (WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_KEYB|WB_LDN8_CRF7_TS|WB_LDN8_CRF7_IRQS) 95 96 #define write_efir_1(sc, value) \ 97 bus_space_write_1((sc)->bst, (sc)->bsh, 0, (value)) 98 #define read_efir_1(sc) \ 99 bus_space_read_1((sc)->bst, (sc)->bsh, 0) 100 #define write_efdr_1(sc, value) \ 101 bus_space_write_1((sc)->bst, (sc)->bsh, 1, (value)) 102 #define read_efdr_1(sc) \ 103 bus_space_read_1((sc)->bst, (sc)->bsh, 1) 104 105 struct wb_softc { 106 device_t dev; 107 struct resource *portres; 108 bus_space_tag_t bst; 109 bus_space_handle_t bsh; 110 int rid; 111 eventhandler_tag ev_tag; 112 int (*ext_cfg_enter_f)(struct wb_softc *); 113 void (*ext_cfg_exit_f)(struct wb_softc *); 114 int debug_verbose; 115 116 /* 117 * Special feature to let the watchdog fire at a different 118 * timeout as set by watchdog(4) but still use that API to 119 * re-load it periodically. 120 */ 121 unsigned int timeout_override; 122 123 /* 124 * Space to save current state temporary and for sysctls. 125 * We want to know the timeout value and usually need two 126 * additional registers for options. Do not name them by 127 * register as these might be different by chip. 128 */ 129 uint8_t reg_timeout; 130 uint8_t reg_1; 131 uint8_t reg_2; 132 }; 133 134 static int ext_cfg_enter_0x87_0x87(struct wb_softc *); 135 static void ext_cfg_exit_0xaa(struct wb_softc *); 136 137 struct winbond_superio_cfg { 138 uint8_t efer; /* and efir */ 139 int (*ext_cfg_enter_f)(struct wb_softc *); 140 void (*ext_cfg_exit_f)(struct wb_softc *); 141 } probe_addrs[] = { 142 { 143 .efer = 0x2e, 144 .ext_cfg_enter_f = ext_cfg_enter_0x87_0x87, 145 .ext_cfg_exit_f = ext_cfg_exit_0xaa, 146 }, 147 { 148 .efer = 0x4e, 149 .ext_cfg_enter_f = ext_cfg_enter_0x87_0x87, 150 .ext_cfg_exit_f = ext_cfg_exit_0xaa, 151 }, 152 }; 153 154 struct winbond_vendor_device_id { 155 uint16_t vendor_id; 156 uint8_t device_id; 157 uint8_t device_rev; 158 const char * descr; 159 } wb_devs[] = { 160 { 161 .vendor_id = 0x5ca3, 162 .device_id = 0x52, 163 .device_rev = 0x17, 164 .descr = "Winbond 83627HF/F/HG/G Rev. G", 165 }, 166 { 167 .vendor_id = 0x5ca3, 168 .device_id = 0x52, 169 .device_rev = 0x3a, 170 .descr = "Winbond 83627HF/F/HG/G Rev. J", 171 }, 172 { 173 .vendor_id = 0x5ca3, 174 .device_id = 0x52, 175 .device_rev = 0x41, 176 .descr = "Winbond 83627HF/F/HG/G Rev. UD-A", 177 }, 178 { 179 .vendor_id = 0x5ca3, 180 .device_id = 0xa0, 181 .device_rev = 0x25, 182 .descr = "Winbond 83627DHG IC ver. 5", 183 }, 184 { 185 .vendor_id = 0x5ca3, 186 .device_id = 0xb0, 187 .device_rev = 0x73, 188 .descr = "Winbond 83627DHG-P", 189 }, 190 }; 191 192 /* 193 * Return the watchdog related registers as we last read them. This will 194 * usually not give the current timeout or state on whether the watchdog 195 * fired. 196 */ 197 static int 198 sysctl_wb_debug(SYSCTL_HANDLER_ARGS) 199 { 200 struct wb_softc *sc; 201 struct sbuf sb; 202 int error; 203 204 sc = arg1; 205 206 sbuf_new_for_sysctl(&sb, NULL, 64, req); 207 208 sbuf_printf(&sb, "LDN8 (GPIO2, Watchdog): "); 209 sbuf_printf(&sb, "CRF5 0x%02x ", sc->reg_1); 210 sbuf_printf(&sb, "CRF6 0x%02x ", sc->reg_timeout); 211 sbuf_printf(&sb, "CRF7 0x%02x ", sc->reg_2); 212 213 sbuf_trim(&sb); 214 error = sbuf_finish(&sb); 215 sbuf_delete(&sb); 216 return (error); 217 } 218 219 /* 220 * Read the current values before returning them. Given this might poke 221 * the registers the same time as the watchdog, this sysctl handler should 222 * be marked CTLFLAG_SKIP to not show up by default. 223 */ 224 static int 225 sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS) 226 { 227 struct wb_softc *sc; 228 229 sc = arg1; 230 231 /* 232 * Enter extended function mode in case someone else has been 233 * poking on the registers. We will not leave it though. 234 */ 235 if ((*sc->ext_cfg_enter_f)(sc) != 0) 236 return (ENXIO); 237 238 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 239 write_efir_1(sc, WB_LDN_REG); 240 write_efdr_1(sc, WB_LDN_REG_LDN8); 241 242 write_efir_1(sc, WB_LDN8_CRF5); 243 sc->reg_1 = read_efdr_1(sc); 244 write_efir_1(sc, WB_LDN8_CRF6); 245 sc->reg_timeout = read_efdr_1(sc); 246 write_efir_1(sc, WB_LDN8_CRF7); 247 sc->reg_2 = read_efdr_1(sc); 248 249 return (sysctl_wb_debug(oidp, arg1, arg2, req)); 250 } 251 252 /* 253 * Sysctl handlers to force a watchdog timeout or to test the NMI functionality 254 * works as expetced. 255 * For testing we could set a test_nmi flag in the softc that, in case of NMI, a 256 * callback function from trap.c could check whether we fired and not report the 257 * timeout but clear the flag for the sysctl again. This is interesting given a 258 * lot of boards have jumpers to change the action on watchdog timeout or 259 * disable the watchdog completely. 260 * XXX-BZ notyet: currently no general infrastructure exists to do this. 261 */ 262 static int 263 sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS) 264 { 265 struct wb_softc *sc; 266 int error, test, val; 267 268 sc = arg1; 269 test = arg2; 270 271 #ifdef notyet 272 val = sc->test_nmi; 273 #else 274 val = 0; 275 #endif 276 error = sysctl_handle_int(oidp, &val, 0, req); 277 if (error || !req->newptr) 278 return (error); 279 280 #ifdef notyet 281 /* Manually clear the test for a value of 0 and do nothing else. */ 282 if (test && val == 0) { 283 sc->test_nmi = 0; 284 return (0); 285 } 286 #endif 287 288 /* 289 * Enter extended function mode in case someone else has been 290 * poking on the registers. We will not leave it though. 291 */ 292 if ((*sc->ext_cfg_enter_f)(sc) != 0) 293 return (ENXIO); 294 295 #ifdef notyet 296 /* 297 * If we are testing the NMI functionality, set the flag before 298 * forcing the timeout. 299 */ 300 if (test) 301 sc->test_nmi = 1; 302 #endif 303 304 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 305 write_efir_1(sc, WB_LDN_REG); 306 write_efdr_1(sc, WB_LDN_REG_LDN8); 307 308 /* Force watchdog to fire. */ 309 write_efir_1(sc, WB_LDN8_CRF7); 310 sc->reg_2 = read_efdr_1(sc); 311 sc->reg_2 |= WB_LDN8_CRF7_FORCE; 312 313 write_efir_1(sc, WB_LDN8_CRF7); 314 write_efdr_1(sc, sc->reg_2); 315 316 return (0); 317 } 318 319 /* 320 * Print current watchdog state. 321 * 322 * Note: it is the responsibility of the caller to update the registers 323 * upfront. 324 */ 325 static void 326 wb_print_state(struct wb_softc *sc, const char *msg) 327 { 328 329 device_printf(sc->dev, "%s%sWatchdog %sabled. %s" 330 "Scaling by %ds, timer at %d (%s=%ds%s). " 331 "CRF5 0x%02x CRF7 0x%02x\n", 332 (msg != NULL) ? msg : "", (msg != NULL) ? ": " : "", 333 (sc->reg_timeout > 0x00) ? "en" : "dis", 334 (sc->reg_2 & WB_LDN8_CRF7_TS) ? "Watchdog fired. " : "", 335 (sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1, 336 sc->reg_timeout, 337 (sc->reg_timeout > 0x00) ? "<" : "", 338 sc->reg_timeout * ((sc->reg_1 & WB_LDN8_CRF5_SCALE) ? 60 : 1), 339 (sc->reg_timeout > 0x00) ? " left" : "", 340 sc->reg_1, sc->reg_2); 341 } 342 343 /* 344 * Functions to enter and exit extended function mode. Possibly shared 345 * between different chips. 346 */ 347 static int 348 ext_cfg_enter_0x87_0x87(struct wb_softc *sc) 349 { 350 351 /* 352 * Enable extended function mode. 353 * Winbond does not allow us to validate so always return success. 354 */ 355 write_efir_1(sc, 0x87); 356 write_efir_1(sc, 0x87); 357 358 return (0); 359 } 360 361 static void 362 ext_cfg_exit_0xaa(struct wb_softc *sc) 363 { 364 365 write_efir_1(sc, 0xaa); 366 } 367 368 /* 369 * (Re)load the watchdog counter depending on timeout. A timeout of 0 will 370 * disable the watchdog. 371 */ 372 static int 373 wb_set_watchdog(struct wb_softc *sc, unsigned int timeout) 374 { 375 376 if (sc->debug_verbose) 377 wb_print_state(sc, "Before watchdog counter (re)load"); 378 379 /* 380 * Enter extended function mode in case someone else has been 381 * poking on the registers. We will not leave it though. 382 */ 383 if ((*sc->ext_cfg_enter_f)(sc) != 0) 384 return (ENXIO); 385 386 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */ 387 write_efir_1(sc, WB_LDN_REG); 388 write_efdr_1(sc, WB_LDN_REG_LDN8); 389 390 /* Disable and validate or arm/reset watchdog. */ 391 if (timeout == 0) { 392 /* Disable watchdog. */ 393 write_efir_1(sc, WB_LDN8_CRF6); 394 write_efdr_1(sc, 0x00); 395 396 /* Re-check. */ 397 write_efir_1(sc, WB_LDN8_CRF6); 398 sc->reg_timeout = read_efdr_1(sc); 399 400 if (sc->reg_timeout != 0x00) { 401 device_printf(sc->dev, "Failed to disable watchdog: " 402 "0x%02x.\n", sc->reg_timeout); 403 return (EIO); 404 } 405 406 } else { 407 /* 408 * In case an override is set, let it override. It may lead 409 * to strange results as we do not check the input of the sysctl. 410 */ 411 if (sc->timeout_override > 0) 412 timeout = sc->timeout_override; 413 414 /* Make sure we support the requested timeout. */ 415 if (timeout > 255 * 60) 416 return (EINVAL); 417 418 /* Read current scaling factor. */ 419 write_efir_1(sc, WB_LDN8_CRF5); 420 sc->reg_1 = read_efdr_1(sc); 421 422 if (timeout > 255) { 423 /* Set scaling factor to 60s. */ 424 sc->reg_1 |= WB_LDN8_CRF5_SCALE; 425 sc->reg_timeout = (timeout / 60); 426 if (timeout % 60) 427 sc->reg_timeout++; 428 } else { 429 /* Set scaling factor to 1s. */ 430 sc->reg_1 &= ~WB_LDN8_CRF5_SCALE; 431 sc->reg_timeout = timeout; 432 } 433 434 /* In case we fired before we need to clear to fire again. */ 435 write_efir_1(sc, WB_LDN8_CRF7); 436 sc->reg_2 = read_efdr_1(sc); 437 if (sc->reg_2 & WB_LDN8_CRF7_TS) { 438 sc->reg_2 &= ~WB_LDN8_CRF7_TS; 439 write_efir_1(sc, WB_LDN8_CRF7); 440 write_efdr_1(sc, sc->reg_2); 441 } 442 443 /* Write back scaling factor. */ 444 write_efir_1(sc, WB_LDN8_CRF5); 445 write_efdr_1(sc, sc->reg_1); 446 447 /* Set timer and arm/reset the watchdog. */ 448 write_efir_1(sc, WB_LDN8_CRF6); 449 write_efdr_1(sc, sc->reg_timeout); 450 } 451 452 if (sc->debug_verbose) 453 wb_print_state(sc, "After watchdog counter (re)load"); 454 455 return (0); 456 } 457 458 /* 459 * watchdog(9) EVENTHANDLER function implementation to (re)load the counter 460 * with the given timeout or disable the watchdog. 461 */ 462 static void 463 wb_watchdog_fn(void *private, u_int cmd, int *error) 464 { 465 struct wb_softc *sc; 466 unsigned int timeout; 467 int e; 468 469 sc = private; 470 KASSERT(sc != NULL, ("%s: watchdog handler function called without " 471 "softc.", __func__)); 472 473 cmd &= WD_INTERVAL; 474 if (cmd > 0 && cmd <= 63) { 475 /* Reset (and arm) watchdog. */ 476 timeout = ((uint64_t)1 << cmd) / 1000000000; 477 if (timeout == 0) 478 timeout = 1; 479 e = wb_set_watchdog(sc, timeout); 480 if (e == 0) { 481 if (error != NULL) 482 *error = 0; 483 } else { 484 /* On error, try to make sure the WD is disabled. */ 485 wb_set_watchdog(sc, 0); 486 } 487 488 } else { 489 /* Disable watchdog. */ 490 e = wb_set_watchdog(sc, 0); 491 if (e != 0 && cmd == 0 && error != NULL) { 492 /* Failed to disable watchdog. */ 493 *error = EOPNOTSUPP; 494 } 495 } 496 } 497 498 /* 499 * Probe/attach the Winbond Super I/O chip. 500 * 501 * Initial abstraction to possibly support more chips: 502 * - Iterate over the well known base ports, try to enable extended function 503 * mode and read and match the device ID and device revision. Unfortunately 504 * the Vendor ID is in the hardware monitoring section accessible by different 505 * base ports only. 506 * - Also HEFRAS, which would tell use the base port, is only accessible after 507 * entering extended function mode, for which the base port is needed. 508 * At least check HEFRAS to match the current base port we are probing. 509 * - On match set the description, remember functions to enter/exit extended 510 * function mode as well as the base port. 511 */ 512 static int 513 wb_probe_enable(device_t dev, int probe) 514 { 515 struct wb_softc *sc; 516 int error, found, i, j; 517 uint8_t dev_id, dev_rev, cr26; 518 519 sc = device_get_softc(dev); 520 bzero(sc, sizeof(*sc)); 521 sc->dev = dev; 522 523 error = ENXIO; 524 for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) { 525 526 /* Allocate bus resources for IO index/data register access. */ 527 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 528 probe_addrs[i].efer, probe_addrs[i].efer + 1, 2, RF_ACTIVE); 529 if (sc->portres == NULL) 530 continue; 531 sc->bst = rman_get_bustag(sc->portres); 532 sc->bsh = rman_get_bushandle(sc->portres); 533 534 found = 0; 535 error = (*probe_addrs[i].ext_cfg_enter_f)(sc); 536 if (error != 0) 537 goto cleanup; 538 539 /* Identify the SuperIO chip. */ 540 write_efir_1(sc, WB_DEVICE_ID_REG); 541 dev_id = read_efdr_1(sc); 542 write_efir_1(sc, WB_DEVICE_REV_REG); 543 dev_rev = read_efdr_1(sc); 544 write_efir_1(sc, WB_CR26); 545 cr26 = read_efdr_1(sc); 546 547 /* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */ 548 if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) || 549 ((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) { 550 device_printf(dev, "HEFRAS and EFER do not align: EFER " 551 "0x%02x DevID 0x%02x DevRev 0x%02x CR26 0x%02x\n", 552 probe_addrs[i].efer, dev_id, dev_rev, cr26); 553 goto cleanup; 554 } 555 556 for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) { 557 if (wb_devs[j].device_id == dev_id && 558 wb_devs[j].device_rev == dev_rev) { 559 if (probe) 560 device_set_desc(dev, wb_devs[j].descr); 561 found++; 562 break; 563 } 564 } 565 if (probe && found && bootverbose) 566 device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x" 567 " CR26 0x%02x (probing)\n", device_get_desc(dev), 568 probe_addrs[i].efer, dev_id, dev_rev, cr26); 569 cleanup: 570 if (probe || !found) { 571 (*probe_addrs[i].ext_cfg_exit_f)(sc); 572 573 (void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, 574 sc->portres); 575 } 576 577 /* 578 * Stop probing if have successfully identified the SuperIO. 579 * Remember the extended function mode enter/exit functions 580 * for operations. 581 */ 582 if (found) { 583 sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f; 584 sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f; 585 error = BUS_PROBE_DEFAULT; 586 break; 587 } else 588 error = ENXIO; 589 } 590 591 return (error); 592 } 593 594 static int 595 wb_probe(device_t dev) 596 { 597 598 /* Make sure we do not claim some ISA PNP device. */ 599 if (isa_get_logicalid(dev) != 0) 600 return (ENXIO); 601 602 return (wb_probe_enable(dev, 1)); 603 } 604 605 static int 606 wb_attach(device_t dev) 607 { 608 struct wb_softc *sc; 609 struct sysctl_ctx_list *sctx; 610 struct sysctl_oid *soid; 611 unsigned long timeout; 612 int error; 613 614 error = wb_probe_enable(dev, 0); 615 if (error > 0) 616 return (ENXIO); 617 618 sc = device_get_softc(dev); 619 KASSERT(sc->ext_cfg_enter_f != NULL && sc->ext_cfg_exit_f != NULL, 620 ("%s: successfull probe result but not setup correctly", __func__)); 621 622 /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */ 623 write_efir_1(sc, WB_LDN_REG); 624 write_efdr_1(sc, WB_LDN_REG_LDN8); 625 626 /* Make sure LDN8 is enabled (Do we need to? Also affects GPIO). */ 627 write_efir_1(sc, WB_LDN8_CR30); 628 write_efdr_1(sc, WB_LDN8_CR30_ACTIVE); 629 630 /* Read the current watchdog configuration. */ 631 write_efir_1(sc, WB_LDN8_CRF5); 632 sc->reg_1 = read_efdr_1(sc); 633 write_efir_1(sc, WB_LDN8_CRF6); 634 sc->reg_timeout = read_efdr_1(sc); 635 write_efir_1(sc, WB_LDN8_CRF7); 636 sc->reg_2 = read_efdr_1(sc); 637 638 /* Print current state if bootverbose or watchdog already enabled. */ 639 if (bootverbose || (sc->reg_timeout > 0x00)) 640 wb_print_state(sc, "Before watchdog attach"); 641 642 /* 643 * Clear a previous watchdog timeout event (if (still) set). 644 * Disable all all interrupt reset sources (defaults). 645 */ 646 sc->reg_1 &= ~(WB_LDN8_CRF5_KEYB_P20); 647 sc->reg_1 |= WB_LDN8_CRF5_KBRST; 648 write_efir_1(sc, WB_LDN8_CRF5); 649 write_efdr_1(sc, sc->reg_1); 650 651 sc->reg_2 &= ~WB_LDN8_CRF7_CLEAR_MASK; 652 write_efir_1(sc, WB_LDN8_CRF7); 653 write_efdr_1(sc, sc->reg_2); 654 655 /* Read global timeout override tunable, Add per device sysctls. */ 656 if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) { 657 if (timeout > 0) 658 sc->timeout_override = timeout; 659 } 660 sctx = device_get_sysctl_ctx(dev); 661 soid = device_get_sysctl_tree(dev); 662 SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 663 "timeout_override", CTLFLAG_RW, &sc->timeout_override, 0, 664 "Timeout in seconds overriding default watchdog timeout"); 665 SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, 666 "debug_verbose", CTLFLAG_RW, &sc->debug_verbose, 0, 667 "Enables extra debugging information"); 668 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug", 669 CTLTYPE_STRING|CTLFLAG_RD, sc, 0, sysctl_wb_debug, "A", 670 "Selected register information from last change by driver"); 671 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug_current", 672 CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_SKIP, sc, 0, 673 sysctl_wb_debug_current, "A", 674 "Selected register information (may interfere)"); 675 SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "force_timeout", 676 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_SKIP, sc, 0, 677 sysctl_wb_force_test_nmi, "I", "Enable to force watchdog to fire."); 678 679 /* Register watchdog. */ 680 sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, wb_watchdog_fn, sc, 681 0); 682 683 if (bootverbose) 684 wb_print_state(sc, "After watchdog attach"); 685 686 return (0); 687 } 688 689 static int 690 wb_detach(device_t dev) 691 { 692 struct wb_softc *sc; 693 694 sc = device_get_softc(dev); 695 696 /* Unregister and stop the watchdog if running. */ 697 if (sc->ev_tag) 698 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag); 699 wb_set_watchdog(sc, 0); 700 701 /* Disable extended function mode. */ 702 (*sc->ext_cfg_exit_f)(sc); 703 704 /* Cleanup resources. */ 705 (void) bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); 706 707 /* Bus subroutines take care of sysctls already. */ 708 709 return (0); 710 } 711 712 static device_method_t wb_methods[] = { 713 /* Device interface */ 714 DEVMETHOD(device_probe, wb_probe), 715 DEVMETHOD(device_attach, wb_attach), 716 DEVMETHOD(device_detach, wb_detach), 717 718 { 0, 0 } 719 }; 720 721 static driver_t wb_isa_driver = { 722 "wbwd", 723 wb_methods, 724 sizeof(struct wb_softc) 725 }; 726 727 static devclass_t wb_devclass; 728 729 DRIVER_MODULE(wb, isa, wb_isa_driver, wb_devclass, NULL, NULL); 730