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