acpi/pstate: Fix error logging messages
[dragonfly.git] / sys / platform / pc64 / acpica5 / acpi_pstate_machdep.c
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
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  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/globaldata.h>
38
39 #include <machine/md_var.h>
40 #include <machine/cpufunc.h>
41 #include <machine/cpufreq.h>
42 #include <machine/specialreg.h>
43
44 #include "acpi.h"
45 #include "acpi_cpu_pstate.h"
46
47 #define AMD_APMI_HWPSTATE               0x80
48
49 #define AMD_MSR_PSTATE_CSR_MASK         0x7ULL
50 #define AMD1X_MSR_PSTATE_CTL            0xc0010062
51 #define AMD1X_MSR_PSTATE_ST             0xc0010063
52
53 #define AMD_MSR_PSTATE_EN               0x8000000000000000ULL
54
55 #define AMD10_MSR_PSTATE_START          0xc0010064
56 #define AMD10_MSR_PSTATE_COUNT          5
57
58 #define AMD0F_PST_CTL_FID(cval)         (((cval) >> 0)  & 0x3f)
59 #define AMD0F_PST_CTL_VID(cval)         (((cval) >> 6)  & 0x1f)
60 #define AMD0F_PST_CTL_VST(cval)         (((cval) >> 11) & 0x7f)
61 #define AMD0F_PST_CTL_MVS(cval)         (((cval) >> 18) & 0x3)
62 #define AMD0F_PST_CTL_PLLTIME(cval)     (((cval) >> 20) & 0x7f)
63 #define AMD0F_PST_CTL_RVO(cval)         (((cval) >> 28) & 0x3)
64 #define AMD0F_PST_CTL_IRT(cval)         (((cval) >> 30) & 0x3)
65
66 #define AMD0F_PST_ST_FID(sval)          (((sval) >> 0) & 0x3f)
67 #define AMD0F_PST_ST_VID(sval)          (((sval) >> 6) & 0x3f)
68
69 #define INTEL_MSR_MISC_ENABLE           0x1a0
70 #define INTEL_MSR_MISC_EST_EN           0x10000ULL
71
72 #define INTEL_MSR_PERF_STATUS           0x198
73 #define INTEL_MSR_PERF_CTL              0x199
74 #define INTEL_MSR_PERF_MASK             0xffffULL
75
76 static const struct acpi_pst_md *
77                 acpi_pst_amd_probe(void);
78 static int      acpi_pst_amd_check_csr(const struct acpi_pst_res *,
79                     const struct acpi_pst_res *);
80 static int      acpi_pst_amd1x_check_pstates(const struct acpi_pstate *, int,
81                     uint32_t, uint32_t);
82 static int      acpi_pst_amd10_check_pstates(const struct acpi_pstate *, int);
83 static int      acpi_pst_amd0f_check_pstates(const struct acpi_pstate *, int);
84 static int      acpi_pst_amd_init(const struct acpi_pst_res *,
85                     const struct acpi_pst_res *);
86 static int      acpi_pst_amd1x_set_pstate(const struct acpi_pst_res *,
87                     const struct acpi_pst_res *, const struct acpi_pstate *);
88 static int      acpi_pst_amd0f_set_pstate(const struct acpi_pst_res *,
89                     const struct acpi_pst_res *, const struct acpi_pstate *);
90 static const struct acpi_pstate *
91                 acpi_pst_amd1x_get_pstate(const struct acpi_pst_res *,
92                     const struct acpi_pstate *, int);
93 static const struct acpi_pstate *
94                 acpi_pst_amd0f_get_pstate(const struct acpi_pst_res *,
95                     const struct acpi_pstate *, int);
96
97 static const struct acpi_pst_md *
98                 acpi_pst_intel_probe(void);
99 static int      acpi_pst_intel_check_csr(const struct acpi_pst_res *,
100                     const struct acpi_pst_res *);
101 static int      acpi_pst_intel_check_pstates(const struct acpi_pstate *, int);
102 static int      acpi_pst_intel_init(const struct acpi_pst_res *,
103                     const struct acpi_pst_res *);
104 static int      acpi_pst_intel_set_pstate(const struct acpi_pst_res *,
105                     const struct acpi_pst_res *, const struct acpi_pstate *);
106 static const struct acpi_pstate *
107                 acpi_pst_intel_get_pstate(const struct acpi_pst_res *,
108                     const struct acpi_pstate *, int);
109
110 static int      acpi_pst_md_gas_asz(const ACPI_GENERIC_ADDRESS *);
111 static int      acpi_pst_md_gas_verify(const ACPI_GENERIC_ADDRESS *);
112 static uint32_t acpi_pst_md_res_read(const struct acpi_pst_res *);
113 static void     acpi_pst_md_res_write(const struct acpi_pst_res *, uint32_t);
114
115 static const struct acpi_pst_md acpi_pst_amd10 = {
116         .pmd_check_csr          = acpi_pst_amd_check_csr,
117         .pmd_check_pstates      = acpi_pst_amd10_check_pstates,
118         .pmd_init               = acpi_pst_amd_init,
119         .pmd_set_pstate         = acpi_pst_amd1x_set_pstate,
120         .pmd_get_pstate         = acpi_pst_amd1x_get_pstate
121 };
122
123 static const struct acpi_pst_md acpi_pst_amd0f = {
124         .pmd_check_csr          = acpi_pst_amd_check_csr,
125         .pmd_check_pstates      = acpi_pst_amd0f_check_pstates,
126         .pmd_init               = acpi_pst_amd_init,
127         .pmd_set_pstate         = acpi_pst_amd0f_set_pstate,
128         .pmd_get_pstate         = acpi_pst_amd0f_get_pstate
129 };
130
131 static const struct acpi_pst_md acpi_pst_intel = {
132         .pmd_check_csr          = acpi_pst_intel_check_csr,
133         .pmd_check_pstates      = acpi_pst_intel_check_pstates,
134         .pmd_init               = acpi_pst_intel_init,
135         .pmd_set_pstate         = acpi_pst_intel_set_pstate,
136         .pmd_get_pstate         = acpi_pst_intel_get_pstate
137 };
138
139 const struct acpi_pst_md *
140 acpi_pst_md_probe(void)
141 {
142         if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
143                 return acpi_pst_amd_probe();
144         else if (strcmp(cpu_vendor, "GenuineIntel") == 0)
145                 return acpi_pst_intel_probe();
146         return NULL;
147 }
148
149 static const struct acpi_pst_md *
150 acpi_pst_amd_probe(void)
151 {
152         uint32_t regs[4], ext_family;
153
154         if ((cpu_id & 0x00000f00) != 0x00000f00)
155                 return NULL;
156
157         /* Check whether APMI exists */
158         do_cpuid(0x80000000, regs);
159         if (regs[0] < 0x80000007)
160                 return NULL;
161
162         /* Fetch APMI */
163         do_cpuid(0x80000007, regs);
164
165         ext_family = cpu_id & 0x0ff00000;
166         switch (ext_family) {
167         case 0x00000000:        /* Family 0fh */
168                 if ((regs[3] & 0x06) == 0x06)
169                         return &acpi_pst_amd0f;
170                 break;
171
172         case 0x00100000:        /* Family 10h */
173                 if (regs[3] & 0x80)
174                         return &acpi_pst_amd10;
175                 break;
176
177         default:
178                 break;
179         }
180         return NULL;
181 }
182
183 static int
184 acpi_pst_amd_check_csr(const struct acpi_pst_res *ctrl,
185                        const struct acpi_pst_res *status)
186 {
187         if (ctrl->pr_gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) {
188                 kprintf("cpu%d: Invalid P-State control register\n", mycpuid);
189                 return EINVAL;
190         }
191         if (status->pr_gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) {
192                 kprintf("cpu%d: Invalid P-State status register\n", mycpuid);
193                 return EINVAL;
194         }
195         return 0;
196 }
197
198 static int
199 acpi_pst_amd1x_check_pstates(const struct acpi_pstate *pstates, int npstates,
200                              uint32_t msr_start, uint32_t msr_end)
201 {
202         int i;
203
204         /*
205          * Make sure that related MSR P-State registers are enabled.
206          *
207          * NOTE:
208          * We don't check status register value here;
209          * it will not be used.
210          */
211         for (i = 0; i < npstates; ++i) {
212                 uint64_t pstate;
213                 uint32_t msr;
214
215                 msr = msr_start +
216                       (pstates[i].st_cval & AMD_MSR_PSTATE_CSR_MASK);
217                 if (msr >= msr_end) {
218                         kprintf("cpu%d: MSR P-State register %#08x "
219                                 "does not exist\n", mycpuid, msr);
220                         return EINVAL;
221                 }
222
223                 pstate = rdmsr(msr);
224                 if ((pstate & AMD_MSR_PSTATE_EN) == 0) {
225                         kprintf("cpu%d: MSR P-State register %#08x "
226                                 "is not enabled\n", mycpuid, msr);
227                         return EINVAL;
228                 }
229         }
230         return 0;
231 }
232
233 static int
234 acpi_pst_amd10_check_pstates(const struct acpi_pstate *pstates, int npstates)
235 {
236         /* Only P0-P4 are supported */
237         if (npstates > AMD10_MSR_PSTATE_COUNT) {
238                 kprintf("cpu%d: only P0-P4 is allowed\n", mycpuid);
239                 return EINVAL;
240         }
241
242         return acpi_pst_amd1x_check_pstates(pstates, npstates,
243                         AMD10_MSR_PSTATE_START,
244                         AMD10_MSR_PSTATE_START + AMD10_MSR_PSTATE_COUNT);
245 }
246
247 static int
248 acpi_pst_amd1x_set_pstate(const struct acpi_pst_res *ctrl __unused,
249                           const struct acpi_pst_res *status __unused,
250                           const struct acpi_pstate *pstate)
251 {
252         uint64_t cval;
253
254         cval = pstate->st_cval & AMD_MSR_PSTATE_CSR_MASK;
255         wrmsr(AMD1X_MSR_PSTATE_CTL, cval);
256
257         /*
258          * Don't check AMD1X_MSR_PSTATE_ST here, since it is
259          * affected by various P-State limits.
260          *
261          * For details:
262          * AMD Family 10h Processor BKDG Rev 3.20 (#31116)
263          * 2.4.2.4 P-state Transition Behavior
264          */
265
266         return 0;
267 }
268
269 static const struct acpi_pstate *
270 acpi_pst_amd1x_get_pstate(const struct acpi_pst_res *status __unused,
271                           const struct acpi_pstate *pstates, int npstates)
272 {
273         uint64_t sval;
274         int i;
275
276         sval = rdmsr(AMD1X_MSR_PSTATE_ST) & AMD_MSR_PSTATE_CSR_MASK;
277         for (i = 0; i < npstates; ++i) {
278                 if ((pstates[i].st_sval & AMD_MSR_PSTATE_CSR_MASK) == sval)
279                         return &pstates[i];
280         }
281         return NULL;
282 }
283
284 static int
285 acpi_pst_amd0f_check_pstates(const struct acpi_pstate *pstates, int npstates)
286 {
287         struct amd0f_fidvid fv_max, fv_min;
288         int i;
289
290         amd0f_fidvid_limit(&fv_min, &fv_max);
291
292         for (i = 0; i < npstates; ++i) {
293                 const struct acpi_pstate *p = &pstates[i];
294                 uint32_t fid, vid, mvs, rvo;
295                 int mvs_mv, rvo_mv;
296
297                 fid = AMD0F_PST_CTL_FID(p->st_cval);
298                 vid = AMD0F_PST_CTL_VID(p->st_cval);
299
300                 if (fid > fv_max.fid || fid < fv_min.fid) {
301                         kprintf("cpu%d: Invalid FID %#x, out [%#x, %#x]\n",
302                                 mycpuid, fid, fv_min.fid, fv_max.fid);
303                         return EINVAL;
304                 }
305                 if (vid < fv_max.vid || vid > fv_min.vid) {
306                         kprintf("cpu%d: Invalid VID %#x, in [%#x, %#x]\n",
307                                 mycpuid, vid, fv_max.vid, fv_min.vid);
308                         return EINVAL;
309                 }
310
311                 mvs = AMD0F_PST_CTL_MVS(p->st_cval);
312                 rvo = AMD0F_PST_CTL_RVO(p->st_cval);
313
314                 /* Only 0 is allowed, i.e. 25mV stepping */
315                 if (mvs != 0) {
316                         kprintf("cpu%d: Invalid MVS %#x\n", mycpuid, mvs);
317                         return EINVAL;
318                 }
319
320                 /* -> mV */
321                 mvs_mv = 25 * (1 << mvs);
322                 rvo_mv = 25 * rvo;
323                 if (rvo_mv % mvs_mv != 0) {
324                         kprintf("cpu%d: Invalid MVS/RVO (%#x/%#x)\n",
325                                 mycpuid, mvs, rvo);
326                         return EINVAL;
327                 }
328         }
329         return 0;
330 }
331
332 static int
333 acpi_pst_amd0f_set_pstate(const struct acpi_pst_res *ctrl __unused,
334                           const struct acpi_pst_res *status __unused,
335                           const struct acpi_pstate *pstate)
336 {
337         struct amd0f_fidvid fv;
338         struct amd0f_xsit xsit;
339
340         fv.fid = AMD0F_PST_CTL_FID(pstate->st_cval);
341         fv.vid = AMD0F_PST_CTL_VID(pstate->st_cval);
342
343         xsit.rvo = AMD0F_PST_CTL_RVO(pstate->st_cval);
344         xsit.mvs = AMD0F_PST_CTL_MVS(pstate->st_cval);
345         xsit.vst = AMD0F_PST_CTL_VST(pstate->st_cval);
346         xsit.pll_time = AMD0F_PST_CTL_PLLTIME(pstate->st_cval);
347         xsit.irt = AMD0F_PST_CTL_IRT(pstate->st_cval);
348
349         return amd0f_set_fidvid(&fv, &xsit);
350 }
351
352 static const struct acpi_pstate *
353 acpi_pst_amd0f_get_pstate(const struct acpi_pst_res *status __unused,
354                           const struct acpi_pstate *pstates, int npstates)
355 {
356         struct amd0f_fidvid fv;
357         int error, i;
358
359         error = amd0f_get_fidvid(&fv);
360         if (error)
361                 return NULL;
362
363         for (i = 0; i < npstates; ++i) {
364                 const struct acpi_pstate *p = &pstates[i];
365
366                 if (fv.fid == AMD0F_PST_ST_FID(p->st_sval) &&
367                     fv.vid == AMD0F_PST_ST_VID(p->st_sval))
368                         return p;
369         }
370         return NULL;
371 }
372
373 static int
374 acpi_pst_amd_init(const struct acpi_pst_res *ctrl __unused,
375                   const struct acpi_pst_res *status __unused)
376 {
377         return 0;
378 }
379
380 static const struct acpi_pst_md *
381 acpi_pst_intel_probe(void)
382 {
383         uint32_t family;
384
385         if ((cpu_feature2 & CPUID2_EST) == 0)
386                 return NULL;
387
388         family = cpu_id & 0xf00;
389         if (family != 0xf00 && family != 0x600)
390                 return NULL;
391         return &acpi_pst_intel;
392 }
393
394 static int
395 acpi_pst_intel_check_csr(const struct acpi_pst_res *ctrl,
396                          const struct acpi_pst_res *status)
397 {
398         int error;
399
400         if (ctrl->pr_gas.SpaceId != status->pr_gas.SpaceId) {
401                 kprintf("cpu%d: P-State control(%d)/status(%d) registers have "
402                         "different SpaceId", mycpuid,
403                         ctrl->pr_gas.SpaceId, status->pr_gas.SpaceId);
404                 return EINVAL;
405         }
406
407         switch (ctrl->pr_gas.SpaceId) {
408         case ACPI_ADR_SPACE_FIXED_HARDWARE:
409                 if (ctrl->pr_res != NULL || status->pr_res != NULL) {
410                         /* XXX should panic() */
411                         kprintf("cpu%d: Allocated resource for fixed hardware "
412                                 "registers\n", mycpuid);
413                         return EINVAL;
414                 }
415                 break;
416
417         case ACPI_ADR_SPACE_SYSTEM_IO:
418                 if (ctrl->pr_res == NULL) {
419                         kprintf("cpu%d: ioport allocation failed for control "
420                                 "register\n", mycpuid);
421                         return ENXIO;
422                 }
423                 error = acpi_pst_md_gas_verify(&ctrl->pr_gas);
424                 if (error) {
425                         kprintf("cpu%d: Invalid control register GAS\n",
426                                 mycpuid);
427                         return error;
428                 }
429
430                 if (status->pr_res == NULL) {
431                         kprintf("cpu%d: ioport allocation failed for status "
432                                 "register\n", mycpuid);
433                         return ENXIO;
434                 }
435                 error = acpi_pst_md_gas_verify(&status->pr_gas);
436                 if (error) {
437                         kprintf("cpu%d: Invalid status register GAS\n",
438                                 mycpuid);
439                         return error;
440                 }
441                 break;
442
443         default:
444                 kprintf("cpu%d: Invalid P-State control/status register "
445                         "SpaceId %d\n", mycpuid, ctrl->pr_gas.SpaceId);
446                 return EOPNOTSUPP;
447         }
448         return 0;
449 }
450
451 static int
452 acpi_pst_intel_check_pstates(const struct acpi_pstate *pstates __unused,
453                              int npstates __unused)
454 {
455         return 0;
456 }
457
458 static int
459 acpi_pst_intel_init(const struct acpi_pst_res *ctrl __unused,
460                     const struct acpi_pst_res *status __unused)
461 {
462         uint32_t family, model;
463         uint64_t misc_enable;
464
465         family = cpu_id & 0xf00;
466         if (family == 0xf00) {
467                 /* EST enable bit is reserved in INTEL_MSR_MISC_ENABLE */
468                 return 0;
469         }
470         KKASSERT(family == 0x600);
471
472         model = ((cpu_id & 0xf0000) >> 12) | ((cpu_id & 0xf0) >> 4);
473         if (model < 0xd) {
474                 /* EST enable bit is reserved in INTEL_MSR_MISC_ENABLE */
475                 return 0;
476         }
477
478         misc_enable = rdmsr(INTEL_MSR_MISC_ENABLE);
479         if ((misc_enable & INTEL_MSR_MISC_EST_EN) == 0) {
480                 misc_enable |= INTEL_MSR_MISC_EST_EN;
481                 wrmsr(INTEL_MSR_MISC_ENABLE, misc_enable);
482
483                 misc_enable = rdmsr(INTEL_MSR_MISC_ENABLE);
484                 if ((misc_enable & INTEL_MSR_MISC_EST_EN) == 0) {
485                         kprintf("cpu%d: Can't enable EST\n", mycpuid);
486                         return EIO;
487                 }
488         }
489         return 0;
490 }
491
492 static int
493 acpi_pst_intel_set_pstate(const struct acpi_pst_res *ctrl,
494                           const struct acpi_pst_res *status __unused,
495                           const struct acpi_pstate *pstate)
496 {
497         if (ctrl->pr_res != NULL) {
498                 acpi_pst_md_res_write(ctrl, pstate->st_cval);
499         } else {
500                 uint64_t ctl;
501
502                 ctl = rdmsr(INTEL_MSR_PERF_CTL);
503                 ctl &= ~INTEL_MSR_PERF_MASK;
504                 ctl |= (pstate->st_cval & INTEL_MSR_PERF_MASK);
505                 wrmsr(INTEL_MSR_PERF_CTL, ctl);
506         }
507         return 0;
508 }
509
510 static const struct acpi_pstate *
511 acpi_pst_intel_get_pstate(const struct acpi_pst_res *status,
512                           const struct acpi_pstate *pstates, int npstates)
513 {
514         int i;
515
516         if (status->pr_res != NULL) {
517                 uint32_t st;
518
519                 st = acpi_pst_md_res_read(status);
520                 for (i = 0; i < npstates; ++i) {
521                         if (pstates[i].st_sval == st)
522                                 return &pstates[i];
523                 }
524         } else {
525                 uint64_t sval;
526
527                 sval = rdmsr(INTEL_MSR_PERF_STATUS) & INTEL_MSR_PERF_MASK;
528                 for (i = 0; i < npstates; ++i) {
529                         if ((pstates[i].st_sval & INTEL_MSR_PERF_MASK) == sval)
530                                 return &pstates[i];
531                 }
532         }
533         return NULL;
534 }
535
536 static int
537 acpi_pst_md_gas_asz(const ACPI_GENERIC_ADDRESS *gas)
538 {
539         int asz;
540
541         if (gas->AccessWidth != 0)
542                 asz = gas->AccessWidth;
543         else
544                 asz = gas->BitWidth / NBBY;
545         switch (asz) {
546         case 1:
547         case 2:
548         case 4:
549                 break;
550         default:
551                 asz = 0;
552                 break;
553         }
554         return asz;
555 }
556
557 static int
558 acpi_pst_md_gas_verify(const ACPI_GENERIC_ADDRESS *gas)
559 {
560         int reg, end, asz;
561
562         if (gas->BitOffset % NBBY != 0)
563                 return EINVAL;
564
565         end = gas->BitWidth / NBBY;
566         reg = gas->BitOffset / NBBY;
567
568         if (reg >= end)
569                 return EINVAL;
570
571         asz = acpi_pst_md_gas_asz(gas);
572         if (asz == 0)
573                 return EINVAL;
574
575         if (reg + asz > end)
576                 return EINVAL;
577         return 0;
578 }
579
580 static uint32_t
581 acpi_pst_md_res_read(const struct acpi_pst_res *res)
582 {
583         int asz, reg;
584
585         KKASSERT(res->pr_res != NULL);
586         asz = acpi_pst_md_gas_asz(&res->pr_gas);
587         reg = res->pr_gas.BitOffset / NBBY;
588
589         switch (asz) {
590         case 1:
591                 return bus_space_read_1(res->pr_bt, res->pr_bh, reg);
592         case 2:
593                 return bus_space_read_2(res->pr_bt, res->pr_bh, reg);
594         case 4:
595                 return bus_space_read_4(res->pr_bt, res->pr_bh, reg);
596         }
597         panic("unsupported access width %d\n", asz);
598
599         /* NEVER REACHED */
600         return 0;
601 }
602
603 static void
604 acpi_pst_md_res_write(const struct acpi_pst_res *res, uint32_t val)
605 {
606         int asz, reg;
607
608         KKASSERT(res->pr_res != NULL);
609         asz = acpi_pst_md_gas_asz(&res->pr_gas);
610         reg = res->pr_gas.BitOffset / NBBY;
611
612         switch (asz) {
613         case 1:
614                 bus_space_write_1(res->pr_bt, res->pr_bh, reg, val);
615                 break;
616         case 2:
617                 bus_space_write_2(res->pr_bt, res->pr_bh, reg, val);
618                 break;
619         case 4:
620                 bus_space_write_4(res->pr_bt, res->pr_bh, reg, val);
621                 break;
622         default:
623                 panic("unsupported access width %d\n", asz);
624         }
625 }