]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/esp.c
esp: fix PDMA target selection
[mirror_qemu.git] / hw / scsi / esp.c
CommitLineData
6f7e9aec 1/*
67e999be 2 * QEMU ESP/NCR53C9x emulation
5fafdf24 3 *
4e9aec74 4 * Copyright (c) 2005-2006 Fabrice Bellard
fabaaf1d 5 * Copyright (c) 2012 Herve Poussineau
5fafdf24 6 *
6f7e9aec
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
5d20fa6b 25
a4ab4792 26#include "qemu/osdep.h"
83c9f4ca 27#include "hw/sysbus.h"
d6454270 28#include "migration/vmstate.h"
64552b6b 29#include "hw/irq.h"
0d09e41a 30#include "hw/scsi/esp.h"
bf4b9889 31#include "trace.h"
1de7afc9 32#include "qemu/log.h"
0b8fa32f 33#include "qemu/module.h"
6f7e9aec 34
67e999be 35/*
5ad6bb97
BS
36 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
37 * also produced as NCR89C100. See
67e999be
FB
38 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
39 * and
40 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
74d71ea1
LV
41 *
42 * On Macintosh Quadra it is a NCR53C96.
67e999be
FB
43 */
44
c73f96fd
BS
45static void esp_raise_irq(ESPState *s)
46{
47 if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
48 s->rregs[ESP_RSTAT] |= STAT_INT;
49 qemu_irq_raise(s->irq);
bf4b9889 50 trace_esp_raise_irq();
c73f96fd
BS
51 }
52}
53
54static void esp_lower_irq(ESPState *s)
55{
56 if (s->rregs[ESP_RSTAT] & STAT_INT) {
57 s->rregs[ESP_RSTAT] &= ~STAT_INT;
58 qemu_irq_lower(s->irq);
bf4b9889 59 trace_esp_lower_irq();
c73f96fd
BS
60 }
61}
62
74d71ea1
LV
63static void esp_raise_drq(ESPState *s)
64{
65 qemu_irq_raise(s->irq_data);
960ebfd9 66 trace_esp_raise_drq();
74d71ea1
LV
67}
68
69static void esp_lower_drq(ESPState *s)
70{
71 qemu_irq_lower(s->irq_data);
960ebfd9 72 trace_esp_lower_drq();
74d71ea1
LV
73}
74
9c7e23fc 75void esp_dma_enable(ESPState *s, int irq, int level)
73d74342 76{
73d74342
BS
77 if (level) {
78 s->dma_enabled = 1;
bf4b9889 79 trace_esp_dma_enable();
73d74342
BS
80 if (s->dma_cb) {
81 s->dma_cb(s);
82 s->dma_cb = NULL;
83 }
84 } else {
bf4b9889 85 trace_esp_dma_disable();
73d74342
BS
86 s->dma_enabled = 0;
87 }
88}
89
9c7e23fc 90void esp_request_cancelled(SCSIRequest *req)
94d3f98a 91{
e6810db8 92 ESPState *s = req->hba_private;
94d3f98a
PB
93
94 if (req == s->current_req) {
95 scsi_req_unref(s->current_req);
96 s->current_req = NULL;
97 s->current_dev = NULL;
98 }
99}
100
c47b5835
MCA
101static uint32_t esp_get_tc(ESPState *s)
102{
103 uint32_t dmalen;
104
105 dmalen = s->rregs[ESP_TCLO];
106 dmalen |= s->rregs[ESP_TCMID] << 8;
107 dmalen |= s->rregs[ESP_TCHI] << 16;
108
109 return dmalen;
110}
111
112static void esp_set_tc(ESPState *s, uint32_t dmalen)
113{
114 s->rregs[ESP_TCLO] = dmalen;
115 s->rregs[ESP_TCMID] = dmalen >> 8;
116 s->rregs[ESP_TCHI] = dmalen >> 16;
117}
118
c04ed569
MCA
119static uint32_t esp_get_stc(ESPState *s)
120{
121 uint32_t dmalen;
122
123 dmalen = s->wregs[ESP_TCLO];
124 dmalen |= s->wregs[ESP_TCMID] << 8;
125 dmalen |= s->wregs[ESP_TCHI] << 16;
126
127 return dmalen;
128}
129
3c421400 130static void set_pdma(ESPState *s, enum pdma_origin_id origin)
74d71ea1
LV
131{
132 s->pdma_origin = origin;
74d71ea1
LV
133}
134
761bef75
MCA
135static uint8_t esp_pdma_read(ESPState *s)
136{
8da90e81
MCA
137 uint32_t dmalen = esp_get_tc(s);
138 uint8_t val;
139
3c421400 140 if (dmalen == 0) {
8da90e81
MCA
141 return 0;
142 }
143
6e3fafa8 144 switch (s->pdma_origin) {
6e3fafa8 145 case TI:
02abe246
MCA
146 if (s->do_cmd) {
147 val = s->cmdbuf[s->cmdlen++];
148 } else {
149 val = s->ti_buf[s->ti_rptr++];
150 }
8da90e81 151 break;
6e3fafa8 152 case ASYNC:
93efe2e6
MCA
153 val = s->async_buf[0];
154 if (s->async_len > 0) {
155 s->async_len--;
156 s->async_buf++;
157 }
8da90e81 158 break;
6e3fafa8
MCA
159 default:
160 g_assert_not_reached();
161 }
8da90e81 162
93efe2e6 163 s->ti_size--;
8da90e81
MCA
164 dmalen--;
165 esp_set_tc(s, dmalen);
166
167 return val;
761bef75
MCA
168}
169
170static void esp_pdma_write(ESPState *s, uint8_t val)
171{
8da90e81
MCA
172 uint32_t dmalen = esp_get_tc(s);
173
3c421400 174 if (dmalen == 0) {
8da90e81
MCA
175 return;
176 }
177
6e3fafa8 178 switch (s->pdma_origin) {
6e3fafa8 179 case TI:
02abe246
MCA
180 if (s->do_cmd) {
181 s->cmdbuf[s->cmdlen++] = val;
182 } else {
183 s->ti_buf[s->ti_wptr++] = val;
184 }
6e3fafa8
MCA
185 break;
186 case ASYNC:
93efe2e6
MCA
187 s->async_buf[0] = val;
188 if (s->async_len > 0) {
189 s->async_len--;
190 s->async_buf++;
191 }
6e3fafa8
MCA
192 break;
193 default:
194 g_assert_not_reached();
195 }
8da90e81 196
93efe2e6 197 s->ti_size++;
8da90e81
MCA
198 dmalen--;
199 esp_set_tc(s, dmalen);
761bef75
MCA
200}
201
c7bce09c 202static int esp_select(ESPState *s)
6130b188
LV
203{
204 int target;
205
206 target = s->wregs[ESP_WBUSID] & BUSID_DID;
207
208 s->ti_size = 0;
209 s->ti_rptr = 0;
210 s->ti_wptr = 0;
211
212 if (s->current_req) {
213 /* Started a new command before the old one finished. Cancel it. */
214 scsi_req_cancel(s->current_req);
215 s->async_len = 0;
216 }
217
218 s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
219 if (!s->current_dev) {
220 /* No such drive */
221 s->rregs[ESP_RSTAT] = 0;
222 s->rregs[ESP_RINTR] = INTR_DC;
223 s->rregs[ESP_RSEQ] = SEQ_0;
224 esp_raise_irq(s);
225 return -1;
226 }
227 return 0;
228}
229
cfcea0f9 230static uint32_t get_cmd(ESPState *s)
2f275b8f 231{
cfcea0f9 232 uint8_t *buf = s->cmdbuf;
a917d384 233 uint32_t dmalen;
2f275b8f
FB
234 int target;
235
8dea1dd4 236 target = s->wregs[ESP_WBUSID] & BUSID_DID;
4f6200f0 237 if (s->dma) {
c47b5835 238 dmalen = esp_get_tc(s);
cfcea0f9 239 if (dmalen > ESP_CMDBUF_SZ) {
6c1fef6b
PP
240 return 0;
241 }
74d71ea1
LV
242 if (s->dma_memory_read) {
243 s->dma_memory_read(s->dma_opaque, buf, dmalen);
244 } else {
02abe246 245 set_pdma(s, TI);
49691315
MCA
246 if (esp_select(s) < 0) {
247 return -1;
248 }
74d71ea1
LV
249 esp_raise_drq(s);
250 return 0;
251 }
4f6200f0 252 } else {
fc4d65da 253 dmalen = s->ti_size;
d3cdc491
PP
254 if (dmalen > TI_BUFSZ) {
255 return 0;
256 }
fc4d65da 257 memcpy(buf, s->ti_buf, dmalen);
75ef8496 258 buf[0] = buf[2] >> 5;
4f6200f0 259 }
bf4b9889 260 trace_esp_get_cmd(dmalen, target);
2e5d83bb 261
c7bce09c 262 if (esp_select(s) < 0) {
49691315 263 return -1;
2f275b8f 264 }
9f149aa9
PB
265 return dmalen;
266}
267
f2818f22 268static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
9f149aa9
PB
269{
270 int32_t datalen;
271 int lun;
f48a7a6e 272 SCSIDevice *current_lun;
9f149aa9 273
bf4b9889 274 trace_esp_do_busid_cmd(busid);
f2818f22 275 lun = busid & 7;
0d3545e7 276 current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
e6810db8 277 s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
c39ce112 278 datalen = scsi_req_enqueue(s->current_req);
67e999be
FB
279 s->ti_size = datalen;
280 if (datalen != 0) {
c73f96fd 281 s->rregs[ESP_RSTAT] = STAT_TC;
6cc88d6b 282 esp_set_tc(s, 0);
2e5d83bb 283 if (datalen > 0) {
5ad6bb97 284 s->rregs[ESP_RSTAT] |= STAT_DI;
2e5d83bb 285 } else {
5ad6bb97 286 s->rregs[ESP_RSTAT] |= STAT_DO;
b9788fc4 287 }
ad3376cc 288 scsi_req_continue(s->current_req);
2f275b8f 289 }
5ad6bb97
BS
290 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
291 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 292 esp_raise_irq(s);
2f275b8f
FB
293}
294
c959f218 295static void do_cmd(ESPState *s)
f2818f22 296{
c959f218 297 uint8_t *buf = s->cmdbuf;
f2818f22
AT
298 uint8_t busid = buf[0];
299
300 do_busid_cmd(s, &buf[1], busid);
301}
302
74d71ea1
LV
303static void satn_pdma_cb(ESPState *s)
304{
bb0bc7bb
MCA
305 s->do_cmd = 0;
306 if (s->cmdlen) {
c959f218 307 do_cmd(s);
74d71ea1
LV
308 }
309}
310
9f149aa9
PB
311static void handle_satn(ESPState *s)
312{
49691315
MCA
313 int32_t cmdlen;
314
1b26eaa1 315 if (s->dma && !s->dma_enabled) {
73d74342
BS
316 s->dma_cb = handle_satn;
317 return;
318 }
74d71ea1 319 s->pdma_cb = satn_pdma_cb;
49691315
MCA
320 cmdlen = get_cmd(s);
321 if (cmdlen > 0) {
322 s->cmdlen = cmdlen;
c959f218 323 do_cmd(s);
49691315
MCA
324 } else if (cmdlen == 0) {
325 s->cmdlen = 0;
bb0bc7bb 326 s->do_cmd = 1;
49691315
MCA
327 /* Target present, but no cmd yet - switch to command phase */
328 s->rregs[ESP_RSEQ] = SEQ_CD;
329 s->rregs[ESP_RSTAT] = STAT_CD;
94d5c79d 330 }
9f149aa9
PB
331}
332
74d71ea1
LV
333static void s_without_satn_pdma_cb(ESPState *s)
334{
bb0bc7bb
MCA
335 s->do_cmd = 0;
336 if (s->cmdlen) {
2c573cfe 337 do_busid_cmd(s, s->cmdbuf, 0);
74d71ea1
LV
338 }
339}
340
f2818f22
AT
341static void handle_s_without_atn(ESPState *s)
342{
49691315
MCA
343 int32_t cmdlen;
344
1b26eaa1 345 if (s->dma && !s->dma_enabled) {
73d74342
BS
346 s->dma_cb = handle_s_without_atn;
347 return;
348 }
74d71ea1 349 s->pdma_cb = s_without_satn_pdma_cb;
49691315
MCA
350 cmdlen = get_cmd(s);
351 if (cmdlen > 0) {
352 s->cmdlen = cmdlen;
bb0bc7bb 353 do_busid_cmd(s, s->cmdbuf, 0);
49691315
MCA
354 } else if (cmdlen == 0) {
355 s->cmdlen = 0;
bb0bc7bb 356 s->do_cmd = 1;
49691315
MCA
357 /* Target present, but no cmd yet - switch to command phase */
358 s->rregs[ESP_RSEQ] = SEQ_CD;
359 s->rregs[ESP_RSTAT] = STAT_CD;
f2818f22
AT
360 }
361}
362
74d71ea1
LV
363static void satn_stop_pdma_cb(ESPState *s)
364{
bb0bc7bb 365 s->do_cmd = 0;
74d71ea1
LV
366 if (s->cmdlen) {
367 trace_esp_handle_satn_stop(s->cmdlen);
368 s->do_cmd = 1;
369 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
370 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
371 s->rregs[ESP_RSEQ] = SEQ_CD;
372 esp_raise_irq(s);
373 }
374}
375
9f149aa9
PB
376static void handle_satn_stop(ESPState *s)
377{
49691315
MCA
378 int32_t cmdlen;
379
1b26eaa1 380 if (s->dma && !s->dma_enabled) {
73d74342
BS
381 s->dma_cb = handle_satn_stop;
382 return;
383 }
c62c1fa0 384 s->pdma_cb = satn_stop_pdma_cb;
49691315
MCA
385 cmdlen = get_cmd(s);
386 if (cmdlen > 0) {
bf4b9889 387 trace_esp_handle_satn_stop(s->cmdlen);
49691315 388 s->cmdlen = cmdlen;
9f149aa9 389 s->do_cmd = 1;
c73f96fd 390 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
5ad6bb97
BS
391 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
392 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 393 esp_raise_irq(s);
49691315
MCA
394 } else if (cmdlen == 0) {
395 s->cmdlen = 0;
bb0bc7bb 396 s->do_cmd = 1;
49691315
MCA
397 /* Target present, but no cmd yet - switch to command phase */
398 s->rregs[ESP_RSEQ] = SEQ_CD;
399 s->rregs[ESP_RSTAT] = STAT_CD;
9f149aa9
PB
400 }
401}
402
74d71ea1
LV
403static void write_response_pdma_cb(ESPState *s)
404{
405 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
406 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
407 s->rregs[ESP_RSEQ] = SEQ_CD;
408 esp_raise_irq(s);
409}
410
0fc5c15a 411static void write_response(ESPState *s)
2f275b8f 412{
bf4b9889 413 trace_esp_write_response(s->status);
3944966d 414 s->ti_buf[0] = s->status;
0fc5c15a 415 s->ti_buf[1] = 0;
4f6200f0 416 if (s->dma) {
74d71ea1
LV
417 if (s->dma_memory_write) {
418 s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
419 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
420 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
421 s->rregs[ESP_RSEQ] = SEQ_CD;
422 } else {
3c421400 423 set_pdma(s, TI);
74d71ea1
LV
424 s->pdma_cb = write_response_pdma_cb;
425 esp_raise_drq(s);
426 return;
427 }
4f6200f0 428 } else {
f930d07e
BS
429 s->ti_size = 2;
430 s->ti_rptr = 0;
d020aa50 431 s->ti_wptr = 2;
5ad6bb97 432 s->rregs[ESP_RFLAGS] = 2;
4f6200f0 433 }
c73f96fd 434 esp_raise_irq(s);
2f275b8f 435}
4f6200f0 436
a917d384
PB
437static void esp_dma_done(ESPState *s)
438{
c73f96fd 439 s->rregs[ESP_RSTAT] |= STAT_TC;
5ad6bb97
BS
440 s->rregs[ESP_RINTR] = INTR_BS;
441 s->rregs[ESP_RSEQ] = 0;
442 s->rregs[ESP_RFLAGS] = 0;
c47b5835 443 esp_set_tc(s, 0);
c73f96fd 444 esp_raise_irq(s);
a917d384
PB
445}
446
74d71ea1
LV
447static void do_dma_pdma_cb(ESPState *s)
448{
4ca2ba6f 449 int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
6cc88d6b 450
74d71ea1
LV
451 if (s->do_cmd) {
452 s->ti_size = 0;
453 s->cmdlen = 0;
454 s->do_cmd = 0;
c959f218 455 do_cmd(s);
74d71ea1
LV
456 return;
457 }
74d71ea1
LV
458 if (s->async_len == 0) {
459 scsi_req_continue(s->current_req);
460 /*
461 * If there is still data to be read from the device then
462 * complete the DMA operation immediately. Otherwise defer
463 * until the scsi layer has completed.
464 */
6cc88d6b 465 if (to_device || esp_get_tc(s) != 0 || s->ti_size == 0) {
74d71ea1
LV
466 return;
467 }
468 }
469
470 /* Partially filled a scsi buffer. Complete immediately. */
471 esp_dma_done(s);
472}
473
4d611c9a
PB
474static void esp_do_dma(ESPState *s)
475{
67e999be 476 uint32_t len;
4ca2ba6f 477 int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
a917d384 478
6cc88d6b 479 len = esp_get_tc(s);
4d611c9a 480 if (s->do_cmd) {
15407433
LV
481 /*
482 * handle_ti_cmd() case: esp_do_dma() is called only from
483 * handle_ti_cmd() with do_cmd != NULL (see the assert())
484 */
bf4b9889 485 trace_esp_do_dma(s->cmdlen, len);
94d5c79d
MCA
486 assert(s->cmdlen <= sizeof(s->cmdbuf) &&
487 len <= sizeof(s->cmdbuf) - s->cmdlen);
74d71ea1
LV
488 if (s->dma_memory_read) {
489 s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
490 } else {
02abe246 491 set_pdma(s, TI);
74d71ea1
LV
492 s->pdma_cb = do_dma_pdma_cb;
493 esp_raise_drq(s);
494 return;
495 }
15407433
LV
496 trace_esp_handle_ti_cmd(s->cmdlen);
497 s->ti_size = 0;
498 s->cmdlen = 0;
499 s->do_cmd = 0;
c959f218 500 do_cmd(s);
4d611c9a 501 return;
a917d384
PB
502 }
503 if (s->async_len == 0) {
504 /* Defer until data is available. */
505 return;
506 }
507 if (len > s->async_len) {
508 len = s->async_len;
509 }
510 if (to_device) {
74d71ea1
LV
511 if (s->dma_memory_read) {
512 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
513 } else {
3c421400 514 set_pdma(s, ASYNC);
74d71ea1
LV
515 s->pdma_cb = do_dma_pdma_cb;
516 esp_raise_drq(s);
517 return;
518 }
4d611c9a 519 } else {
74d71ea1
LV
520 if (s->dma_memory_write) {
521 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
522 } else {
3c421400 523 set_pdma(s, ASYNC);
74d71ea1
LV
524 s->pdma_cb = do_dma_pdma_cb;
525 esp_raise_drq(s);
526 return;
527 }
a917d384 528 }
6cc88d6b 529 esp_set_tc(s, esp_get_tc(s) - len);
a917d384
PB
530 s->async_buf += len;
531 s->async_len -= len;
94d5c79d 532 if (to_device) {
6787f5fa 533 s->ti_size += len;
94d5c79d 534 } else {
6787f5fa 535 s->ti_size -= len;
94d5c79d 536 }
a917d384 537 if (s->async_len == 0) {
ad3376cc 538 scsi_req_continue(s->current_req);
94d5c79d
MCA
539 /*
540 * If there is still data to be read from the device then
541 * complete the DMA operation immediately. Otherwise defer
542 * until the scsi layer has completed.
543 */
6cc88d6b 544 if (to_device || esp_get_tc(s) != 0 || s->ti_size == 0) {
ad3376cc 545 return;
4d611c9a 546 }
a917d384 547 }
ad3376cc
PB
548
549 /* Partially filled a scsi buffer. Complete immediately. */
550 esp_dma_done(s);
4d611c9a
PB
551}
552
ea84a442 553static void esp_report_command_complete(ESPState *s, uint32_t status)
2e5d83bb 554{
bf4b9889 555 trace_esp_command_complete();
c6df7102 556 if (s->ti_size != 0) {
bf4b9889 557 trace_esp_command_complete_unexpected();
c6df7102
PB
558 }
559 s->ti_size = 0;
c6df7102 560 s->async_len = 0;
aba1f023 561 if (status) {
bf4b9889 562 trace_esp_command_complete_fail();
c6df7102 563 }
aba1f023 564 s->status = status;
c6df7102
PB
565 s->rregs[ESP_RSTAT] = STAT_ST;
566 esp_dma_done(s);
567 if (s->current_req) {
568 scsi_req_unref(s->current_req);
569 s->current_req = NULL;
570 s->current_dev = NULL;
571 }
572}
573
17ea26c2 574void esp_command_complete(SCSIRequest *req, size_t resid)
ea84a442
GR
575{
576 ESPState *s = req->hba_private;
577
578 if (s->rregs[ESP_RSTAT] & STAT_INT) {
94d5c79d
MCA
579 /*
580 * Defer handling command complete until the previous
ea84a442
GR
581 * interrupt has been handled.
582 */
583 trace_esp_command_complete_deferred();
17ea26c2 584 s->deferred_status = req->status;
ea84a442
GR
585 s->deferred_complete = true;
586 return;
587 }
17ea26c2 588 esp_report_command_complete(s, req->status);
ea84a442
GR
589}
590
9c7e23fc 591void esp_transfer_data(SCSIRequest *req, uint32_t len)
c6df7102 592{
e6810db8 593 ESPState *s = req->hba_private;
6cc88d6b 594 uint32_t dmalen = esp_get_tc(s);
c6df7102 595
7f0b6e11 596 assert(!s->do_cmd);
6cc88d6b 597 trace_esp_transfer_data(dmalen, s->ti_size);
aba1f023 598 s->async_len = len;
c6df7102 599 s->async_buf = scsi_req_get_buf(req);
6cc88d6b 600 if (dmalen) {
c6df7102 601 esp_do_dma(s);
5eb7a23f 602 } else if (s->ti_size <= 0) {
94d5c79d
MCA
603 /*
604 * If this was the last part of a DMA transfer then the
605 * completion interrupt is deferred to here.
606 */
a917d384 607 esp_dma_done(s);
4d611c9a 608 }
2e5d83bb
PB
609}
610
2f275b8f
FB
611static void handle_ti(ESPState *s)
612{
b76624de 613 uint32_t dmalen;
2f275b8f 614
7246e160
HP
615 if (s->dma && !s->dma_enabled) {
616 s->dma_cb = handle_ti;
617 return;
618 }
619
c47b5835 620 dmalen = esp_get_tc(s);
4f6200f0 621 if (s->dma) {
b76624de 622 trace_esp_handle_ti(dmalen);
5ad6bb97 623 s->rregs[ESP_RSTAT] &= ~STAT_TC;
4d611c9a 624 esp_do_dma(s);
15407433 625 } else if (s->do_cmd) {
bf4b9889 626 trace_esp_handle_ti_cmd(s->cmdlen);
9f149aa9
PB
627 s->ti_size = 0;
628 s->cmdlen = 0;
629 s->do_cmd = 0;
c959f218 630 do_cmd(s);
9f149aa9 631 }
2f275b8f
FB
632}
633
9c7e23fc 634void esp_hard_reset(ESPState *s)
6f7e9aec 635{
5aca8c3b
BS
636 memset(s->rregs, 0, ESP_REGS);
637 memset(s->wregs, 0, ESP_REGS);
c9cf45c1 638 s->tchi_written = 0;
4e9aec74
PB
639 s->ti_size = 0;
640 s->ti_rptr = 0;
641 s->ti_wptr = 0;
4e9aec74 642 s->dma = 0;
9f149aa9 643 s->do_cmd = 0;
73d74342 644 s->dma_cb = NULL;
8dea1dd4
BS
645
646 s->rregs[ESP_CFG1] = 7;
6f7e9aec
FB
647}
648
a391fdbc 649static void esp_soft_reset(ESPState *s)
85948643 650{
85948643 651 qemu_irq_lower(s->irq);
74d71ea1 652 qemu_irq_lower(s->irq_data);
a391fdbc 653 esp_hard_reset(s);
85948643
BS
654}
655
a391fdbc 656static void parent_esp_reset(ESPState *s, int irq, int level)
2d069bab 657{
85948643 658 if (level) {
a391fdbc 659 esp_soft_reset(s);
85948643 660 }
2d069bab
BS
661}
662
9c7e23fc 663uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
73d74342 664{
b630c075 665 uint32_t val;
73d74342 666
6f7e9aec 667 switch (saddr) {
5ad6bb97 668 case ESP_FIFO:
ff589551
PP
669 if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
670 /* Data out. */
671 qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
672 s->rregs[ESP_FIFO] = 0;
ff589551 673 } else if (s->ti_rptr < s->ti_wptr) {
f930d07e 674 s->ti_size--;
ff589551 675 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
f930d07e 676 }
ff589551 677 if (s->ti_rptr == s->ti_wptr) {
4f6200f0
FB
678 s->ti_rptr = 0;
679 s->ti_wptr = 0;
680 }
b630c075 681 val = s->rregs[ESP_FIFO];
f930d07e 682 break;
5ad6bb97 683 case ESP_RINTR:
94d5c79d
MCA
684 /*
685 * Clear sequence step, interrupt register and all status bits
686 * except TC
687 */
b630c075 688 val = s->rregs[ESP_RINTR];
2814df28
BS
689 s->rregs[ESP_RINTR] = 0;
690 s->rregs[ESP_RSTAT] &= ~STAT_TC;
691 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 692 esp_lower_irq(s);
ea84a442
GR
693 if (s->deferred_complete) {
694 esp_report_command_complete(s, s->deferred_status);
695 s->deferred_complete = false;
696 }
b630c075 697 break;
c9cf45c1
HR
698 case ESP_TCHI:
699 /* Return the unique id if the value has never been written */
700 if (!s->tchi_written) {
b630c075
MCA
701 val = s->chip_id;
702 } else {
703 val = s->rregs[saddr];
c9cf45c1 704 }
b630c075 705 break;
6f7e9aec 706 default:
b630c075 707 val = s->rregs[saddr];
f930d07e 708 break;
6f7e9aec 709 }
b630c075
MCA
710
711 trace_esp_mem_readb(saddr, val);
712 return val;
6f7e9aec
FB
713}
714
9c7e23fc 715void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
6f7e9aec 716{
bf4b9889 717 trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
6f7e9aec 718 switch (saddr) {
c9cf45c1
HR
719 case ESP_TCHI:
720 s->tchi_written = true;
721 /* fall through */
5ad6bb97
BS
722 case ESP_TCLO:
723 case ESP_TCMID:
724 s->rregs[ESP_RSTAT] &= ~STAT_TC;
4f6200f0 725 break;
5ad6bb97 726 case ESP_FIFO:
9f149aa9 727 if (s->do_cmd) {
926cde5f 728 if (s->cmdlen < ESP_CMDBUF_SZ) {
c98c6c10
PP
729 s->cmdbuf[s->cmdlen++] = val & 0xff;
730 } else {
731 trace_esp_error_fifo_overrun();
732 }
ff589551 733 } else if (s->ti_wptr == TI_BUFSZ - 1) {
3af4e9aa 734 trace_esp_error_fifo_overrun();
2e5d83bb
PB
735 } else {
736 s->ti_size++;
737 s->ti_buf[s->ti_wptr++] = val & 0xff;
738 }
f930d07e 739 break;
5ad6bb97 740 case ESP_CMD:
4f6200f0 741 s->rregs[saddr] = val;
5ad6bb97 742 if (val & CMD_DMA) {
f930d07e 743 s->dma = 1;
6787f5fa 744 /* Reload DMA counter. */
96676c2f
MCA
745 if (esp_get_stc(s) == 0) {
746 esp_set_tc(s, 0x10000);
747 } else {
748 esp_set_tc(s, esp_get_stc(s));
749 }
f930d07e
BS
750 } else {
751 s->dma = 0;
752 }
94d5c79d 753 switch (val & CMD_CMD) {
5ad6bb97 754 case CMD_NOP:
bf4b9889 755 trace_esp_mem_writeb_cmd_nop(val);
f930d07e 756 break;
5ad6bb97 757 case CMD_FLUSH:
bf4b9889 758 trace_esp_mem_writeb_cmd_flush(val);
94d5c79d 759 /*s->ti_size = 0;*/
5ad6bb97
BS
760 s->rregs[ESP_RINTR] = INTR_FC;
761 s->rregs[ESP_RSEQ] = 0;
a214c598 762 s->rregs[ESP_RFLAGS] = 0;
f930d07e 763 break;
5ad6bb97 764 case CMD_RESET:
bf4b9889 765 trace_esp_mem_writeb_cmd_reset(val);
a391fdbc 766 esp_soft_reset(s);
f930d07e 767 break;
5ad6bb97 768 case CMD_BUSRESET:
bf4b9889 769 trace_esp_mem_writeb_cmd_bus_reset(val);
5ad6bb97
BS
770 s->rregs[ESP_RINTR] = INTR_RST;
771 if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
c73f96fd 772 esp_raise_irq(s);
9e61bde5 773 }
f930d07e 774 break;
5ad6bb97 775 case CMD_TI:
0097d3ec 776 trace_esp_mem_writeb_cmd_ti(val);
f930d07e
BS
777 handle_ti(s);
778 break;
5ad6bb97 779 case CMD_ICCS:
bf4b9889 780 trace_esp_mem_writeb_cmd_iccs(val);
f930d07e 781 write_response(s);
4bf5801d
BS
782 s->rregs[ESP_RINTR] = INTR_FC;
783 s->rregs[ESP_RSTAT] |= STAT_MI;
f930d07e 784 break;
5ad6bb97 785 case CMD_MSGACC:
bf4b9889 786 trace_esp_mem_writeb_cmd_msgacc(val);
5ad6bb97
BS
787 s->rregs[ESP_RINTR] = INTR_DC;
788 s->rregs[ESP_RSEQ] = 0;
4e2a68c1
AT
789 s->rregs[ESP_RFLAGS] = 0;
790 esp_raise_irq(s);
f930d07e 791 break;
0fd0eb21 792 case CMD_PAD:
bf4b9889 793 trace_esp_mem_writeb_cmd_pad(val);
0fd0eb21
BS
794 s->rregs[ESP_RSTAT] = STAT_TC;
795 s->rregs[ESP_RINTR] = INTR_FC;
796 s->rregs[ESP_RSEQ] = 0;
797 break;
5ad6bb97 798 case CMD_SATN:
bf4b9889 799 trace_esp_mem_writeb_cmd_satn(val);
f930d07e 800 break;
6915bff1
HP
801 case CMD_RSTATN:
802 trace_esp_mem_writeb_cmd_rstatn(val);
803 break;
5e1e0a3b 804 case CMD_SEL:
bf4b9889 805 trace_esp_mem_writeb_cmd_sel(val);
f2818f22 806 handle_s_without_atn(s);
5e1e0a3b 807 break;
5ad6bb97 808 case CMD_SELATN:
bf4b9889 809 trace_esp_mem_writeb_cmd_selatn(val);
f930d07e
BS
810 handle_satn(s);
811 break;
5ad6bb97 812 case CMD_SELATNS:
bf4b9889 813 trace_esp_mem_writeb_cmd_selatns(val);
f930d07e
BS
814 handle_satn_stop(s);
815 break;
5ad6bb97 816 case CMD_ENSEL:
bf4b9889 817 trace_esp_mem_writeb_cmd_ensel(val);
e3926838 818 s->rregs[ESP_RINTR] = 0;
74ec6048 819 break;
6fe84c18
HP
820 case CMD_DISSEL:
821 trace_esp_mem_writeb_cmd_dissel(val);
822 s->rregs[ESP_RINTR] = 0;
823 esp_raise_irq(s);
824 break;
f930d07e 825 default:
3af4e9aa 826 trace_esp_error_unhandled_command(val);
f930d07e
BS
827 break;
828 }
829 break;
5ad6bb97 830 case ESP_WBUSID ... ESP_WSYNO:
f930d07e 831 break;
5ad6bb97 832 case ESP_CFG1:
9ea73f8b
PB
833 case ESP_CFG2: case ESP_CFG3:
834 case ESP_RES3: case ESP_RES4:
4f6200f0
FB
835 s->rregs[saddr] = val;
836 break;
5ad6bb97 837 case ESP_WCCF ... ESP_WTEST:
4f6200f0 838 break;
6f7e9aec 839 default:
3af4e9aa 840 trace_esp_error_invalid_write(val, saddr);
8dea1dd4 841 return;
6f7e9aec 842 }
2f275b8f 843 s->wregs[saddr] = val;
6f7e9aec
FB
844}
845
a8170e5e 846static bool esp_mem_accepts(void *opaque, hwaddr addr,
8372d383
PM
847 unsigned size, bool is_write,
848 MemTxAttrs attrs)
67bb5314
AK
849{
850 return (size == 1) || (is_write && size == 4);
851}
6f7e9aec 852
74d71ea1
LV
853static bool esp_pdma_needed(void *opaque)
854{
855 ESPState *s = opaque;
856 return s->dma_memory_read == NULL && s->dma_memory_write == NULL &&
857 s->dma_enabled;
858}
859
860static const VMStateDescription vmstate_esp_pdma = {
861 .name = "esp/pdma",
bb0bc7bb
MCA
862 .version_id = 2,
863 .minimum_version_id = 2,
74d71ea1
LV
864 .needed = esp_pdma_needed,
865 .fields = (VMStateField[]) {
74d71ea1 866 VMSTATE_INT32(pdma_origin, ESPState),
74d71ea1
LV
867 VMSTATE_END_OF_LIST()
868 }
869};
870
6cc88d6b
MCA
871static bool esp_is_before_version_5(void *opaque, int version_id)
872{
873 ESPState *s = ESP(opaque);
874
875 version_id = MIN(version_id, s->mig_version_id);
876 return version_id < 5;
877}
878
0bd005be
MCA
879static int esp_pre_save(void *opaque)
880{
881 ESPState *s = ESP(opaque);
882
883 s->mig_version_id = vmstate_esp.version_id;
884 return 0;
885}
886
887static int esp_post_load(void *opaque, int version_id)
888{
889 ESPState *s = ESP(opaque);
890
6cc88d6b
MCA
891 version_id = MIN(version_id, s->mig_version_id);
892
893 if (version_id < 5) {
894 esp_set_tc(s, s->mig_dma_left);
895 }
896
0bd005be
MCA
897 s->mig_version_id = vmstate_esp.version_id;
898 return 0;
899}
900
9c7e23fc 901const VMStateDescription vmstate_esp = {
94d5c79d 902 .name = "esp",
0bd005be 903 .version_id = 5,
cc9952f3 904 .minimum_version_id = 3,
0bd005be
MCA
905 .pre_save = esp_pre_save,
906 .post_load = esp_post_load,
35d08458 907 .fields = (VMStateField[]) {
cc9952f3
BS
908 VMSTATE_BUFFER(rregs, ESPState),
909 VMSTATE_BUFFER(wregs, ESPState),
910 VMSTATE_INT32(ti_size, ESPState),
911 VMSTATE_UINT32(ti_rptr, ESPState),
912 VMSTATE_UINT32(ti_wptr, ESPState),
913 VMSTATE_BUFFER(ti_buf, ESPState),
3944966d 914 VMSTATE_UINT32(status, ESPState),
ea84a442
GR
915 VMSTATE_UINT32(deferred_status, ESPState),
916 VMSTATE_BOOL(deferred_complete, ESPState),
cc9952f3 917 VMSTATE_UINT32(dma, ESPState),
cc966774
PB
918 VMSTATE_PARTIAL_BUFFER(cmdbuf, ESPState, 16),
919 VMSTATE_BUFFER_START_MIDDLE_V(cmdbuf, ESPState, 16, 4),
cc9952f3
BS
920 VMSTATE_UINT32(cmdlen, ESPState),
921 VMSTATE_UINT32(do_cmd, ESPState),
6cc88d6b 922 VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5),
cc9952f3 923 VMSTATE_END_OF_LIST()
74d71ea1
LV
924 },
925 .subsections = (const VMStateDescription * []) {
926 &vmstate_esp_pdma,
927 NULL
cc9952f3
BS
928 }
929};
6f7e9aec 930
a8170e5e 931static void sysbus_esp_mem_write(void *opaque, hwaddr addr,
a391fdbc
HP
932 uint64_t val, unsigned int size)
933{
934 SysBusESPState *sysbus = opaque;
eb169c76 935 ESPState *s = ESP(&sysbus->esp);
a391fdbc
HP
936 uint32_t saddr;
937
938 saddr = addr >> sysbus->it_shift;
eb169c76 939 esp_reg_write(s, saddr, val);
a391fdbc
HP
940}
941
a8170e5e 942static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr,
a391fdbc
HP
943 unsigned int size)
944{
945 SysBusESPState *sysbus = opaque;
eb169c76 946 ESPState *s = ESP(&sysbus->esp);
a391fdbc
HP
947 uint32_t saddr;
948
949 saddr = addr >> sysbus->it_shift;
eb169c76 950 return esp_reg_read(s, saddr);
a391fdbc
HP
951}
952
953static const MemoryRegionOps sysbus_esp_mem_ops = {
954 .read = sysbus_esp_mem_read,
955 .write = sysbus_esp_mem_write,
956 .endianness = DEVICE_NATIVE_ENDIAN,
957 .valid.accepts = esp_mem_accepts,
958};
959
74d71ea1
LV
960static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
961 uint64_t val, unsigned int size)
962{
963 SysBusESPState *sysbus = opaque;
eb169c76 964 ESPState *s = ESP(&sysbus->esp);
3c421400 965 uint32_t dmalen;
74d71ea1 966
960ebfd9
MCA
967 trace_esp_pdma_write(size);
968
74d71ea1
LV
969 switch (size) {
970 case 1:
761bef75 971 esp_pdma_write(s, val);
74d71ea1
LV
972 break;
973 case 2:
761bef75
MCA
974 esp_pdma_write(s, val >> 8);
975 esp_pdma_write(s, val);
74d71ea1
LV
976 break;
977 }
3c421400
MCA
978 dmalen = esp_get_tc(s);
979 if (dmalen == 0 && s->pdma_cb) {
74d71ea1
LV
980 esp_lower_drq(s);
981 s->pdma_cb(s);
982 s->pdma_cb = NULL;
983 }
984}
985
986static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr,
987 unsigned int size)
988{
989 SysBusESPState *sysbus = opaque;
eb169c76 990 ESPState *s = ESP(&sysbus->esp);
6cc88d6b 991 uint32_t dmalen = esp_get_tc(s);
74d71ea1
LV
992 uint64_t val = 0;
993
960ebfd9
MCA
994 trace_esp_pdma_read(size);
995
3c421400 996 if (dmalen == 0) {
74d71ea1
LV
997 return 0;
998 }
999 switch (size) {
1000 case 1:
761bef75 1001 val = esp_pdma_read(s);
74d71ea1
LV
1002 break;
1003 case 2:
761bef75
MCA
1004 val = esp_pdma_read(s);
1005 val = (val << 8) | esp_pdma_read(s);
74d71ea1
LV
1006 break;
1007 }
8da90e81 1008 dmalen = esp_get_tc(s);
3c421400 1009 if (dmalen == 0 && s->pdma_cb) {
74d71ea1
LV
1010 esp_lower_drq(s);
1011 s->pdma_cb(s);
1012 s->pdma_cb = NULL;
1013 }
1014 return val;
1015}
1016
1017static const MemoryRegionOps sysbus_esp_pdma_ops = {
1018 .read = sysbus_esp_pdma_read,
1019 .write = sysbus_esp_pdma_write,
1020 .endianness = DEVICE_NATIVE_ENDIAN,
1021 .valid.min_access_size = 1,
1022 .valid.max_access_size = 2,
1023};
1024
afd4030c
PB
1025static const struct SCSIBusInfo esp_scsi_info = {
1026 .tcq = false,
7e0380b9
PB
1027 .max_target = ESP_MAX_DEVS,
1028 .max_lun = 7,
afd4030c 1029
c6df7102 1030 .transfer_data = esp_transfer_data,
94d3f98a
PB
1031 .complete = esp_command_complete,
1032 .cancel = esp_request_cancelled
cfdc1bb0
PB
1033};
1034
a391fdbc 1035static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
cfb9de9c 1036{
84fbefed 1037 SysBusESPState *sysbus = SYSBUS_ESP(opaque);
eb169c76 1038 ESPState *s = ESP(&sysbus->esp);
a391fdbc
HP
1039
1040 switch (irq) {
1041 case 0:
1042 parent_esp_reset(s, irq, level);
1043 break;
1044 case 1:
1045 esp_dma_enable(opaque, irq, level);
1046 break;
1047 }
1048}
1049
b09318ca 1050static void sysbus_esp_realize(DeviceState *dev, Error **errp)
a391fdbc 1051{
b09318ca 1052 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
84fbefed 1053 SysBusESPState *sysbus = SYSBUS_ESP(dev);
eb169c76
MCA
1054 ESPState *s = ESP(&sysbus->esp);
1055
1056 if (!qdev_realize(DEVICE(s), NULL, errp)) {
1057 return;
1058 }
6f7e9aec 1059
b09318ca 1060 sysbus_init_irq(sbd, &s->irq);
74d71ea1 1061 sysbus_init_irq(sbd, &s->irq_data);
a391fdbc 1062 assert(sysbus->it_shift != -1);
6f7e9aec 1063
d32e4b3d 1064 s->chip_id = TCHI_FAS100A;
29776739 1065 memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
74d71ea1 1066 sysbus, "esp-regs", ESP_REGS << sysbus->it_shift);
b09318ca 1067 sysbus_init_mmio(sbd, &sysbus->iomem);
74d71ea1
LV
1068 memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_ops,
1069 sysbus, "esp-pdma", 2);
1070 sysbus_init_mmio(sbd, &sysbus->pdma);
6f7e9aec 1071
b09318ca 1072 qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
2d069bab 1073
b1187b51 1074 scsi_bus_new(&s->bus, sizeof(s->bus), dev, &esp_scsi_info, NULL);
67e999be 1075}
cfb9de9c 1076
a391fdbc
HP
1077static void sysbus_esp_hard_reset(DeviceState *dev)
1078{
84fbefed 1079 SysBusESPState *sysbus = SYSBUS_ESP(dev);
eb169c76
MCA
1080 ESPState *s = ESP(&sysbus->esp);
1081
1082 esp_hard_reset(s);
1083}
1084
1085static void sysbus_esp_init(Object *obj)
1086{
1087 SysBusESPState *sysbus = SYSBUS_ESP(obj);
1088
1089 object_initialize_child(obj, "esp", &sysbus->esp, TYPE_ESP);
a391fdbc
HP
1090}
1091
1092static const VMStateDescription vmstate_sysbus_esp_scsi = {
1093 .name = "sysbusespscsi",
0bd005be 1094 .version_id = 2,
ea84a442 1095 .minimum_version_id = 1,
a391fdbc 1096 .fields = (VMStateField[]) {
0bd005be 1097 VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2),
a391fdbc
HP
1098 VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
1099 VMSTATE_END_OF_LIST()
1100 }
999e12bb
AL
1101};
1102
a391fdbc 1103static void sysbus_esp_class_init(ObjectClass *klass, void *data)
999e12bb 1104{
39bffca2 1105 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 1106
b09318ca 1107 dc->realize = sysbus_esp_realize;
a391fdbc
HP
1108 dc->reset = sysbus_esp_hard_reset;
1109 dc->vmsd = &vmstate_sysbus_esp_scsi;
125ee0ed 1110 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
999e12bb
AL
1111}
1112
1f077308 1113static const TypeInfo sysbus_esp_info = {
84fbefed 1114 .name = TYPE_SYSBUS_ESP,
39bffca2 1115 .parent = TYPE_SYS_BUS_DEVICE,
eb169c76 1116 .instance_init = sysbus_esp_init,
a391fdbc
HP
1117 .instance_size = sizeof(SysBusESPState),
1118 .class_init = sysbus_esp_class_init,
63235df8
BS
1119};
1120
eb169c76
MCA
1121static void esp_class_init(ObjectClass *klass, void *data)
1122{
1123 DeviceClass *dc = DEVICE_CLASS(klass);
1124
1125 /* internal device for sysbusesp/pciespscsi, not user-creatable */
1126 dc->user_creatable = false;
1127 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1128}
1129
1130static const TypeInfo esp_info = {
1131 .name = TYPE_ESP,
1132 .parent = TYPE_DEVICE,
1133 .instance_size = sizeof(ESPState),
1134 .class_init = esp_class_init,
1135};
1136
83f7d43a 1137static void esp_register_types(void)
cfb9de9c 1138{
a391fdbc 1139 type_register_static(&sysbus_esp_info);
eb169c76 1140 type_register_static(&esp_info);
cfb9de9c
PB
1141}
1142
83f7d43a 1143type_init(esp_register_types)