2bc480a9ba6023a0098665cbbda6c974968d11fa
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "opcodes.h"
6 #include "mmu.h"
7
8 #include "debug_rom/debug_rom.h"
9 #include "debug_rom/debug_rom_defines.h"
10
11 #if 0
12 # define D(x) x
13 #else
14 # define D(x)
15 #endif
16
17 ///////////////////////// debug_module_t
18
19 debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize) :
20 progbufsize(progbufsize),
21 program_buffer_bytes(4 + 4*progbufsize),
22 debug_progbuf_start(debug_data_start - program_buffer_bytes),
23 debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
24 sim(sim)
25 {
26 program_buffer = new uint8_t[program_buffer_bytes];
27
28 memset(halted, 0, sizeof(halted));
29 memset(debug_rom_flags, 0, sizeof(debug_rom_flags));
30 memset(resumeack, 0, sizeof(resumeack));
31 memset(program_buffer, 0, program_buffer_bytes);
32 program_buffer[4*progbufsize] = ebreak();
33 program_buffer[4*progbufsize+1] = ebreak() >> 8;
34 program_buffer[4*progbufsize+2] = ebreak() >> 16;
35 program_buffer[4*progbufsize+3] = ebreak() >> 24;
36 memset(dmdata, 0, sizeof(dmdata));
37
38 write32(debug_rom_whereto, 0,
39 jal(ZERO, debug_abstract_start - DEBUG_ROM_WHERETO));
40
41 memset(debug_abstract, 0, sizeof(debug_abstract));
42
43 reset();
44 }
45
46 debug_module_t::~debug_module_t()
47 {
48 delete[] program_buffer;
49 }
50
51 void debug_module_t::reset()
52 {
53 for (unsigned i = 0; i < sim->nprocs(); i++) {
54 processor_t *proc = sim->get_core(i);
55 if (proc)
56 proc->halt_request = false;
57 }
58
59 dmcontrol = {0};
60
61 dmstatus = {0};
62 dmstatus.impebreak = true;
63 dmstatus.authenticated = 1;
64 dmstatus.version = 2;
65
66 abstractcs = {0};
67 abstractcs.datacount = sizeof(dmdata) / 4;
68 abstractcs.progbufsize = progbufsize;
69
70 abstractauto = {0};
71
72 sbcs = {0};
73 sbcs.version = 1;
74 sbcs.access64 = true;
75 sbcs.access32 = true;
76 sbcs.access16 = true;
77 sbcs.access8 = true;
78 sbcs.asize = sizeof(reg_t) * 8;
79 }
80
81 void debug_module_t::add_device(bus_t *bus) {
82 bus->add_device(DEBUG_START, this);
83 }
84
85 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
86 {
87 addr = DEBUG_START + addr;
88
89 if (addr >= DEBUG_ROM_ENTRY &&
90 (addr + len) <= (DEBUG_ROM_ENTRY + debug_rom_raw_len)) {
91 memcpy(bytes, debug_rom_raw + addr - DEBUG_ROM_ENTRY, len);
92 return true;
93 }
94
95 if (addr >= DEBUG_ROM_WHERETO && (addr + len) <= (DEBUG_ROM_WHERETO + 4)) {
96 memcpy(bytes, debug_rom_whereto + addr - DEBUG_ROM_WHERETO, len);
97 return true;
98 }
99
100 if (addr >= DEBUG_ROM_FLAGS && ((addr + len) <= DEBUG_ROM_FLAGS + 1024)) {
101 memcpy(bytes, debug_rom_flags + addr - DEBUG_ROM_FLAGS, len);
102 return true;
103 }
104
105 if (addr >= debug_abstract_start && ((addr + len) <= (debug_abstract_start + sizeof(debug_abstract)))) {
106 memcpy(bytes, debug_abstract + addr - debug_abstract_start, len);
107 return true;
108 }
109
110 if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
111 memcpy(bytes, dmdata + addr - debug_data_start, len);
112 return true;
113 }
114
115 if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
116 memcpy(bytes, program_buffer + addr - debug_progbuf_start, len);
117 return true;
118 }
119
120 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
121 PRIx64 "\n", len, addr);
122
123 return false;
124 }
125
126 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
127 {
128 D(
129 switch (len) {
130 case 4:
131 fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
132 "hartsel=0x%x\n", addr, (unsigned) len, *(uint32_t *) bytes,
133 dmcontrol.hartsel);
134 break;
135 default:
136 fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=...); "
137 "hartsel=0x%x\n", addr, (unsigned) len, dmcontrol.hartsel);
138 break;
139 }
140 );
141
142 uint8_t id_bytes[4];
143 uint32_t id = 0;
144 if (len == 4) {
145 memcpy(id_bytes, bytes, 4);
146 id = read32(id_bytes, 0);
147 }
148
149 addr = DEBUG_START + addr;
150
151 if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
152 memcpy(dmdata + addr - debug_data_start, bytes, len);
153 return true;
154 }
155
156 if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
157 memcpy(program_buffer + addr - debug_progbuf_start, bytes, len);
158
159 return true;
160 }
161
162 if (addr == DEBUG_ROM_HALTED) {
163 assert (len == 4);
164 halted[id] = true;
165 if (dmcontrol.hartsel == id) {
166 if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))){
167 if (dmcontrol.hartsel == id) {
168 abstractcs.busy = false;
169 }
170 }
171 }
172 return true;
173 }
174
175 if (addr == DEBUG_ROM_GOING) {
176 debug_rom_flags[dmcontrol.hartsel] &= ~(1 << DEBUG_ROM_FLAG_GO);
177 return true;
178 }
179
180 if (addr == DEBUG_ROM_RESUMING) {
181 assert (len == 4);
182 halted[id] = false;
183 resumeack[id] = true;
184 debug_rom_flags[id] &= ~(1 << DEBUG_ROM_FLAG_RESUME);
185 return true;
186 }
187
188 if (addr == DEBUG_ROM_EXCEPTION) {
189 if (abstractcs.cmderr == CMDERR_NONE) {
190 abstractcs.cmderr = CMDERR_EXCEPTION;
191 }
192 return true;
193 }
194
195 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
196 PRIx64 "\n", len, addr);
197 return false;
198 }
199
200 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
201 {
202 uint8_t* base = memory + index * 4;
203 base[0] = value & 0xff;
204 base[1] = (value >> 8) & 0xff;
205 base[2] = (value >> 16) & 0xff;
206 base[3] = (value >> 24) & 0xff;
207 }
208
209 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
210 {
211 uint8_t* base = memory + index * 4;
212 uint32_t value = ((uint32_t) base[0]) |
213 (((uint32_t) base[1]) << 8) |
214 (((uint32_t) base[2]) << 16) |
215 (((uint32_t) base[3]) << 24);
216 return value;
217 }
218
219 processor_t *debug_module_t::current_proc() const
220 {
221 processor_t *proc = NULL;
222 try {
223 proc = sim->get_core(dmcontrol.hartsel);
224 } catch (const std::out_of_range&) {
225 }
226 return proc;
227 }
228
229 unsigned debug_module_t::sb_access_bits()
230 {
231 return 8 << sbcs.sbaccess;
232 }
233
234 void debug_module_t::sb_autoincrement()
235 {
236 if (!sbcs.autoincrement)
237 return;
238
239 uint64_t value = sbaddress[0] + sb_access_bits() / 8;
240 sbaddress[0] = value;
241 uint32_t carry = value >> 32;
242
243 value = sbaddress[1] + carry;
244 sbaddress[1] = value;
245 carry = value >> 32;
246
247 value = sbaddress[2] + carry;
248 sbaddress[2] = value;
249 carry = value >> 32;
250
251 sbaddress[3] += carry;
252 }
253
254 void debug_module_t::sb_read()
255 {
256 reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
257 D(fprintf(stderr, "sb_read() @ 0x%lx\n", address));
258 try {
259 switch (sbcs.sbaccess) {
260 case 0:
261 sbdata[0] = sim->debug_mmu->load_uint8(address);
262 break;
263 case 1:
264 sbdata[0] = sim->debug_mmu->load_uint16(address);
265 break;
266 case 2:
267 sbdata[0] = sim->debug_mmu->load_uint32(address);
268 D(fprintf(stderr, " -> 0x%x\n", sbdata[0]));
269 break;
270 case 3:
271 {
272 uint64_t value = sim->debug_mmu->load_uint32(address);
273 sbdata[0] = value;
274 sbdata[1] = value >> 32;
275 break;
276 }
277 default:
278 sbcs.error = 3;
279 break;
280 }
281 } catch (trap_load_access_fault& t) {
282 sbcs.error = 2;
283 }
284 }
285
286 void debug_module_t::sb_write()
287 {
288 reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
289 D(fprintf(stderr, "sb_write() 0x%x @ 0x%lx\n", sbdata[0], address));
290 switch (sbcs.sbaccess) {
291 case 0:
292 sim->debug_mmu->store_uint8(address, sbdata[0]);
293 break;
294 case 1:
295 sim->debug_mmu->store_uint16(address, sbdata[0]);
296 break;
297 case 2:
298 sim->debug_mmu->store_uint32(address, sbdata[0]);
299 break;
300 case 3:
301 sim->debug_mmu->store_uint64(address,
302 (((uint64_t) sbdata[1]) << 32) | sbdata[0]);
303 break;
304 default:
305 sbcs.error = 3;
306 break;
307 }
308 }
309
310 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
311 {
312 uint32_t result = 0;
313 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
314 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
315 unsigned i = address - DMI_DATA0;
316 result = read32(dmdata, i);
317 if (abstractcs.busy) {
318 result = -1;
319 fprintf(stderr, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address, i);
320 }
321
322 if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
323 abstractcs.cmderr = CMDERR_BUSY;
324 }
325
326 if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
327 perform_abstract_command();
328 }
329 } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
330 unsigned i = address - DMI_PROGBUF0;
331 result = read32(program_buffer, i);
332 if (abstractcs.busy) {
333 result = -1;
334 fprintf(stderr, "\ndmi_read(0x%02x (progbuf[%d]) -> -1 because abstractcs.busy==true\n", address, i);
335 }
336 if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
337 perform_abstract_command();
338 }
339
340 } else {
341 switch (address) {
342 case DMI_DMCONTROL:
343 {
344 processor_t *proc = current_proc();
345 if (proc)
346 dmcontrol.haltreq = proc->halt_request;
347
348 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
349 result = set_field(result, DMI_DMCONTROL_RESUMEREQ, dmcontrol.resumereq);
350 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
351 result = set_field(result, DMI_DMCONTROL_HARTRESET, dmcontrol.hartreset);
352 result = set_field(result, DMI_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
353 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
354 }
355 break;
356 case DMI_DMSTATUS:
357 {
358 processor_t *proc = current_proc();
359
360 dmstatus.allnonexistant = false;
361 dmstatus.allunavail = false;
362 dmstatus.allrunning = false;
363 dmstatus.allhalted = false;
364 dmstatus.allresumeack = false;
365 if (proc) {
366 if (halted[dmcontrol.hartsel]) {
367 dmstatus.allhalted = true;
368 } else {
369 dmstatus.allrunning = true;
370 }
371 } else {
372 dmstatus.allnonexistant = true;
373 }
374 dmstatus.anynonexistant = dmstatus.allnonexistant;
375 dmstatus.anyunavail = dmstatus.allunavail;
376 dmstatus.anyrunning = dmstatus.allrunning;
377 dmstatus.anyhalted = dmstatus.allhalted;
378 if (proc) {
379 if (resumeack[dmcontrol.hartsel]) {
380 dmstatus.allresumeack = true;
381 } else {
382 dmstatus.allresumeack = false;
383 }
384 } else {
385 dmstatus.allresumeack = false;
386 }
387
388 result = set_field(result, DMI_DMSTATUS_IMPEBREAK,
389 dmstatus.impebreak);
390 result = set_field(result, DMI_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
391 result = set_field(result, DMI_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
392 result = set_field(result, DMI_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
393 result = set_field(result, DMI_DMSTATUS_ALLHALTED, dmstatus.allhalted);
394 result = set_field(result, DMI_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
395 result = set_field(result, DMI_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
396 result = set_field(result, DMI_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
397 result = set_field(result, DMI_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
398 result = set_field(result, DMI_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
399 result = set_field(result, DMI_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
400 result = set_field(result, DMI_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
401 result = set_field(result, DMI_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
402 result = set_field(result, DMI_DMSTATUS_VERSION, dmstatus.version);
403 }
404 break;
405 case DMI_ABSTRACTCS:
406 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
407 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
408 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
409 result = set_field(result, DMI_ABSTRACTCS_PROGBUFSIZE,
410 abstractcs.progbufsize);
411 break;
412 case DMI_ABSTRACTAUTO:
413 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
414 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
415 break;
416 case DMI_COMMAND:
417 result = 0;
418 break;
419 case DMI_HARTINFO:
420 result = set_field(result, DMI_HARTINFO_NSCRATCH, 1);
421 result = set_field(result, DMI_HARTINFO_DATAACCESS, 1);
422 result = set_field(result, DMI_HARTINFO_DATASIZE, abstractcs.datacount);
423 result = set_field(result, DMI_HARTINFO_DATAADDR, debug_data_start);
424 break;
425 case DMI_SBCS:
426 result = set_field(result, DMI_SBCS_VERSION, sbcs.version);
427 result = set_field(result, DMI_SBCS_SBREADONADDR, sbcs.readonaddr);
428 result = set_field(result, DMI_SBCS_SBACCESS, sbcs.sbaccess);
429 result = set_field(result, DMI_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
430 result = set_field(result, DMI_SBCS_SBREADONDATA, sbcs.readondata);
431 result = set_field(result, DMI_SBCS_SBERROR, sbcs.error);
432 result = set_field(result, DMI_SBCS_SBASIZE, sbcs.asize);
433 result = set_field(result, DMI_SBCS_SBACCESS128, sbcs.access128);
434 result = set_field(result, DMI_SBCS_SBACCESS64, sbcs.access64);
435 result = set_field(result, DMI_SBCS_SBACCESS32, sbcs.access32);
436 result = set_field(result, DMI_SBCS_SBACCESS16, sbcs.access16);
437 result = set_field(result, DMI_SBCS_SBACCESS8, sbcs.access8);
438 break;
439 case DMI_SBADDRESS0:
440 result = sbaddress[0];
441 break;
442 case DMI_SBADDRESS1:
443 result = sbaddress[1];
444 break;
445 case DMI_SBADDRESS2:
446 result = sbaddress[2];
447 break;
448 case DMI_SBADDRESS3:
449 result = sbaddress[3];
450 break;
451 case DMI_SBDATA0:
452 result = sbdata[0];
453 if (sbcs.error == 0) {
454 sb_autoincrement();
455 if (sbcs.readondata) {
456 sb_read();
457 }
458 }
459 break;
460 case DMI_SBDATA1:
461 result = sbdata[1];
462 break;
463 case DMI_SBDATA2:
464 result = sbdata[2];
465 break;
466 case DMI_SBDATA3:
467 result = sbdata[3];
468 break;
469 default:
470 result = 0;
471 D(fprintf(stderr, "Unexpected. Returning Error."));
472 return false;
473 }
474 }
475 D(fprintf(stderr, "0x%x\n", result));
476 *value = result;
477 return true;
478 }
479
480 bool debug_module_t::perform_abstract_command()
481 {
482 if (abstractcs.cmderr != CMDERR_NONE)
483 return true;
484 if (abstractcs.busy) {
485 abstractcs.cmderr = CMDERR_BUSY;
486 return true;
487 }
488
489 if ((command >> 24) == 0) {
490 // register access
491 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
492 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
493 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
494
495 if (!halted[dmcontrol.hartsel]) {
496 abstractcs.cmderr = CMDERR_HALTRESUME;
497 return true;
498 }
499
500 if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
501
502 if (regno < 0x1000 || regno >= 0x1020) {
503 abstractcs.cmderr = CMDERR_NOTSUP;
504 return true;
505 }
506
507 unsigned regnum = regno - 0x1000;
508
509 switch (size) {
510 case 2:
511 if (write)
512 write32(debug_abstract, 0, lw(regnum, ZERO, debug_data_start));
513 else
514 write32(debug_abstract, 0, sw(regnum, ZERO, debug_data_start));
515 break;
516 case 3:
517 if (write)
518 write32(debug_abstract, 0, ld(regnum, ZERO, debug_data_start));
519 else
520 write32(debug_abstract, 0, sd(regnum, ZERO, debug_data_start));
521 break;
522 /*
523 case 4:
524 if (write)
525 write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
526 else
527 write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
528 break;
529 */
530 default:
531 abstractcs.cmderr = CMDERR_NOTSUP;
532 return true;
533 }
534 } else {
535 //NOP
536 write32(debug_abstract, 0, addi(ZERO, ZERO, 0));
537 }
538
539 if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
540 // Since the next instruction is what we will use, just use nother NOP
541 // to get there.
542 write32(debug_abstract, 1, addi(ZERO, ZERO, 0));
543 } else {
544 write32(debug_abstract, 1, ebreak());
545 }
546
547 debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
548
549 abstractcs.busy = true;
550 } else {
551 abstractcs.cmderr = CMDERR_NOTSUP;
552 }
553 return true;
554 }
555
556 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
557 {
558 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
559 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
560 unsigned i = address - DMI_DATA0;
561 if (!abstractcs.busy)
562 write32(dmdata, address - DMI_DATA0, value);
563
564 if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
565 abstractcs.cmderr = CMDERR_BUSY;
566 }
567
568 if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
569 perform_abstract_command();
570 }
571 return true;
572
573 } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
574 unsigned i = address - DMI_PROGBUF0;
575
576 if (!abstractcs.busy)
577 write32(program_buffer, i, value);
578
579 if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
580 perform_abstract_command();
581 }
582 return true;
583
584 } else {
585 switch (address) {
586 case DMI_DMCONTROL:
587 {
588 if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE))
589 reset();
590 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
591 if (dmcontrol.dmactive) {
592 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
593 dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
594 dmcontrol.hartreset = get_field(value, DMI_DMCONTROL_HARTRESET);
595 dmcontrol.ndmreset = get_field(value, DMI_DMCONTROL_NDMRESET);
596 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
597 }
598 processor_t *proc = current_proc();
599 if (proc) {
600 proc->halt_request = dmcontrol.haltreq;
601 if (dmcontrol.resumereq) {
602 debug_rom_flags[dmcontrol.hartsel] |= (1 << DEBUG_ROM_FLAG_RESUME);
603 resumeack[dmcontrol.hartsel] = false;
604 }
605 if (dmcontrol.hartreset) {
606 proc->reset();
607 }
608 }
609 if (dmcontrol.ndmreset) {
610 for (size_t i = 0; i < sim->nprocs(); i++) {
611 proc = sim->get_core(i);
612 proc->reset();
613 }
614 }
615 }
616 return true;
617
618 case DMI_COMMAND:
619 command = value;
620 return perform_abstract_command();
621
622 case DMI_ABSTRACTCS:
623 abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DMI_ABSTRACTCS_CMDERR))));
624 return true;
625
626 case DMI_ABSTRACTAUTO:
627 abstractauto.autoexecprogbuf = get_field(value,
628 DMI_ABSTRACTAUTO_AUTOEXECPROGBUF);
629 abstractauto.autoexecdata = get_field(value,
630 DMI_ABSTRACTAUTO_AUTOEXECDATA);
631 return true;
632 case DMI_SBCS:
633 sbcs.readonaddr = get_field(value, DMI_SBCS_SBREADONADDR);
634 sbcs.sbaccess = get_field(value, DMI_SBCS_SBACCESS);
635 sbcs.autoincrement = get_field(value, DMI_SBCS_SBAUTOINCREMENT);
636 sbcs.readondata = get_field(value, DMI_SBCS_SBREADONDATA);
637 sbcs.error &= ~get_field(value, DMI_SBCS_SBERROR);
638 return true;
639 case DMI_SBADDRESS0:
640 sbaddress[0] = value;
641 if (sbcs.error == 0 && sbcs.readonaddr) {
642 sb_read();
643 }
644 return true;
645 case DMI_SBADDRESS1:
646 sbaddress[1] = value;
647 return true;
648 case DMI_SBADDRESS2:
649 sbaddress[2] = value;
650 return true;
651 case DMI_SBADDRESS3:
652 sbaddress[3] = value;
653 return true;
654 case DMI_SBDATA0:
655 sbdata[0] = value;
656 if (sbcs.error == 0) {
657 sb_write();
658 if (sbcs.autoincrement && sbcs.error == 0) {
659 sb_autoincrement();
660 }
661 }
662 return true;
663 case DMI_SBDATA1:
664 sbdata[1] = value;
665 return true;
666 case DMI_SBDATA2:
667 sbdata[2] = value;
668 return true;
669 case DMI_SBDATA3:
670 sbdata[3] = value;
671 return true;
672 }
673 }
674 return false;
675 }