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