Disable preadv/pwritev support
[qemu-kvm/fedora.git] / hw / smbus.c
blob5618902e7a28093fdf269be07d07ef13e5311de4
1 /*
2 * QEMU SMBus device emulation.
4 * Copyright (c) 2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the LGPL.
8 */
10 /* TODO: Implement PEC. */
12 #include "hw.h"
13 #include "i2c.h"
14 #include "smbus.h"
16 //#define DEBUG_SMBUS 1
18 #ifdef DEBUG_SMBUS
19 #define DPRINTF(fmt, ...) \
20 do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
21 #define BADF(fmt, ...) \
22 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
23 #else
24 #define DPRINTF(fmt, ...) do {} while(0)
25 #define BADF(fmt, ...) \
26 do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
27 #endif
29 enum {
30 SMBUS_IDLE,
31 SMBUS_WRITE_DATA,
32 SMBUS_RECV_BYTE,
33 SMBUS_READ_DATA,
34 SMBUS_DONE,
35 SMBUS_CONFUSED = -1
38 static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
40 SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
42 DPRINTF("Quick Command %d\n", recv);
43 if (t->quick_cmd)
44 t->quick_cmd(dev, recv);
47 static void smbus_do_write(SMBusDevice *dev)
49 SMBusDeviceInfo *t = container_of(dev->i2c.info, SMBusDeviceInfo, i2c);
51 if (dev->data_len == 0) {
52 smbus_do_quick_cmd(dev, 0);
53 } else if (dev->data_len == 1) {
54 DPRINTF("Send Byte\n");
55 if (t->send_byte) {
56 t->send_byte(dev, dev->data_buf[0]);
58 } else {
59 dev->command = dev->data_buf[0];
60 DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
61 if (t->write_data) {
62 t->write_data(dev, dev->command, dev->data_buf + 1,
63 dev->data_len - 1);
68 static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
70 SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
72 switch (event) {
73 case I2C_START_SEND:
74 switch (dev->mode) {
75 case SMBUS_IDLE:
76 DPRINTF("Incoming data\n");
77 dev->mode = SMBUS_WRITE_DATA;
78 break;
79 default:
80 BADF("Unexpected send start condition in state %d\n", dev->mode);
81 dev->mode = SMBUS_CONFUSED;
82 break;
84 break;
86 case I2C_START_RECV:
87 switch (dev->mode) {
88 case SMBUS_IDLE:
89 DPRINTF("Read mode\n");
90 dev->mode = SMBUS_RECV_BYTE;
91 break;
92 case SMBUS_WRITE_DATA:
93 if (dev->data_len == 0) {
94 BADF("Read after write with no data\n");
95 dev->mode = SMBUS_CONFUSED;
96 } else {
97 if (dev->data_len > 1) {
98 smbus_do_write(dev);
99 } else {
100 dev->command = dev->data_buf[0];
101 DPRINTF("%02x: Command %d\n", dev->i2c.address,
102 dev->command);
104 DPRINTF("Read mode\n");
105 dev->data_len = 0;
106 dev->mode = SMBUS_READ_DATA;
108 break;
109 default:
110 BADF("Unexpected recv start condition in state %d\n", dev->mode);
111 dev->mode = SMBUS_CONFUSED;
112 break;
114 break;
116 case I2C_FINISH:
117 switch (dev->mode) {
118 case SMBUS_WRITE_DATA:
119 smbus_do_write(dev);
120 break;
121 case SMBUS_RECV_BYTE:
122 smbus_do_quick_cmd(dev, 1);
123 break;
124 case SMBUS_READ_DATA:
125 BADF("Unexpected stop during receive\n");
126 break;
127 default:
128 /* Nothing to do. */
129 break;
131 dev->mode = SMBUS_IDLE;
132 dev->data_len = 0;
133 break;
135 case I2C_NACK:
136 switch (dev->mode) {
137 case SMBUS_DONE:
138 /* Nothing to do. */
139 break;
140 case SMBUS_READ_DATA:
141 dev->mode = SMBUS_DONE;
142 break;
143 default:
144 BADF("Unexpected NACK in state %d\n", dev->mode);
145 dev->mode = SMBUS_CONFUSED;
146 break;
151 static int smbus_i2c_recv(i2c_slave *s)
153 SMBusDeviceInfo *t = container_of(s->info, SMBusDeviceInfo, i2c);
154 SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
155 int ret;
157 switch (dev->mode) {
158 case SMBUS_RECV_BYTE:
159 if (t->receive_byte) {
160 ret = t->receive_byte(dev);
161 } else {
162 ret = 0;
164 DPRINTF("Receive Byte %02x\n", ret);
165 dev->mode = SMBUS_DONE;
166 break;
167 case SMBUS_READ_DATA:
168 if (t->read_data) {
169 ret = t->read_data(dev, dev->command, dev->data_len);
170 dev->data_len++;
171 } else {
172 ret = 0;
174 DPRINTF("Read data %02x\n", ret);
175 break;
176 default:
177 BADF("Unexpected read in state %d\n", dev->mode);
178 dev->mode = SMBUS_CONFUSED;
179 ret = 0;
180 break;
182 return ret;
185 static int smbus_i2c_send(i2c_slave *s, uint8_t data)
187 SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, s);
189 switch (dev->mode) {
190 case SMBUS_WRITE_DATA:
191 DPRINTF("Write data %02x\n", data);
192 dev->data_buf[dev->data_len++] = data;
193 break;
194 default:
195 BADF("Unexpected write in state %d\n", dev->mode);
196 break;
198 return 0;
201 static void smbus_device_init(i2c_slave *i2c)
203 SMBusDeviceInfo *t = container_of(i2c->info, SMBusDeviceInfo, i2c);
204 SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, i2c);
206 t->init(dev);
209 void smbus_register_device(SMBusDeviceInfo *info)
211 assert(info->i2c.qdev.size >= sizeof(SMBusDevice));
212 info->i2c.init = smbus_device_init;
213 info->i2c.event = smbus_i2c_event;
214 info->i2c.recv = smbus_i2c_recv;
215 info->i2c.send = smbus_i2c_send;
216 i2c_register_slave(&info->i2c);
219 /* Master device commands. */
220 void smbus_quick_command(i2c_bus *bus, int addr, int read)
222 i2c_start_transfer(bus, addr, read);
223 i2c_end_transfer(bus);
226 uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
228 uint8_t data;
230 i2c_start_transfer(bus, addr, 1);
231 data = i2c_recv(bus);
232 i2c_nack(bus);
233 i2c_end_transfer(bus);
234 return data;
237 void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data)
239 i2c_start_transfer(bus, addr, 0);
240 i2c_send(bus, data);
241 i2c_end_transfer(bus);
244 uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command)
246 uint8_t data;
247 i2c_start_transfer(bus, addr, 0);
248 i2c_send(bus, command);
249 i2c_start_transfer(bus, addr, 1);
250 data = i2c_recv(bus);
251 i2c_nack(bus);
252 i2c_end_transfer(bus);
253 return data;
256 void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data)
258 i2c_start_transfer(bus, addr, 0);
259 i2c_send(bus, command);
260 i2c_send(bus, data);
261 i2c_end_transfer(bus);
264 uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command)
266 uint16_t data;
267 i2c_start_transfer(bus, addr, 0);
268 i2c_send(bus, command);
269 i2c_start_transfer(bus, addr, 1);
270 data = i2c_recv(bus);
271 data |= i2c_recv(bus) << 8;
272 i2c_nack(bus);
273 i2c_end_transfer(bus);
274 return data;
277 void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data)
279 i2c_start_transfer(bus, addr, 0);
280 i2c_send(bus, command);
281 i2c_send(bus, data & 0xff);
282 i2c_send(bus, data >> 8);
283 i2c_end_transfer(bus);
286 int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data)
288 int len;
289 int i;
291 i2c_start_transfer(bus, addr, 0);
292 i2c_send(bus, command);
293 i2c_start_transfer(bus, addr, 1);
294 len = i2c_recv(bus);
295 if (len > 32)
296 len = 0;
297 for (i = 0; i < len; i++)
298 data[i] = i2c_recv(bus);
299 i2c_nack(bus);
300 i2c_end_transfer(bus);
301 return len;
304 void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
305 int len)
307 int i;
309 if (len > 32)
310 len = 32;
312 i2c_start_transfer(bus, addr, 0);
313 i2c_send(bus, command);
314 i2c_send(bus, len);
315 for (i = 0; i < len; i++)
316 i2c_send(bus, data[i]);
317 i2c_end_transfer(bus);