root/dev/acpi/acpicpu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpicpu_set_throttle
  2. acpicpu_find_cstate
  3. acpicpu_add_cstate
  4. acpicpu_add_cstatepkg
  5. acpicpu_match
  6. acpicpu_attach
  7. acpicpu_getpct
  8. acpicpu_getpss
  9. acpicpu_fetch_pss
  10. acpicpu_notify
  11. acpicpu_set_notify
  12. acpicpu_setperf

    1 /* $OpenBSD: acpicpu.c,v 1.26 2007/06/15 22:37:40 gwk Exp $ */
    2 /*
    3  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
    4  *
    5  * Permission to use, copy, modify, and distribute this software for any
    6  * purpose with or without fee is hereby granted, provided that the above
    7  * copyright notice and this permission notice appear in all copies.
    8  *
    9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16  */
   17 
   18 #include <sys/param.h>
   19 #include <sys/proc.h>
   20 #include <sys/signalvar.h>
   21 #include <sys/sysctl.h>
   22 #include <sys/systm.h>
   23 #include <sys/device.h>
   24 #include <sys/malloc.h>
   25 #include <sys/queue.h>
   26 
   27 #include <machine/bus.h>
   28 #include <machine/cpu.h>
   29 #include <machine/cpufunc.h>
   30 #include <machine/specialreg.h>
   31 
   32 #include <dev/acpi/acpireg.h>
   33 #include <dev/acpi/acpivar.h>
   34 #include <dev/acpi/acpidev.h>
   35 #include <dev/acpi/amltypes.h>
   36 #include <dev/acpi/dsdt.h>
   37 
   38 #include <sys/sensors.h>
   39 
   40 int     acpicpu_match(struct device *, void *, void *);
   41 void    acpicpu_attach(struct device *, struct device *, void *);
   42 int     acpicpu_notify(struct aml_node *, int, void *);
   43 void    acpicpu_setperf(int);
   44 
   45 #define ACPI_STATE_C0           0x00
   46 #define ACPI_STATE_C1           0x01
   47 #define ACPI_STATE_C2           0x02
   48 #define ACPI_STATE_C3           0x03
   49 
   50 #define FLAGS_NO_C2             0x01
   51 #define FLAGS_NO_C3             0x02
   52 #define FLAGS_BMCHECK           0x04
   53 #define FLAGS_NOTHROTTLE        0x08
   54 #define FLAGS_NOPSS             0x10
   55 #define FLAGS_NOPCT             0x20
   56 
   57 #define CPU_THT_EN              (1L << 4)
   58 #define CPU_MAXSTATE(sc)        (1L << (sc)->sc_duty_wid)
   59 #define CPU_STATE(sc,pct)       ((pct * CPU_MAXSTATE(sc) / 100) << (sc)->sc_duty_off)
   60 #define CPU_STATEMASK(sc)       ((CPU_MAXSTATE(sc) - 1) << (sc)->sc_duty_off)
   61 
   62 #define ACPI_MAX_C2_LATENCY     100
   63 #define ACPI_MAX_C3_LATENCY     1000
   64 
   65 /* Make sure throttling bits are valid,a=addr,o=offset,w=width */
   66 #define valid_throttle(o,w,a) (a && w && (o+w)<=31 && (o>4 || (o+w)<=4))
   67 
   68 struct acpi_cstate
   69 {
   70         int      type;
   71         int      latency;
   72         int      power;
   73         int      address;
   74 
   75         SLIST_ENTRY(acpi_cstate) link;
   76 };
   77 
   78 struct acpicpu_softc {
   79         struct device           sc_dev;
   80         int                     sc_cpu;
   81 
   82         int                     sc_duty_wid;
   83         int                     sc_duty_off;
   84         int                     sc_pblk_addr;
   85         int                     sc_pblk_len;
   86         int                     sc_flags;
   87 
   88         SLIST_HEAD(,acpi_cstate) sc_cstates;
   89 
   90         bus_space_tag_t         sc_iot;
   91         bus_space_handle_t      sc_ioh;
   92 
   93         struct acpi_softc       *sc_acpi;
   94         struct aml_node         *sc_devnode;
   95 
   96         int                     sc_pss_len;
   97         struct acpicpu_pss      *sc_pss;
   98 
   99         struct acpicpu_pct      sc_pct;
  100         /* XXX: _PPC Change listener
  101          * PPC changes can occur when for example a machine is disconnected
  102          * from AC power and can no loger support the highest frequency or
  103          * voltage when driven from the battery.
  104          * Should probably be reimplemented as a list for now we assume only 
  105          * one listener */
  106         void                    (*sc_notify)(struct acpicpu_pss *, int);
  107 };
  108 
  109 void    acpicpu_set_throttle(struct acpicpu_softc *, int);
  110 void    acpicpu_add_cstatepkg(struct aml_value *, void *);
  111 int     acpicpu_getpct(struct acpicpu_softc *);
  112 int     acpicpu_getpss(struct acpicpu_softc *);
  113 struct acpi_cstate *acpicpu_add_cstate(struct acpicpu_softc *, int, int, int, int);
  114 struct acpi_cstate *acpicpu_find_cstate(struct acpicpu_softc *, int);
  115 
  116 struct cfattach acpicpu_ca = {
  117         sizeof(struct acpicpu_softc), acpicpu_match, acpicpu_attach
  118 };
  119 
  120 struct cfdriver acpicpu_cd = {
  121         NULL, "acpicpu", DV_DULL
  122 };
  123 
  124 extern int setperf_prio;
  125 
  126 #ifdef __i386__
  127 struct acpicpu_softc *acpicpu_sc[I386_MAXPROCS];
  128 #elif __amd64__
  129 struct acpicpu_softc *acpicpu_sc[X86_MAXPROCS];
  130 #endif
  131 
  132 void
  133 acpicpu_set_throttle(struct acpicpu_softc *sc, int level)
  134 {
  135         uint32_t pbval;
  136 
  137         if (sc->sc_flags & FLAGS_NOTHROTTLE)
  138                 return;
  139 
  140         /* Disable throttling control */
  141         pbval = inl(sc->sc_pblk_addr);
  142         outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
  143         if (level < 100) {
  144                 pbval &= ~CPU_STATEMASK(sc);
  145                 pbval |= CPU_STATE(sc, level);
  146                 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
  147                 outl(sc->sc_pblk_addr, pbval | CPU_THT_EN);
  148         }
  149 }
  150 
  151 struct acpi_cstate *
  152 acpicpu_find_cstate(struct acpicpu_softc *sc, int type)
  153 {
  154         struct acpi_cstate *cx;
  155 
  156         SLIST_FOREACH(cx, &sc->sc_cstates, link)
  157                 if (cx->type == type)
  158                         return cx;
  159         return NULL;
  160 }
  161 
  162 struct acpi_cstate *
  163 acpicpu_add_cstate(struct acpicpu_softc *sc, int type,
  164                    int latency, int power, int address)
  165 {
  166         struct acpi_cstate *cx;
  167 
  168         dnprintf(10," C%d: latency:.%4x power:%.4x addr:%.8x\n",
  169                type, latency, power, address);
  170 
  171         switch (type) {
  172         case ACPI_STATE_C2:
  173                 if (latency > ACPI_MAX_C2_LATENCY || !address ||
  174                     (sc->sc_flags & FLAGS_NO_C2))
  175                         goto bad;
  176                 break;
  177         case ACPI_STATE_C3:
  178                 if (latency > ACPI_MAX_C3_LATENCY || !address ||
  179                     (sc->sc_flags & FLAGS_NO_C3))
  180                         goto bad;
  181                 break;
  182         }
  183 
  184         cx = malloc(sizeof(struct acpi_cstate), M_DEVBUF, M_WAITOK);
  185         memset(cx, 0, sizeof(struct acpi_cstate));
  186 
  187         cx->type = type;
  188         cx->power = power;
  189         cx->latency = latency;
  190         cx->address = address;
  191 
  192         SLIST_INSERT_HEAD(&sc->sc_cstates, cx, link);
  193 
  194         return cx;
  195  bad:
  196         dprintf("acpicpu%d: C%d not supported", sc->sc_cpu, type);
  197         return NULL;
  198 }
  199 
  200 /* Found a _CST object, add new cstate for each entry */
  201 void
  202 acpicpu_add_cstatepkg(struct aml_value *val, void *arg)
  203 {
  204         struct acpicpu_softc *sc = arg;
  205 
  206 #ifdef ACPI_DEBUG
  207         aml_showvalue(val, 0);
  208 #endif
  209         if (val->type != AML_OBJTYPE_PACKAGE || val->length != 4)
  210                 return;
  211         acpicpu_add_cstate(sc, val->v_package[1]->v_integer,
  212                            val->v_package[2]->v_integer,
  213                            val->v_package[3]->v_integer,
  214                            -1);
  215 }
  216 
  217 
  218 int
  219 acpicpu_match(struct device *parent, void *match, void *aux)
  220 {
  221         struct acpi_attach_args *aa = aux;
  222         struct cfdata           *cf = match;
  223 
  224         /* sanity */
  225         if (aa->aaa_name == NULL ||
  226             strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
  227             aa->aaa_table != NULL)
  228                 return (0);
  229 
  230         return (1);
  231 }
  232 
  233 void
  234 acpicpu_attach(struct device *parent, struct device *self, void *aux)
  235 {
  236         struct acpicpu_softc    *sc = (struct acpicpu_softc *)self;
  237         struct acpi_attach_args *aa = aux;
  238         struct                  aml_value res;
  239         int                     i;
  240         struct acpi_cstate      *cx;
  241 
  242         sc->sc_acpi = (struct acpi_softc *)parent;
  243         sc->sc_devnode = aa->aaa_node;
  244         acpicpu_sc[sc->sc_dev.dv_unit] = sc;
  245 
  246         SLIST_INIT(&sc->sc_cstates);
  247 
  248         sc->sc_pss = NULL;
  249 
  250         if (aml_evalnode(sc->sc_acpi, sc->sc_devnode, 0, NULL, &res) == 0) {
  251                 if (res.type == AML_OBJTYPE_PROCESSOR) {
  252                         sc->sc_cpu = res.v_processor.proc_id;
  253                         sc->sc_pblk_addr = res.v_processor.proc_addr;
  254                         sc->sc_pblk_len = res.v_processor.proc_len;
  255                 }
  256                 aml_freevalue(&res);
  257         }
  258         sc->sc_duty_off = sc->sc_acpi->sc_fadt->duty_offset;
  259         sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width;
  260         if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr))
  261                 sc->sc_flags |= FLAGS_NOTHROTTLE;
  262 
  263 #ifdef ACPI_DEBUG
  264         printf(": %s: ", sc->sc_devnode->name);
  265         printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x (%d throttling states)\n",
  266                 sc->sc_acpi->sc_fadt->hdr_revision,
  267                 sc->sc_pblk_addr, sc->sc_pblk_len, 
  268                 sc->sc_duty_off, sc->sc_duty_wid,
  269                 sc->sc_acpi->sc_fadt->pstate_cnt,
  270                 CPU_MAXSTATE(sc));
  271 #endif
  272 
  273         /* Get C-States from _CST or FADT */
  274         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CST", 0, NULL, &res) == 0) {
  275                 aml_foreachpkg(&res, 1, acpicpu_add_cstatepkg, sc);
  276                 aml_freevalue(&res);
  277         }
  278         else {
  279                 /* Some systems don't export a full PBLK, reduce functionality */
  280                 if (sc->sc_pblk_len < 5)
  281                         sc->sc_flags |= FLAGS_NO_C2;
  282                 if (sc->sc_pblk_len < 6)
  283                         sc->sc_flags |= FLAGS_NO_C3;
  284                 acpicpu_add_cstate(sc, ACPI_STATE_C2,
  285                                    sc->sc_acpi->sc_fadt->p_lvl2_lat, -1,
  286                                    sc->sc_pblk_addr + 4);
  287                 acpicpu_add_cstate(sc, ACPI_STATE_C3,
  288                                    sc->sc_acpi->sc_fadt->p_lvl3_lat, -1,
  289                                    sc->sc_pblk_addr + 5);
  290         }
  291         if (acpicpu_getpss(sc)) {
  292                 /* XXX not the right test but has to do for now */
  293                 sc->sc_flags |= FLAGS_NOPSS;
  294         } else {
  295 
  296 #ifdef ACPI_DEBUG
  297                 for (i = 0; i < sc->sc_pss_len; i++) {
  298                         dnprintf(20, "%d %d %d %d %d %d\n",
  299                             sc->sc_pss[i].pss_core_freq,
  300                             sc->sc_pss[i].pss_power,
  301                             sc->sc_pss[i].pss_trans_latency,
  302                             sc->sc_pss[i].pss_bus_latency,
  303                             sc->sc_pss[i].pss_ctrl,
  304                             sc->sc_pss[i].pss_status);
  305                 }
  306                 dnprintf(20, "\n");
  307 #endif
  308                 /* XXX this needs to be moved to probe routine */
  309                 if (acpicpu_getpct(sc))
  310                         sc->sc_flags |= FLAGS_NOPCT;
  311                 else {
  312 
  313                         /* Notify BIOS we are handing p-states */
  314                         if (sc->sc_acpi->sc_fadt->pstate_cnt)
  315                                 acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0,
  316                                 sc->sc_acpi->sc_fadt->pstate_cnt);
  317 
  318                         aml_register_notify(sc->sc_devnode, NULL,
  319                             acpicpu_notify, sc, ACPIDEV_NOPOLL);
  320 
  321                         if (setperf_prio < 30) {
  322                                 cpu_setperf = acpicpu_setperf;
  323                                 setperf_prio = 30;
  324                                 acpi_hasprocfvs = 1;
  325                         }
  326                 }
  327         }
  328 
  329         /* 
  330          * Nicely enumerate what power management capabilities
  331          * ACPI CPU provides.
  332          * */
  333         i = 0;
  334         SLIST_FOREACH(cx, &sc->sc_cstates, link) {
  335                 if (i)
  336                         printf(",");
  337                 switch(cx->type) {
  338                 case ACPI_STATE_C0:
  339                         printf(" C0");
  340                         break;
  341                 case ACPI_STATE_C1:
  342                         printf(" C1");
  343                         break;
  344                 case ACPI_STATE_C2:
  345                         printf(" C2");
  346                         break;
  347                 case ACPI_STATE_C3:
  348                         printf(" C3");
  349                         break;
  350                 }
  351                 i++;
  352         }
  353         if (!(sc->sc_flags & FLAGS_NOPSS) && !(sc->sc_flags & FLAGS_NOPCT)) {
  354                 if (i)
  355                         printf(",");
  356                 printf(" FVS");
  357         } else if (!(sc->sc_flags & FLAGS_NOPSS)) {
  358                 if (i)
  359                         printf(",");
  360                 printf(" PSS");
  361         }
  362         printf("\n");
  363 
  364         /*
  365          * If acpicpu is itself providing the capability to transition
  366          * states, enumerate them in the fashion that est and powernow
  367          * would.
  368          */
  369         if (!(sc->sc_flags & FLAGS_NOPSS) && !(sc->sc_flags & FLAGS_NOPCT)) {
  370                 printf("%s: ", sc->sc_dev.dv_xname);
  371                 for (i = 0; i < sc->sc_pss_len; i++)
  372                         printf("%d%s", sc->sc_pss[i].pss_core_freq,
  373                             i < sc->sc_pss_len - 1 ? ", " : " MHz\n");
  374         }
  375 }
  376 
  377 int
  378 acpicpu_getpct(struct acpicpu_softc *sc)
  379 {
  380         struct aml_value        res;
  381         int                     rv = 1;
  382 
  383         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) {
  384                 dnprintf(20, "%s: no _PPC\n", DEVNAME(sc));
  385                 dnprintf(10, "%s: no _PPC\n", DEVNAME(sc));
  386                 return (1);
  387         }
  388 
  389         dnprintf(10, "_PPC: %d\n", aml_val2int(&res));
  390         aml_freevalue(&res);
  391 
  392         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) {
  393                 dnprintf(20, "%s: no _PCT\n", DEVNAME(sc));
  394                 return (1);
  395         }
  396 
  397         if (res.length != 2) {
  398                 dnprintf(20, "%s: %s: invalid _PCT length\n", DEVNAME(sc),
  399                     sc->sc_devnode->name);
  400                 return (1);
  401         }
  402 
  403         memcpy(&sc->sc_pct.pct_ctrl, res.v_package[0]->v_buffer,
  404             sizeof sc->sc_pct.pct_ctrl);
  405         if (sc->sc_pct.pct_ctrl.grd_gas.address_space_id ==
  406             GAS_FUNCTIONAL_FIXED) {
  407                 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
  408                 goto ffh;
  409         }
  410 
  411         memcpy(&sc->sc_pct.pct_status, res.v_package[1]->v_buffer,
  412             sizeof sc->sc_pct.pct_status);
  413         if (sc->sc_pct.pct_status.grd_gas.address_space_id ==
  414             GAS_FUNCTIONAL_FIXED) {
  415                 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
  416                 goto ffh;
  417         }
  418 
  419         dnprintf(10, "_PCT(ctrl)  : %02x %04x %02x %02x %02x %02x %016x\n",
  420             sc->sc_pct.pct_ctrl.grd_descriptor,
  421             sc->sc_pct.pct_ctrl.grd_length,
  422             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
  423             sc->sc_pct.pct_ctrl.grd_gas.register_bit_width,
  424             sc->sc_pct.pct_ctrl.grd_gas.register_bit_offset,
  425             sc->sc_pct.pct_ctrl.grd_gas.access_size,
  426             sc->sc_pct.pct_ctrl.grd_gas.address);
  427 
  428         dnprintf(10, "_PCT(status): %02x %04x %02x %02x %02x %02x %016x\n",
  429             sc->sc_pct.pct_status.grd_descriptor,
  430             sc->sc_pct.pct_status.grd_length,
  431             sc->sc_pct.pct_status.grd_gas.address_space_id,
  432             sc->sc_pct.pct_status.grd_gas.register_bit_width,
  433             sc->sc_pct.pct_status.grd_gas.register_bit_offset,
  434             sc->sc_pct.pct_status.grd_gas.access_size,
  435             sc->sc_pct.pct_status.grd_gas.address);
  436 
  437         rv = 0;
  438 ffh:
  439         aml_freevalue(&res);
  440         return (rv);
  441 }
  442 
  443 int
  444 acpicpu_getpss(struct acpicpu_softc *sc)
  445 {
  446         struct aml_value        res;
  447         int                     i;
  448 
  449         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) {
  450                 dprintf("%s: no _PSS\n", DEVNAME(sc));
  451                 return (1);
  452         }
  453 
  454         if (sc->sc_pss)
  455                 free(sc->sc_pss, M_DEVBUF);
  456 
  457         sc->sc_pss = malloc(res.length * sizeof *sc->sc_pss, M_DEVBUF,
  458             M_WAITOK);
  459 
  460         memset(sc->sc_pss, 0, res.length * sizeof *sc->sc_pss);
  461 
  462         for (i = 0; i < res.length; i++) {
  463                 sc->sc_pss[i].pss_core_freq = aml_val2int(
  464                     res.v_package[i]->v_package[0]);
  465                 sc->sc_pss[i].pss_power = aml_val2int(
  466                     res.v_package[i]->v_package[1]);
  467                 sc->sc_pss[i].pss_trans_latency = aml_val2int(
  468                     res.v_package[i]->v_package[2]);
  469                 sc->sc_pss[i].pss_bus_latency = aml_val2int(
  470                     res.v_package[i]->v_package[3]);
  471                 sc->sc_pss[i].pss_ctrl = aml_val2int(
  472                     res.v_package[i]->v_package[4]);
  473                 sc->sc_pss[i].pss_status = aml_val2int(
  474                     res.v_package[i]->v_package[5]);
  475         }
  476         aml_freevalue(&res);
  477 
  478         sc->sc_pss_len = res.length;
  479 
  480         return (0);
  481 }
  482 
  483 int
  484 acpicpu_fetch_pss(struct acpicpu_pss **pss) {
  485         /*XXX: According to the ACPI spec in an SMP system all processors
  486          * are supposed to support the same states. For now we prey
  487          * the bios ensures this...
  488          */
  489         struct acpicpu_softc *sc;
  490 
  491         sc = acpicpu_sc[0];
  492         if (!sc) {
  493                 printf("couldnt fetch acpicpu_softc\n");
  494                 return 0;
  495         }
  496         *pss = sc->sc_pss;
  497 
  498         return sc->sc_pss_len;
  499 }
  500 
  501 int
  502 acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
  503 {
  504         struct acpicpu_softc    *sc = arg;
  505 
  506         dnprintf(10, "acpicpu_notify: %.2x %s\n", notify_type,
  507             sc->sc_devnode->name);
  508 
  509         switch (notify_type) {
  510         case 0x80:      /* _PPC changed, retrieve new values */
  511                 acpicpu_getpct(sc);
  512                 acpicpu_getpss(sc);
  513                 if (sc->sc_notify)
  514                         sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
  515                 break;
  516         default:
  517                 printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
  518                     notify_type);
  519                 break;
  520         }
  521 
  522         return (0);
  523 }
  524 
  525 void
  526 acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int)) {
  527         struct acpicpu_softc    *sc;
  528 
  529         sc = acpicpu_sc[0];
  530         if (sc != NULL)
  531                 sc->sc_notify = func;
  532 }
  533 
  534 void
  535 acpicpu_setperf(int level) {
  536         struct acpicpu_softc    *sc;
  537         struct acpicpu_pss      *pss = NULL;
  538         int                     idx;
  539         u_int32_t               stat_as, ctrl_as, stat_len, ctrl_len;
  540         u_int32_t               status = 0;
  541 
  542         sc = acpicpu_sc[cpu_number()];
  543 
  544         dnprintf(10, "%s: acpicpu setperf level %d\n",
  545             sc->sc_devnode->name, level);
  546 
  547         if (level < 0 || level > 100) {
  548                 dnprintf(10, "%s: acpicpu setperf illegal percentage\n",
  549                     sc->sc_devnode->name);
  550                 return;
  551         }
  552 
  553         idx = (sc->sc_pss_len - 1) - (level / (100 / sc->sc_pss_len));
  554         if (idx < 0)
  555                 idx = 0; /* compensate */
  556         if (idx > sc->sc_pss_len) {
  557                 /* XXX should never happen */
  558                 printf("%s: acpicpu setperf index out of range\n",
  559                     sc->sc_devnode->name);
  560                 return;
  561         }
  562 
  563         dnprintf(10, "%s: acpicpu setperf index %d\n",
  564             sc->sc_devnode->name, idx);
  565 
  566         pss = &sc->sc_pss[idx];
  567 
  568         /* if not set assume single 32 bit access */
  569         stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width / 8;
  570         if (stat_as == 0)
  571                 stat_as = 4;
  572         ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8;
  573         if (ctrl_as == 0)
  574                 ctrl_as = 4;
  575         stat_len = sc->sc_pct.pct_status.grd_gas.access_size;
  576         if (stat_len == 0)
  577                 stat_len = stat_as;
  578         ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size;
  579         if (ctrl_len == 0)
  580                 ctrl_len = ctrl_as;
  581 
  582 #ifdef ACPI_DEBUG
  583         /* keep this for now since we will need this for debug in the field */
  584         printf("0 status: %x %llx %u %u ctrl: %x %llx %u %u\n",
  585             sc->sc_pct.pct_status.grd_gas.address_space_id,
  586             sc->sc_pct.pct_status.grd_gas.address,
  587             stat_as, stat_len,
  588             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
  589             sc->sc_pct.pct_ctrl.grd_gas.address,
  590             ctrl_as, ctrl_len);
  591 #endif
  592         acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
  593             sc->sc_pct.pct_status.grd_gas.address_space_id,
  594             sc->sc_pct.pct_status.grd_gas.address, stat_as, stat_len,
  595             &status);
  596         dnprintf(20, "status: %u <- %u\n", status, pss->pss_status);
  597 
  598         /* Are we already at the requested frequency? */
  599         if (status == pss->pss_status)
  600                 return;
  601 
  602         acpi_gasio(sc->sc_acpi, ACPI_IOWRITE,
  603             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
  604             sc->sc_pct.pct_ctrl.grd_gas.address, ctrl_as, ctrl_len,
  605             &pss->pss_ctrl);
  606         dnprintf(20, "pss_ctrl: %x\n", pss->pss_ctrl);
  607 
  608         acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
  609             sc->sc_pct.pct_status.grd_gas.address_space_id,
  610             sc->sc_pct.pct_status.grd_gas.address, stat_as, stat_as,
  611             &status);
  612         dnprintf(20, "3 status: %d\n", status);
  613 
  614         /* Did the transition succeed? */
  615          if (status == pss->pss_status)
  616                 cpuspeed = pss->pss_core_freq;
  617         else
  618                 printf("%s: acpicpu setperf failed to alter frequency\n",
  619                     sc->sc_devnode->name);
  620 }

/* [<][>][^][v][top][bottom][index][help] */