1 /* $NetBSD: obio.c,v 1.46 2018/06/08 23:39:31 macallan Exp $ */ 2 3 /*- 4 * Copyright (C) 1998 Internet Research Institute, Inc. 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by 18 * Internet Research Institute, Inc. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.46 2018/06/08 23:39:31 macallan Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/sysctl.h> 42 43 #include <dev/pci/pcivar.h> 44 #include <dev/pci/pcidevs.h> 45 46 #include <dev/ofw/openfirm.h> 47 48 #include <machine/autoconf.h> 49 50 #include <macppc/dev/obiovar.h> 51 52 #include <powerpc/cpu.h> 53 #include <sys/cpufreq.h> 54 55 #include "opt_obio.h" 56 57 #ifdef OBIO_DEBUG 58 # define DPRINTF printf 59 #else 60 # define DPRINTF while (0) printf 61 #endif 62 63 static void obio_attach(device_t, device_t, void *); 64 static int obio_match(device_t, cfdata_t, void *); 65 static int obio_print(void *, const char *); 66 67 struct obio_softc { 68 device_t sc_dev; 69 bus_space_tag_t sc_tag; 70 bus_space_handle_t sc_bh; 71 int sc_node; 72 #ifdef OBIO_SPEED_CONTROL 73 int sc_voltage; 74 int sc_busspeed; 75 int sc_spd_hi, sc_spd_lo; 76 struct cpufreq sc_cf; 77 #endif 78 }; 79 80 static struct obio_softc *obio0 = NULL; 81 82 #ifdef OBIO_SPEED_CONTROL 83 static void obio_setup_gpios(struct obio_softc *, int); 84 static void obio_set_cpu_speed(struct obio_softc *, int); 85 static int obio_get_cpu_speed(struct obio_softc *); 86 static int sysctl_cpuspeed_temp(SYSCTLFN_ARGS); 87 static int sysctl_cpuspeed_cur(SYSCTLFN_ARGS); 88 static int sysctl_cpuspeed_available(SYSCTLFN_ARGS); 89 static void obio_get_freq(void *, void *); 90 static void obio_set_freq(void *, void *); 91 static const char *keylargo[] = {"Keylargo", 92 "AAPL,Keylargo", 93 NULL}; 94 95 #endif 96 97 CFATTACH_DECL_NEW(obio, sizeof(struct obio_softc), 98 obio_match, obio_attach, NULL, NULL); 99 100 int 101 obio_match(device_t parent, cfdata_t cf, void *aux) 102 { 103 struct pci_attach_args *pa = aux; 104 105 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE) 106 switch (PCI_PRODUCT(pa->pa_id)) { 107 case PCI_PRODUCT_APPLE_GC: 108 case PCI_PRODUCT_APPLE_OHARE: 109 case PCI_PRODUCT_APPLE_HEATHROW: 110 case PCI_PRODUCT_APPLE_PADDINGTON: 111 case PCI_PRODUCT_APPLE_KEYLARGO: 112 case PCI_PRODUCT_APPLE_PANGEA_MACIO: 113 case PCI_PRODUCT_APPLE_INTREPID: 114 case PCI_PRODUCT_APPLE_K2: 115 case PCI_PRODUCT_APPLE_SHASTA: 116 return 1; 117 } 118 119 return 0; 120 } 121 122 /* 123 * Attach all the sub-devices we can find 124 */ 125 void 126 obio_attach(device_t parent, device_t self, void *aux) 127 { 128 struct obio_softc *sc = device_private(self); 129 struct pci_attach_args *pa = aux; 130 struct confargs ca; 131 bus_space_handle_t bsh; 132 int node, child, namelen, error; 133 u_int reg[20]; 134 int intr[6], parent_intr = 0, parent_nintr = 0; 135 int map_size = 0x1000; 136 char name[32]; 137 char compat[32]; 138 139 sc->sc_dev = self; 140 #ifdef OBIO_SPEED_CONTROL 141 sc->sc_voltage = -1; 142 sc->sc_busspeed = -1; 143 sc->sc_spd_lo = 600; 144 sc->sc_spd_hi = 800; 145 #endif 146 147 switch (PCI_PRODUCT(pa->pa_id)) { 148 149 case PCI_PRODUCT_APPLE_GC: 150 case PCI_PRODUCT_APPLE_OHARE: 151 case PCI_PRODUCT_APPLE_HEATHROW: 152 case PCI_PRODUCT_APPLE_PADDINGTON: 153 case PCI_PRODUCT_APPLE_KEYLARGO: 154 case PCI_PRODUCT_APPLE_PANGEA_MACIO: 155 case PCI_PRODUCT_APPLE_INTREPID: 156 node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag); 157 if (node == -1) 158 node = OF_finddevice("mac-io"); 159 if (node == -1) 160 node = OF_finddevice("/pci/mac-io"); 161 break; 162 case PCI_PRODUCT_APPLE_K2: 163 case PCI_PRODUCT_APPLE_SHASTA: 164 node = OF_finddevice("mac-io"); 165 map_size = 0x10000; 166 break; 167 168 default: 169 node = -1; 170 break; 171 } 172 if (node == -1) 173 panic("macio not found or unknown"); 174 175 sc->sc_node = node; 176 177 #if defined (PMAC_G5) 178 if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 20) 179 { 180 return; 181 } 182 #else 183 if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 12) 184 return; 185 #endif /* PMAC_G5 */ 186 187 /* 188 * XXX 189 * This relies on the primary obio always attaching first which is 190 * true on the PowerBook 3400c and similar machines but may or may 191 * not work on others. We can't rely on the node name since Apple 192 * didn't follow anything remotely resembling a consistent naming 193 * scheme. 194 */ 195 if (obio0 == NULL) 196 obio0 = sc; 197 198 ca.ca_baseaddr = reg[2]; 199 ca.ca_tag = pa->pa_memt; 200 sc->sc_tag = pa->pa_memt; 201 error = bus_space_map (pa->pa_memt, ca.ca_baseaddr, map_size, 0, &bsh); 202 if (error) 203 panic(": failed to map mac-io %#x", ca.ca_baseaddr); 204 sc->sc_bh = bsh; 205 206 printf(": addr 0x%x\n", ca.ca_baseaddr); 207 208 /* Enable internal modem (KeyLargo) */ 209 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_KEYLARGO) { 210 aprint_normal("%s: enabling KeyLargo internal modem\n", 211 device_xname(self)); 212 bus_space_write_4(ca.ca_tag, bsh, 0x40, 213 bus_space_read_4(ca.ca_tag, bsh, 0x40) & ~(1<<25)); 214 } 215 216 /* Enable internal modem (Pangea) */ 217 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) { 218 /* set reset */ 219 bus_space_write_1(ca.ca_tag, bsh, 0x006a + 0x03, 0x04); 220 /* power modem on */ 221 bus_space_write_1(ca.ca_tag, bsh, 0x006a + 0x02, 0x04); 222 /* unset reset */ 223 bus_space_write_1(ca.ca_tag, bsh, 0x006a + 0x03, 0x05); 224 } 225 226 /* Gatwick and Paddington use same product ID */ 227 namelen = OF_getprop(node, "compatible", compat, sizeof(compat)); 228 229 if (strcmp(compat, "gatwick") == 0) { 230 parent_nintr = OF_getprop(node, "AAPL,interrupts", intr, 231 sizeof(intr)); 232 parent_intr = intr[0]; 233 } else { 234 /* Enable CD and microphone sound input. */ 235 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_PADDINGTON) 236 bus_space_write_1(ca.ca_tag, bsh, 0x37, 0x03); 237 } 238 239 for (child = OF_child(node); child; child = OF_peer(child)) { 240 namelen = OF_getprop(child, "name", name, sizeof(name)); 241 if (namelen < 0) 242 continue; 243 if (namelen >= sizeof(name)) 244 continue; 245 246 #ifdef OBIO_SPEED_CONTROL 247 if (strcmp(name, "gpio") == 0) { 248 249 obio_setup_gpios(sc, child); 250 continue; 251 } 252 #endif 253 254 name[namelen] = 0; 255 ca.ca_name = name; 256 ca.ca_node = child; 257 ca.ca_tag = pa->pa_memt; 258 259 ca.ca_nreg = OF_getprop(child, "reg", reg, sizeof(reg)); 260 261 if (strcmp(compat, "gatwick") != 0) { 262 ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr, 263 sizeof(intr)); 264 if (ca.ca_nintr == -1) 265 ca.ca_nintr = OF_getprop(child, "interrupts", intr, 266 sizeof(intr)); 267 } else { 268 intr[0] = parent_intr; 269 ca.ca_nintr = parent_nintr; 270 } 271 ca.ca_reg = reg; 272 ca.ca_intr = intr; 273 274 config_found(self, &ca, obio_print); 275 } 276 } 277 278 static const char * const skiplist[] = { 279 "interrupt-controller", 280 "gpio", 281 "escc-legacy", 282 "timer", 283 "i2c", 284 "power-mgt", 285 "escc", 286 "battery", 287 "backlight" 288 289 }; 290 291 #define N_LIST (sizeof(skiplist) / sizeof(skiplist[0])) 292 293 int 294 obio_print(void *aux, const char *obio) 295 { 296 struct confargs *ca = aux; 297 int i; 298 299 for (i = 0; i < N_LIST; i++) 300 if (strcmp(ca->ca_name, skiplist[i]) == 0) 301 return QUIET; 302 303 if (obio) 304 aprint_normal("%s at %s", ca->ca_name, obio); 305 306 if (ca->ca_nreg > 0) 307 aprint_normal(" offset 0x%x", ca->ca_reg[0]); 308 309 return UNCONF; 310 } 311 312 void obio_write_4(int offset, uint32_t value) 313 { 314 if (obio0 == NULL) 315 return; 316 bus_space_write_4(obio0->sc_tag, obio0->sc_bh, offset, value); 317 } 318 319 void obio_write_1(int offset, uint8_t value) 320 { 321 if (obio0 == NULL) 322 return; 323 bus_space_write_1(obio0->sc_tag, obio0->sc_bh, offset, value); 324 } 325 326 uint32_t obio_read_4(int offset) 327 { 328 if (obio0 == NULL) 329 return 0xffffffff; 330 return bus_space_read_4(obio0->sc_tag, obio0->sc_bh, offset); 331 } 332 333 uint8_t obio_read_1(int offset) 334 { 335 if (obio0 == NULL) 336 return 0xff; 337 return bus_space_read_1(obio0->sc_tag, obio0->sc_bh, offset); 338 } 339 340 int 341 obio_space_map(bus_addr_t addr, bus_size_t size, bus_space_handle_t *bh) 342 { 343 if (obio0 == NULL) 344 return 0xff; 345 return bus_space_subregion(obio0->sc_tag, obio0->sc_bh, 346 addr & 0xfffff, size, bh); 347 } 348 349 #ifdef OBIO_SPEED_CONTROL 350 351 static void 352 obio_setup_cpufreq(device_t dev) 353 { 354 struct obio_softc *sc = device_private(dev); 355 int ret; 356 357 ret = cpufreq_register(&sc->sc_cf); 358 if (ret != 0) 359 aprint_error_dev(sc->sc_dev, "cpufreq_register() failed, error %d\n", ret); 360 } 361 362 static void 363 obio_setup_gpios(struct obio_softc *sc, int node) 364 { 365 uint32_t gpio_base, reg[6]; 366 const struct sysctlnode *sysctl_node, *me, *freq; 367 struct cpufreq *cf = &sc->sc_cf; 368 char name[32]; 369 int child, use_dfs, cpunode, hiclock; 370 371 if (of_compatible(sc->sc_node, keylargo) == -1) 372 return; 373 374 if (OF_getprop(node, "reg", reg, sizeof(reg)) < 4) 375 return; 376 377 gpio_base = reg[0]; 378 DPRINTF("gpio_base: %02x\n", gpio_base); 379 380 /* now look for voltage and bus speed gpios */ 381 use_dfs = 0; 382 for (child = OF_child(node); child; child = OF_peer(child)) { 383 384 if (OF_getprop(child, "name", name, sizeof(name)) < 1) 385 continue; 386 387 if (OF_getprop(child, "reg", reg, sizeof(reg)) < 4) 388 continue; 389 390 /* 391 * These register offsets either have to be added to the obio 392 * base address or to the gpio base address. This differs 393 * even in the same OF-tree! So we guess the offset is 394 * based on obio when it is larger than the gpio_base. 395 */ 396 if (reg[0] >= gpio_base) 397 reg[0] -= gpio_base; 398 399 if (strcmp(name, "frequency-gpio") == 0) { 400 DPRINTF("found frequency_gpio at %02x\n", reg[0]); 401 sc->sc_busspeed = gpio_base + reg[0]; 402 } 403 if (strcmp(name, "voltage-gpio") == 0) { 404 DPRINTF("found voltage_gpio at %02x\n", reg[0]); 405 sc->sc_voltage = gpio_base + reg[0]; 406 } 407 if (strcmp(name, "cpu-vcore-select") == 0) { 408 DPRINTF("found cpu-vcore-select at %02x\n", reg[0]); 409 sc->sc_voltage = gpio_base + reg[0]; 410 /* frequency gpio is not needed, we use cpu's DFS */ 411 use_dfs = 1; 412 } 413 } 414 415 if ((sc->sc_voltage < 0) || (sc->sc_busspeed < 0 && !use_dfs)) 416 return; 417 418 printf("%s: enabling Intrepid CPU speed control\n", 419 device_xname(sc->sc_dev)); 420 421 sc->sc_spd_lo = curcpu()->ci_khz / 1000; 422 hiclock = 0; 423 cpunode = OF_finddevice("/cpus/@0"); 424 OF_getprop(cpunode, "clock-frequency", &hiclock, 4); 425 if (hiclock != 0) 426 sc->sc_spd_hi = (hiclock + 500000) / 1000000; 427 printf("hiclock: %d\n", sc->sc_spd_hi); 428 if (use_dfs) sc->sc_spd_lo = sc->sc_spd_hi / 2; 429 430 sysctl_node = NULL; 431 432 if (sysctl_createv(NULL, 0, NULL, 433 &me, 434 CTLFLAG_READWRITE, CTLTYPE_NODE, "intrepid", NULL, NULL, 435 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0) 436 printf("couldn't create 'intrepid' node\n"); 437 438 if (sysctl_createv(NULL, 0, NULL, 439 &freq, 440 CTLFLAG_READWRITE, CTLTYPE_NODE, "frequency", NULL, NULL, 441 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL) != 0) 442 printf("couldn't create 'frequency' node\n"); 443 444 if (sysctl_createv(NULL, 0, NULL, 445 &sysctl_node, 446 CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 447 CTLTYPE_INT, "target", "CPU speed", sysctl_cpuspeed_temp, 448 0, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 449 CTL_CREATE, CTL_EOL) == 0) { 450 } else 451 printf("couldn't create 'target' node\n"); 452 453 if (sysctl_createv(NULL, 0, NULL, 454 &sysctl_node, 455 CTLFLAG_READWRITE, 456 CTLTYPE_INT, "current", NULL, sysctl_cpuspeed_cur, 457 1, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 458 CTL_CREATE, CTL_EOL) == 0) { 459 } else 460 printf("couldn't create 'current' node\n"); 461 462 if (sysctl_createv(NULL, 0, NULL, 463 &sysctl_node, 464 CTLFLAG_READWRITE, 465 CTLTYPE_STRING, "available", NULL, sysctl_cpuspeed_available, 466 2, (void *)sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num, 467 CTL_CREATE, CTL_EOL) == 0) { 468 } else 469 printf("couldn't create 'available' node\n"); 470 printf("speed: %d\n", curcpu()->ci_khz); 471 472 /* support cpufreq */ 473 snprintf(cf->cf_name, CPUFREQ_NAME_MAX, "Intrepid"); 474 cf->cf_state[0].cfs_freq = sc->sc_spd_hi; 475 cf->cf_state[1].cfs_freq = sc->sc_spd_lo; 476 cf->cf_state_count = 2; 477 cf->cf_mp = FALSE; 478 cf->cf_cookie = sc; 479 cf->cf_get_freq = obio_get_freq; 480 cf->cf_set_freq = obio_set_freq; 481 /* 482 * XXX 483 * cpufreq_register() calls xc_broadcast() which relies on kthreads 484 * running so we need to postpone it 485 */ 486 config_interrupts(sc->sc_dev, obio_setup_cpufreq); 487 } 488 489 static void 490 obio_set_cpu_speed(struct obio_softc *sc, int fast) 491 { 492 493 if (sc->sc_voltage < 0) 494 return; 495 496 if (sc->sc_busspeed >= 0) { 497 /* set voltage and speed via gpio */ 498 if (fast) { 499 bus_space_write_1(sc->sc_tag, sc->sc_bh, 500 sc->sc_voltage, 5); 501 bus_space_write_1(sc->sc_tag, sc->sc_bh, 502 sc->sc_busspeed, 5); 503 } else { 504 bus_space_write_1(sc->sc_tag, sc->sc_bh, 505 sc->sc_busspeed, 4); 506 bus_space_write_1(sc->sc_tag, sc->sc_bh, 507 sc->sc_voltage, 4); 508 } 509 } 510 else { 511 /* set voltage via gpio and speed via the 7447A's DFS bit */ 512 if (fast) { 513 bus_space_write_1(sc->sc_tag, sc->sc_bh, 514 sc->sc_voltage, 5); 515 DELAY(1000); 516 } 517 518 /* set DFS for all cpus */ 519 cpu_set_dfs(fast ? 1 : 2); 520 DELAY(100); 521 522 if (!fast) { 523 bus_space_write_1(sc->sc_tag, sc->sc_bh, 524 sc->sc_voltage, 4); 525 DELAY(1000); 526 } 527 } 528 } 529 530 static int 531 obio_get_cpu_speed(struct obio_softc *sc) 532 { 533 534 if (sc->sc_voltage < 0) 535 return 0; 536 537 if (sc->sc_busspeed >= 0) { 538 if (bus_space_read_1(sc->sc_tag, sc->sc_bh, sc->sc_busspeed) 539 & 1) 540 return 1; 541 } 542 else 543 return cpu_get_dfs() == 1; 544 545 return 0; 546 } 547 548 static void 549 obio_get_freq(void *cookie, void *spd) 550 { 551 struct obio_softc *sc = cookie; 552 uint32_t *freq; 553 554 freq = spd; 555 if (obio_get_cpu_speed(sc) == 0) { 556 *freq = sc->sc_spd_lo; 557 } else 558 *freq = sc->sc_spd_hi; 559 } 560 561 static void 562 obio_set_freq(void *cookie, void *spd) 563 { 564 struct obio_softc *sc = cookie; 565 uint32_t *freq; 566 567 freq = spd; 568 if (*freq == sc->sc_spd_lo) { 569 obio_set_cpu_speed(sc, 0); 570 } else if (*freq == sc->sc_spd_hi) { 571 obio_set_cpu_speed(sc, 1); 572 } else 573 aprint_error_dev(sc->sc_dev, "%s(%d) bogus CPU speed\n", __func__, *freq); 574 } 575 576 static int 577 sysctl_cpuspeed_temp(SYSCTLFN_ARGS) 578 { 579 struct sysctlnode node = *rnode; 580 struct obio_softc *sc = node.sysctl_data; 581 int speed, mhz; 582 583 speed = obio_get_cpu_speed(sc); 584 switch (speed) { 585 case 0: 586 mhz = sc->sc_spd_lo; 587 break; 588 case 1: 589 mhz = sc->sc_spd_hi; 590 break; 591 default: 592 speed = -1; 593 } 594 node.sysctl_data = &mhz; 595 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { 596 int new_reg; 597 598 new_reg = *(int *)node.sysctl_data; 599 if (new_reg == sc->sc_spd_lo) { 600 obio_set_cpu_speed(sc, 0); 601 } else if (new_reg == sc->sc_spd_hi) { 602 obio_set_cpu_speed(sc, 1); 603 } else { 604 printf("%s: new_reg %d\n", __func__, new_reg); 605 return EINVAL; 606 } 607 return 0; 608 } 609 return EINVAL; 610 } 611 612 static int 613 sysctl_cpuspeed_cur(SYSCTLFN_ARGS) 614 { 615 struct sysctlnode node = *rnode; 616 struct obio_softc *sc = node.sysctl_data; 617 int speed, mhz; 618 619 speed = obio_get_cpu_speed(sc); 620 switch (speed) { 621 case 0: 622 mhz = sc->sc_spd_lo; 623 break; 624 case 1: 625 mhz = sc->sc_spd_hi; 626 break; 627 default: 628 speed = -1; 629 } 630 node.sysctl_data = &mhz; 631 return sysctl_lookup(SYSCTLFN_CALL(&node)); 632 } 633 634 static int 635 sysctl_cpuspeed_available(SYSCTLFN_ARGS) 636 { 637 struct sysctlnode node = *rnode; 638 struct obio_softc *sc = node.sysctl_data; 639 char buf[128]; 640 641 snprintf(buf, 128, "%d %d", sc->sc_spd_lo, sc->sc_spd_hi); 642 node.sysctl_data = buf; 643 return(sysctl_lookup(SYSCTLFN_CALL(&node))); 644 } 645 646 SYSCTL_SETUP(sysctl_ams_setup, "sysctl obio subtree setup") 647 { 648 649 sysctl_createv(NULL, 0, NULL, NULL, 650 CTLFLAG_PERMANENT, 651 CTLTYPE_NODE, "machdep", NULL, 652 NULL, 0, NULL, 0, 653 CTL_MACHDEP, CTL_EOL); 654 } 655 656 #endif /* OBIO_SPEEDCONTROL */ 657