]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/esp.c
esp: move get_cmd() post-DMA code to get_cmd_cb()
[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
41 */
42
c73f96fd
BS
43static void esp_raise_irq(ESPState *s)
44{
45 if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
46 s->rregs[ESP_RSTAT] |= STAT_INT;
47 qemu_irq_raise(s->irq);
bf4b9889 48 trace_esp_raise_irq();
c73f96fd
BS
49 }
50}
51
52static void esp_lower_irq(ESPState *s)
53{
54 if (s->rregs[ESP_RSTAT] & STAT_INT) {
55 s->rregs[ESP_RSTAT] &= ~STAT_INT;
56 qemu_irq_lower(s->irq);
bf4b9889 57 trace_esp_lower_irq();
c73f96fd
BS
58 }
59}
60
9c7e23fc 61void esp_dma_enable(ESPState *s, int irq, int level)
73d74342 62{
73d74342
BS
63 if (level) {
64 s->dma_enabled = 1;
bf4b9889 65 trace_esp_dma_enable();
73d74342
BS
66 if (s->dma_cb) {
67 s->dma_cb(s);
68 s->dma_cb = NULL;
69 }
70 } else {
bf4b9889 71 trace_esp_dma_disable();
73d74342
BS
72 s->dma_enabled = 0;
73 }
74}
75
9c7e23fc 76void esp_request_cancelled(SCSIRequest *req)
94d3f98a 77{
e6810db8 78 ESPState *s = req->hba_private;
94d3f98a
PB
79
80 if (req == s->current_req) {
81 scsi_req_unref(s->current_req);
82 s->current_req = NULL;
83 s->current_dev = NULL;
84 }
85}
86
6130b188
LV
87static int get_cmd_cb(ESPState *s)
88{
89 int target;
90
91 target = s->wregs[ESP_WBUSID] & BUSID_DID;
92
93 s->ti_size = 0;
94 s->ti_rptr = 0;
95 s->ti_wptr = 0;
96
97 if (s->current_req) {
98 /* Started a new command before the old one finished. Cancel it. */
99 scsi_req_cancel(s->current_req);
100 s->async_len = 0;
101 }
102
103 s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
104 if (!s->current_dev) {
105 /* No such drive */
106 s->rregs[ESP_RSTAT] = 0;
107 s->rregs[ESP_RINTR] = INTR_DC;
108 s->rregs[ESP_RSEQ] = SEQ_0;
109 esp_raise_irq(s);
110 return -1;
111 }
112 return 0;
113}
114
6c1fef6b 115static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
2f275b8f 116{
a917d384 117 uint32_t dmalen;
2f275b8f
FB
118 int target;
119
8dea1dd4 120 target = s->wregs[ESP_WBUSID] & BUSID_DID;
4f6200f0 121 if (s->dma) {
9ea73f8b
PB
122 dmalen = s->rregs[ESP_TCLO];
123 dmalen |= s->rregs[ESP_TCMID] << 8;
124 dmalen |= s->rregs[ESP_TCHI] << 16;
6c1fef6b
PP
125 if (dmalen > buflen) {
126 return 0;
127 }
8b17de88 128 s->dma_memory_read(s->dma_opaque, buf, dmalen);
4f6200f0 129 } else {
fc4d65da 130 dmalen = s->ti_size;
d3cdc491
PP
131 if (dmalen > TI_BUFSZ) {
132 return 0;
133 }
fc4d65da 134 memcpy(buf, s->ti_buf, dmalen);
75ef8496 135 buf[0] = buf[2] >> 5;
4f6200f0 136 }
bf4b9889 137 trace_esp_get_cmd(dmalen, target);
2e5d83bb 138
6130b188 139 if (get_cmd_cb(s) < 0) {
f930d07e 140 return 0;
2f275b8f 141 }
9f149aa9
PB
142 return dmalen;
143}
144
f2818f22 145static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
9f149aa9
PB
146{
147 int32_t datalen;
148 int lun;
f48a7a6e 149 SCSIDevice *current_lun;
9f149aa9 150
bf4b9889 151 trace_esp_do_busid_cmd(busid);
f2818f22 152 lun = busid & 7;
0d3545e7 153 current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
e6810db8 154 s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
c39ce112 155 datalen = scsi_req_enqueue(s->current_req);
67e999be
FB
156 s->ti_size = datalen;
157 if (datalen != 0) {
c73f96fd 158 s->rregs[ESP_RSTAT] = STAT_TC;
a917d384 159 s->dma_left = 0;
6787f5fa 160 s->dma_counter = 0;
2e5d83bb 161 if (datalen > 0) {
5ad6bb97 162 s->rregs[ESP_RSTAT] |= STAT_DI;
2e5d83bb 163 } else {
5ad6bb97 164 s->rregs[ESP_RSTAT] |= STAT_DO;
b9788fc4 165 }
ad3376cc 166 scsi_req_continue(s->current_req);
2f275b8f 167 }
5ad6bb97
BS
168 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
169 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 170 esp_raise_irq(s);
2f275b8f
FB
171}
172
f2818f22
AT
173static void do_cmd(ESPState *s, uint8_t *buf)
174{
175 uint8_t busid = buf[0];
176
177 do_busid_cmd(s, &buf[1], busid);
178}
179
9f149aa9
PB
180static void handle_satn(ESPState *s)
181{
182 uint8_t buf[32];
183 int len;
184
1b26eaa1 185 if (s->dma && !s->dma_enabled) {
73d74342
BS
186 s->dma_cb = handle_satn;
187 return;
188 }
6c1fef6b 189 len = get_cmd(s, buf, sizeof(buf));
9f149aa9
PB
190 if (len)
191 do_cmd(s, buf);
192}
193
f2818f22
AT
194static void handle_s_without_atn(ESPState *s)
195{
196 uint8_t buf[32];
197 int len;
198
1b26eaa1 199 if (s->dma && !s->dma_enabled) {
73d74342
BS
200 s->dma_cb = handle_s_without_atn;
201 return;
202 }
6c1fef6b 203 len = get_cmd(s, buf, sizeof(buf));
f2818f22
AT
204 if (len) {
205 do_busid_cmd(s, buf, 0);
206 }
207}
208
9f149aa9
PB
209static void handle_satn_stop(ESPState *s)
210{
1b26eaa1 211 if (s->dma && !s->dma_enabled) {
73d74342
BS
212 s->dma_cb = handle_satn_stop;
213 return;
214 }
6c1fef6b 215 s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf));
9f149aa9 216 if (s->cmdlen) {
bf4b9889 217 trace_esp_handle_satn_stop(s->cmdlen);
9f149aa9 218 s->do_cmd = 1;
c73f96fd 219 s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
5ad6bb97
BS
220 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
221 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 222 esp_raise_irq(s);
9f149aa9
PB
223 }
224}
225
0fc5c15a 226static void write_response(ESPState *s)
2f275b8f 227{
bf4b9889 228 trace_esp_write_response(s->status);
3944966d 229 s->ti_buf[0] = s->status;
0fc5c15a 230 s->ti_buf[1] = 0;
4f6200f0 231 if (s->dma) {
8b17de88 232 s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
c73f96fd 233 s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
5ad6bb97
BS
234 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
235 s->rregs[ESP_RSEQ] = SEQ_CD;
4f6200f0 236 } else {
f930d07e
BS
237 s->ti_size = 2;
238 s->ti_rptr = 0;
d020aa50 239 s->ti_wptr = 2;
5ad6bb97 240 s->rregs[ESP_RFLAGS] = 2;
4f6200f0 241 }
c73f96fd 242 esp_raise_irq(s);
2f275b8f 243}
4f6200f0 244
a917d384
PB
245static void esp_dma_done(ESPState *s)
246{
c73f96fd 247 s->rregs[ESP_RSTAT] |= STAT_TC;
5ad6bb97
BS
248 s->rregs[ESP_RINTR] = INTR_BS;
249 s->rregs[ESP_RSEQ] = 0;
250 s->rregs[ESP_RFLAGS] = 0;
251 s->rregs[ESP_TCLO] = 0;
252 s->rregs[ESP_TCMID] = 0;
9ea73f8b 253 s->rregs[ESP_TCHI] = 0;
c73f96fd 254 esp_raise_irq(s);
a917d384
PB
255}
256
4d611c9a
PB
257static void esp_do_dma(ESPState *s)
258{
67e999be 259 uint32_t len;
4d611c9a 260 int to_device;
a917d384 261
a917d384 262 len = s->dma_left;
4d611c9a 263 if (s->do_cmd) {
15407433
LV
264 /*
265 * handle_ti_cmd() case: esp_do_dma() is called only from
266 * handle_ti_cmd() with do_cmd != NULL (see the assert())
267 */
bf4b9889 268 trace_esp_do_dma(s->cmdlen, len);
926cde5f
PP
269 assert (s->cmdlen <= sizeof(s->cmdbuf) &&
270 len <= sizeof(s->cmdbuf) - s->cmdlen);
8b17de88 271 s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
15407433
LV
272 trace_esp_handle_ti_cmd(s->cmdlen);
273 s->ti_size = 0;
274 s->cmdlen = 0;
275 s->do_cmd = 0;
276 do_cmd(s, s->cmdbuf);
4d611c9a 277 return;
a917d384
PB
278 }
279 if (s->async_len == 0) {
280 /* Defer until data is available. */
281 return;
282 }
283 if (len > s->async_len) {
284 len = s->async_len;
285 }
7f0b6e11 286 to_device = (s->ti_size < 0);
a917d384 287 if (to_device) {
8b17de88 288 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
4d611c9a 289 } else {
8b17de88 290 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
a917d384 291 }
a917d384
PB
292 s->dma_left -= len;
293 s->async_buf += len;
294 s->async_len -= len;
6787f5fa
PB
295 if (to_device)
296 s->ti_size += len;
297 else
298 s->ti_size -= len;
a917d384 299 if (s->async_len == 0) {
ad3376cc
PB
300 scsi_req_continue(s->current_req);
301 /* If there is still data to be read from the device then
302 complete the DMA operation immediately. Otherwise defer
303 until the scsi layer has completed. */
304 if (to_device || s->dma_left != 0 || s->ti_size == 0) {
305 return;
4d611c9a 306 }
a917d384 307 }
ad3376cc
PB
308
309 /* Partially filled a scsi buffer. Complete immediately. */
310 esp_dma_done(s);
4d611c9a
PB
311}
312
ea84a442 313static void esp_report_command_complete(ESPState *s, uint32_t status)
2e5d83bb 314{
bf4b9889 315 trace_esp_command_complete();
c6df7102 316 if (s->ti_size != 0) {
bf4b9889 317 trace_esp_command_complete_unexpected();
c6df7102
PB
318 }
319 s->ti_size = 0;
320 s->dma_left = 0;
321 s->async_len = 0;
aba1f023 322 if (status) {
bf4b9889 323 trace_esp_command_complete_fail();
c6df7102 324 }
aba1f023 325 s->status = status;
c6df7102
PB
326 s->rregs[ESP_RSTAT] = STAT_ST;
327 esp_dma_done(s);
328 if (s->current_req) {
329 scsi_req_unref(s->current_req);
330 s->current_req = NULL;
331 s->current_dev = NULL;
332 }
333}
334
ea84a442
GR
335void esp_command_complete(SCSIRequest *req, uint32_t status,
336 size_t resid)
337{
338 ESPState *s = req->hba_private;
339
340 if (s->rregs[ESP_RSTAT] & STAT_INT) {
341 /* Defer handling command complete until the previous
342 * interrupt has been handled.
343 */
344 trace_esp_command_complete_deferred();
345 s->deferred_status = status;
346 s->deferred_complete = true;
347 return;
348 }
349 esp_report_command_complete(s, status);
350}
351
9c7e23fc 352void esp_transfer_data(SCSIRequest *req, uint32_t len)
c6df7102 353{
e6810db8 354 ESPState *s = req->hba_private;
c6df7102 355
7f0b6e11 356 assert(!s->do_cmd);
bf4b9889 357 trace_esp_transfer_data(s->dma_left, s->ti_size);
aba1f023 358 s->async_len = len;
c6df7102
PB
359 s->async_buf = scsi_req_get_buf(req);
360 if (s->dma_left) {
361 esp_do_dma(s);
362 } else if (s->dma_counter != 0 && s->ti_size <= 0) {
363 /* If this was the last part of a DMA transfer then the
364 completion interrupt is deferred to here. */
a917d384 365 esp_dma_done(s);
4d611c9a 366 }
2e5d83bb
PB
367}
368
2f275b8f
FB
369static void handle_ti(ESPState *s)
370{
4d611c9a 371 uint32_t dmalen, minlen;
2f275b8f 372
7246e160
HP
373 if (s->dma && !s->dma_enabled) {
374 s->dma_cb = handle_ti;
375 return;
376 }
377
9ea73f8b
PB
378 dmalen = s->rregs[ESP_TCLO];
379 dmalen |= s->rregs[ESP_TCMID] << 8;
380 dmalen |= s->rregs[ESP_TCHI] << 16;
db59203d
PB
381 if (dmalen==0) {
382 dmalen=0x10000;
383 }
6787f5fa 384 s->dma_counter = dmalen;
db59203d 385
9f149aa9 386 if (s->do_cmd)
926cde5f 387 minlen = (dmalen < ESP_CMDBUF_SZ) ? dmalen : ESP_CMDBUF_SZ;
67e999be
FB
388 else if (s->ti_size < 0)
389 minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
9f149aa9
PB
390 else
391 minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
bf4b9889 392 trace_esp_handle_ti(minlen);
4f6200f0 393 if (s->dma) {
4d611c9a 394 s->dma_left = minlen;
5ad6bb97 395 s->rregs[ESP_RSTAT] &= ~STAT_TC;
4d611c9a 396 esp_do_dma(s);
15407433 397 } else if (s->do_cmd) {
bf4b9889 398 trace_esp_handle_ti_cmd(s->cmdlen);
9f149aa9
PB
399 s->ti_size = 0;
400 s->cmdlen = 0;
401 s->do_cmd = 0;
402 do_cmd(s, s->cmdbuf);
9f149aa9 403 }
2f275b8f
FB
404}
405
9c7e23fc 406void esp_hard_reset(ESPState *s)
6f7e9aec 407{
5aca8c3b
BS
408 memset(s->rregs, 0, ESP_REGS);
409 memset(s->wregs, 0, ESP_REGS);
c9cf45c1 410 s->tchi_written = 0;
4e9aec74
PB
411 s->ti_size = 0;
412 s->ti_rptr = 0;
413 s->ti_wptr = 0;
4e9aec74 414 s->dma = 0;
9f149aa9 415 s->do_cmd = 0;
73d74342 416 s->dma_cb = NULL;
8dea1dd4
BS
417
418 s->rregs[ESP_CFG1] = 7;
6f7e9aec
FB
419}
420
a391fdbc 421static void esp_soft_reset(ESPState *s)
85948643 422{
85948643 423 qemu_irq_lower(s->irq);
a391fdbc 424 esp_hard_reset(s);
85948643
BS
425}
426
a391fdbc 427static void parent_esp_reset(ESPState *s, int irq, int level)
2d069bab 428{
85948643 429 if (level) {
a391fdbc 430 esp_soft_reset(s);
85948643 431 }
2d069bab
BS
432}
433
9c7e23fc 434uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
73d74342 435{
a391fdbc 436 uint32_t old_val;
73d74342 437
bf4b9889 438 trace_esp_mem_readb(saddr, s->rregs[saddr]);
6f7e9aec 439 switch (saddr) {
5ad6bb97 440 case ESP_FIFO:
ff589551
PP
441 if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
442 /* Data out. */
443 qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
444 s->rregs[ESP_FIFO] = 0;
ff589551 445 } else if (s->ti_rptr < s->ti_wptr) {
f930d07e 446 s->ti_size--;
ff589551 447 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
f930d07e 448 }
ff589551 449 if (s->ti_rptr == s->ti_wptr) {
4f6200f0
FB
450 s->ti_rptr = 0;
451 s->ti_wptr = 0;
452 }
f930d07e 453 break;
5ad6bb97 454 case ESP_RINTR:
2814df28
BS
455 /* Clear sequence step, interrupt register and all status bits
456 except TC */
457 old_val = s->rregs[ESP_RINTR];
458 s->rregs[ESP_RINTR] = 0;
459 s->rregs[ESP_RSTAT] &= ~STAT_TC;
460 s->rregs[ESP_RSEQ] = SEQ_CD;
c73f96fd 461 esp_lower_irq(s);
ea84a442
GR
462 if (s->deferred_complete) {
463 esp_report_command_complete(s, s->deferred_status);
464 s->deferred_complete = false;
465 }
2814df28 466 return old_val;
c9cf45c1
HR
467 case ESP_TCHI:
468 /* Return the unique id if the value has never been written */
469 if (!s->tchi_written) {
470 return s->chip_id;
471 }
6f7e9aec 472 default:
f930d07e 473 break;
6f7e9aec 474 }
2f275b8f 475 return s->rregs[saddr];
6f7e9aec
FB
476}
477
9c7e23fc 478void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
6f7e9aec 479{
bf4b9889 480 trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
6f7e9aec 481 switch (saddr) {
c9cf45c1
HR
482 case ESP_TCHI:
483 s->tchi_written = true;
484 /* fall through */
5ad6bb97
BS
485 case ESP_TCLO:
486 case ESP_TCMID:
487 s->rregs[ESP_RSTAT] &= ~STAT_TC;
4f6200f0 488 break;
5ad6bb97 489 case ESP_FIFO:
9f149aa9 490 if (s->do_cmd) {
926cde5f 491 if (s->cmdlen < ESP_CMDBUF_SZ) {
c98c6c10
PP
492 s->cmdbuf[s->cmdlen++] = val & 0xff;
493 } else {
494 trace_esp_error_fifo_overrun();
495 }
ff589551 496 } else if (s->ti_wptr == TI_BUFSZ - 1) {
3af4e9aa 497 trace_esp_error_fifo_overrun();
2e5d83bb
PB
498 } else {
499 s->ti_size++;
500 s->ti_buf[s->ti_wptr++] = val & 0xff;
501 }
f930d07e 502 break;
5ad6bb97 503 case ESP_CMD:
4f6200f0 504 s->rregs[saddr] = val;
5ad6bb97 505 if (val & CMD_DMA) {
f930d07e 506 s->dma = 1;
6787f5fa 507 /* Reload DMA counter. */
5ad6bb97
BS
508 s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
509 s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
9ea73f8b 510 s->rregs[ESP_TCHI] = s->wregs[ESP_TCHI];
f930d07e
BS
511 } else {
512 s->dma = 0;
513 }
5ad6bb97
BS
514 switch(val & CMD_CMD) {
515 case CMD_NOP:
bf4b9889 516 trace_esp_mem_writeb_cmd_nop(val);
f930d07e 517 break;
5ad6bb97 518 case CMD_FLUSH:
bf4b9889 519 trace_esp_mem_writeb_cmd_flush(val);
9e61bde5 520 //s->ti_size = 0;
5ad6bb97
BS
521 s->rregs[ESP_RINTR] = INTR_FC;
522 s->rregs[ESP_RSEQ] = 0;
a214c598 523 s->rregs[ESP_RFLAGS] = 0;
f930d07e 524 break;
5ad6bb97 525 case CMD_RESET:
bf4b9889 526 trace_esp_mem_writeb_cmd_reset(val);
a391fdbc 527 esp_soft_reset(s);
f930d07e 528 break;
5ad6bb97 529 case CMD_BUSRESET:
bf4b9889 530 trace_esp_mem_writeb_cmd_bus_reset(val);
5ad6bb97
BS
531 s->rregs[ESP_RINTR] = INTR_RST;
532 if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
c73f96fd 533 esp_raise_irq(s);
9e61bde5 534 }
f930d07e 535 break;
5ad6bb97 536 case CMD_TI:
f930d07e
BS
537 handle_ti(s);
538 break;
5ad6bb97 539 case CMD_ICCS:
bf4b9889 540 trace_esp_mem_writeb_cmd_iccs(val);
f930d07e 541 write_response(s);
4bf5801d
BS
542 s->rregs[ESP_RINTR] = INTR_FC;
543 s->rregs[ESP_RSTAT] |= STAT_MI;
f930d07e 544 break;
5ad6bb97 545 case CMD_MSGACC:
bf4b9889 546 trace_esp_mem_writeb_cmd_msgacc(val);
5ad6bb97
BS
547 s->rregs[ESP_RINTR] = INTR_DC;
548 s->rregs[ESP_RSEQ] = 0;
4e2a68c1
AT
549 s->rregs[ESP_RFLAGS] = 0;
550 esp_raise_irq(s);
f930d07e 551 break;
0fd0eb21 552 case CMD_PAD:
bf4b9889 553 trace_esp_mem_writeb_cmd_pad(val);
0fd0eb21
BS
554 s->rregs[ESP_RSTAT] = STAT_TC;
555 s->rregs[ESP_RINTR] = INTR_FC;
556 s->rregs[ESP_RSEQ] = 0;
557 break;
5ad6bb97 558 case CMD_SATN:
bf4b9889 559 trace_esp_mem_writeb_cmd_satn(val);
f930d07e 560 break;
6915bff1
HP
561 case CMD_RSTATN:
562 trace_esp_mem_writeb_cmd_rstatn(val);
563 break;
5e1e0a3b 564 case CMD_SEL:
bf4b9889 565 trace_esp_mem_writeb_cmd_sel(val);
f2818f22 566 handle_s_without_atn(s);
5e1e0a3b 567 break;
5ad6bb97 568 case CMD_SELATN:
bf4b9889 569 trace_esp_mem_writeb_cmd_selatn(val);
f930d07e
BS
570 handle_satn(s);
571 break;
5ad6bb97 572 case CMD_SELATNS:
bf4b9889 573 trace_esp_mem_writeb_cmd_selatns(val);
f930d07e
BS
574 handle_satn_stop(s);
575 break;
5ad6bb97 576 case CMD_ENSEL:
bf4b9889 577 trace_esp_mem_writeb_cmd_ensel(val);
e3926838 578 s->rregs[ESP_RINTR] = 0;
74ec6048 579 break;
6fe84c18
HP
580 case CMD_DISSEL:
581 trace_esp_mem_writeb_cmd_dissel(val);
582 s->rregs[ESP_RINTR] = 0;
583 esp_raise_irq(s);
584 break;
f930d07e 585 default:
3af4e9aa 586 trace_esp_error_unhandled_command(val);
f930d07e
BS
587 break;
588 }
589 break;
5ad6bb97 590 case ESP_WBUSID ... ESP_WSYNO:
f930d07e 591 break;
5ad6bb97 592 case ESP_CFG1:
9ea73f8b
PB
593 case ESP_CFG2: case ESP_CFG3:
594 case ESP_RES3: case ESP_RES4:
4f6200f0
FB
595 s->rregs[saddr] = val;
596 break;
5ad6bb97 597 case ESP_WCCF ... ESP_WTEST:
4f6200f0 598 break;
6f7e9aec 599 default:
3af4e9aa 600 trace_esp_error_invalid_write(val, saddr);
8dea1dd4 601 return;
6f7e9aec 602 }
2f275b8f 603 s->wregs[saddr] = val;
6f7e9aec
FB
604}
605
a8170e5e 606static bool esp_mem_accepts(void *opaque, hwaddr addr,
8372d383
PM
607 unsigned size, bool is_write,
608 MemTxAttrs attrs)
67bb5314
AK
609{
610 return (size == 1) || (is_write && size == 4);
611}
6f7e9aec 612
9c7e23fc 613const VMStateDescription vmstate_esp = {
cc9952f3 614 .name ="esp",
cc966774 615 .version_id = 4,
cc9952f3 616 .minimum_version_id = 3,
35d08458 617 .fields = (VMStateField[]) {
cc9952f3
BS
618 VMSTATE_BUFFER(rregs, ESPState),
619 VMSTATE_BUFFER(wregs, ESPState),
620 VMSTATE_INT32(ti_size, ESPState),
621 VMSTATE_UINT32(ti_rptr, ESPState),
622 VMSTATE_UINT32(ti_wptr, ESPState),
623 VMSTATE_BUFFER(ti_buf, ESPState),
3944966d 624 VMSTATE_UINT32(status, ESPState),
ea84a442
GR
625 VMSTATE_UINT32(deferred_status, ESPState),
626 VMSTATE_BOOL(deferred_complete, ESPState),
cc9952f3 627 VMSTATE_UINT32(dma, ESPState),
cc966774
PB
628 VMSTATE_PARTIAL_BUFFER(cmdbuf, ESPState, 16),
629 VMSTATE_BUFFER_START_MIDDLE_V(cmdbuf, ESPState, 16, 4),
cc9952f3
BS
630 VMSTATE_UINT32(cmdlen, ESPState),
631 VMSTATE_UINT32(do_cmd, ESPState),
632 VMSTATE_UINT32(dma_left, ESPState),
633 VMSTATE_END_OF_LIST()
634 }
635};
6f7e9aec 636
a8170e5e 637static void sysbus_esp_mem_write(void *opaque, hwaddr addr,
a391fdbc
HP
638 uint64_t val, unsigned int size)
639{
640 SysBusESPState *sysbus = opaque;
641 uint32_t saddr;
642
643 saddr = addr >> sysbus->it_shift;
644 esp_reg_write(&sysbus->esp, saddr, val);
645}
646
a8170e5e 647static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr,
a391fdbc
HP
648 unsigned int size)
649{
650 SysBusESPState *sysbus = opaque;
651 uint32_t saddr;
652
653 saddr = addr >> sysbus->it_shift;
654 return esp_reg_read(&sysbus->esp, saddr);
655}
656
657static const MemoryRegionOps sysbus_esp_mem_ops = {
658 .read = sysbus_esp_mem_read,
659 .write = sysbus_esp_mem_write,
660 .endianness = DEVICE_NATIVE_ENDIAN,
661 .valid.accepts = esp_mem_accepts,
662};
663
afd4030c
PB
664static const struct SCSIBusInfo esp_scsi_info = {
665 .tcq = false,
7e0380b9
PB
666 .max_target = ESP_MAX_DEVS,
667 .max_lun = 7,
afd4030c 668
c6df7102 669 .transfer_data = esp_transfer_data,
94d3f98a
PB
670 .complete = esp_command_complete,
671 .cancel = esp_request_cancelled
cfdc1bb0
PB
672};
673
a391fdbc 674static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
cfb9de9c 675{
80cac47e 676 SysBusESPState *sysbus = ESP_STATE(opaque);
a391fdbc
HP
677 ESPState *s = &sysbus->esp;
678
679 switch (irq) {
680 case 0:
681 parent_esp_reset(s, irq, level);
682 break;
683 case 1:
684 esp_dma_enable(opaque, irq, level);
685 break;
686 }
687}
688
b09318ca 689static void sysbus_esp_realize(DeviceState *dev, Error **errp)
a391fdbc 690{
b09318ca 691 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
80cac47e 692 SysBusESPState *sysbus = ESP_STATE(dev);
a391fdbc 693 ESPState *s = &sysbus->esp;
6f7e9aec 694
b09318ca 695 sysbus_init_irq(sbd, &s->irq);
a391fdbc 696 assert(sysbus->it_shift != -1);
6f7e9aec 697
d32e4b3d 698 s->chip_id = TCHI_FAS100A;
29776739
PB
699 memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
700 sysbus, "esp", ESP_REGS << sysbus->it_shift);
b09318ca 701 sysbus_init_mmio(sbd, &sysbus->iomem);
6f7e9aec 702
b09318ca 703 qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
2d069bab 704
b1187b51 705 scsi_bus_new(&s->bus, sizeof(s->bus), dev, &esp_scsi_info, NULL);
67e999be 706}
cfb9de9c 707
a391fdbc
HP
708static void sysbus_esp_hard_reset(DeviceState *dev)
709{
80cac47e 710 SysBusESPState *sysbus = ESP_STATE(dev);
a391fdbc
HP
711 esp_hard_reset(&sysbus->esp);
712}
713
714static const VMStateDescription vmstate_sysbus_esp_scsi = {
715 .name = "sysbusespscsi",
ea84a442
GR
716 .version_id = 1,
717 .minimum_version_id = 1,
a391fdbc
HP
718 .fields = (VMStateField[]) {
719 VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
720 VMSTATE_END_OF_LIST()
721 }
999e12bb
AL
722};
723
a391fdbc 724static void sysbus_esp_class_init(ObjectClass *klass, void *data)
999e12bb 725{
39bffca2 726 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 727
b09318ca 728 dc->realize = sysbus_esp_realize;
a391fdbc
HP
729 dc->reset = sysbus_esp_hard_reset;
730 dc->vmsd = &vmstate_sysbus_esp_scsi;
125ee0ed 731 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
999e12bb
AL
732}
733
1f077308 734static const TypeInfo sysbus_esp_info = {
a71c7ec5 735 .name = TYPE_ESP,
39bffca2 736 .parent = TYPE_SYS_BUS_DEVICE,
a391fdbc
HP
737 .instance_size = sizeof(SysBusESPState),
738 .class_init = sysbus_esp_class_init,
63235df8
BS
739};
740
83f7d43a 741static void esp_register_types(void)
cfb9de9c 742{
a391fdbc 743 type_register_static(&sysbus_esp_info);
cfb9de9c
PB
744}
745
83f7d43a 746type_init(esp_register_types)