1/* 2 * ssdt_pm.asl 3 * 4 * Copyright (c) 2008 Kamala Narasimhan 5 * Copyright (c) 2008 Citrix Systems, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as published 9 * by the Free Software Foundation; version 2.1 only. with the special 10 * exception on linking described in file LICENSE. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Lesser General Public License for more details. 16 */ 17 18/* 19 * SSDT for extended power management within HVM guest. Power management beyond 20 * S3, S4, S5 is handled by this vACPI layer. 21 * 22 * Battery Management Implementation - 23 * Xen vACPI layer exposes battery information to guest using CMBattery 24 * interface. This virtual firmware CMBattery implementation is very similar to 25 * the actual firmware CMBattery implementation. In fact, a good part of the 26 * below is heavily borrowed from the underlying firmware to support 27 * pass-through and non-pass-through battery management approaches using the 28 * same CMBattery interface implementation. When pass-through approach is used, 29 * the battery ports are directly mapped using xc_domain_ioport_mapping thus 30 * not relying on qemu battery port handling to intercept port reads/writes to 31 * feed relevant battery information to the guest. 32 * 33 * Following are the battery ports read/written to in order to implement 34 * battery support: 35 * Battery command port - 0xb2 36 * Batter data port - 0x86 37 * Battery commands (written to port 0xb2) - 38 * 0x7b - Battery operation init 39 * 0x7c - Type of battery operation 40 * 0x79 - Get battery data length 41 * 0x7d - Get battery data 42 * 43 * Also the following ports are used for debugging/logging: 44 * 0xB040, 0xB044, 0xB046, 0xB048 45 */ 46 47DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) 48{ 49 Scope (\_SB) 50 { 51 OperationRegion (DBGA, SystemIO, 0xB040, 0x01) 52 Field (DBGA, ByteAcc, NoLock, Preserve) 53 { 54 DBG1, 8, 55 } 56 57 OperationRegion (DBGB, SystemIO, 0xB044, 0x01) 58 Field (DBGB, ByteAcc, NoLock, Preserve) 59 { 60 DBG2, 8, 61 } 62 63 OperationRegion (DBGC, SystemIO, 0xB046, 0x01) 64 Field (DBGC, ByteAcc, NoLock, Preserve) 65 { 66 DBG3, 8, 67 } 68 69 OperationRegion (DBGD, SystemIO, 0xB048, 0x01) 70 Field (DBGD, ByteAcc, NoLock, Preserve) 71 { 72 DBG4, 8, 73 } 74 75 OperationRegion (PRT1, SystemIO, 0xB2, 0x02) 76 Field (PRT1, ByteAcc, NoLock, Preserve) 77 { 78 PB2, 8, 79 PB2A, 8 80 } 81 82 OperationRegion (PRT2, SystemIO, 0x86, 0x01) 83 Field (PRT2, ByteAcc, NoLock, Preserve) 84 { 85 P86, 8 86 } 87 88 OperationRegion (PRT3, SystemIO, 0x88, 0x01) 89 Field (PRT3, ByteAcc, NoLock, Preserve) 90 { 91 P88, 8 92 } 93 94 95 Mutex (SYNC, 0x01) 96 Name (BUF0, Buffer (0x0100) {}) 97 Name (BUF1, Buffer (0x08) {}) 98 CreateWordField (BUF1, 0x00, BUFA) 99 CreateWordField (BUF1, 0x04, BUFB) 100 Method (ACQR, 0, NotSerialized) 101 { 102 Acquire (SYNC, 0xFFFF) 103 Store (0x00, BUFA) 104 } 105 106 /* 107 * Initialize relevant buffer to indicate what type of 108 * information is being queried and by what object (e.g. 109 * by battery device 0 or 1). 110 */ 111 Method (INIT, 1, NotSerialized) 112 { 113 Store (BUFA, Local0) 114 Increment (Local0) 115 If (LLessEqual (Local0, SizeOf (BUF0))) 116 { 117 CreateByteField (BUF0, BUFA, TMP1) 118 Store (Arg0, TMP1) 119 Store (Local0, BUFA) 120 } 121 } 122 123 /* 124 * Write to battery port 0xb2 indicating the type of information 125 * to request, initialize battery data port 0x86 and then return 126 * value provided through data port 0x86. 127 */ 128 Method (WPRT, 2, NotSerialized) 129 { 130 Store (Arg1, \_SB.P86) 131 Store (Arg0, \_SB.PB2) 132 Store (Arg0, \_SB.DBG2) 133 Store (Arg1, \_SB.DBG4) 134 Store (\_SB.PB2, Local0) 135 While (LNotEqual (Local0, 0x00)) 136 { 137 Store (\_SB.PB2, Local0) 138 } 139 140 Store (\_SB.P86, Local1) 141 Store (Local1, \_SB.DBG3) 142 Return (\_SB.P86) 143 } 144 145 /* 146 * Helper method 1 to write to battery command and data port. 147 * 0x7c written to port 0xb2 indicating battery info type command. 148 * Value 1 or 2 written to port 0x86. 1 for BIF (batterry info) and 2 149 * for BST (battery status). 150 */ 151 Method (HLP1, 2, NotSerialized) 152 { 153 If (LLess (Arg1, SizeOf (Arg0))) 154 { 155 CreateByteField (Arg0, Arg1, TMP1) 156 WPRT (0x7C, TMP1) 157 } 158 } 159 160 /* 161 * Helper method 2. Value 0x7b written to battery command port 0xb2 162 * indicating battery info initialization request. First thing written 163 * to battery port before querying for further information pertaining 164 * to the battery. 165 */ 166 Method (HLP2, 0, NotSerialized) 167 { 168 WPRT (0x7B, 0x00) 169 Store (0x00, Local0) 170 While (LLess (Local0, BUFA)) 171 { 172 HLP1 (BUF0, Local0) 173 Increment (Local0) 174 } 175 } 176 177 /* 178 * Helper method 3. 0x7d written to battery command port 0xb2 179 * indicating request of battery data returned through battery data 180 * port 0x86. 181 */ 182 Method (HLP3, 2, NotSerialized) 183 { 184 If (LLess (Arg1, SizeOf (Arg0))) 185 { 186 CreateByteField (Arg0, Arg1, TMP1) 187 Store (WPRT (0x7D, 0x00), TMP1) 188 } 189 } 190 191 /* 192 * Helper method 4 to indirectly get battery data and store it in a 193 * local buffer. 194 */ 195 Method (HLP4, 0, NotSerialized) 196 { 197 Store (0x00, Local0) 198 While (LLess (Local0, BUFB)) 199 { 200 Add (BUFA, Local0, Local1) 201 HLP3 (BUF0, Local1) 202 Increment (Local0) 203 } 204 } 205 206 /* 207 * Helper method 5 to indirectly initialize battery port and get 208 * battery data. Also get battery data length by writing 0x79 to 209 * battery command port and receiving battery data length in port 0x86. 210 */ 211 Method (HLP5, 0, NotSerialized) 212 { 213 HLP2 () 214 Store (WPRT (0x79, 0x00), BUFB) 215 Add (BUFA, BUFB, Local0) 216 If (LLess (SizeOf (BUF0), Local0)) 217 { 218 Store (SizeOf (BUF0), Local0) 219 Subtract (Local0, BUFA, Local0) 220 Store (Local0, BUFB) 221 } 222 223 HLP4 () 224 } 225 226 /* Helper method for local buffer housekeeping... */ 227 Method (HLP6, 0, NotSerialized) 228 { 229 Store (BUFA, Local0) 230 Increment (Local0) 231 If (LLessEqual (Local0, SizeOf (BUF0))) 232 { 233 CreateByteField (BUF0, BUFA, TMP1) 234 Store (Local0, BUFA) 235 Return (TMP1) 236 } 237 238 Return (0x00) 239 } 240 241 /* Helper methods to help store battery data retrieved through 242 * battery data port 0x86. */ 243 244 Method (HLP7, 0, NotSerialized) 245 { 246 Store (BUFA, Local0) 247 Add (Local0, 0x04, Local0) 248 If (LLessEqual (Local0, SizeOf (BUF0))) 249 { 250 CreateDWordField (BUF0, BUFA, SX22) 251 Store (Local0, BUFA) 252 Return (SX22) 253 } 254 255 Return (0x00) 256 } 257 258 Method (HLP8, 2, NotSerialized) 259 { 260 If (LLess (Arg1, SizeOf (Arg0))) 261 { 262 CreateByteField (Arg0, Arg1, TMP1) 263 Store (HLP6 (), TMP1) 264 } 265 } 266 267 Method (HLP9, 2, NotSerialized) 268 { 269 Store (0x00, Local0) 270 While (LLess (Local0, Arg1)) 271 { 272 HLP8 (Arg0, Local0) 273 Increment (Local0) 274 } 275 Return (Arg0) 276 } 277 278 Method (HLPA, 0, NotSerialized) 279 { 280 Store (HLP6 (), Local0) 281 Return (HLP9 (Buffer (Local0) {}, Local0)) 282 } 283 284 Method (REL, 0, NotSerialized) 285 { 286 Release (SYNC) 287 } 288 289 /* Future patches will extend AC object to better account for 290 * AC to DC transition and more. */ 291 Device (AC) 292 { 293 Name (_HID, "ACPI0003") 294 Name (_PCL, Package (0x03) 295 { 296 \_SB, 297 BAT0, 298 BAT1 299 }) 300 Method (_PSR, 0, NotSerialized) 301 { 302 Return (0x0) 303 } 304 305 Method (_STA, 0, NotSerialized) 306 { 307 Return (0x0F) 308 } 309 } 310 311 /* Main battery information helper method. */ 312 Name (BIFP, Package (0x0D) {}) 313 Method (BIF, 1, NotSerialized) 314 { 315 ACQR () 316 INIT (0x01) 317 INIT (Arg0) 318 HLP5 () 319 Store (HLP7 (), Index (BIFP, 0x00)) 320 Store (HLP7 (), Index (BIFP, 0x01)) 321 Store (HLP7 (), Index (BIFP, 0x02)) 322 Store (HLP7 (), Index (BIFP, 0x03)) 323 Store (HLP7 (), Index (BIFP, 0x04)) 324 Store (HLP7 (), Index (BIFP, 0x05)) 325 Store (HLP7 (), Index (BIFP, 0x06)) 326 Store (HLP7 (), Index (BIFP, 0x07)) 327 Store (HLP7 (), Index (BIFP, 0x08)) 328 Store (HLPA (), Index (BIFP, 0x09)) 329 Store (HLPA (), Index (BIFP, 0x0A)) 330 Store (HLPA (), Index (BIFP, 0x0B)) 331 Store (HLPA (), Index (BIFP, 0x0C)) 332 REL () 333 Return (BIFP) 334 } 335 336 /* Battery object 0 - Always exposed as present. */ 337 Device (BAT0) 338 { 339 Name (_HID, EisaId ("PNP0C0A")) 340 Name (_UID, 0x01) 341 Name (_PCL, Package (0x01) 342 { 343 \_SB 344 }) 345 346 /* Always returns 0x1f indicating battery present. */ 347 Method (_STA, 0, NotSerialized) 348 { 349 Store (\_SB.P88, Local0) 350 Return ( Local0 ) 351 } 352 353 /* Battery generic info: design capacity, voltage, model # etc. */ 354 Method (_BIF, 0, NotSerialized) 355 { 356 //Store (1, \_SB.DBG1) 357 Store(BIF ( 0x01 ), Local0) 358 //Store (2, \_SB.DBG1) 359 Return( Local0 ) 360 } 361 362 /* Battery status including battery charging/discharging rate. */ 363 Method (_BST, 0, NotSerialized) 364 { 365 Store (1, \_SB.DBG1) 366 ACQR () 367 INIT (0x02) 368 INIT (0x01) 369 HLP5 () 370 Store (Package (0x04) {}, Local0) 371 Store (HLP7 (), Index (Local0, 0x00)) 372 Store (HLP7 (), Index (Local0, 0x01)) 373 Store (HLP7 (), Index (Local0, 0x02)) 374 Store (HLP7 (), Index (Local0, 0x03)) 375 REL () 376 Store (2, \_SB.DBG1) 377 Return (Local0) 378 } 379 } 380 381 /* Battery object 1 - Always exposed as not present. */ 382 Device (BAT1) 383 { 384 Name (_HID, EisaId ("PNP0C0A")) 385 Name (_UID, 0x02) 386 Name (_PCL, Package (0x01) 387 { 388 \_SB 389 }) 390 Method (_STA, 0, NotSerialized) 391 { 392 Return (0x0F) 393 } 394 395 Method (_BIF, 0, NotSerialized) 396 { 397 Store (\_SB.PB2, Local0) 398 Return (BIF (0x02)) 399 } 400 401 Method (_BST, 0, NotSerialized) 402 { 403 ACQR () 404 INIT (0x02) 405 INIT (0x02) 406 HLP5 () 407 Store (Package (0x04) {}, Local0) 408 Store (HLP7 (), Index (Local0, 0x00)) 409 Store (HLP7 (), Index (Local0, 0x01)) 410 Store (HLP7 (), Index (Local0, 0x02)) 411 Store (HLP7 (), Index (Local0, 0x03)) 412 REL () 413 Return (Local0) 414 } 415 } 416 } 417} 418 419