]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/misc/applesmc.c
applesmc: cosmetic whitespace and indentation cleanup
[thirdparty/qemu.git] / hw / misc / applesmc.c
CommitLineData
1ddda5cd
AG
1/*
2 * Apple SMC controller
3 *
4 * Copyright (c) 2007 Alexander Graf
5 *
6 * Authors: Alexander Graf <agraf@suse.de>
7 * Susanne Graf <suse@csgraf.de>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 *
22 * *****************************************************************
23 *
24 * In all Intel-based Apple hardware there is an SMC chip to control the
25 * backlight, fans and several other generic device parameters. It also
26 * contains the magic keys used to dongle Mac OS X to the device.
27 *
28 * This driver was mostly created by looking at the Linux AppleSMC driver
29 * implementation and does not support IRQ.
30 *
31 */
32
0d1c9782 33#include "qemu/osdep.h"
83c9f4ca 34#include "hw/hw.h"
0d09e41a 35#include "hw/isa/isa.h"
28ecbaee 36#include "ui/console.h"
1de7afc9 37#include "qemu/timer.h"
1ddda5cd
AG
38
39/* #define DEBUG_SMC */
40
41#define APPLESMC_DEFAULT_IOBASE 0x300
1ddda5cd 42
36bcd035
GS
43enum {
44 APPLESMC_DATA_PORT = 0x00,
45 APPLESMC_CMD_PORT = 0x04,
46 APPLESMC_NUM_PORTS = 0x20,
47};
48
49enum {
50 APPLESMC_READ_CMD = 0x10,
51 APPLESMC_WRITE_CMD = 0x11,
52 APPLESMC_GET_KEY_BY_INDEX_CMD = 0x12,
53 APPLESMC_GET_KEY_TYPE_CMD = 0x13,
54};
1ddda5cd
AG
55
56#ifdef DEBUG_SMC
57#define smc_debug(...) fprintf(stderr, "AppleSMC: " __VA_ARGS__)
58#else
36bcd035 59#define smc_debug(...) do { } while (0)
1ddda5cd
AG
60#endif
61
62static char default_osk[64] = "This is a dummy key. Enter the real key "
63 "using the -osk parameter";
64
65struct AppleSMCData {
66 uint8_t len;
67 const char *key;
68 const char *data;
69 QLIST_ENTRY(AppleSMCData) node;
70};
71
82407b6c
AF
72#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
73
74typedef struct AppleSMCState AppleSMCState;
75struct AppleSMCState {
76 ISADevice parent_obj;
77
e3914e3a
JK
78 MemoryRegion io_data;
79 MemoryRegion io_cmd;
1ddda5cd
AG
80 uint32_t iobase;
81 uint8_t cmd;
82 uint8_t status;
36bcd035 83 char key[4];
1ddda5cd
AG
84 uint8_t read_pos;
85 uint8_t data_len;
86 uint8_t data_pos;
87 uint8_t data[255];
1ddda5cd
AG
88 char *osk;
89 QLIST_HEAD(, AppleSMCData) data_def;
90};
91
e3914e3a
JK
92static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val,
93 unsigned size)
1ddda5cd 94{
82407b6c 95 AppleSMCState *s = opaque;
1ddda5cd
AG
96
97 smc_debug("CMD Write B: %#x = %#x\n", addr, val);
36bcd035
GS
98 switch (val) {
99 case APPLESMC_READ_CMD:
100 s->status = 0x0c;
101 break;
1ddda5cd
AG
102 }
103 s->cmd = val;
104 s->read_pos = 0;
105 s->data_pos = 0;
106}
107
82407b6c 108static void applesmc_fill_data(AppleSMCState *s)
1ddda5cd
AG
109{
110 struct AppleSMCData *d;
111
112 QLIST_FOREACH(d, &s->data_def, node) {
113 if (!memcmp(d->key, s->key, 4)) {
114 smc_debug("Key matched (%s Len=%d Data=%s)\n", d->key,
115 d->len, d->data);
116 memcpy(s->data, d->data, d->len);
117 return;
118 }
119 }
120}
121
e3914e3a
JK
122static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val,
123 unsigned size)
1ddda5cd 124{
82407b6c 125 AppleSMCState *s = opaque;
1ddda5cd
AG
126
127 smc_debug("DATA Write B: %#x = %#x\n", addr, val);
36bcd035
GS
128 switch (s->cmd) {
129 case APPLESMC_READ_CMD:
130 if (s->read_pos < 4) {
131 s->key[s->read_pos] = val;
132 s->status = 0x04;
133 } else if (s->read_pos == 4) {
134 s->data_len = val;
135 s->status = 0x05;
136 s->data_pos = 0;
137 smc_debug("Key = %c%c%c%c Len = %d\n", s->key[0],
138 s->key[1], s->key[2], s->key[3], val);
139 applesmc_fill_data(s);
140 }
141 s->read_pos++;
142 break;
1ddda5cd
AG
143 }
144}
145
36bcd035 146static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr, unsigned size)
1ddda5cd 147{
82407b6c 148 AppleSMCState *s = opaque;
1ddda5cd
AG
149 uint8_t retval = 0;
150
36bcd035
GS
151 switch (s->cmd) {
152 case APPLESMC_READ_CMD:
153 if (s->data_pos < s->data_len) {
154 retval = s->data[s->data_pos];
155 smc_debug("READ_DATA[%d] = %#hhx\n", s->data_pos,
156 retval);
157 s->data_pos++;
158 if (s->data_pos == s->data_len) {
159 s->status = 0x00;
160 smc_debug("EOF\n");
161 } else {
162 s->status = 0x05;
1ddda5cd 163 }
36bcd035 164 }
1ddda5cd 165 }
36bcd035 166 smc_debug("DATA Read b: %#x = %#x\n", addr, retval);
1ddda5cd
AG
167
168 return retval;
169}
170
36bcd035 171static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr, unsigned size)
1ddda5cd 172{
82407b6c 173 AppleSMCState *s = opaque;
1ddda5cd 174
36bcd035 175 smc_debug("CMD Read B: %#x\n", addr);
1ddda5cd
AG
176 return s->status;
177}
178
82407b6c 179static void applesmc_add_key(AppleSMCState *s, const char *key,
1ddda5cd
AG
180 int len, const char *data)
181{
182 struct AppleSMCData *def;
183
7267c094 184 def = g_malloc0(sizeof(struct AppleSMCData));
1ddda5cd
AG
185 def->key = key;
186 def->len = len;
187 def->data = data;
188
189 QLIST_INSERT_HEAD(&s->data_def, def, node);
190}
191
192static void qdev_applesmc_isa_reset(DeviceState *dev)
193{
82407b6c 194 AppleSMCState *s = APPLE_SMC(dev);
1ddda5cd
AG
195 struct AppleSMCData *d, *next;
196
197 /* Remove existing entries */
198 QLIST_FOREACH_SAFE(d, &s->data_def, node, next) {
199 QLIST_REMOVE(d, node);
200 }
201
7f90fa77 202 applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03");
1ddda5cd
AG
203 applesmc_add_key(s, "OSK0", 32, s->osk);
204 applesmc_add_key(s, "OSK1", 32, s->osk + 32);
205 applesmc_add_key(s, "NATJ", 1, "\0");
206 applesmc_add_key(s, "MSSP", 1, "\0");
207 applesmc_add_key(s, "MSSD", 1, "\0x3");
208}
209
e3914e3a
JK
210static const MemoryRegionOps applesmc_data_io_ops = {
211 .write = applesmc_io_data_write,
212 .read = applesmc_io_data_read,
213 .endianness = DEVICE_NATIVE_ENDIAN,
214 .impl = {
215 .min_access_size = 1,
216 .max_access_size = 1,
217 },
218};
219
220static const MemoryRegionOps applesmc_cmd_io_ops = {
221 .write = applesmc_io_cmd_write,
222 .read = applesmc_io_cmd_read,
223 .endianness = DEVICE_NATIVE_ENDIAN,
224 .impl = {
225 .min_access_size = 1,
226 .max_access_size = 1,
227 },
228};
229
db895a1e 230static void applesmc_isa_realize(DeviceState *dev, Error **errp)
1ddda5cd 231{
82407b6c 232 AppleSMCState *s = APPLE_SMC(dev);
1ddda5cd 233
3c161542 234 memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s,
e3914e3a
JK
235 "applesmc-data", 4);
236 isa_register_ioport(&s->parent_obj, &s->io_data,
237 s->iobase + APPLESMC_DATA_PORT);
238
3c161542 239 memory_region_init_io(&s->io_cmd, OBJECT(s), &applesmc_cmd_io_ops, s,
e3914e3a
JK
240 "applesmc-cmd", 4);
241 isa_register_ioport(&s->parent_obj, &s->io_cmd,
242 s->iobase + APPLESMC_CMD_PORT);
1ddda5cd
AG
243
244 if (!s->osk || (strlen(s->osk) != 64)) {
245 fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n");
246 s->osk = default_osk;
247 }
248
249 QLIST_INIT(&s->data_def);
db895a1e 250 qdev_applesmc_isa_reset(dev);
1ddda5cd
AG
251}
252
39bffca2 253static Property applesmc_isa_properties[] = {
1142e45f
IM
254 DEFINE_PROP_UINT32(APPLESMC_PROP_IO_BASE, AppleSMCState, iobase,
255 APPLESMC_DEFAULT_IOBASE),
82407b6c 256 DEFINE_PROP_STRING("osk", AppleSMCState, osk),
39bffca2
AL
257 DEFINE_PROP_END_OF_LIST(),
258};
259
8f04ee08
AL
260static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
261{
39bffca2 262 DeviceClass *dc = DEVICE_CLASS(klass);
db895a1e
AF
263
264 dc->realize = applesmc_isa_realize;
39bffca2
AL
265 dc->reset = qdev_applesmc_isa_reset;
266 dc->props = applesmc_isa_properties;
125ee0ed 267 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
8f04ee08
AL
268}
269
8c43a6f0 270static const TypeInfo applesmc_isa_info = {
82407b6c 271 .name = TYPE_APPLE_SMC,
39bffca2 272 .parent = TYPE_ISA_DEVICE,
82407b6c 273 .instance_size = sizeof(AppleSMCState),
39bffca2 274 .class_init = qdev_applesmc_class_init,
1ddda5cd
AG
275};
276
83f7d43a 277static void applesmc_register_types(void)
1ddda5cd 278{
39bffca2 279 type_register_static(&applesmc_isa_info);
1ddda5cd
AG
280}
281
83f7d43a 282type_init(applesmc_register_types)