Update debug_defines
[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, ((1L<<hartsellen)-1) <<
351 DMI_DMCONTROL_HARTSEL_OFFSET, dmcontrol.hartsel);
352 result = set_field(result, DMI_DMCONTROL_HARTRESET, dmcontrol.hartreset);
353 result = set_field(result, DMI_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
354 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
355 }
356 break;
357 case DMI_DMSTATUS:
358 {
359 processor_t *proc = current_proc();
360
361 dmstatus.allnonexistant = false;
362 dmstatus.allunavail = false;
363 dmstatus.allrunning = false;
364 dmstatus.allhalted = false;
365 dmstatus.allresumeack = false;
366 if (proc) {
367 if (halted[dmcontrol.hartsel]) {
368 dmstatus.allhalted = true;
369 } else {
370 dmstatus.allrunning = true;
371 }
372 } else {
373 dmstatus.allnonexistant = true;
374 }
375 dmstatus.anynonexistant = dmstatus.allnonexistant;
376 dmstatus.anyunavail = dmstatus.allunavail;
377 dmstatus.anyrunning = dmstatus.allrunning;
378 dmstatus.anyhalted = dmstatus.allhalted;
379 if (proc) {
380 if (resumeack[dmcontrol.hartsel]) {
381 dmstatus.allresumeack = true;
382 } else {
383 dmstatus.allresumeack = false;
384 }
385 } else {
386 dmstatus.allresumeack = false;
387 }
388
389 result = set_field(result, DMI_DMSTATUS_IMPEBREAK,
390 dmstatus.impebreak);
391 result = set_field(result, DMI_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
392 result = set_field(result, DMI_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
393 result = set_field(result, DMI_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
394 result = set_field(result, DMI_DMSTATUS_ALLHALTED, dmstatus.allhalted);
395 result = set_field(result, DMI_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
396 result = set_field(result, DMI_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
397 result = set_field(result, DMI_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
398 result = set_field(result, DMI_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
399 result = set_field(result, DMI_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
400 result = set_field(result, DMI_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
401 result = set_field(result, DMI_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
402 result = set_field(result, DMI_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
403 result = set_field(result, DMI_DMSTATUS_VERSION, dmstatus.version);
404 }
405 break;
406 case DMI_ABSTRACTCS:
407 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
408 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
409 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
410 result = set_field(result, DMI_ABSTRACTCS_PROGBUFSIZE,
411 abstractcs.progbufsize);
412 break;
413 case DMI_ABSTRACTAUTO:
414 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
415 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
416 break;
417 case DMI_COMMAND:
418 result = 0;
419 break;
420 case DMI_HARTINFO:
421 result = set_field(result, DMI_HARTINFO_NSCRATCH, 1);
422 result = set_field(result, DMI_HARTINFO_DATAACCESS, 1);
423 result = set_field(result, DMI_HARTINFO_DATASIZE, abstractcs.datacount);
424 result = set_field(result, DMI_HARTINFO_DATAADDR, debug_data_start);
425 break;
426 case DMI_SBCS:
427 result = set_field(result, DMI_SBCS_SBVERSION, sbcs.version);
428 result = set_field(result, DMI_SBCS_SBREADONADDR, sbcs.readonaddr);
429 result = set_field(result, DMI_SBCS_SBACCESS, sbcs.sbaccess);
430 result = set_field(result, DMI_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
431 result = set_field(result, DMI_SBCS_SBREADONDATA, sbcs.readondata);
432 result = set_field(result, DMI_SBCS_SBERROR, sbcs.error);
433 result = set_field(result, DMI_SBCS_SBASIZE, sbcs.asize);
434 result = set_field(result, DMI_SBCS_SBACCESS128, sbcs.access128);
435 result = set_field(result, DMI_SBCS_SBACCESS64, sbcs.access64);
436 result = set_field(result, DMI_SBCS_SBACCESS32, sbcs.access32);
437 result = set_field(result, DMI_SBCS_SBACCESS16, sbcs.access16);
438 result = set_field(result, DMI_SBCS_SBACCESS8, sbcs.access8);
439 break;
440 case DMI_SBADDRESS0:
441 result = sbaddress[0];
442 break;
443 case DMI_SBADDRESS1:
444 result = sbaddress[1];
445 break;
446 case DMI_SBADDRESS2:
447 result = sbaddress[2];
448 break;
449 case DMI_SBADDRESS3:
450 result = sbaddress[3];
451 break;
452 case DMI_SBDATA0:
453 result = sbdata[0];
454 if (sbcs.error == 0) {
455 sb_autoincrement();
456 if (sbcs.readondata) {
457 sb_read();
458 }
459 }
460 break;
461 case DMI_SBDATA1:
462 result = sbdata[1];
463 break;
464 case DMI_SBDATA2:
465 result = sbdata[2];
466 break;
467 case DMI_SBDATA3:
468 result = sbdata[3];
469 break;
470 default:
471 result = 0;
472 D(fprintf(stderr, "Unexpected. Returning Error."));
473 return false;
474 }
475 }
476 D(fprintf(stderr, "0x%x\n", result));
477 *value = result;
478 return true;
479 }
480
481 bool debug_module_t::perform_abstract_command()
482 {
483 if (abstractcs.cmderr != CMDERR_NONE)
484 return true;
485 if (abstractcs.busy) {
486 abstractcs.cmderr = CMDERR_BUSY;
487 return true;
488 }
489
490 if ((command >> 24) == 0) {
491 // register access
492 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
493 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
494 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
495
496 if (!halted[dmcontrol.hartsel]) {
497 abstractcs.cmderr = CMDERR_HALTRESUME;
498 return true;
499 }
500
501 if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
502
503 if (regno < 0x1000 || regno >= 0x1020) {
504 abstractcs.cmderr = CMDERR_NOTSUP;
505 return true;
506 }
507
508 unsigned regnum = regno - 0x1000;
509
510 switch (size) {
511 case 2:
512 if (write)
513 write32(debug_abstract, 0, lw(regnum, ZERO, debug_data_start));
514 else
515 write32(debug_abstract, 0, sw(regnum, ZERO, debug_data_start));
516 break;
517 case 3:
518 if (write)
519 write32(debug_abstract, 0, ld(regnum, ZERO, debug_data_start));
520 else
521 write32(debug_abstract, 0, sd(regnum, ZERO, debug_data_start));
522 break;
523 /*
524 case 4:
525 if (write)
526 write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
527 else
528 write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
529 break;
530 */
531 default:
532 abstractcs.cmderr = CMDERR_NOTSUP;
533 return true;
534 }
535 } else {
536 //NOP
537 write32(debug_abstract, 0, addi(ZERO, ZERO, 0));
538 }
539
540 if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
541 // Since the next instruction is what we will use, just use nother NOP
542 // to get there.
543 write32(debug_abstract, 1, addi(ZERO, ZERO, 0));
544 } else {
545 write32(debug_abstract, 1, ebreak());
546 }
547
548 debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
549
550 abstractcs.busy = true;
551 } else {
552 abstractcs.cmderr = CMDERR_NOTSUP;
553 }
554 return true;
555 }
556
557 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
558 {
559 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
560 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
561 unsigned i = address - DMI_DATA0;
562 if (!abstractcs.busy)
563 write32(dmdata, address - DMI_DATA0, value);
564
565 if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
566 abstractcs.cmderr = CMDERR_BUSY;
567 }
568
569 if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
570 perform_abstract_command();
571 }
572 return true;
573
574 } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
575 unsigned i = address - DMI_PROGBUF0;
576
577 if (!abstractcs.busy)
578 write32(program_buffer, i, value);
579
580 if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
581 perform_abstract_command();
582 }
583 return true;
584
585 } else {
586 switch (address) {
587 case DMI_DMCONTROL:
588 {
589 if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE))
590 reset();
591 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
592 if (dmcontrol.dmactive) {
593 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
594 dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
595 dmcontrol.hartreset = get_field(value, DMI_DMCONTROL_HARTRESET);
596 dmcontrol.ndmreset = get_field(value, DMI_DMCONTROL_NDMRESET);
597 dmcontrol.hartsel = get_field(value, ((1L<<hartsellen)-1) <<
598 DMI_DMCONTROL_HARTSEL_OFFSET);
599 }
600 processor_t *proc = current_proc();
601 if (proc) {
602 proc->halt_request = dmcontrol.haltreq;
603 if (dmcontrol.resumereq) {
604 debug_rom_flags[dmcontrol.hartsel] |= (1 << DEBUG_ROM_FLAG_RESUME);
605 resumeack[dmcontrol.hartsel] = false;
606 }
607 if (dmcontrol.hartreset) {
608 proc->reset();
609 }
610 }
611 if (dmcontrol.ndmreset) {
612 for (size_t i = 0; i < sim->nprocs(); i++) {
613 proc = sim->get_core(i);
614 proc->reset();
615 }
616 }
617 }
618 return true;
619
620 case DMI_COMMAND:
621 command = value;
622 return perform_abstract_command();
623
624 case DMI_ABSTRACTCS:
625 abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DMI_ABSTRACTCS_CMDERR))));
626 return true;
627
628 case DMI_ABSTRACTAUTO:
629 abstractauto.autoexecprogbuf = get_field(value,
630 DMI_ABSTRACTAUTO_AUTOEXECPROGBUF);
631 abstractauto.autoexecdata = get_field(value,
632 DMI_ABSTRACTAUTO_AUTOEXECDATA);
633 return true;
634 case DMI_SBCS:
635 sbcs.readonaddr = get_field(value, DMI_SBCS_SBREADONADDR);
636 sbcs.sbaccess = get_field(value, DMI_SBCS_SBACCESS);
637 sbcs.autoincrement = get_field(value, DMI_SBCS_SBAUTOINCREMENT);
638 sbcs.readondata = get_field(value, DMI_SBCS_SBREADONDATA);
639 sbcs.error &= ~get_field(value, DMI_SBCS_SBERROR);
640 return true;
641 case DMI_SBADDRESS0:
642 sbaddress[0] = value;
643 if (sbcs.error == 0 && sbcs.readonaddr) {
644 sb_read();
645 }
646 return true;
647 case DMI_SBADDRESS1:
648 sbaddress[1] = value;
649 return true;
650 case DMI_SBADDRESS2:
651 sbaddress[2] = value;
652 return true;
653 case DMI_SBADDRESS3:
654 sbaddress[3] = value;
655 return true;
656 case DMI_SBDATA0:
657 sbdata[0] = value;
658 if (sbcs.error == 0) {
659 sb_write();
660 if (sbcs.autoincrement && sbcs.error == 0) {
661 sb_autoincrement();
662 }
663 }
664 return true;
665 case DMI_SBDATA1:
666 sbdata[1] = value;
667 return true;
668 case DMI_SBDATA2:
669 sbdata[2] = value;
670 return true;
671 case DMI_SBDATA3:
672 sbdata[3] = value;
673 return true;
674 }
675 }
676 return false;
677 }