1 /* $NetBSD: ug.c,v 1.11 2008/03/26 16:09:37 xtraeme Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Mihai Chelaru <kefren@netbsd.ro> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: ug.c,v 1.11 2008/03/26 16:09:37 xtraeme Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/proc.h> 35 #include <sys/device.h> 36 #include <sys/malloc.h> 37 #include <sys/errno.h> 38 #include <sys/conf.h> 39 #include <sys/envsys.h> 40 #include <sys/time.h> 41 42 #include <sys/bus.h> 43 #include <sys/intr.h> 44 45 #include <dev/isa/isareg.h> 46 #include <dev/isa/isavar.h> 47 48 #include <dev/sysmon/sysmonvar.h> 49 50 #include <dev/ic/ugreg.h> 51 #include <dev/ic/ugvar.h> 52 53 uint8_t ug_ver; 54 55 /* 56 * Imported from linux driver 57 */ 58 59 struct ug2_motherboard_info ug2_mb[] = { 60 { 0x000C, "unknown. Please send-pr(1)", { 61 { "CPU Core", 0, 0, 10, 1, 0 }, 62 { "DDR", 1, 0, 10, 1, 0 }, 63 { "DDR VTT", 2, 0, 10, 1, 0 }, 64 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 65 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 66 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 67 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 68 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 69 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 70 { "ATX +5V", 9, 0, 30, 1, 0 }, 71 { "+3.3V", 10, 0, 20, 1, 0 }, 72 { "5VSB", 11, 0, 30, 1, 0 }, 73 { "CPU", 24, 1, 1, 1, 0 }, 74 { "System", 25, 1, 1, 1, 0 }, 75 { "PWM", 26, 1, 1, 1, 0 }, 76 { "CPU Fan", 32, 2, 60, 1, 0 }, 77 { "NB Fan", 33, 2, 60, 1, 0 }, 78 { "SYS FAN", 34, 2, 60, 1, 0 }, 79 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 80 { NULL, 0, 0, 0, 0, 0 } } 81 }, 82 { 0x000D, "Abit AW8", { 83 { "CPU Core", 0, 0, 10, 1, 0 }, 84 { "DDR", 1, 0, 10, 1, 0 }, 85 { "DDR VTT", 2, 0, 10, 1, 0 }, 86 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 87 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 88 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 89 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 90 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 91 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 92 { "ATX +5V", 9, 0, 30, 1, 0 }, 93 { "+3.3V", 10, 0, 20, 1, 0 }, 94 { "5VSB", 11, 0, 30, 1, 0 }, 95 { "CPU", 24, 1, 1, 1, 0 }, 96 { "System", 25, 1, 1, 1, 0 }, 97 { "PWM1", 26, 1, 1, 1, 0 }, 98 { "PWM2", 27, 1, 1, 1, 0 }, 99 { "PWM3", 28, 1, 1, 1, 0 }, 100 { "PWM4", 29, 1, 1, 1, 0 }, 101 { "CPU Fan", 32, 2, 60, 1, 0 }, 102 { "NB Fan", 33, 2, 60, 1, 0 }, 103 { "SYS Fan", 34, 2, 60, 1, 0 }, 104 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 105 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 106 { "AUX3 Fan", 37, 2, 60, 1, 0 }, 107 { "AUX4 Fan", 38, 2, 60, 1, 0 }, 108 { "AUX5 Fan", 39, 2, 60, 1, 0 }, 109 { NULL, 0, 0, 0, 0, 0 } } 110 }, 111 { 0x000E, "Abit AL8", { 112 { "CPU Core", 0, 0, 10, 1, 0 }, 113 { "DDR", 1, 0, 10, 1, 0 }, 114 { "DDR VTT", 2, 0, 10, 1, 0 }, 115 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 116 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 117 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 118 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 119 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 120 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 121 { "ATX +5V", 9, 0, 30, 1, 0 }, 122 { "+3.3V", 10, 0, 20, 1, 0 }, 123 { "5VSB", 11, 0, 30, 1, 0 }, 124 { "CPU", 24, 1, 1, 1, 0 }, 125 { "System", 25, 1, 1, 1, 0 }, 126 { "PWM", 26, 1, 1, 1, 0 }, 127 { "CPU Fan", 32, 2, 60, 1, 0 }, 128 { "NB Fan", 33, 2, 60, 1, 0 }, 129 { "SYS Fan", 34, 2, 60, 1, 0 }, 130 { NULL, 0, 0, 0, 0, 0 } } 131 }, 132 { 0x000F, "unknown. Please send-pr(1)", { 133 { "CPU Core", 0, 0, 10, 1, 0 }, 134 { "DDR", 1, 0, 10, 1, 0 }, 135 { "DDR VTT", 2, 0, 10, 1, 0 }, 136 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 137 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 138 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 139 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 140 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 141 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 142 { "ATX +5V", 9, 0, 30, 1, 0 }, 143 { "+3.3V", 10, 0, 20, 1, 0 }, 144 { "5VSB", 11, 0, 30, 1, 0 }, 145 { "CPU", 24, 1, 1, 1, 0 }, 146 { "System", 25, 1, 1, 1, 0 }, 147 { "PWM", 26, 1, 1, 1, 0 }, 148 { "CPU Fan", 32, 2, 60, 1, 0 }, 149 { "NB Fan", 33, 2, 60, 1, 0 }, 150 { "SYS Fan", 34, 2, 60, 1, 0 }, 151 { NULL, 0, 0, 0, 0, 0 } } 152 }, 153 { 0x0010, "Abit NI8 SLI GR", { 154 { "CPU Core", 0, 0, 10, 1, 0 }, 155 { "DDR", 1, 0, 10, 1, 0 }, 156 { "DDR VTT", 2, 0, 10, 1, 0 }, 157 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 158 { "NB 1.4V", 4, 0, 10, 1, 0 }, 159 { "SB 1.5V", 6, 0, 10, 1, 0 }, 160 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 161 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 162 { "ATX +5V", 9, 0, 30, 1, 0 }, 163 { "+3.3V", 10, 0, 20, 1, 0 }, 164 { "5VSB", 11, 0, 30, 1, 0 }, 165 { "CPU", 24, 1, 1, 1, 0 }, 166 { "SYS", 25, 1, 1, 1, 0 }, 167 { "PWM", 26, 1, 1, 1, 0 }, 168 { "CPU Fan", 32, 2, 60, 1, 0 }, 169 { "NB Fan", 33, 2, 60, 1, 0 }, 170 { "SYS Fan", 34, 2, 60, 1, 0 }, 171 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 172 { "OTES1 Fan", 36, 2, 60, 1, 0 }, 173 { NULL, 0, 0, 0, 0, 0 } } 174 }, 175 { 0x0011, "Abit AT8 32X", { 176 { "CPU Core", 0, 0, 10, 1, 0 }, 177 { "DDR", 1, 0, 20, 1, 0 }, 178 { "DDR VTT", 2, 0, 10, 1, 0 }, 179 { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 }, 180 { "NB 1.8V", 4, 0, 10, 1, 0 }, 181 { "NB 1.8V Dual", 5, 0, 10, 1, 0 }, 182 { "HTV 1.2", 3, 0, 10, 1, 0 }, 183 { "PCIE 1.2V", 12, 0, 10, 1, 0 }, 184 { "NB 1.2V", 13, 0, 10, 1, 0 }, 185 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 186 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 187 { "ATX +5V", 9, 0, 30, 1, 0 }, 188 { "+3.3V", 10, 0, 20, 1, 0 }, 189 { "5VSB", 11, 0, 30, 1, 0 }, 190 { "CPU", 24, 1, 1, 1, 0 }, 191 { "NB", 25, 1, 1, 1, 0 }, 192 { "System", 26, 1, 1, 1, 0 }, 193 { "PWM", 27, 1, 1, 1, 0 }, 194 { "CPU Fan", 32, 2, 60, 1, 0 }, 195 { "NB Fan", 33, 2, 60, 1, 0 }, 196 { "SYS Fan", 34, 2, 60, 1, 0 }, 197 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 198 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 199 { NULL, 0, 0, 0, 0, 0 } } 200 }, 201 { 0x0012, "unknown. Please send-pr(1)", { 202 { "CPU Core", 0, 0, 10, 1, 0 }, 203 { "DDR", 1, 0, 20, 1, 0 }, 204 { "DDR VTT", 2, 0, 10, 1, 0 }, 205 { "HyperTransport", 3, 0, 10, 1, 0 }, 206 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, 207 { "NB", 4, 0, 10, 1, 0 }, 208 { "SB", 6, 0, 10, 1, 0 }, 209 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 210 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 211 { "ATX +5V", 9, 0, 30, 1, 0 }, 212 { "+3.3V", 10, 0, 20, 1, 0 }, 213 { "5VSB", 11, 0, 30, 1, 0 }, 214 { "CPU", 24, 1, 1, 1, 0 }, 215 { "SYS", 25, 1, 1, 1, 0 }, 216 { "PWM", 26, 1, 1, 1, 0 }, 217 { "CPU Fan", 32, 2, 60, 1, 0 }, 218 { "NB Fan", 33, 2, 60, 1, 0 }, 219 { "SYS Fan", 34, 2, 60, 1, 0 }, 220 { "AUX1 Fan", 36, 2, 60, 1, 0 }, 221 { NULL, 0, 0, 0, 0, 0 } } 222 }, 223 { 0x0013, "unknown. Please send-pr(1)", { 224 { "CPU Core", 0, 0, 10, 1, 0 }, 225 { "DDR", 1, 0, 10, 1, 0 }, 226 { "DDR VTT", 2, 0, 10, 1, 0 }, 227 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 228 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 229 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 230 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 231 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 232 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 233 { "ATX +5V", 9, 0, 30, 1, 0 }, 234 { "+3.3V", 10, 0, 20, 1, 0 }, 235 { "5VSB", 11, 0, 30, 1, 0 }, 236 { "CPU", 24, 1, 1, 1, 0 }, 237 { "System", 25, 1, 1, 1, 0 }, 238 { "PWM1", 26, 1, 1, 1, 0 }, 239 { "PWM2", 27, 1, 1, 1, 0 }, 240 { "PWM3", 28, 1, 1, 1, 0 }, 241 { "PWM4", 29, 1, 1, 1, 0 }, 242 { "CPU Fan", 32, 2, 60, 1, 0 }, 243 { "NB Fan", 33, 2, 60, 1, 0 }, 244 { "SYS Fan", 34, 2, 60, 1, 0 }, 245 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 246 { "AUX2 Fan", 36, 2, 60, 1, 0 }, 247 { "AUX3 Fan", 37, 2, 60, 1, 0 }, 248 { "AUX4 Fan", 38, 2, 60, 1, 0 }, 249 { NULL, 0, 0, 0, 0, 0 } } 250 }, 251 { 0x0014, "Abit AB9 Pro", { 252 { "CPU Core", 0, 0, 10, 1, 0 }, 253 { "DDR", 1, 0, 10, 1, 0 }, 254 { "DDR VTT", 2, 0, 10, 1, 0 }, 255 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 256 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 257 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 258 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 259 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 260 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 261 { "ATX +5V", 9, 0, 30, 1, 0 }, 262 { "+3.3V", 10, 0, 20, 1, 0 }, 263 { "5VSB", 11, 0, 30, 1, 0 }, 264 { "CPU", 24, 1, 1, 1, 0 }, 265 { "System", 25, 1, 1, 1, 0 }, 266 { "PWM", 26, 1, 1, 1, 0 }, 267 { "CPU Fan", 32, 2, 60, 1, 0 }, 268 { "NB Fan", 33, 2, 60, 1, 0 }, 269 { "SYS Fan", 34, 2, 60, 1, 0 }, 270 { NULL, 0, 0, 0, 0, 0 } } 271 }, 272 { 0x0015, "unknown. Please send-pr(1)", { 273 { "CPU Core", 0, 0, 10, 1, 0 }, 274 { "DDR", 1, 0, 20, 1, 0 }, 275 { "DDR VTT", 2, 0, 10, 1, 0 }, 276 { "HyperTransport", 3, 0, 10, 1, 0 }, 277 { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, 278 { "NB", 4, 0, 10, 1, 0 }, 279 { "SB", 6, 0, 10, 1, 0 }, 280 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 281 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 282 { "ATX +5V", 9, 0, 30, 1, 0 }, 283 { "+3.3V", 10, 0, 20, 1, 0 }, 284 { "5VSB", 11, 0, 30, 1, 0 }, 285 { "CPU", 24, 1, 1, 1, 0 }, 286 { "SYS", 25, 1, 1, 1, 0 }, 287 { "PWM", 26, 1, 1, 1, 0 }, 288 { "CPU Fan", 32, 2, 60, 1, 0 }, 289 { "NB Fan", 33, 2, 60, 1, 0 }, 290 { "SYS Fan", 34, 2, 60, 1, 0 }, 291 { "AUX1 Fan", 33, 2, 60, 1, 0 }, 292 { "AUX2 Fan", 35, 2, 60, 1, 0 }, 293 { "AUX3 Fan", 36, 2, 60, 1, 0 }, 294 { NULL, 0, 0, 0, 0, 0 } } 295 }, 296 { 0x0016, "generic", { 297 { "CPU Core", 0, 0, 10, 1, 0 }, 298 { "DDR", 1, 0, 20, 1, 0 }, 299 { "DDR VTT", 2, 0, 10, 1, 0 }, 300 { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, 301 { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, 302 { "MCH 2.5V", 5, 0, 20, 1, 0 }, 303 { "ICH 1.05V", 6, 0, 10, 1, 0 }, 304 { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, 305 { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, 306 { "ATX +5V", 9, 0, 30, 1, 0 }, 307 { "+3.3V", 10, 0, 20, 1, 0 }, 308 { "5VSB", 11, 0, 30, 1, 0 }, 309 { "CPU", 24, 1, 1, 1, 0 }, 310 { "System", 25, 1, 1, 1, 0 }, 311 { "PWM", 26, 1, 1, 1, 0 }, 312 { "CPU Fan", 32, 2, 60, 1, 0 }, 313 { "NB Fan", 33, 2, 60, 1, 0 }, 314 { "SYS FAN", 34, 2, 60, 1, 0 }, 315 { "AUX1 Fan", 35, 2, 60, 1, 0 }, 316 { NULL, 0, 0, 0, 0, 0 } } 317 }, 318 { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } } 319 }; 320 321 322 int 323 ug_reset(struct ug_softc *sc) 324 { 325 int cnt = 0; 326 327 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) != 0x08) { 328 /* 8 meaning Voodoo */ 329 330 if (cnt++ > UG_DELAY_CYCLES) 331 return 0; 332 333 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0); 334 335 /* Wait for 0x09 at Data Port */ 336 if (!ug_waitfor(sc, UG_DATA, 0x09)) 337 return 0; 338 339 /* Wait for 0xAC at Cmd Port */ 340 if (!ug_waitfor(sc, UG_CMD, 0xAC)) 341 return 0; 342 } 343 344 return 1; 345 } 346 347 uint8_t 348 ug_read(struct ug_softc *sc, unsigned short sensor) 349 { 350 uint8_t bank, sens, rv; 351 352 bank = (sensor & 0xFF00) >> 8; 353 sens = sensor & 0x00FF; 354 355 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, bank); 356 357 /* Wait 8 at Data Port */ 358 if (!ug_waitfor(sc, UG_DATA, 8)) 359 return 0; 360 361 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, sens); 362 363 /* Wait 1 at Data Port */ 364 if (!ug_waitfor(sc, UG_DATA, 1)) 365 return 0; 366 367 /* Finally read the sensor */ 368 rv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD); 369 370 ug_reset(sc); 371 372 return rv; 373 } 374 375 int 376 ug_waitfor(struct ug_softc *sc, uint16_t offset, uint8_t value) 377 { 378 int cnt = 0; 379 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset) != value) { 380 if (cnt++ > UG_DELAY_CYCLES) 381 return 0; 382 } 383 return 1; 384 } 385 386 void 387 ug_setup_sensors(struct ug_softc *sc) 388 { 389 int i; 390 391 /* Setup Temps */ 392 for (i = 0; i < UG_VOLT_MIN; i++) 393 sc->sc_sensor[i].units = ENVSYS_STEMP; 394 395 #define COPYDESCR(x, y) \ 396 do { \ 397 strlcpy((x), (y), sizeof(x)); \ 398 } while (0) 399 400 COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp"); 401 COPYDESCR(sc->sc_sensor[1].desc, "SYS Temp"); 402 COPYDESCR(sc->sc_sensor[2].desc, "PWN Temp"); 403 404 /* Right, Now setup U sensors */ 405 406 for (i = UG_VOLT_MIN; i < UG_FAN_MIN; i++) { 407 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 408 sc->sc_sensor[i].rfact = UG_RFACT; 409 } 410 411 COPYDESCR(sc->sc_sensor[3].desc, "HTVdd"); 412 COPYDESCR(sc->sc_sensor[4].desc, "VCore"); 413 COPYDESCR(sc->sc_sensor[5].desc, "DDRVdd"); 414 COPYDESCR(sc->sc_sensor[6].desc, "Vdd3V3"); 415 COPYDESCR(sc->sc_sensor[7].desc, "Vdd5V"); 416 COPYDESCR(sc->sc_sensor[8].desc, "NBVdd"); 417 COPYDESCR(sc->sc_sensor[9].desc, "AGPVdd"); 418 COPYDESCR(sc->sc_sensor[10].desc, "DDRVtt"); 419 COPYDESCR(sc->sc_sensor[11].desc, "Vdd5VSB"); 420 COPYDESCR(sc->sc_sensor[12].desc, "Vdd3VDual"); 421 COPYDESCR(sc->sc_sensor[13].desc, "SBVdd"); 422 423 /* Fan sensors */ 424 for (i = UG_FAN_MIN; i < UG_NUM_SENSORS; i++) 425 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 426 427 COPYDESCR(sc->sc_sensor[14].desc, "CPU Fan"); 428 COPYDESCR(sc->sc_sensor[15].desc, "NB Fan"); 429 COPYDESCR(sc->sc_sensor[16].desc, "SYS Fan"); 430 COPYDESCR(sc->sc_sensor[17].desc, "AUX Fan 1"); 431 COPYDESCR(sc->sc_sensor[18].desc, "AUX Fan 2"); 432 } 433 434 void 435 ug_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 436 { 437 struct ug_softc *sc = sme->sme_cookie; 438 439 /* Sensors return C while we need uK */ 440 441 if (edata->sensor < UG_VOLT_MIN - 1) /* CPU and SYS Temps */ 442 edata->value_cur = ug_read(sc, UG_CPUTEMP + edata->sensor) 443 * 1000000 + 273150000; 444 else if (edata->sensor == 2) /* PWMTEMP */ 445 edata->value_cur = ug_read(sc, UG_PWMTEMP) 446 * 1000000 + 273150000; 447 448 /* Voltages */ 449 450 #define VOLT_SENSOR UG_HTV + edata->sensor - UG_VOLT_MIN 451 452 else 453 if ((edata->sensor >= UG_VOLT_MIN) && (edata->sensor < UG_FAN_MIN)) { 454 edata->value_cur = ug_read(sc, VOLT_SENSOR); 455 switch(VOLT_SENSOR) { 456 case UG_5V: /* 6V RFact */ 457 case UG_5VSB: 458 edata->value_cur *= UG_RFACT6; 459 break; 460 case UG_3V3: /* 4V RFact */ 461 case UG_3VDUAL: 462 edata->value_cur *= UG_RFACT4; 463 break; 464 default: /* 3V RFact */ 465 edata->value_cur *= UG_RFACT3; 466 break; 467 } 468 } else 469 470 #undef VOLT_SENSOR 471 472 /* and Fans */ 473 if (edata->sensor >= UG_FAN_MIN) 474 edata->value_cur = ug_read(sc, UG_CPUFAN + 475 edata->sensor - UG_FAN_MIN) * UG_RFACT_FAN; 476 } 477 478 void 479 ug2_attach(device_t dv) 480 { 481 struct ug_softc *sc = device_private(dv); 482 uint8_t buf[2]; 483 int i; 484 struct ug2_motherboard_info *ai; 485 struct ug2_sensor_info *si; 486 487 aprint_normal(": Abit uGuru 2005 system monitor\n"); 488 489 if (ug2_read(sc, UG2_MISC_BANK, UG2_BOARD_ID, 2, buf) != 2) { 490 aprint_error_dev(dv, "Cannot detect board ID. Using default\n"); 491 buf[0] = UG_MAX_MSB_BOARD; 492 buf[1] = UG_MAX_LSB_BOARD; 493 } 494 495 if (buf[0] > UG_MAX_MSB_BOARD || buf[1] > UG_MAX_LSB_BOARD || 496 buf[1] < UG_MIN_LSB_BOARD) { 497 aprint_error_dev(dv, "Invalid board ID(%X,%X). Using default\n", 498 buf[0], buf[1]); 499 buf[0] = UG_MAX_MSB_BOARD; 500 buf[1] = UG_MAX_LSB_BOARD; 501 } 502 503 ai = &ug2_mb[buf[1] - UG_MIN_LSB_BOARD]; 504 505 aprint_normal_dev(dv, "mainboard %s (%.2X%.2X)\n", 506 ai->name, buf[0], buf[1]); 507 508 sc->mbsens = (void*)ai->sensors; 509 sc->sc_sme = sysmon_envsys_create(); 510 511 for (i = 0, si = ai->sensors; si && si->name; si++, i++) { 512 COPYDESCR(sc->sc_sensor[i].desc, si->name); 513 sc->sc_sensor[i].rfact = 1; 514 sc->sc_sensor[i].state = ENVSYS_SVALID; 515 switch (si->type) { 516 case UG2_VOLTAGE_SENSOR: 517 sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; 518 sc->sc_sensor[i].rfact = UG_RFACT; 519 break; 520 case UG2_TEMP_SENSOR: 521 sc->sc_sensor[i].units = ENVSYS_STEMP; 522 break; 523 case UG2_FAN_SENSOR: 524 sc->sc_sensor[i].units = ENVSYS_SFANRPM; 525 break; 526 default: 527 break; 528 } 529 if (sysmon_envsys_sensor_attach(sc->sc_sme, 530 &sc->sc_sensor[i])) { 531 sysmon_envsys_destroy(sc->sc_sme); 532 return; 533 } 534 } 535 #undef COPYDESCR 536 537 sc->sc_sme->sme_name = device_xname(dv); 538 sc->sc_sme->sme_cookie = sc; 539 sc->sc_sme->sme_refresh = ug2_refresh; 540 541 if (sysmon_envsys_register(sc->sc_sme)) { 542 aprint_error_dev(dv, "unable to register with sysmon\n"); 543 sysmon_envsys_destroy(sc->sc_sme); 544 } 545 } 546 547 void 548 ug2_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 549 { 550 struct ug_softc *sc = sme->sme_cookie; 551 struct ug2_sensor_info *si = (struct ug2_sensor_info *)sc->mbsens; 552 int rfact = 1; 553 uint8_t v; 554 555 si += edata->sensor; 556 557 #define SENSOR_VALUE (v * si->multiplier * rfact / si->divisor + si->offset) 558 559 if (ug2_read(sc, UG2_SENSORS_BANK, UG2_VALUES_OFFSET + 560 si->port, 1, &v) == 1) { 561 switch (si->type) { 562 case UG2_TEMP_SENSOR: 563 edata->value_cur = SENSOR_VALUE * 1000000 564 + 273150000; 565 break; 566 case UG2_VOLTAGE_SENSOR: 567 rfact = UG_RFACT; 568 edata->value_cur = SENSOR_VALUE; 569 break; 570 default: 571 edata->value_cur = SENSOR_VALUE; 572 break; 573 } 574 } 575 #undef SENSOR_VALUE 576 } 577 578 int 579 ug2_wait_ready(struct ug_softc *sc) 580 { 581 int cnt = 0; 582 583 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x1a); 584 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) & 585 UG2_STATUS_BUSY) { 586 if (cnt++ > UG_DELAY_CYCLES) 587 return 0; 588 } 589 return 1; 590 } 591 592 int 593 ug2_wait_readable(struct ug_softc *sc) 594 { 595 int cnt = 0; 596 597 while (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) & 598 UG2_STATUS_READY_FOR_READ)) { 599 if (cnt++ > UG_DELAY_CYCLES) 600 return 0; 601 } 602 return 1; 603 } 604 605 int 606 ug2_sync(struct ug_softc *sc) 607 { 608 int cnt = 0; 609 610 #define UG2_WAIT_READY if(ug2_wait_ready(sc) == 0) return 0; 611 612 /* Don't sync two times in a row */ 613 if(ug_ver != 0) { 614 ug_ver = 0; 615 return 1; 616 } 617 618 UG2_WAIT_READY; 619 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x20); 620 UG2_WAIT_READY; 621 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, 0x10); 622 UG2_WAIT_READY; 623 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, 0x00); 624 UG2_WAIT_READY; 625 if (ug2_wait_readable(sc) == 0) 626 return 0; 627 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD) != 0xAC) 628 if (cnt++ > UG_DELAY_CYCLES) 629 return 0; 630 return 1; 631 } 632 633 int 634 ug2_read(struct ug_softc *sc, uint8_t bank, uint8_t offset, uint8_t count, 635 uint8_t *ret) 636 { 637 int i; 638 639 if (ug2_sync(sc) == 0) 640 return 0; 641 642 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x1A); 643 UG2_WAIT_READY; 644 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, bank); 645 UG2_WAIT_READY; 646 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, offset); 647 UG2_WAIT_READY; 648 bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, count); 649 UG2_WAIT_READY; 650 651 #undef UG2_WAIT_READY 652 653 /* Now wait for the results */ 654 for (i = 0; i < count; i++) { 655 if (ug2_wait_readable(sc) == 0) 656 break; 657 ret[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD); 658 } 659 660 return i; 661 } 662