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