1 | /* |
2 | * QEMU PC APM controller Emulation |
3 | * This is split out from acpi.c |
4 | * |
5 | * Copyright (c) 2006 Fabrice Bellard |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License version 2 as published by the Free Software Foundation. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/> |
18 | * |
19 | * Contributions after 2012-01-13 are licensed under the terms of the |
20 | * GNU GPL, version 2 or (at your option) any later version. |
21 | */ |
22 | |
23 | #include "qemu/osdep.h" |
24 | #include "hw/isa/apm.h" |
25 | #include "hw/pci/pci.h" |
26 | #include "migration/vmstate.h" |
27 | |
28 | //#define DEBUG |
29 | |
30 | #ifdef DEBUG |
31 | # define APM_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) |
32 | #else |
33 | # define APM_DPRINTF(format, ...) do { } while (0) |
34 | #endif |
35 | |
36 | /* fixed I/O location */ |
37 | #define APM_STS_IOPORT 0xb3 |
38 | |
39 | static void apm_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, |
40 | unsigned size) |
41 | { |
42 | APMState *apm = opaque; |
43 | addr &= 1; |
44 | APM_DPRINTF("apm_ioport_writeb addr=0x%" HWADDR_PRIx |
45 | " val=0x%02" PRIx64 "\n" , addr, val); |
46 | if (addr == 0) { |
47 | apm->apmc = val; |
48 | |
49 | if (apm->callback) { |
50 | (apm->callback)(val, apm->arg); |
51 | } |
52 | } else { |
53 | apm->apms = val; |
54 | } |
55 | } |
56 | |
57 | static uint64_t apm_ioport_readb(void *opaque, hwaddr addr, unsigned size) |
58 | { |
59 | APMState *apm = opaque; |
60 | uint32_t val; |
61 | |
62 | addr &= 1; |
63 | if (addr == 0) { |
64 | val = apm->apmc; |
65 | } else { |
66 | val = apm->apms; |
67 | } |
68 | APM_DPRINTF("apm_ioport_readb addr=0x%" HWADDR_PRIx " val=0x%02x\n" , addr, val); |
69 | return val; |
70 | } |
71 | |
72 | const VMStateDescription vmstate_apm = { |
73 | .name = "APM State" , |
74 | .version_id = 1, |
75 | .minimum_version_id = 1, |
76 | .fields = (VMStateField[]) { |
77 | VMSTATE_UINT8(apmc, APMState), |
78 | VMSTATE_UINT8(apms, APMState), |
79 | VMSTATE_END_OF_LIST() |
80 | } |
81 | }; |
82 | |
83 | static const MemoryRegionOps apm_ops = { |
84 | .read = apm_ioport_readb, |
85 | .write = apm_ioport_writeb, |
86 | .impl = { |
87 | .min_access_size = 1, |
88 | .max_access_size = 1, |
89 | }, |
90 | }; |
91 | |
92 | void apm_init(PCIDevice *dev, APMState *apm, apm_ctrl_changed_t callback, |
93 | void *arg) |
94 | { |
95 | apm->callback = callback; |
96 | apm->arg = arg; |
97 | |
98 | /* ioport 0xb2, 0xb3 */ |
99 | memory_region_init_io(&apm->io, OBJECT(dev), &apm_ops, apm, "apm-io" , 2); |
100 | memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT, |
101 | &apm->io); |
102 | } |
103 | |