xref: /qemu/hw/scsi/esp.c (revision 1828000b)
149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini  * QEMU ESP/NCR53C9x emulation
349ab747fSPaolo Bonzini  *
449ab747fSPaolo Bonzini  * Copyright (c) 2005-2006 Fabrice Bellard
549ab747fSPaolo Bonzini  * Copyright (c) 2012 Herve Poussineau
678d68f31SMark Cave-Ayland  * Copyright (c) 2023 Mark Cave-Ayland
749ab747fSPaolo Bonzini  *
849ab747fSPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
949ab747fSPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
1049ab747fSPaolo Bonzini  * in the Software without restriction, including without limitation the rights
1149ab747fSPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1249ab747fSPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1349ab747fSPaolo Bonzini  * furnished to do so, subject to the following conditions:
1449ab747fSPaolo Bonzini  *
1549ab747fSPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1649ab747fSPaolo Bonzini  * all copies or substantial portions of the Software.
1749ab747fSPaolo Bonzini  *
1849ab747fSPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1949ab747fSPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2049ab747fSPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2149ab747fSPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2249ab747fSPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2349ab747fSPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2449ab747fSPaolo Bonzini  * THE SOFTWARE.
2549ab747fSPaolo Bonzini  */
2649ab747fSPaolo Bonzini 
27a4ab4792SPeter Maydell #include "qemu/osdep.h"
2849ab747fSPaolo Bonzini #include "hw/sysbus.h"
29d6454270SMarkus Armbruster #include "migration/vmstate.h"
3064552b6bSMarkus Armbruster #include "hw/irq.h"
3149ab747fSPaolo Bonzini #include "hw/scsi/esp.h"
3249ab747fSPaolo Bonzini #include "trace.h"
3349ab747fSPaolo Bonzini #include "qemu/log.h"
340b8fa32fSMarkus Armbruster #include "qemu/module.h"
3549ab747fSPaolo Bonzini 
3649ab747fSPaolo Bonzini /*
3749ab747fSPaolo Bonzini  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
3849ab747fSPaolo Bonzini  * also produced as NCR89C100. See
3949ab747fSPaolo Bonzini  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
4049ab747fSPaolo Bonzini  * and
4149ab747fSPaolo Bonzini  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
4274d71ea1SLaurent Vivier  *
4374d71ea1SLaurent Vivier  * On Macintosh Quadra it is a NCR53C96.
4449ab747fSPaolo Bonzini  */
4549ab747fSPaolo Bonzini 
4649ab747fSPaolo Bonzini static void esp_raise_irq(ESPState *s)
4749ab747fSPaolo Bonzini {
4849ab747fSPaolo Bonzini     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
4949ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] |= STAT_INT;
5049ab747fSPaolo Bonzini         qemu_irq_raise(s->irq);
5149ab747fSPaolo Bonzini         trace_esp_raise_irq();
5249ab747fSPaolo Bonzini     }
5349ab747fSPaolo Bonzini }
5449ab747fSPaolo Bonzini 
5549ab747fSPaolo Bonzini static void esp_lower_irq(ESPState *s)
5649ab747fSPaolo Bonzini {
5749ab747fSPaolo Bonzini     if (s->rregs[ESP_RSTAT] & STAT_INT) {
5849ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] &= ~STAT_INT;
5949ab747fSPaolo Bonzini         qemu_irq_lower(s->irq);
6049ab747fSPaolo Bonzini         trace_esp_lower_irq();
6149ab747fSPaolo Bonzini     }
6249ab747fSPaolo Bonzini }
6349ab747fSPaolo Bonzini 
6474d71ea1SLaurent Vivier static void esp_raise_drq(ESPState *s)
6574d71ea1SLaurent Vivier {
66442de89aSMark Cave-Ayland     if (!(s->drq_state)) {
676dec7c0dSMark Cave-Ayland         qemu_irq_raise(s->drq_irq);
68960ebfd9SMark Cave-Ayland         trace_esp_raise_drq();
69442de89aSMark Cave-Ayland         s->drq_state = true;
70442de89aSMark Cave-Ayland     }
7174d71ea1SLaurent Vivier }
7274d71ea1SLaurent Vivier 
7374d71ea1SLaurent Vivier static void esp_lower_drq(ESPState *s)
7474d71ea1SLaurent Vivier {
75442de89aSMark Cave-Ayland     if (s->drq_state) {
766dec7c0dSMark Cave-Ayland         qemu_irq_lower(s->drq_irq);
77960ebfd9SMark Cave-Ayland         trace_esp_lower_drq();
78442de89aSMark Cave-Ayland         s->drq_state = false;
79442de89aSMark Cave-Ayland     }
8074d71ea1SLaurent Vivier }
8174d71ea1SLaurent Vivier 
8249ab747fSPaolo Bonzini void esp_dma_enable(ESPState *s, int irq, int level)
8349ab747fSPaolo Bonzini {
8449ab747fSPaolo Bonzini     if (level) {
8549ab747fSPaolo Bonzini         s->dma_enabled = 1;
8649ab747fSPaolo Bonzini         trace_esp_dma_enable();
8749ab747fSPaolo Bonzini         if (s->dma_cb) {
8849ab747fSPaolo Bonzini             s->dma_cb(s);
8949ab747fSPaolo Bonzini             s->dma_cb = NULL;
9049ab747fSPaolo Bonzini         }
9149ab747fSPaolo Bonzini     } else {
9249ab747fSPaolo Bonzini         trace_esp_dma_disable();
9349ab747fSPaolo Bonzini         s->dma_enabled = 0;
9449ab747fSPaolo Bonzini     }
9549ab747fSPaolo Bonzini }
9649ab747fSPaolo Bonzini 
9749ab747fSPaolo Bonzini void esp_request_cancelled(SCSIRequest *req)
9849ab747fSPaolo Bonzini {
9949ab747fSPaolo Bonzini     ESPState *s = req->hba_private;
10049ab747fSPaolo Bonzini 
10149ab747fSPaolo Bonzini     if (req == s->current_req) {
10249ab747fSPaolo Bonzini         scsi_req_unref(s->current_req);
10349ab747fSPaolo Bonzini         s->current_req = NULL;
10449ab747fSPaolo Bonzini         s->current_dev = NULL;
105324c8809SMark Cave-Ayland         s->async_len = 0;
10649ab747fSPaolo Bonzini     }
10749ab747fSPaolo Bonzini }
10849ab747fSPaolo Bonzini 
109e5455b8cSMark Cave-Ayland static void esp_fifo_push(Fifo8 *fifo, uint8_t val)
110042879fcSMark Cave-Ayland {
111e5455b8cSMark Cave-Ayland     if (fifo8_num_used(fifo) == fifo->capacity) {
112042879fcSMark Cave-Ayland         trace_esp_error_fifo_overrun();
113042879fcSMark Cave-Ayland         return;
114042879fcSMark Cave-Ayland     }
115042879fcSMark Cave-Ayland 
116e5455b8cSMark Cave-Ayland     fifo8_push(fifo, val);
117042879fcSMark Cave-Ayland }
118c5fef911SMark Cave-Ayland 
119c5fef911SMark Cave-Ayland static uint8_t esp_fifo_pop(Fifo8 *fifo)
120042879fcSMark Cave-Ayland {
121c5fef911SMark Cave-Ayland     if (fifo8_is_empty(fifo)) {
122042879fcSMark Cave-Ayland         return 0;
123042879fcSMark Cave-Ayland     }
124042879fcSMark Cave-Ayland 
125c5fef911SMark Cave-Ayland     return fifo8_pop(fifo);
126023666daSMark Cave-Ayland }
127023666daSMark Cave-Ayland 
128d103d0dbSMark Cave-Ayland static uint32_t esp_fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen)
1297b320a8eSMark Cave-Ayland {
1307b320a8eSMark Cave-Ayland     const uint8_t *buf;
13149c60d16SMark Cave-Ayland     uint32_t n, n2;
13249c60d16SMark Cave-Ayland     int len;
1337b320a8eSMark Cave-Ayland 
1347b320a8eSMark Cave-Ayland     if (maxlen == 0) {
1357b320a8eSMark Cave-Ayland         return 0;
1367b320a8eSMark Cave-Ayland     }
1377b320a8eSMark Cave-Ayland 
13849c60d16SMark Cave-Ayland     len = maxlen;
13949c60d16SMark Cave-Ayland     buf = fifo8_pop_buf(fifo, len, &n);
1407b320a8eSMark Cave-Ayland     if (dest) {
1417b320a8eSMark Cave-Ayland         memcpy(dest, buf, n);
1427b320a8eSMark Cave-Ayland     }
1437b320a8eSMark Cave-Ayland 
14449c60d16SMark Cave-Ayland     /* Add FIFO wraparound if needed */
14549c60d16SMark Cave-Ayland     len -= n;
14649c60d16SMark Cave-Ayland     len = MIN(len, fifo8_num_used(fifo));
14749c60d16SMark Cave-Ayland     if (len) {
14849c60d16SMark Cave-Ayland         buf = fifo8_pop_buf(fifo, len, &n2);
14949c60d16SMark Cave-Ayland         if (dest) {
15049c60d16SMark Cave-Ayland             memcpy(&dest[n], buf, n2);
15149c60d16SMark Cave-Ayland         }
15249c60d16SMark Cave-Ayland         n += n2;
15349c60d16SMark Cave-Ayland     }
15449c60d16SMark Cave-Ayland 
1557b320a8eSMark Cave-Ayland     return n;
1567b320a8eSMark Cave-Ayland }
1577b320a8eSMark Cave-Ayland 
158d103d0dbSMark Cave-Ayland static uint32_t esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen)
159d103d0dbSMark Cave-Ayland {
160d103d0dbSMark Cave-Ayland     return esp_fifo8_pop_buf(fifo, dest, maxlen);
161d103d0dbSMark Cave-Ayland }
162d103d0dbSMark Cave-Ayland 
163c47b5835SMark Cave-Ayland static uint32_t esp_get_tc(ESPState *s)
164c47b5835SMark Cave-Ayland {
165c47b5835SMark Cave-Ayland     uint32_t dmalen;
166c47b5835SMark Cave-Ayland 
167c47b5835SMark Cave-Ayland     dmalen = s->rregs[ESP_TCLO];
168c47b5835SMark Cave-Ayland     dmalen |= s->rregs[ESP_TCMID] << 8;
169c47b5835SMark Cave-Ayland     dmalen |= s->rregs[ESP_TCHI] << 16;
170c47b5835SMark Cave-Ayland 
171c47b5835SMark Cave-Ayland     return dmalen;
172c47b5835SMark Cave-Ayland }
173c47b5835SMark Cave-Ayland 
174c47b5835SMark Cave-Ayland static void esp_set_tc(ESPState *s, uint32_t dmalen)
175c47b5835SMark Cave-Ayland {
176c5d7df28SMark Cave-Ayland     uint32_t old_tc = esp_get_tc(s);
177c5d7df28SMark Cave-Ayland 
178c47b5835SMark Cave-Ayland     s->rregs[ESP_TCLO] = dmalen;
179c47b5835SMark Cave-Ayland     s->rregs[ESP_TCMID] = dmalen >> 8;
180c47b5835SMark Cave-Ayland     s->rregs[ESP_TCHI] = dmalen >> 16;
181c5d7df28SMark Cave-Ayland 
182c5d7df28SMark Cave-Ayland     if (old_tc && dmalen == 0) {
183c5d7df28SMark Cave-Ayland         s->rregs[ESP_RSTAT] |= STAT_TC;
184c5d7df28SMark Cave-Ayland     }
185c47b5835SMark Cave-Ayland }
186c47b5835SMark Cave-Ayland 
187c04ed569SMark Cave-Ayland static uint32_t esp_get_stc(ESPState *s)
188c04ed569SMark Cave-Ayland {
189c04ed569SMark Cave-Ayland     uint32_t dmalen;
190c04ed569SMark Cave-Ayland 
191c04ed569SMark Cave-Ayland     dmalen = s->wregs[ESP_TCLO];
192c04ed569SMark Cave-Ayland     dmalen |= s->wregs[ESP_TCMID] << 8;
193c04ed569SMark Cave-Ayland     dmalen |= s->wregs[ESP_TCHI] << 16;
194c04ed569SMark Cave-Ayland 
195c04ed569SMark Cave-Ayland     return dmalen;
196c04ed569SMark Cave-Ayland }
197c04ed569SMark Cave-Ayland 
198abc139cdSMark Cave-Ayland static const char *esp_phase_names[8] = {
199abc139cdSMark Cave-Ayland     "DATA OUT", "DATA IN", "COMMAND", "STATUS",
200abc139cdSMark Cave-Ayland     "(reserved)", "(reserved)", "MESSAGE OUT", "MESSAGE IN"
201abc139cdSMark Cave-Ayland };
202abc139cdSMark Cave-Ayland 
203abc139cdSMark Cave-Ayland static void esp_set_phase(ESPState *s, uint8_t phase)
204abc139cdSMark Cave-Ayland {
205abc139cdSMark Cave-Ayland     s->rregs[ESP_RSTAT] &= ~7;
206abc139cdSMark Cave-Ayland     s->rregs[ESP_RSTAT] |= phase;
207abc139cdSMark Cave-Ayland 
208abc139cdSMark Cave-Ayland     trace_esp_set_phase(esp_phase_names[phase]);
209abc139cdSMark Cave-Ayland }
210abc139cdSMark Cave-Ayland 
2115a83e83eSMark Cave-Ayland static uint8_t esp_get_phase(ESPState *s)
2125a83e83eSMark Cave-Ayland {
2135a83e83eSMark Cave-Ayland     return s->rregs[ESP_RSTAT] & 7;
2145a83e83eSMark Cave-Ayland }
2155a83e83eSMark Cave-Ayland 
216761bef75SMark Cave-Ayland static uint8_t esp_pdma_read(ESPState *s)
217761bef75SMark Cave-Ayland {
2188da90e81SMark Cave-Ayland     uint8_t val;
2198da90e81SMark Cave-Ayland 
220c5fef911SMark Cave-Ayland     val = esp_fifo_pop(&s->fifo);
2218da90e81SMark Cave-Ayland     return val;
222761bef75SMark Cave-Ayland }
223761bef75SMark Cave-Ayland 
224761bef75SMark Cave-Ayland static void esp_pdma_write(ESPState *s, uint8_t val)
225761bef75SMark Cave-Ayland {
2268da90e81SMark Cave-Ayland     uint32_t dmalen = esp_get_tc(s);
2278da90e81SMark Cave-Ayland 
2283c421400SMark Cave-Ayland     if (dmalen == 0) {
2298da90e81SMark Cave-Ayland         return;
2308da90e81SMark Cave-Ayland     }
2318da90e81SMark Cave-Ayland 
232e5455b8cSMark Cave-Ayland     esp_fifo_push(&s->fifo, val);
2338da90e81SMark Cave-Ayland 
2348da90e81SMark Cave-Ayland     dmalen--;
2358da90e81SMark Cave-Ayland     esp_set_tc(s, dmalen);
236761bef75SMark Cave-Ayland }
237761bef75SMark Cave-Ayland 
238c7bce09cSMark Cave-Ayland static int esp_select(ESPState *s)
2396130b188SLaurent Vivier {
2406130b188SLaurent Vivier     int target;
2416130b188SLaurent Vivier 
2426130b188SLaurent Vivier     target = s->wregs[ESP_WBUSID] & BUSID_DID;
2436130b188SLaurent Vivier 
2446130b188SLaurent Vivier     s->ti_size = 0;
2459b2cdca2SMark Cave-Ayland     s->rregs[ESP_RSEQ] = SEQ_0;
2466130b188SLaurent Vivier 
247cf40a5e4SMark Cave-Ayland     if (s->current_req) {
248cf40a5e4SMark Cave-Ayland         /* Started a new command before the old one finished. Cancel it. */
249cf40a5e4SMark Cave-Ayland         scsi_req_cancel(s->current_req);
250cf40a5e4SMark Cave-Ayland     }
251cf40a5e4SMark Cave-Ayland 
2526130b188SLaurent Vivier     s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
2536130b188SLaurent Vivier     if (!s->current_dev) {
2546130b188SLaurent Vivier         /* No such drive */
2556130b188SLaurent Vivier         s->rregs[ESP_RSTAT] = 0;
256cf1a7a9bSMark Cave-Ayland         s->rregs[ESP_RINTR] = INTR_DC;
2576130b188SLaurent Vivier         esp_raise_irq(s);
2586130b188SLaurent Vivier         return -1;
2596130b188SLaurent Vivier     }
2604e78f3bfSMark Cave-Ayland 
2614e78f3bfSMark Cave-Ayland     /*
2624e78f3bfSMark Cave-Ayland      * Note that we deliberately don't raise the IRQ here: this will be done
263c90b2792SMark Cave-Ayland      * either in esp_transfer_data() or esp_command_complete()
2644e78f3bfSMark Cave-Ayland      */
2656130b188SLaurent Vivier     return 0;
2666130b188SLaurent Vivier }
2676130b188SLaurent Vivier 
2683ee9a475SMark Cave-Ayland static void esp_do_dma(ESPState *s);
2693ee9a475SMark Cave-Ayland static void esp_do_nodma(ESPState *s);
2703ee9a475SMark Cave-Ayland 
2714eb86065SPaolo Bonzini static void do_command_phase(ESPState *s)
27249ab747fSPaolo Bonzini {
2737b320a8eSMark Cave-Ayland     uint32_t cmdlen;
27449ab747fSPaolo Bonzini     int32_t datalen;
27549ab747fSPaolo Bonzini     SCSIDevice *current_lun;
2767b320a8eSMark Cave-Ayland     uint8_t buf[ESP_CMDFIFO_SZ];
27749ab747fSPaolo Bonzini 
2784eb86065SPaolo Bonzini     trace_esp_do_command_phase(s->lun);
279023666daSMark Cave-Ayland     cmdlen = fifo8_num_used(&s->cmdfifo);
28099545751SMark Cave-Ayland     if (!cmdlen || !s->current_dev) {
28199545751SMark Cave-Ayland         return;
28299545751SMark Cave-Ayland     }
283f87d0487SMark Cave-Ayland     esp_fifo8_pop_buf(&s->cmdfifo, buf, cmdlen);
284023666daSMark Cave-Ayland 
2854eb86065SPaolo Bonzini     current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
286b22f83d8SAlexandra Diupina     if (!current_lun) {
287b22f83d8SAlexandra Diupina         /* No such drive */
288b22f83d8SAlexandra Diupina         s->rregs[ESP_RSTAT] = 0;
289b22f83d8SAlexandra Diupina         s->rregs[ESP_RINTR] = INTR_DC;
290b22f83d8SAlexandra Diupina         s->rregs[ESP_RSEQ] = SEQ_0;
291b22f83d8SAlexandra Diupina         esp_raise_irq(s);
292b22f83d8SAlexandra Diupina         return;
293b22f83d8SAlexandra Diupina     }
294b22f83d8SAlexandra Diupina 
295fe9d8927SJohn Millikin     s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s);
29649ab747fSPaolo Bonzini     datalen = scsi_req_enqueue(s->current_req);
29749ab747fSPaolo Bonzini     s->ti_size = datalen;
298023666daSMark Cave-Ayland     fifo8_reset(&s->cmdfifo);
299c90b2792SMark Cave-Ayland     s->data_ready = false;
30049ab747fSPaolo Bonzini     if (datalen != 0) {
3014e78f3bfSMark Cave-Ayland         /*
302c90b2792SMark Cave-Ayland          * Switch to DATA phase but wait until initial data xfer is
3034e78f3bfSMark Cave-Ayland          * complete before raising the command completion interrupt
3044e78f3bfSMark Cave-Ayland          */
305c90b2792SMark Cave-Ayland         if (datalen > 0) {
306abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_DI);
30749ab747fSPaolo Bonzini         } else {
308abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_DO);
30949ab747fSPaolo Bonzini         }
3104e78f3bfSMark Cave-Ayland         scsi_req_continue(s->current_req);
3114e78f3bfSMark Cave-Ayland         return;
3124e78f3bfSMark Cave-Ayland     }
3134e78f3bfSMark Cave-Ayland }
31449ab747fSPaolo Bonzini 
3154eb86065SPaolo Bonzini static void do_message_phase(ESPState *s)
31649ab747fSPaolo Bonzini {
3174eb86065SPaolo Bonzini     if (s->cmdfifo_cdb_offset) {
318*1828000bSMark Cave-Ayland         uint8_t message = fifo8_is_empty(&s->cmdfifo) ? 0 :
319*1828000bSMark Cave-Ayland                           fifo8_pop(&s->cmdfifo);
320023666daSMark Cave-Ayland 
3214eb86065SPaolo Bonzini         trace_esp_do_identify(message);
3224eb86065SPaolo Bonzini         s->lun = message & 7;
323023666daSMark Cave-Ayland         s->cmdfifo_cdb_offset--;
3244eb86065SPaolo Bonzini     }
32549ab747fSPaolo Bonzini 
326799d90d8SMark Cave-Ayland     /* Ignore extended messages for now */
327023666daSMark Cave-Ayland     if (s->cmdfifo_cdb_offset) {
3284eb86065SPaolo Bonzini         int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
3292260402bSMark Cave-Ayland         esp_fifo8_pop_buf(&s->cmdfifo, NULL, len);
330023666daSMark Cave-Ayland         s->cmdfifo_cdb_offset = 0;
331023666daSMark Cave-Ayland     }
3324eb86065SPaolo Bonzini }
333023666daSMark Cave-Ayland 
3344eb86065SPaolo Bonzini static void do_cmd(ESPState *s)
3354eb86065SPaolo Bonzini {
3364eb86065SPaolo Bonzini     do_message_phase(s);
3374eb86065SPaolo Bonzini     assert(s->cmdfifo_cdb_offset == 0);
3384eb86065SPaolo Bonzini     do_command_phase(s);
33949ab747fSPaolo Bonzini }
34049ab747fSPaolo Bonzini 
34149ab747fSPaolo Bonzini static void handle_satn(ESPState *s)
34249ab747fSPaolo Bonzini {
34349ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
34449ab747fSPaolo Bonzini         s->dma_cb = handle_satn;
34549ab747fSPaolo Bonzini         return;
34649ab747fSPaolo Bonzini     }
347b46a43a2SMark Cave-Ayland 
3481bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3491bcaf71bSMark Cave-Ayland         return;
3501bcaf71bSMark Cave-Ayland     }
3513ee9a475SMark Cave-Ayland 
3523ee9a475SMark Cave-Ayland     esp_set_phase(s, STAT_MO);
3533ee9a475SMark Cave-Ayland 
3543ee9a475SMark Cave-Ayland     if (s->dma) {
3553ee9a475SMark Cave-Ayland         esp_do_dma(s);
3563ee9a475SMark Cave-Ayland     } else {
357d39592ffSMark Cave-Ayland         esp_do_nodma(s);
35849ab747fSPaolo Bonzini     }
35994d5c79dSMark Cave-Ayland }
36049ab747fSPaolo Bonzini 
36149ab747fSPaolo Bonzini static void handle_s_without_atn(ESPState *s)
36249ab747fSPaolo Bonzini {
36349ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
36449ab747fSPaolo Bonzini         s->dma_cb = handle_s_without_atn;
36549ab747fSPaolo Bonzini         return;
36649ab747fSPaolo Bonzini     }
367b46a43a2SMark Cave-Ayland 
3681bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3691bcaf71bSMark Cave-Ayland         return;
3701bcaf71bSMark Cave-Ayland     }
3719ff0fd12SMark Cave-Ayland 
372abc139cdSMark Cave-Ayland     esp_set_phase(s, STAT_CD);
3739ff0fd12SMark Cave-Ayland     s->cmdfifo_cdb_offset = 0;
3749ff0fd12SMark Cave-Ayland 
3759ff0fd12SMark Cave-Ayland     if (s->dma) {
3769ff0fd12SMark Cave-Ayland         esp_do_dma(s);
3779ff0fd12SMark Cave-Ayland     } else {
378d39592ffSMark Cave-Ayland         esp_do_nodma(s);
37949ab747fSPaolo Bonzini     }
38049ab747fSPaolo Bonzini }
38149ab747fSPaolo Bonzini 
38249ab747fSPaolo Bonzini static void handle_satn_stop(ESPState *s)
38349ab747fSPaolo Bonzini {
38449ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
38549ab747fSPaolo Bonzini         s->dma_cb = handle_satn_stop;
38649ab747fSPaolo Bonzini         return;
38749ab747fSPaolo Bonzini     }
388b46a43a2SMark Cave-Ayland 
3891bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3901bcaf71bSMark Cave-Ayland         return;
3911bcaf71bSMark Cave-Ayland     }
392db4d4150SMark Cave-Ayland 
393abc139cdSMark Cave-Ayland     esp_set_phase(s, STAT_MO);
3945d02add4SMark Cave-Ayland     s->cmdfifo_cdb_offset = 0;
395db4d4150SMark Cave-Ayland 
396db4d4150SMark Cave-Ayland     if (s->dma) {
397db4d4150SMark Cave-Ayland         esp_do_dma(s);
398db4d4150SMark Cave-Ayland     } else {
399d39592ffSMark Cave-Ayland         esp_do_nodma(s);
40049ab747fSPaolo Bonzini     }
40149ab747fSPaolo Bonzini }
40249ab747fSPaolo Bonzini 
403a6cad7cdSMark Cave-Ayland static void handle_pad(ESPState *s)
404a6cad7cdSMark Cave-Ayland {
405a6cad7cdSMark Cave-Ayland     if (s->dma) {
406a6cad7cdSMark Cave-Ayland         esp_do_dma(s);
407a6cad7cdSMark Cave-Ayland     } else {
408a6cad7cdSMark Cave-Ayland         esp_do_nodma(s);
409a6cad7cdSMark Cave-Ayland     }
410a6cad7cdSMark Cave-Ayland }
411a6cad7cdSMark Cave-Ayland 
41249ab747fSPaolo Bonzini static void write_response(ESPState *s)
41349ab747fSPaolo Bonzini {
41449ab747fSPaolo Bonzini     trace_esp_write_response(s->status);
415042879fcSMark Cave-Ayland 
4168baa1472SMark Cave-Ayland     if (s->dma) {
4178baa1472SMark Cave-Ayland         esp_do_dma(s);
4188baa1472SMark Cave-Ayland     } else {
41983428f7aSMark Cave-Ayland         esp_do_nodma(s);
42049ab747fSPaolo Bonzini     }
4218baa1472SMark Cave-Ayland }
42249ab747fSPaolo Bonzini 
4235d02add4SMark Cave-Ayland static int esp_cdb_length(ESPState *s)
4245d02add4SMark Cave-Ayland {
4255d02add4SMark Cave-Ayland     const uint8_t *pbuf;
4265d02add4SMark Cave-Ayland     int cmdlen, len;
4275d02add4SMark Cave-Ayland 
4285d02add4SMark Cave-Ayland     cmdlen = fifo8_num_used(&s->cmdfifo);
4295d02add4SMark Cave-Ayland     if (cmdlen < s->cmdfifo_cdb_offset) {
4305d02add4SMark Cave-Ayland         return 0;
4315d02add4SMark Cave-Ayland     }
4325d02add4SMark Cave-Ayland 
4335d02add4SMark Cave-Ayland     pbuf = fifo8_peek_buf(&s->cmdfifo, cmdlen, NULL);
4345d02add4SMark Cave-Ayland     len = scsi_cdb_length((uint8_t *)&pbuf[s->cmdfifo_cdb_offset]);
4355d02add4SMark Cave-Ayland 
4365d02add4SMark Cave-Ayland     return len;
4375d02add4SMark Cave-Ayland }
4385d02add4SMark Cave-Ayland 
439004826d0SMark Cave-Ayland static void esp_dma_ti_check(ESPState *s)
44049ab747fSPaolo Bonzini {
441af74b3c1SMark Cave-Ayland     if (esp_get_tc(s) == 0 && fifo8_num_used(&s->fifo) < 2) {
442cf47a41eSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS;
44349ab747fSPaolo Bonzini         esp_raise_irq(s);
444af74b3c1SMark Cave-Ayland         esp_lower_drq(s);
445af74b3c1SMark Cave-Ayland     }
44649ab747fSPaolo Bonzini }
44749ab747fSPaolo Bonzini 
44849ab747fSPaolo Bonzini static void esp_do_dma(ESPState *s)
44949ab747fSPaolo Bonzini {
450023666daSMark Cave-Ayland     uint32_t len, cmdlen;
451023666daSMark Cave-Ayland     uint8_t buf[ESP_CMDFIFO_SZ];
45249ab747fSPaolo Bonzini 
4536cc88d6bSMark Cave-Ayland     len = esp_get_tc(s);
454ad2725afSMark Cave-Ayland 
455ad2725afSMark Cave-Ayland     switch (esp_get_phase(s)) {
456ad2725afSMark Cave-Ayland     case STAT_MO:
45746b0c361SMark Cave-Ayland         if (s->dma_memory_read) {
45846b0c361SMark Cave-Ayland             len = MIN(len, fifo8_num_free(&s->cmdfifo));
45946b0c361SMark Cave-Ayland             s->dma_memory_read(s->dma_opaque, buf, len);
46046b0c361SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
46146b0c361SMark Cave-Ayland         } else {
46267ea170eSMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
46367ea170eSMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
46467ea170eSMark Cave-Ayland             esp_raise_drq(s);
46546b0c361SMark Cave-Ayland         }
46646b0c361SMark Cave-Ayland 
46767ea170eSMark Cave-Ayland         fifo8_push_all(&s->cmdfifo, buf, len);
46867ea170eSMark Cave-Ayland         s->cmdfifo_cdb_offset += len;
46946b0c361SMark Cave-Ayland 
4703ee9a475SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
4713ee9a475SMark Cave-Ayland         case CMD_SELATN | CMD_DMA:
4723ee9a475SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
4733ee9a475SMark Cave-Ayland                 /* First byte received, switch to command phase */
4743ee9a475SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
4759b2cdca2SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_CD;
4763ee9a475SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
4773ee9a475SMark Cave-Ayland 
4783ee9a475SMark Cave-Ayland                 if (fifo8_num_used(&s->cmdfifo) > 1) {
4793ee9a475SMark Cave-Ayland                     /* Process any additional command phase data */
4803ee9a475SMark Cave-Ayland                     esp_do_dma(s);
4813ee9a475SMark Cave-Ayland                 }
4823ee9a475SMark Cave-Ayland             }
4833ee9a475SMark Cave-Ayland             break;
4843ee9a475SMark Cave-Ayland 
485db4d4150SMark Cave-Ayland         case CMD_SELATNS | CMD_DMA:
486db4d4150SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) == 1) {
487db4d4150SMark Cave-Ayland                 /* First byte received, stop in message out phase */
4889b2cdca2SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_MO;
489db4d4150SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
490db4d4150SMark Cave-Ayland 
491db4d4150SMark Cave-Ayland                 /* Raise command completion interrupt */
492db4d4150SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
493db4d4150SMark Cave-Ayland                 esp_raise_irq(s);
494db4d4150SMark Cave-Ayland             }
495db4d4150SMark Cave-Ayland             break;
496db4d4150SMark Cave-Ayland 
4973fd325a2SMark Cave-Ayland         case CMD_TI | CMD_DMA:
49846b0c361SMark Cave-Ayland             /* ATN remains asserted until TC == 0 */
49946b0c361SMark Cave-Ayland             if (esp_get_tc(s) == 0) {
50046b0c361SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
501cb22ce50SMark Cave-Ayland                 s->rregs[ESP_CMD] = 0;
50246b0c361SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS;
50346b0c361SMark Cave-Ayland                 esp_raise_irq(s);
50446b0c361SMark Cave-Ayland             }
50546b0c361SMark Cave-Ayland             break;
5063fd325a2SMark Cave-Ayland         }
5073fd325a2SMark Cave-Ayland         break;
50846b0c361SMark Cave-Ayland 
509ad2725afSMark Cave-Ayland     case STAT_CD:
510023666daSMark Cave-Ayland         cmdlen = fifo8_num_used(&s->cmdfifo);
511023666daSMark Cave-Ayland         trace_esp_do_dma(cmdlen, len);
51274d71ea1SLaurent Vivier         if (s->dma_memory_read) {
5130ebb5fd8SMark Cave-Ayland             len = MIN(len, fifo8_num_free(&s->cmdfifo));
514023666daSMark Cave-Ayland             s->dma_memory_read(s->dma_opaque, buf, len);
515023666daSMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
516a0347651SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
51774d71ea1SLaurent Vivier         } else {
518406e8a3eSMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
519406e8a3eSMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
520406e8a3eSMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
52174d71ea1SLaurent Vivier             esp_raise_drq(s);
5223c7f3c8bSMark Cave-Ayland         }
523023666daSMark Cave-Ayland         trace_esp_handle_ti_cmd(cmdlen);
52415407433SLaurent Vivier         s->ti_size = 0;
52546b0c361SMark Cave-Ayland         if (esp_get_tc(s) == 0) {
526799d90d8SMark Cave-Ayland             /* Command has been received */
527c959f218SMark Cave-Ayland             do_cmd(s);
528799d90d8SMark Cave-Ayland         }
529ad2725afSMark Cave-Ayland         break;
5301454dc76SMark Cave-Ayland 
5311454dc76SMark Cave-Ayland     case STAT_DO:
5320db89536SMark Cave-Ayland         if (!s->current_req) {
5330db89536SMark Cave-Ayland             return;
5340db89536SMark Cave-Ayland         }
5354460b86aSMark Cave-Ayland         if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
53649ab747fSPaolo Bonzini             /* Defer until data is available.  */
53749ab747fSPaolo Bonzini             return;
53849ab747fSPaolo Bonzini         }
53949ab747fSPaolo Bonzini         if (len > s->async_len) {
54049ab747fSPaolo Bonzini             len = s->async_len;
54149ab747fSPaolo Bonzini         }
5420d17ce82SMark Cave-Ayland 
543a6cad7cdSMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
544a6cad7cdSMark Cave-Ayland         case CMD_TI | CMD_DMA:
54574d71ea1SLaurent Vivier             if (s->dma_memory_read) {
54649ab747fSPaolo Bonzini                 s->dma_memory_read(s->dma_opaque, s->async_buf, len);
547f3666223SMark Cave-Ayland                 esp_set_tc(s, esp_get_tc(s) - len);
5480d17ce82SMark Cave-Ayland             } else {
5490d17ce82SMark Cave-Ayland                 /* Copy FIFO data to device */
5500d17ce82SMark Cave-Ayland                 len = MIN(s->async_len, ESP_FIFO_SZ);
5510d17ce82SMark Cave-Ayland                 len = MIN(len, fifo8_num_used(&s->fifo));
5520d17ce82SMark Cave-Ayland                 len = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
5530d17ce82SMark Cave-Ayland                 esp_raise_drq(s);
5540d17ce82SMark Cave-Ayland             }
5550d17ce82SMark Cave-Ayland 
556f3666223SMark Cave-Ayland             s->async_buf += len;
557f3666223SMark Cave-Ayland             s->async_len -= len;
558f3666223SMark Cave-Ayland             s->ti_size += len;
559a6cad7cdSMark Cave-Ayland             break;
560a6cad7cdSMark Cave-Ayland 
561a6cad7cdSMark Cave-Ayland         case CMD_PAD | CMD_DMA:
562a6cad7cdSMark Cave-Ayland             /* Copy TC zero bytes into the incoming stream */
563a6cad7cdSMark Cave-Ayland             if (!s->dma_memory_read) {
564a6cad7cdSMark Cave-Ayland                 len = MIN(s->async_len, ESP_FIFO_SZ);
565a6cad7cdSMark Cave-Ayland                 len = MIN(len, fifo8_num_free(&s->fifo));
566a6cad7cdSMark Cave-Ayland             }
567a6cad7cdSMark Cave-Ayland 
568a6cad7cdSMark Cave-Ayland             memset(s->async_buf, 0, len);
569a6cad7cdSMark Cave-Ayland 
570a6cad7cdSMark Cave-Ayland             s->async_buf += len;
571a6cad7cdSMark Cave-Ayland             s->async_len -= len;
572a6cad7cdSMark Cave-Ayland             s->ti_size += len;
573a6cad7cdSMark Cave-Ayland             break;
574a6cad7cdSMark Cave-Ayland         }
575f3666223SMark Cave-Ayland 
576e4e166c8SMark Cave-Ayland         if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
577e4e166c8SMark Cave-Ayland             /* Defer until the scsi layer has completed */
578f3666223SMark Cave-Ayland             scsi_req_continue(s->current_req);
579f3666223SMark Cave-Ayland             return;
580f3666223SMark Cave-Ayland         }
581f3666223SMark Cave-Ayland 
582004826d0SMark Cave-Ayland         esp_dma_ti_check(s);
5831454dc76SMark Cave-Ayland         break;
5841454dc76SMark Cave-Ayland 
5851454dc76SMark Cave-Ayland     case STAT_DI:
5861454dc76SMark Cave-Ayland         if (!s->current_req) {
5871454dc76SMark Cave-Ayland             return;
5881454dc76SMark Cave-Ayland         }
5891454dc76SMark Cave-Ayland         if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
5901454dc76SMark Cave-Ayland             /* Defer until data is available.  */
5911454dc76SMark Cave-Ayland             return;
5921454dc76SMark Cave-Ayland         }
5931454dc76SMark Cave-Ayland         if (len > s->async_len) {
5941454dc76SMark Cave-Ayland             len = s->async_len;
5951454dc76SMark Cave-Ayland         }
596c37cc88eSMark Cave-Ayland 
597a6cad7cdSMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
598a6cad7cdSMark Cave-Ayland         case CMD_TI | CMD_DMA:
59974d71ea1SLaurent Vivier             if (s->dma_memory_write) {
60049ab747fSPaolo Bonzini                 s->dma_memory_write(s->dma_opaque, s->async_buf, len);
60174d71ea1SLaurent Vivier             } else {
60282141c8bSMark Cave-Ayland                 /* Copy device data to FIFO */
603042879fcSMark Cave-Ayland                 len = MIN(len, fifo8_num_free(&s->fifo));
604042879fcSMark Cave-Ayland                 fifo8_push_all(&s->fifo, s->async_buf, len);
605c37cc88eSMark Cave-Ayland                 esp_raise_drq(s);
606c37cc88eSMark Cave-Ayland             }
607c37cc88eSMark Cave-Ayland 
60882141c8bSMark Cave-Ayland             s->async_buf += len;
60982141c8bSMark Cave-Ayland             s->async_len -= len;
61082141c8bSMark Cave-Ayland             s->ti_size -= len;
61182141c8bSMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
612a6cad7cdSMark Cave-Ayland             break;
613a6cad7cdSMark Cave-Ayland 
614a6cad7cdSMark Cave-Ayland         case CMD_PAD | CMD_DMA:
615a6cad7cdSMark Cave-Ayland             /* Drop TC bytes from the incoming stream */
616a6cad7cdSMark Cave-Ayland             if (!s->dma_memory_write) {
617a6cad7cdSMark Cave-Ayland                 len = MIN(len, fifo8_num_free(&s->fifo));
618a6cad7cdSMark Cave-Ayland             }
619a6cad7cdSMark Cave-Ayland 
620a6cad7cdSMark Cave-Ayland             s->async_buf += len;
621a6cad7cdSMark Cave-Ayland             s->async_len -= len;
622a6cad7cdSMark Cave-Ayland             s->ti_size -= len;
623a6cad7cdSMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
624a6cad7cdSMark Cave-Ayland             break;
625a6cad7cdSMark Cave-Ayland         }
626e4e166c8SMark Cave-Ayland 
62702a3ce56SMark Cave-Ayland         if (s->async_len == 0 && s->ti_size == 0 && esp_get_tc(s)) {
62802a3ce56SMark Cave-Ayland             /* If the guest underflows TC then terminate SCSI request */
62902a3ce56SMark Cave-Ayland             scsi_req_continue(s->current_req);
63002a3ce56SMark Cave-Ayland             return;
63102a3ce56SMark Cave-Ayland         }
63202a3ce56SMark Cave-Ayland 
633e4e166c8SMark Cave-Ayland         if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
634e4e166c8SMark Cave-Ayland             /* Defer until the scsi layer has completed */
635e4e166c8SMark Cave-Ayland             scsi_req_continue(s->current_req);
636e4e166c8SMark Cave-Ayland             return;
637e4e166c8SMark Cave-Ayland         }
638e4e166c8SMark Cave-Ayland 
639004826d0SMark Cave-Ayland         esp_dma_ti_check(s);
6401454dc76SMark Cave-Ayland         break;
6418baa1472SMark Cave-Ayland 
6428baa1472SMark Cave-Ayland     case STAT_ST:
6438baa1472SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
6448baa1472SMark Cave-Ayland         case CMD_ICCS | CMD_DMA:
6458baa1472SMark Cave-Ayland             len = MIN(len, 1);
6468baa1472SMark Cave-Ayland 
6478baa1472SMark Cave-Ayland             if (len) {
6488baa1472SMark Cave-Ayland                 buf[0] = s->status;
6498baa1472SMark Cave-Ayland 
6508baa1472SMark Cave-Ayland                 if (s->dma_memory_write) {
6518baa1472SMark Cave-Ayland                     s->dma_memory_write(s->dma_opaque, buf, len);
6528baa1472SMark Cave-Ayland                 } else {
6538baa1472SMark Cave-Ayland                     fifo8_push_all(&s->fifo, buf, len);
6548baa1472SMark Cave-Ayland                 }
6558baa1472SMark Cave-Ayland 
656421d1ca5SMark Cave-Ayland                 esp_set_tc(s, esp_get_tc(s) - len);
6578baa1472SMark Cave-Ayland                 esp_set_phase(s, STAT_MI);
6588baa1472SMark Cave-Ayland 
6598baa1472SMark Cave-Ayland                 if (esp_get_tc(s) > 0) {
6608baa1472SMark Cave-Ayland                     /* Process any message in phase data */
6618baa1472SMark Cave-Ayland                     esp_do_dma(s);
6628baa1472SMark Cave-Ayland                 }
6638baa1472SMark Cave-Ayland             }
6648baa1472SMark Cave-Ayland             break;
66502a3ce56SMark Cave-Ayland 
66602a3ce56SMark Cave-Ayland         default:
66702a3ce56SMark Cave-Ayland             /* Consume remaining data if the guest underflows TC */
66802a3ce56SMark Cave-Ayland             if (fifo8_num_used(&s->fifo) < 2) {
66902a3ce56SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS;
67002a3ce56SMark Cave-Ayland                 esp_raise_irq(s);
67102a3ce56SMark Cave-Ayland                 esp_lower_drq(s);
67202a3ce56SMark Cave-Ayland             }
67302a3ce56SMark Cave-Ayland             break;
6748baa1472SMark Cave-Ayland         }
6758baa1472SMark Cave-Ayland         break;
6768baa1472SMark Cave-Ayland 
6778baa1472SMark Cave-Ayland     case STAT_MI:
6788baa1472SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
6798baa1472SMark Cave-Ayland         case CMD_ICCS | CMD_DMA:
6808baa1472SMark Cave-Ayland             len = MIN(len, 1);
6818baa1472SMark Cave-Ayland 
6828baa1472SMark Cave-Ayland             if (len) {
6838baa1472SMark Cave-Ayland                 buf[0] = 0;
6848baa1472SMark Cave-Ayland 
6858baa1472SMark Cave-Ayland                 if (s->dma_memory_write) {
6868baa1472SMark Cave-Ayland                     s->dma_memory_write(s->dma_opaque, buf, len);
6878baa1472SMark Cave-Ayland                 } else {
6888baa1472SMark Cave-Ayland                     fifo8_push_all(&s->fifo, buf, len);
6898baa1472SMark Cave-Ayland                 }
6908baa1472SMark Cave-Ayland 
691421d1ca5SMark Cave-Ayland                 esp_set_tc(s, esp_get_tc(s) - len);
692421d1ca5SMark Cave-Ayland 
6938baa1472SMark Cave-Ayland                 /* Raise end of command interrupt */
6940ee71db4SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_FC;
6958baa1472SMark Cave-Ayland                 esp_raise_irq(s);
6968baa1472SMark Cave-Ayland             }
6978baa1472SMark Cave-Ayland             break;
6988baa1472SMark Cave-Ayland         }
6998baa1472SMark Cave-Ayland         break;
70074d71ea1SLaurent Vivier     }
70149ab747fSPaolo Bonzini }
70249ab747fSPaolo Bonzini 
703a1b8d389SMark Cave-Ayland static void esp_nodma_ti_dataout(ESPState *s)
704a1b8d389SMark Cave-Ayland {
705a1b8d389SMark Cave-Ayland     int len;
706a1b8d389SMark Cave-Ayland 
707a1b8d389SMark Cave-Ayland     if (!s->current_req) {
708a1b8d389SMark Cave-Ayland         return;
709a1b8d389SMark Cave-Ayland     }
710a1b8d389SMark Cave-Ayland     if (s->async_len == 0) {
711a1b8d389SMark Cave-Ayland         /* Defer until data is available.  */
712a1b8d389SMark Cave-Ayland         return;
713a1b8d389SMark Cave-Ayland     }
714a1b8d389SMark Cave-Ayland     len = MIN(s->async_len, ESP_FIFO_SZ);
715a1b8d389SMark Cave-Ayland     len = MIN(len, fifo8_num_used(&s->fifo));
716a1b8d389SMark Cave-Ayland     esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
717a1b8d389SMark Cave-Ayland     s->async_buf += len;
718a1b8d389SMark Cave-Ayland     s->async_len -= len;
719a1b8d389SMark Cave-Ayland     s->ti_size += len;
720a1b8d389SMark Cave-Ayland 
721a1b8d389SMark Cave-Ayland     if (s->async_len == 0) {
722a1b8d389SMark Cave-Ayland         scsi_req_continue(s->current_req);
723a1b8d389SMark Cave-Ayland         return;
724a1b8d389SMark Cave-Ayland     }
725a1b8d389SMark Cave-Ayland 
726a1b8d389SMark Cave-Ayland     s->rregs[ESP_RINTR] |= INTR_BS;
727a1b8d389SMark Cave-Ayland     esp_raise_irq(s);
728a1b8d389SMark Cave-Ayland }
729a1b8d389SMark Cave-Ayland 
7301b9e48a5SMark Cave-Ayland static void esp_do_nodma(ESPState *s)
7311b9e48a5SMark Cave-Ayland {
7322572689bSMark Cave-Ayland     uint8_t buf[ESP_FIFO_SZ];
7337b320a8eSMark Cave-Ayland     uint32_t cmdlen;
7345a857339SMark Cave-Ayland     int len;
7351b9e48a5SMark Cave-Ayland 
73683e803deSMark Cave-Ayland     switch (esp_get_phase(s)) {
73783e803deSMark Cave-Ayland     case STAT_MO:
738215d2579SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
739215d2579SMark Cave-Ayland         case CMD_SELATN:
7402572689bSMark Cave-Ayland             /* Copy FIFO into cmdfifo */
7415a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
7425a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
7435a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
7442572689bSMark Cave-Ayland 
7455d02add4SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
7465d02add4SMark Cave-Ayland                 /* First byte received, switch to command phase */
7475d02add4SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
7489b2cdca2SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_CD;
7495d02add4SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
7505d02add4SMark Cave-Ayland 
7515d02add4SMark Cave-Ayland                 if (fifo8_num_used(&s->cmdfifo) > 1) {
7525d02add4SMark Cave-Ayland                     /* Process any additional command phase data */
7535d02add4SMark Cave-Ayland                     esp_do_nodma(s);
7545d02add4SMark Cave-Ayland                 }
7555d02add4SMark Cave-Ayland             }
7565d02add4SMark Cave-Ayland             break;
7575d02add4SMark Cave-Ayland 
7585d02add4SMark Cave-Ayland         case CMD_SELATNS:
759215d2579SMark Cave-Ayland             /* Copy one byte from FIFO into cmdfifo */
7605a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, 1);
7615a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
7625a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
763215d2579SMark Cave-Ayland 
764d39592ffSMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
7655d02add4SMark Cave-Ayland                 /* First byte received, stop in message out phase */
7669b2cdca2SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_MO;
7675d02add4SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
7685d02add4SMark Cave-Ayland 
7695d02add4SMark Cave-Ayland                 /* Raise command completion interrupt */
7705d02add4SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
7715d02add4SMark Cave-Ayland                 esp_raise_irq(s);
7725d02add4SMark Cave-Ayland             }
7735d02add4SMark Cave-Ayland             break;
7745d02add4SMark Cave-Ayland 
7755d02add4SMark Cave-Ayland         case CMD_TI:
776215d2579SMark Cave-Ayland             /* Copy FIFO into cmdfifo */
7775a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
7785a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
7795a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
780215d2579SMark Cave-Ayland 
7815d02add4SMark Cave-Ayland             /* ATN remains asserted until FIFO empty */
7821b9e48a5SMark Cave-Ayland             s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo);
783abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_CD);
784cb22ce50SMark Cave-Ayland             s->rregs[ESP_CMD] = 0;
7851b9e48a5SMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_BS;
7861b9e48a5SMark Cave-Ayland             esp_raise_irq(s);
78779a6c7c6SMark Cave-Ayland             break;
7885d02add4SMark Cave-Ayland         }
7895d02add4SMark Cave-Ayland         break;
79079a6c7c6SMark Cave-Ayland 
79179a6c7c6SMark Cave-Ayland     case STAT_CD:
792acdee66dSMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
793acdee66dSMark Cave-Ayland         case CMD_TI:
79479a6c7c6SMark Cave-Ayland             /* Copy FIFO into cmdfifo */
7955a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
7965a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
7975a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
79879a6c7c6SMark Cave-Ayland 
79979a6c7c6SMark Cave-Ayland             cmdlen = fifo8_num_used(&s->cmdfifo);
80079a6c7c6SMark Cave-Ayland             trace_esp_handle_ti_cmd(cmdlen);
80179a6c7c6SMark Cave-Ayland 
8025d02add4SMark Cave-Ayland             /* CDB may be transferred in one or more TI commands */
8035d02add4SMark Cave-Ayland             if (esp_cdb_length(s) && esp_cdb_length(s) ==
8045d02add4SMark Cave-Ayland                 fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset) {
80579a6c7c6SMark Cave-Ayland                     /* Command has been received */
80679a6c7c6SMark Cave-Ayland                     do_cmd(s);
8075d02add4SMark Cave-Ayland             } else {
8085d02add4SMark Cave-Ayland                 /*
8095d02add4SMark Cave-Ayland                  * If data was transferred from the FIFO then raise bus
8105d02add4SMark Cave-Ayland                  * service interrupt to indicate transfer complete. Otherwise
8115d02add4SMark Cave-Ayland                  * defer until the next FIFO write.
8125d02add4SMark Cave-Ayland                  */
8135a857339SMark Cave-Ayland                 if (len) {
8145d02add4SMark Cave-Ayland                     /* Raise interrupt to indicate transfer complete */
8155d02add4SMark Cave-Ayland                     s->rregs[ESP_RINTR] |= INTR_BS;
8165d02add4SMark Cave-Ayland                     esp_raise_irq(s);
8175d02add4SMark Cave-Ayland                 }
8185d02add4SMark Cave-Ayland             }
8195d02add4SMark Cave-Ayland             break;
8205d02add4SMark Cave-Ayland 
8218ba32048SMark Cave-Ayland         case CMD_SEL | CMD_DMA:
8228ba32048SMark Cave-Ayland         case CMD_SELATN | CMD_DMA:
823acdee66dSMark Cave-Ayland             /* Copy FIFO into cmdfifo */
8245a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
8255a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
8265a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
827acdee66dSMark Cave-Ayland 
8288ba32048SMark Cave-Ayland             /* Handle when DMA transfer is terminated by non-DMA FIFO write */
8298ba32048SMark Cave-Ayland             if (esp_cdb_length(s) && esp_cdb_length(s) ==
8308ba32048SMark Cave-Ayland                 fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset) {
8318ba32048SMark Cave-Ayland                     /* Command has been received */
8328ba32048SMark Cave-Ayland                     do_cmd(s);
8338ba32048SMark Cave-Ayland             }
8348ba32048SMark Cave-Ayland             break;
8358ba32048SMark Cave-Ayland 
8365d02add4SMark Cave-Ayland         case CMD_SEL:
8375d02add4SMark Cave-Ayland         case CMD_SELATN:
838acdee66dSMark Cave-Ayland             /* FIFO already contain entire CDB: copy to cmdfifo and execute */
8395a857339SMark Cave-Ayland             len = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
8405a857339SMark Cave-Ayland             len = MIN(fifo8_num_free(&s->cmdfifo), len);
8415a857339SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
842acdee66dSMark Cave-Ayland 
8435d02add4SMark Cave-Ayland             do_cmd(s);
8445d02add4SMark Cave-Ayland             break;
8455d02add4SMark Cave-Ayland         }
84683e803deSMark Cave-Ayland         break;
8471b9e48a5SMark Cave-Ayland 
8489d1aa52bSMark Cave-Ayland     case STAT_DO:
8495d02add4SMark Cave-Ayland         /* Accumulate data in FIFO until non-DMA TI is executed */
8509d1aa52bSMark Cave-Ayland         break;
8519d1aa52bSMark Cave-Ayland 
8529d1aa52bSMark Cave-Ayland     case STAT_DI:
8539d1aa52bSMark Cave-Ayland         if (!s->current_req) {
8549d1aa52bSMark Cave-Ayland             return;
8559d1aa52bSMark Cave-Ayland         }
8569d1aa52bSMark Cave-Ayland         if (s->async_len == 0) {
8579d1aa52bSMark Cave-Ayland             /* Defer until data is available.  */
8589d1aa52bSMark Cave-Ayland             return;
8599d1aa52bSMark Cave-Ayland         }
8606ef2cabcSMark Cave-Ayland         if (fifo8_is_empty(&s->fifo)) {
8616ef2cabcSMark Cave-Ayland             fifo8_push(&s->fifo, s->async_buf[0]);
8626ef2cabcSMark Cave-Ayland             s->async_buf++;
8636ef2cabcSMark Cave-Ayland             s->async_len--;
8646ef2cabcSMark Cave-Ayland             s->ti_size--;
8656ef2cabcSMark Cave-Ayland         }
8661b9e48a5SMark Cave-Ayland 
8671b9e48a5SMark Cave-Ayland         if (s->async_len == 0) {
8681b9e48a5SMark Cave-Ayland             scsi_req_continue(s->current_req);
8691b9e48a5SMark Cave-Ayland             return;
8701b9e48a5SMark Cave-Ayland         }
8711b9e48a5SMark Cave-Ayland 
8729655f72cSMark Cave-Ayland         /* If preloading the FIFO, defer until TI command issued */
8739655f72cSMark Cave-Ayland         if (s->rregs[ESP_CMD] != CMD_TI) {
8749655f72cSMark Cave-Ayland             return;
8759655f72cSMark Cave-Ayland         }
8769655f72cSMark Cave-Ayland 
8771b9e48a5SMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS;
8781b9e48a5SMark Cave-Ayland         esp_raise_irq(s);
8799d1aa52bSMark Cave-Ayland         break;
88083428f7aSMark Cave-Ayland 
88183428f7aSMark Cave-Ayland     case STAT_ST:
88283428f7aSMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
88383428f7aSMark Cave-Ayland         case CMD_ICCS:
88483428f7aSMark Cave-Ayland             fifo8_push(&s->fifo, s->status);
88583428f7aSMark Cave-Ayland             esp_set_phase(s, STAT_MI);
88683428f7aSMark Cave-Ayland 
88783428f7aSMark Cave-Ayland             /* Process any message in phase data */
88883428f7aSMark Cave-Ayland             esp_do_nodma(s);
88983428f7aSMark Cave-Ayland             break;
89083428f7aSMark Cave-Ayland         }
89183428f7aSMark Cave-Ayland         break;
89283428f7aSMark Cave-Ayland 
89383428f7aSMark Cave-Ayland     case STAT_MI:
89483428f7aSMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
89583428f7aSMark Cave-Ayland         case CMD_ICCS:
89683428f7aSMark Cave-Ayland             fifo8_push(&s->fifo, 0);
89783428f7aSMark Cave-Ayland 
8980ee71db4SMark Cave-Ayland             /* Raise end of command interrupt */
8990ee71db4SMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_FC;
90083428f7aSMark Cave-Ayland             esp_raise_irq(s);
90183428f7aSMark Cave-Ayland             break;
90283428f7aSMark Cave-Ayland         }
90383428f7aSMark Cave-Ayland         break;
9049d1aa52bSMark Cave-Ayland     }
9051b9e48a5SMark Cave-Ayland }
9061b9e48a5SMark Cave-Ayland 
9074aaa6ac3SMark Cave-Ayland void esp_command_complete(SCSIRequest *req, size_t resid)
90849ab747fSPaolo Bonzini {
9094aaa6ac3SMark Cave-Ayland     ESPState *s = req->hba_private;
9105a83e83eSMark Cave-Ayland     int to_device = (esp_get_phase(s) == STAT_DO);
9114aaa6ac3SMark Cave-Ayland 
91249ab747fSPaolo Bonzini     trace_esp_command_complete();
9136ef2cabcSMark Cave-Ayland 
9146ef2cabcSMark Cave-Ayland     /*
9156ef2cabcSMark Cave-Ayland      * Non-DMA transfers from the target will leave the last byte in
9166ef2cabcSMark Cave-Ayland      * the FIFO so don't reset ti_size in this case
9176ef2cabcSMark Cave-Ayland      */
9186ef2cabcSMark Cave-Ayland     if (s->dma || to_device) {
91949ab747fSPaolo Bonzini         if (s->ti_size != 0) {
92049ab747fSPaolo Bonzini             trace_esp_command_complete_unexpected();
92149ab747fSPaolo Bonzini         }
9226ef2cabcSMark Cave-Ayland     }
9236ef2cabcSMark Cave-Ayland 
92449ab747fSPaolo Bonzini     s->async_len = 0;
9254aaa6ac3SMark Cave-Ayland     if (req->status) {
92649ab747fSPaolo Bonzini         trace_esp_command_complete_fail();
92749ab747fSPaolo Bonzini     }
9284aaa6ac3SMark Cave-Ayland     s->status = req->status;
9296ef2cabcSMark Cave-Ayland 
9306ef2cabcSMark Cave-Ayland     /*
931cb988199SMark Cave-Ayland      * Switch to status phase. For non-DMA transfers from the target the last
932cb988199SMark Cave-Ayland      * byte is still in the FIFO
9336ef2cabcSMark Cave-Ayland      */
9348bb22495SMark Cave-Ayland     s->ti_size = 0;
9358bb22495SMark Cave-Ayland 
9368bb22495SMark Cave-Ayland     switch (s->rregs[ESP_CMD]) {
9378bb22495SMark Cave-Ayland     case CMD_SEL | CMD_DMA:
9388bb22495SMark Cave-Ayland     case CMD_SEL:
9398bb22495SMark Cave-Ayland     case CMD_SELATN | CMD_DMA:
9408bb22495SMark Cave-Ayland     case CMD_SELATN:
941cb988199SMark Cave-Ayland         /*
9428bb22495SMark Cave-Ayland          * No data phase for sequencer command so raise deferred bus service
943c90b2792SMark Cave-Ayland          * and function complete interrupt
944cb988199SMark Cave-Ayland          */
945c90b2792SMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
9469b2cdca2SMark Cave-Ayland         s->rregs[ESP_RSEQ] = SEQ_CD;
9478bb22495SMark Cave-Ayland         break;
948cb22ce50SMark Cave-Ayland 
949cb22ce50SMark Cave-Ayland     case CMD_TI | CMD_DMA:
950cb22ce50SMark Cave-Ayland     case CMD_TI:
951cb22ce50SMark Cave-Ayland         s->rregs[ESP_CMD] = 0;
952cb22ce50SMark Cave-Ayland         break;
9536ef2cabcSMark Cave-Ayland     }
9546ef2cabcSMark Cave-Ayland 
9558bb22495SMark Cave-Ayland     /* Raise bus service interrupt to indicate change to STATUS phase */
9568bb22495SMark Cave-Ayland     esp_set_phase(s, STAT_ST);
9578bb22495SMark Cave-Ayland     s->rregs[ESP_RINTR] |= INTR_BS;
9588bb22495SMark Cave-Ayland     esp_raise_irq(s);
95902a3ce56SMark Cave-Ayland 
96002a3ce56SMark Cave-Ayland     /* Ensure DRQ is set correctly for TC underflow or normal completion */
96102a3ce56SMark Cave-Ayland     esp_dma_ti_check(s);
9628bb22495SMark Cave-Ayland 
96349ab747fSPaolo Bonzini     if (s->current_req) {
96449ab747fSPaolo Bonzini         scsi_req_unref(s->current_req);
96549ab747fSPaolo Bonzini         s->current_req = NULL;
96649ab747fSPaolo Bonzini         s->current_dev = NULL;
96749ab747fSPaolo Bonzini     }
96849ab747fSPaolo Bonzini }
96949ab747fSPaolo Bonzini 
97049ab747fSPaolo Bonzini void esp_transfer_data(SCSIRequest *req, uint32_t len)
97149ab747fSPaolo Bonzini {
97249ab747fSPaolo Bonzini     ESPState *s = req->hba_private;
9736cc88d6bSMark Cave-Ayland     uint32_t dmalen = esp_get_tc(s);
97449ab747fSPaolo Bonzini 
9756cc88d6bSMark Cave-Ayland     trace_esp_transfer_data(dmalen, s->ti_size);
97649ab747fSPaolo Bonzini     s->async_len = len;
97749ab747fSPaolo Bonzini     s->async_buf = scsi_req_get_buf(req);
9784e78f3bfSMark Cave-Ayland 
979c90b2792SMark Cave-Ayland     if (!s->data_ready) {
980a4608fa0SMark Cave-Ayland         s->data_ready = true;
981a4608fa0SMark Cave-Ayland 
982a4608fa0SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
983a4608fa0SMark Cave-Ayland         case CMD_SEL | CMD_DMA:
984a4608fa0SMark Cave-Ayland         case CMD_SEL:
985a4608fa0SMark Cave-Ayland         case CMD_SELATN | CMD_DMA:
986a4608fa0SMark Cave-Ayland         case CMD_SELATN:
987c90b2792SMark Cave-Ayland             /*
988c90b2792SMark Cave-Ayland              * Initial incoming data xfer is complete for sequencer command
989c90b2792SMark Cave-Ayland              * so raise deferred bus service and function complete interrupt
990c90b2792SMark Cave-Ayland              */
991c90b2792SMark Cave-Ayland              s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
9929b2cdca2SMark Cave-Ayland              s->rregs[ESP_RSEQ] = SEQ_CD;
993c90b2792SMark Cave-Ayland              break;
994c90b2792SMark Cave-Ayland 
995a4608fa0SMark Cave-Ayland         case CMD_SELATNS | CMD_DMA:
996a4608fa0SMark Cave-Ayland         case CMD_SELATNS:
9974e78f3bfSMark Cave-Ayland             /*
9984e78f3bfSMark Cave-Ayland              * Initial incoming data xfer is complete so raise command
9994e78f3bfSMark Cave-Ayland              * completion interrupt
10004e78f3bfSMark Cave-Ayland              */
10014e78f3bfSMark Cave-Ayland              s->rregs[ESP_RINTR] |= INTR_BS;
10029b2cdca2SMark Cave-Ayland              s->rregs[ESP_RSEQ] = SEQ_MO;
1003a4608fa0SMark Cave-Ayland              break;
1004a4608fa0SMark Cave-Ayland 
1005a4608fa0SMark Cave-Ayland         case CMD_TI | CMD_DMA:
1006a4608fa0SMark Cave-Ayland         case CMD_TI:
1007a4608fa0SMark Cave-Ayland             /*
1008a4608fa0SMark Cave-Ayland              * Bus service interrupt raised because of initial change to
1009a4608fa0SMark Cave-Ayland              * DATA phase
1010a4608fa0SMark Cave-Ayland              */
1011cb22ce50SMark Cave-Ayland             s->rregs[ESP_CMD] = 0;
1012a4608fa0SMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_BS;
1013a4608fa0SMark Cave-Ayland             break;
1014a4608fa0SMark Cave-Ayland         }
1015c90b2792SMark Cave-Ayland 
1016c90b2792SMark Cave-Ayland         esp_raise_irq(s);
10174e78f3bfSMark Cave-Ayland     }
10184e78f3bfSMark Cave-Ayland 
10191b9e48a5SMark Cave-Ayland     /*
10201b9e48a5SMark Cave-Ayland      * Always perform the initial transfer upon reception of the next TI
10211b9e48a5SMark Cave-Ayland      * command to ensure the DMA/non-DMA status of the command is correct.
10221b9e48a5SMark Cave-Ayland      * It is not possible to use s->dma directly in the section below as
10231b9e48a5SMark Cave-Ayland      * some OSs send non-DMA NOP commands after a DMA transfer. Hence if the
10241b9e48a5SMark Cave-Ayland      * async data transfer is delayed then s->dma is set incorrectly.
10251b9e48a5SMark Cave-Ayland      */
10261b9e48a5SMark Cave-Ayland 
102782003450SMark Cave-Ayland     if (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA)) {
1028a79e767aSMark Cave-Ayland         /* When the SCSI layer returns more data, raise deferred INTR_BS */
1029004826d0SMark Cave-Ayland         esp_dma_ti_check(s);
1030a79e767aSMark Cave-Ayland 
1031a79e767aSMark Cave-Ayland         esp_do_dma(s);
103282003450SMark Cave-Ayland     } else if (s->rregs[ESP_CMD] == CMD_TI) {
10331b9e48a5SMark Cave-Ayland         esp_do_nodma(s);
10341b9e48a5SMark Cave-Ayland     }
103549ab747fSPaolo Bonzini }
103649ab747fSPaolo Bonzini 
103749ab747fSPaolo Bonzini static void handle_ti(ESPState *s)
103849ab747fSPaolo Bonzini {
10391b9e48a5SMark Cave-Ayland     uint32_t dmalen;
104049ab747fSPaolo Bonzini 
104149ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
104249ab747fSPaolo Bonzini         s->dma_cb = handle_ti;
104349ab747fSPaolo Bonzini         return;
104449ab747fSPaolo Bonzini     }
104549ab747fSPaolo Bonzini 
104649ab747fSPaolo Bonzini     if (s->dma) {
10471b9e48a5SMark Cave-Ayland         dmalen = esp_get_tc(s);
1048b76624deSMark Cave-Ayland         trace_esp_handle_ti(dmalen);
104949ab747fSPaolo Bonzini         esp_do_dma(s);
1050799d90d8SMark Cave-Ayland     } else {
10511b9e48a5SMark Cave-Ayland         trace_esp_handle_ti(s->ti_size);
10521b9e48a5SMark Cave-Ayland         esp_do_nodma(s);
10535d02add4SMark Cave-Ayland 
10545d02add4SMark Cave-Ayland         if (esp_get_phase(s) == STAT_DO) {
10555d02add4SMark Cave-Ayland             esp_nodma_ti_dataout(s);
10565d02add4SMark Cave-Ayland         }
105749ab747fSPaolo Bonzini     }
105849ab747fSPaolo Bonzini }
105949ab747fSPaolo Bonzini 
106049ab747fSPaolo Bonzini void esp_hard_reset(ESPState *s)
106149ab747fSPaolo Bonzini {
106249ab747fSPaolo Bonzini     memset(s->rregs, 0, ESP_REGS);
106349ab747fSPaolo Bonzini     memset(s->wregs, 0, ESP_REGS);
1064c9cf45c1SHannes Reinecke     s->tchi_written = 0;
106549ab747fSPaolo Bonzini     s->ti_size = 0;
10663f26c975SMark Cave-Ayland     s->async_len = 0;
1067042879fcSMark Cave-Ayland     fifo8_reset(&s->fifo);
1068023666daSMark Cave-Ayland     fifo8_reset(&s->cmdfifo);
106949ab747fSPaolo Bonzini     s->dma = 0;
107049ab747fSPaolo Bonzini     s->dma_cb = NULL;
107149ab747fSPaolo Bonzini 
107249ab747fSPaolo Bonzini     s->rregs[ESP_CFG1] = 7;
107349ab747fSPaolo Bonzini }
107449ab747fSPaolo Bonzini 
107549ab747fSPaolo Bonzini static void esp_soft_reset(ESPState *s)
107649ab747fSPaolo Bonzini {
107749ab747fSPaolo Bonzini     qemu_irq_lower(s->irq);
10786dec7c0dSMark Cave-Ayland     qemu_irq_lower(s->drq_irq);
107949ab747fSPaolo Bonzini     esp_hard_reset(s);
108049ab747fSPaolo Bonzini }
108149ab747fSPaolo Bonzini 
1082c6e51f1bSJohn Millikin static void esp_bus_reset(ESPState *s)
1083c6e51f1bSJohn Millikin {
10844a5fc890SPeter Maydell     bus_cold_reset(BUS(&s->bus));
1085c6e51f1bSJohn Millikin }
1086c6e51f1bSJohn Millikin 
108749ab747fSPaolo Bonzini static void parent_esp_reset(ESPState *s, int irq, int level)
108849ab747fSPaolo Bonzini {
108949ab747fSPaolo Bonzini     if (level) {
109049ab747fSPaolo Bonzini         esp_soft_reset(s);
109149ab747fSPaolo Bonzini     }
109249ab747fSPaolo Bonzini }
109349ab747fSPaolo Bonzini 
1094f21fe39dSMark Cave-Ayland static void esp_run_cmd(ESPState *s)
1095f21fe39dSMark Cave-Ayland {
1096f21fe39dSMark Cave-Ayland     uint8_t cmd = s->rregs[ESP_CMD];
1097f21fe39dSMark Cave-Ayland 
1098f21fe39dSMark Cave-Ayland     if (cmd & CMD_DMA) {
1099f21fe39dSMark Cave-Ayland         s->dma = 1;
1100f21fe39dSMark Cave-Ayland         /* Reload DMA counter.  */
1101f21fe39dSMark Cave-Ayland         if (esp_get_stc(s) == 0) {
1102f21fe39dSMark Cave-Ayland             esp_set_tc(s, 0x10000);
1103f21fe39dSMark Cave-Ayland         } else {
1104f21fe39dSMark Cave-Ayland             esp_set_tc(s, esp_get_stc(s));
1105f21fe39dSMark Cave-Ayland         }
1106f21fe39dSMark Cave-Ayland     } else {
1107f21fe39dSMark Cave-Ayland         s->dma = 0;
1108f21fe39dSMark Cave-Ayland     }
1109f21fe39dSMark Cave-Ayland     switch (cmd & CMD_CMD) {
1110f21fe39dSMark Cave-Ayland     case CMD_NOP:
1111f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_nop(cmd);
1112f21fe39dSMark Cave-Ayland         break;
1113f21fe39dSMark Cave-Ayland     case CMD_FLUSH:
1114f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_flush(cmd);
1115f21fe39dSMark Cave-Ayland         fifo8_reset(&s->fifo);
1116f21fe39dSMark Cave-Ayland         break;
1117f21fe39dSMark Cave-Ayland     case CMD_RESET:
1118f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_reset(cmd);
1119f21fe39dSMark Cave-Ayland         esp_soft_reset(s);
1120f21fe39dSMark Cave-Ayland         break;
1121f21fe39dSMark Cave-Ayland     case CMD_BUSRESET:
1122f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_bus_reset(cmd);
1123f21fe39dSMark Cave-Ayland         esp_bus_reset(s);
1124f21fe39dSMark Cave-Ayland         if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1125f21fe39dSMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_RST;
1126f21fe39dSMark Cave-Ayland             esp_raise_irq(s);
1127f21fe39dSMark Cave-Ayland         }
1128f21fe39dSMark Cave-Ayland         break;
1129f21fe39dSMark Cave-Ayland     case CMD_TI:
1130f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_ti(cmd);
1131f21fe39dSMark Cave-Ayland         handle_ti(s);
1132f21fe39dSMark Cave-Ayland         break;
1133f21fe39dSMark Cave-Ayland     case CMD_ICCS:
1134f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_iccs(cmd);
1135f21fe39dSMark Cave-Ayland         write_response(s);
1136f21fe39dSMark Cave-Ayland         break;
1137f21fe39dSMark Cave-Ayland     case CMD_MSGACC:
1138f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_msgacc(cmd);
1139f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_DC;
1140f21fe39dSMark Cave-Ayland         s->rregs[ESP_RSEQ] = 0;
1141f21fe39dSMark Cave-Ayland         s->rregs[ESP_RFLAGS] = 0;
1142f21fe39dSMark Cave-Ayland         esp_raise_irq(s);
1143f21fe39dSMark Cave-Ayland         break;
1144f21fe39dSMark Cave-Ayland     case CMD_PAD:
1145f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_pad(cmd);
1146a6cad7cdSMark Cave-Ayland         handle_pad(s);
1147f21fe39dSMark Cave-Ayland         break;
1148f21fe39dSMark Cave-Ayland     case CMD_SATN:
1149f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_satn(cmd);
1150f21fe39dSMark Cave-Ayland         break;
1151f21fe39dSMark Cave-Ayland     case CMD_RSTATN:
1152f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_rstatn(cmd);
1153f21fe39dSMark Cave-Ayland         break;
1154f21fe39dSMark Cave-Ayland     case CMD_SEL:
1155f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_sel(cmd);
1156f21fe39dSMark Cave-Ayland         handle_s_without_atn(s);
1157f21fe39dSMark Cave-Ayland         break;
1158f21fe39dSMark Cave-Ayland     case CMD_SELATN:
1159f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_selatn(cmd);
1160f21fe39dSMark Cave-Ayland         handle_satn(s);
1161f21fe39dSMark Cave-Ayland         break;
1162f21fe39dSMark Cave-Ayland     case CMD_SELATNS:
1163f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_selatns(cmd);
1164f21fe39dSMark Cave-Ayland         handle_satn_stop(s);
1165f21fe39dSMark Cave-Ayland         break;
1166f21fe39dSMark Cave-Ayland     case CMD_ENSEL:
1167f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_ensel(cmd);
1168f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] = 0;
1169f21fe39dSMark Cave-Ayland         break;
1170f21fe39dSMark Cave-Ayland     case CMD_DISSEL:
1171f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_dissel(cmd);
1172f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] = 0;
1173f21fe39dSMark Cave-Ayland         esp_raise_irq(s);
1174f21fe39dSMark Cave-Ayland         break;
1175f21fe39dSMark Cave-Ayland     default:
1176f21fe39dSMark Cave-Ayland         trace_esp_error_unhandled_command(cmd);
1177f21fe39dSMark Cave-Ayland         break;
1178f21fe39dSMark Cave-Ayland     }
1179f21fe39dSMark Cave-Ayland }
1180f21fe39dSMark Cave-Ayland 
118149ab747fSPaolo Bonzini uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
118249ab747fSPaolo Bonzini {
1183b630c075SMark Cave-Ayland     uint32_t val;
118449ab747fSPaolo Bonzini 
118549ab747fSPaolo Bonzini     switch (saddr) {
118649ab747fSPaolo Bonzini     case ESP_FIFO:
1187c5fef911SMark Cave-Ayland         s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo);
1188b630c075SMark Cave-Ayland         val = s->rregs[ESP_FIFO];
118949ab747fSPaolo Bonzini         break;
119049ab747fSPaolo Bonzini     case ESP_RINTR:
119194d5c79dSMark Cave-Ayland         /*
119294d5c79dSMark Cave-Ayland          * Clear sequence step, interrupt register and all status bits
119394d5c79dSMark Cave-Ayland          * except TC
119494d5c79dSMark Cave-Ayland          */
1195b630c075SMark Cave-Ayland         val = s->rregs[ESP_RINTR];
119649ab747fSPaolo Bonzini         s->rregs[ESP_RINTR] = 0;
1197d294b77aSMark Cave-Ayland         esp_lower_irq(s);
1198d68212cdSMark Cave-Ayland         s->rregs[ESP_RSTAT] &= STAT_TC | 7;
1199af947a3dSMark Cave-Ayland         /*
1200af947a3dSMark Cave-Ayland          * According to the datasheet ESP_RSEQ should be cleared, but as the
1201af947a3dSMark Cave-Ayland          * emulation currently defers information transfers to the next TI
1202af947a3dSMark Cave-Ayland          * command leave it for now so that pedantic guests such as the old
1203af947a3dSMark Cave-Ayland          * Linux 2.6 driver see the correct flags before the next SCSI phase
1204af947a3dSMark Cave-Ayland          * transition.
1205af947a3dSMark Cave-Ayland          *
1206af947a3dSMark Cave-Ayland          * s->rregs[ESP_RSEQ] = SEQ_0;
1207af947a3dSMark Cave-Ayland          */
1208b630c075SMark Cave-Ayland         break;
1209c9cf45c1SHannes Reinecke     case ESP_TCHI:
1210c9cf45c1SHannes Reinecke         /* Return the unique id if the value has never been written */
1211c9cf45c1SHannes Reinecke         if (!s->tchi_written) {
1212b630c075SMark Cave-Ayland             val = s->chip_id;
1213b630c075SMark Cave-Ayland         } else {
1214b630c075SMark Cave-Ayland             val = s->rregs[saddr];
1215c9cf45c1SHannes Reinecke         }
1216b630c075SMark Cave-Ayland         break;
1217238ec4d7SMark Cave-Ayland      case ESP_RFLAGS:
1218238ec4d7SMark Cave-Ayland         /* Bottom 5 bits indicate number of bytes in FIFO */
1219238ec4d7SMark Cave-Ayland         val = fifo8_num_used(&s->fifo);
1220238ec4d7SMark Cave-Ayland         break;
122149ab747fSPaolo Bonzini     default:
1222b630c075SMark Cave-Ayland         val = s->rregs[saddr];
122349ab747fSPaolo Bonzini         break;
122449ab747fSPaolo Bonzini     }
1225b630c075SMark Cave-Ayland 
1226b630c075SMark Cave-Ayland     trace_esp_mem_readb(saddr, val);
1227b630c075SMark Cave-Ayland     return val;
122849ab747fSPaolo Bonzini }
122949ab747fSPaolo Bonzini 
123049ab747fSPaolo Bonzini void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
123149ab747fSPaolo Bonzini {
123249ab747fSPaolo Bonzini     trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
123349ab747fSPaolo Bonzini     switch (saddr) {
1234c9cf45c1SHannes Reinecke     case ESP_TCHI:
1235c9cf45c1SHannes Reinecke         s->tchi_written = true;
1236c9cf45c1SHannes Reinecke         /* fall through */
123749ab747fSPaolo Bonzini     case ESP_TCLO:
123849ab747fSPaolo Bonzini     case ESP_TCMID:
123949ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] &= ~STAT_TC;
124049ab747fSPaolo Bonzini         break;
124149ab747fSPaolo Bonzini     case ESP_FIFO:
12422572689bSMark Cave-Ayland         if (!fifo8_is_full(&s->fifo)) {
12432572689bSMark Cave-Ayland             esp_fifo_push(&s->fifo, val);
12442572689bSMark Cave-Ayland         }
12455d02add4SMark Cave-Ayland         esp_do_nodma(s);
124649ab747fSPaolo Bonzini         break;
124749ab747fSPaolo Bonzini     case ESP_CMD:
124849ab747fSPaolo Bonzini         s->rregs[saddr] = val;
1249f21fe39dSMark Cave-Ayland         esp_run_cmd(s);
125049ab747fSPaolo Bonzini         break;
125149ab747fSPaolo Bonzini     case ESP_WBUSID ... ESP_WSYNO:
125249ab747fSPaolo Bonzini         break;
125349ab747fSPaolo Bonzini     case ESP_CFG1:
125449ab747fSPaolo Bonzini     case ESP_CFG2: case ESP_CFG3:
125549ab747fSPaolo Bonzini     case ESP_RES3: case ESP_RES4:
125649ab747fSPaolo Bonzini         s->rregs[saddr] = val;
125749ab747fSPaolo Bonzini         break;
125849ab747fSPaolo Bonzini     case ESP_WCCF ... ESP_WTEST:
125949ab747fSPaolo Bonzini         break;
126049ab747fSPaolo Bonzini     default:
126149ab747fSPaolo Bonzini         trace_esp_error_invalid_write(val, saddr);
126249ab747fSPaolo Bonzini         return;
126349ab747fSPaolo Bonzini     }
126449ab747fSPaolo Bonzini     s->wregs[saddr] = val;
126549ab747fSPaolo Bonzini }
126649ab747fSPaolo Bonzini 
126749ab747fSPaolo Bonzini static bool esp_mem_accepts(void *opaque, hwaddr addr,
12688372d383SPeter Maydell                             unsigned size, bool is_write,
12698372d383SPeter Maydell                             MemTxAttrs attrs)
127049ab747fSPaolo Bonzini {
127149ab747fSPaolo Bonzini     return (size == 1) || (is_write && size == 4);
127249ab747fSPaolo Bonzini }
127349ab747fSPaolo Bonzini 
12746cc88d6bSMark Cave-Ayland static bool esp_is_before_version_5(void *opaque, int version_id)
12756cc88d6bSMark Cave-Ayland {
12766cc88d6bSMark Cave-Ayland     ESPState *s = ESP(opaque);
12776cc88d6bSMark Cave-Ayland 
12786cc88d6bSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
12796cc88d6bSMark Cave-Ayland     return version_id < 5;
12806cc88d6bSMark Cave-Ayland }
12816cc88d6bSMark Cave-Ayland 
12824e78f3bfSMark Cave-Ayland static bool esp_is_version_5(void *opaque, int version_id)
12834e78f3bfSMark Cave-Ayland {
12844e78f3bfSMark Cave-Ayland     ESPState *s = ESP(opaque);
12854e78f3bfSMark Cave-Ayland 
12864e78f3bfSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
12870bcd5a18SMark Cave-Ayland     return version_id >= 5;
12884e78f3bfSMark Cave-Ayland }
12894e78f3bfSMark Cave-Ayland 
12904eb86065SPaolo Bonzini static bool esp_is_version_6(void *opaque, int version_id)
12914eb86065SPaolo Bonzini {
12924eb86065SPaolo Bonzini     ESPState *s = ESP(opaque);
12934eb86065SPaolo Bonzini 
12944eb86065SPaolo Bonzini     version_id = MIN(version_id, s->mig_version_id);
12954eb86065SPaolo Bonzini     return version_id >= 6;
12964eb86065SPaolo Bonzini }
12974eb86065SPaolo Bonzini 
129882003450SMark Cave-Ayland static bool esp_is_between_version_5_and_6(void *opaque, int version_id)
129982003450SMark Cave-Ayland {
130082003450SMark Cave-Ayland     ESPState *s = ESP(opaque);
130182003450SMark Cave-Ayland 
130282003450SMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
130382003450SMark Cave-Ayland     return version_id >= 5 && version_id <= 6;
130482003450SMark Cave-Ayland }
130582003450SMark Cave-Ayland 
1306ff4a1dabSMark Cave-Ayland int esp_pre_save(void *opaque)
13070bd005beSMark Cave-Ayland {
1308ff4a1dabSMark Cave-Ayland     ESPState *s = ESP(object_resolve_path_component(
1309ff4a1dabSMark Cave-Ayland                       OBJECT(opaque), "esp"));
13100bd005beSMark Cave-Ayland 
13110bd005beSMark Cave-Ayland     s->mig_version_id = vmstate_esp.version_id;
13120bd005beSMark Cave-Ayland     return 0;
13130bd005beSMark Cave-Ayland }
13140bd005beSMark Cave-Ayland 
13150bd005beSMark Cave-Ayland static int esp_post_load(void *opaque, int version_id)
13160bd005beSMark Cave-Ayland {
13170bd005beSMark Cave-Ayland     ESPState *s = ESP(opaque);
1318042879fcSMark Cave-Ayland     int len, i;
13190bd005beSMark Cave-Ayland 
13206cc88d6bSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
13216cc88d6bSMark Cave-Ayland 
13226cc88d6bSMark Cave-Ayland     if (version_id < 5) {
13236cc88d6bSMark Cave-Ayland         esp_set_tc(s, s->mig_dma_left);
1324042879fcSMark Cave-Ayland 
1325042879fcSMark Cave-Ayland         /* Migrate ti_buf to fifo */
1326042879fcSMark Cave-Ayland         len = s->mig_ti_wptr - s->mig_ti_rptr;
1327042879fcSMark Cave-Ayland         for (i = 0; i < len; i++) {
1328042879fcSMark Cave-Ayland             fifo8_push(&s->fifo, s->mig_ti_buf[i]);
1329042879fcSMark Cave-Ayland         }
1330023666daSMark Cave-Ayland 
1331023666daSMark Cave-Ayland         /* Migrate cmdbuf to cmdfifo */
1332023666daSMark Cave-Ayland         for (i = 0; i < s->mig_cmdlen; i++) {
1333023666daSMark Cave-Ayland             fifo8_push(&s->cmdfifo, s->mig_cmdbuf[i]);
1334023666daSMark Cave-Ayland         }
13356cc88d6bSMark Cave-Ayland     }
13366cc88d6bSMark Cave-Ayland 
13370bd005beSMark Cave-Ayland     s->mig_version_id = vmstate_esp.version_id;
13380bd005beSMark Cave-Ayland     return 0;
13390bd005beSMark Cave-Ayland }
13400bd005beSMark Cave-Ayland 
134149ab747fSPaolo Bonzini const VMStateDescription vmstate_esp = {
134249ab747fSPaolo Bonzini     .name = "esp",
134382003450SMark Cave-Ayland     .version_id = 7,
134449ab747fSPaolo Bonzini     .minimum_version_id = 3,
13450bd005beSMark Cave-Ayland     .post_load = esp_post_load,
13462d7b39a6SRichard Henderson     .fields = (const VMStateField[]) {
134749ab747fSPaolo Bonzini         VMSTATE_BUFFER(rregs, ESPState),
134849ab747fSPaolo Bonzini         VMSTATE_BUFFER(wregs, ESPState),
134949ab747fSPaolo Bonzini         VMSTATE_INT32(ti_size, ESPState),
1350042879fcSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_ti_rptr, ESPState, esp_is_before_version_5),
1351042879fcSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_ti_wptr, ESPState, esp_is_before_version_5),
1352042879fcSMark Cave-Ayland         VMSTATE_BUFFER_TEST(mig_ti_buf, ESPState, esp_is_before_version_5),
135349ab747fSPaolo Bonzini         VMSTATE_UINT32(status, ESPState),
13544aaa6ac3SMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_deferred_status, ESPState,
13554aaa6ac3SMark Cave-Ayland                             esp_is_before_version_5),
13564aaa6ac3SMark Cave-Ayland         VMSTATE_BOOL_TEST(mig_deferred_complete, ESPState,
13574aaa6ac3SMark Cave-Ayland                           esp_is_before_version_5),
135849ab747fSPaolo Bonzini         VMSTATE_UINT32(dma, ESPState),
1359023666daSMark Cave-Ayland         VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 0,
1360023666daSMark Cave-Ayland                               esp_is_before_version_5, 0, 16),
1361023666daSMark Cave-Ayland         VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 4,
1362023666daSMark Cave-Ayland                               esp_is_before_version_5, 16,
1363023666daSMark Cave-Ayland                               sizeof(typeof_field(ESPState, mig_cmdbuf))),
1364023666daSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_cmdlen, ESPState, esp_is_before_version_5),
136549ab747fSPaolo Bonzini         VMSTATE_UINT32(do_cmd, ESPState),
13666cc88d6bSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5),
13678dded6deSMark Cave-Ayland         VMSTATE_BOOL_TEST(data_ready, ESPState, esp_is_version_5),
1368023666daSMark Cave-Ayland         VMSTATE_UINT8_TEST(cmdfifo_cdb_offset, ESPState, esp_is_version_5),
1369042879fcSMark Cave-Ayland         VMSTATE_FIFO8_TEST(fifo, ESPState, esp_is_version_5),
1370023666daSMark Cave-Ayland         VMSTATE_FIFO8_TEST(cmdfifo, ESPState, esp_is_version_5),
137182003450SMark Cave-Ayland         VMSTATE_UINT8_TEST(mig_ti_cmd, ESPState,
137282003450SMark Cave-Ayland                            esp_is_between_version_5_and_6),
13734eb86065SPaolo Bonzini         VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6),
1374442de89aSMark Cave-Ayland         VMSTATE_BOOL(drq_state, ESPState),
137549ab747fSPaolo Bonzini         VMSTATE_END_OF_LIST()
137674d71ea1SLaurent Vivier     },
137749ab747fSPaolo Bonzini };
137849ab747fSPaolo Bonzini 
137949ab747fSPaolo Bonzini static void sysbus_esp_mem_write(void *opaque, hwaddr addr,
138049ab747fSPaolo Bonzini                                  uint64_t val, unsigned int size)
138149ab747fSPaolo Bonzini {
138249ab747fSPaolo Bonzini     SysBusESPState *sysbus = opaque;
1383eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
138449ab747fSPaolo Bonzini     uint32_t saddr;
138549ab747fSPaolo Bonzini 
138649ab747fSPaolo Bonzini     saddr = addr >> sysbus->it_shift;
1387eb169c76SMark Cave-Ayland     esp_reg_write(s, saddr, val);
138849ab747fSPaolo Bonzini }
138949ab747fSPaolo Bonzini 
139049ab747fSPaolo Bonzini static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr,
139149ab747fSPaolo Bonzini                                     unsigned int size)
139249ab747fSPaolo Bonzini {
139349ab747fSPaolo Bonzini     SysBusESPState *sysbus = opaque;
1394eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
139549ab747fSPaolo Bonzini     uint32_t saddr;
139649ab747fSPaolo Bonzini 
139749ab747fSPaolo Bonzini     saddr = addr >> sysbus->it_shift;
1398eb169c76SMark Cave-Ayland     return esp_reg_read(s, saddr);
139949ab747fSPaolo Bonzini }
140049ab747fSPaolo Bonzini 
140149ab747fSPaolo Bonzini static const MemoryRegionOps sysbus_esp_mem_ops = {
140249ab747fSPaolo Bonzini     .read = sysbus_esp_mem_read,
140349ab747fSPaolo Bonzini     .write = sysbus_esp_mem_write,
140449ab747fSPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
140549ab747fSPaolo Bonzini     .valid.accepts = esp_mem_accepts,
140649ab747fSPaolo Bonzini };
140749ab747fSPaolo Bonzini 
140874d71ea1SLaurent Vivier static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
140974d71ea1SLaurent Vivier                                   uint64_t val, unsigned int size)
141074d71ea1SLaurent Vivier {
141174d71ea1SLaurent Vivier     SysBusESPState *sysbus = opaque;
1412eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
141374d71ea1SLaurent Vivier 
1414960ebfd9SMark Cave-Ayland     trace_esp_pdma_write(size);
1415960ebfd9SMark Cave-Ayland 
141674d71ea1SLaurent Vivier     switch (size) {
141774d71ea1SLaurent Vivier     case 1:
1418761bef75SMark Cave-Ayland         esp_pdma_write(s, val);
141974d71ea1SLaurent Vivier         break;
142074d71ea1SLaurent Vivier     case 2:
1421761bef75SMark Cave-Ayland         esp_pdma_write(s, val >> 8);
1422761bef75SMark Cave-Ayland         esp_pdma_write(s, val);
142374d71ea1SLaurent Vivier         break;
142474d71ea1SLaurent Vivier     }
1425b46a43a2SMark Cave-Ayland     esp_do_dma(s);
142674d71ea1SLaurent Vivier }
142774d71ea1SLaurent Vivier 
142874d71ea1SLaurent Vivier static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr,
142974d71ea1SLaurent Vivier                                      unsigned int size)
143074d71ea1SLaurent Vivier {
143174d71ea1SLaurent Vivier     SysBusESPState *sysbus = opaque;
1432eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
143374d71ea1SLaurent Vivier     uint64_t val = 0;
143474d71ea1SLaurent Vivier 
1435960ebfd9SMark Cave-Ayland     trace_esp_pdma_read(size);
1436960ebfd9SMark Cave-Ayland 
143774d71ea1SLaurent Vivier     switch (size) {
143874d71ea1SLaurent Vivier     case 1:
1439761bef75SMark Cave-Ayland         val = esp_pdma_read(s);
144074d71ea1SLaurent Vivier         break;
144174d71ea1SLaurent Vivier     case 2:
1442761bef75SMark Cave-Ayland         val = esp_pdma_read(s);
1443761bef75SMark Cave-Ayland         val = (val << 8) | esp_pdma_read(s);
144474d71ea1SLaurent Vivier         break;
144574d71ea1SLaurent Vivier     }
1446b46a43a2SMark Cave-Ayland     esp_do_dma(s);
144774d71ea1SLaurent Vivier     return val;
144874d71ea1SLaurent Vivier }
144974d71ea1SLaurent Vivier 
1450a7a22088SMark Cave-Ayland static void *esp_load_request(QEMUFile *f, SCSIRequest *req)
1451a7a22088SMark Cave-Ayland {
1452a7a22088SMark Cave-Ayland     ESPState *s = container_of(req->bus, ESPState, bus);
1453a7a22088SMark Cave-Ayland 
1454a7a22088SMark Cave-Ayland     scsi_req_ref(req);
1455a7a22088SMark Cave-Ayland     s->current_req = req;
1456a7a22088SMark Cave-Ayland     return s;
1457a7a22088SMark Cave-Ayland }
1458a7a22088SMark Cave-Ayland 
145974d71ea1SLaurent Vivier static const MemoryRegionOps sysbus_esp_pdma_ops = {
146074d71ea1SLaurent Vivier     .read = sysbus_esp_pdma_read,
146174d71ea1SLaurent Vivier     .write = sysbus_esp_pdma_write,
146274d71ea1SLaurent Vivier     .endianness = DEVICE_NATIVE_ENDIAN,
146374d71ea1SLaurent Vivier     .valid.min_access_size = 1,
1464cf1b8286SMark Cave-Ayland     .valid.max_access_size = 4,
1465cf1b8286SMark Cave-Ayland     .impl.min_access_size = 1,
1466cf1b8286SMark Cave-Ayland     .impl.max_access_size = 2,
146774d71ea1SLaurent Vivier };
146874d71ea1SLaurent Vivier 
146949ab747fSPaolo Bonzini static const struct SCSIBusInfo esp_scsi_info = {
147049ab747fSPaolo Bonzini     .tcq = false,
147149ab747fSPaolo Bonzini     .max_target = ESP_MAX_DEVS,
147249ab747fSPaolo Bonzini     .max_lun = 7,
147349ab747fSPaolo Bonzini 
1474a7a22088SMark Cave-Ayland     .load_request = esp_load_request,
147549ab747fSPaolo Bonzini     .transfer_data = esp_transfer_data,
147649ab747fSPaolo Bonzini     .complete = esp_command_complete,
147749ab747fSPaolo Bonzini     .cancel = esp_request_cancelled
147849ab747fSPaolo Bonzini };
147949ab747fSPaolo Bonzini 
148049ab747fSPaolo Bonzini static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
148149ab747fSPaolo Bonzini {
148284fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(opaque);
1483eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
148449ab747fSPaolo Bonzini 
148549ab747fSPaolo Bonzini     switch (irq) {
148649ab747fSPaolo Bonzini     case 0:
148749ab747fSPaolo Bonzini         parent_esp_reset(s, irq, level);
148849ab747fSPaolo Bonzini         break;
148949ab747fSPaolo Bonzini     case 1:
1490b86dc5cbSMark Cave-Ayland         esp_dma_enable(s, irq, level);
149149ab747fSPaolo Bonzini         break;
149249ab747fSPaolo Bonzini     }
149349ab747fSPaolo Bonzini }
149449ab747fSPaolo Bonzini 
1495b09318caSHu Tao static void sysbus_esp_realize(DeviceState *dev, Error **errp)
149649ab747fSPaolo Bonzini {
1497b09318caSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
149884fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(dev);
1499eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
1500eb169c76SMark Cave-Ayland 
1501eb169c76SMark Cave-Ayland     if (!qdev_realize(DEVICE(s), NULL, errp)) {
1502eb169c76SMark Cave-Ayland         return;
1503eb169c76SMark Cave-Ayland     }
150449ab747fSPaolo Bonzini 
1505b09318caSHu Tao     sysbus_init_irq(sbd, &s->irq);
15066dec7c0dSMark Cave-Ayland     sysbus_init_irq(sbd, &s->drq_irq);
150749ab747fSPaolo Bonzini     assert(sysbus->it_shift != -1);
150849ab747fSPaolo Bonzini 
150949ab747fSPaolo Bonzini     s->chip_id = TCHI_FAS100A;
151029776739SPaolo Bonzini     memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
151174d71ea1SLaurent Vivier                           sysbus, "esp-regs", ESP_REGS << sysbus->it_shift);
1512b09318caSHu Tao     sysbus_init_mmio(sbd, &sysbus->iomem);
151374d71ea1SLaurent Vivier     memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_ops,
1514cf1b8286SMark Cave-Ayland                           sysbus, "esp-pdma", 4);
151574d71ea1SLaurent Vivier     sysbus_init_mmio(sbd, &sysbus->pdma);
151649ab747fSPaolo Bonzini 
1517b09318caSHu Tao     qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
151849ab747fSPaolo Bonzini 
1519739e95f5SPeter Maydell     scsi_bus_init(&s->bus, sizeof(s->bus), dev, &esp_scsi_info);
152049ab747fSPaolo Bonzini }
152149ab747fSPaolo Bonzini 
152249ab747fSPaolo Bonzini static void sysbus_esp_hard_reset(DeviceState *dev)
152349ab747fSPaolo Bonzini {
152484fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(dev);
1525eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
1526eb169c76SMark Cave-Ayland 
1527eb169c76SMark Cave-Ayland     esp_hard_reset(s);
1528eb169c76SMark Cave-Ayland }
1529eb169c76SMark Cave-Ayland 
1530eb169c76SMark Cave-Ayland static void sysbus_esp_init(Object *obj)
1531eb169c76SMark Cave-Ayland {
1532eb169c76SMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(obj);
1533eb169c76SMark Cave-Ayland 
1534eb169c76SMark Cave-Ayland     object_initialize_child(obj, "esp", &sysbus->esp, TYPE_ESP);
153549ab747fSPaolo Bonzini }
153649ab747fSPaolo Bonzini 
153749ab747fSPaolo Bonzini static const VMStateDescription vmstate_sysbus_esp_scsi = {
153849ab747fSPaolo Bonzini     .name = "sysbusespscsi",
15390bd005beSMark Cave-Ayland     .version_id = 2,
1540ea84a442SGuenter Roeck     .minimum_version_id = 1,
1541ff4a1dabSMark Cave-Ayland     .pre_save = esp_pre_save,
15422d7b39a6SRichard Henderson     .fields = (const VMStateField[]) {
15430bd005beSMark Cave-Ayland         VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2),
154449ab747fSPaolo Bonzini         VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
154549ab747fSPaolo Bonzini         VMSTATE_END_OF_LIST()
154649ab747fSPaolo Bonzini     }
154749ab747fSPaolo Bonzini };
154849ab747fSPaolo Bonzini 
154949ab747fSPaolo Bonzini static void sysbus_esp_class_init(ObjectClass *klass, void *data)
155049ab747fSPaolo Bonzini {
155149ab747fSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
155249ab747fSPaolo Bonzini 
1553b09318caSHu Tao     dc->realize = sysbus_esp_realize;
155449ab747fSPaolo Bonzini     dc->reset = sysbus_esp_hard_reset;
155549ab747fSPaolo Bonzini     dc->vmsd = &vmstate_sysbus_esp_scsi;
1556125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
155749ab747fSPaolo Bonzini }
155849ab747fSPaolo Bonzini 
1559042879fcSMark Cave-Ayland static void esp_finalize(Object *obj)
1560042879fcSMark Cave-Ayland {
1561042879fcSMark Cave-Ayland     ESPState *s = ESP(obj);
1562042879fcSMark Cave-Ayland 
1563042879fcSMark Cave-Ayland     fifo8_destroy(&s->fifo);
1564023666daSMark Cave-Ayland     fifo8_destroy(&s->cmdfifo);
1565042879fcSMark Cave-Ayland }
1566042879fcSMark Cave-Ayland 
1567042879fcSMark Cave-Ayland static void esp_init(Object *obj)
1568042879fcSMark Cave-Ayland {
1569042879fcSMark Cave-Ayland     ESPState *s = ESP(obj);
1570042879fcSMark Cave-Ayland 
1571042879fcSMark Cave-Ayland     fifo8_create(&s->fifo, ESP_FIFO_SZ);
1572023666daSMark Cave-Ayland     fifo8_create(&s->cmdfifo, ESP_CMDFIFO_SZ);
1573042879fcSMark Cave-Ayland }
1574042879fcSMark Cave-Ayland 
1575eb169c76SMark Cave-Ayland static void esp_class_init(ObjectClass *klass, void *data)
1576eb169c76SMark Cave-Ayland {
1577eb169c76SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(klass);
1578eb169c76SMark Cave-Ayland 
1579eb169c76SMark Cave-Ayland     /* internal device for sysbusesp/pciespscsi, not user-creatable */
1580eb169c76SMark Cave-Ayland     dc->user_creatable = false;
1581eb169c76SMark Cave-Ayland     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1582eb169c76SMark Cave-Ayland }
1583eb169c76SMark Cave-Ayland 
1584499f4089SMark Cave-Ayland static const TypeInfo esp_info_types[] = {
1585499f4089SMark Cave-Ayland     {
1586499f4089SMark Cave-Ayland         .name          = TYPE_SYSBUS_ESP,
1587499f4089SMark Cave-Ayland         .parent        = TYPE_SYS_BUS_DEVICE,
1588499f4089SMark Cave-Ayland         .instance_init = sysbus_esp_init,
1589499f4089SMark Cave-Ayland         .instance_size = sizeof(SysBusESPState),
1590499f4089SMark Cave-Ayland         .class_init    = sysbus_esp_class_init,
1591499f4089SMark Cave-Ayland     },
1592499f4089SMark Cave-Ayland     {
1593eb169c76SMark Cave-Ayland         .name = TYPE_ESP,
1594eb169c76SMark Cave-Ayland         .parent = TYPE_DEVICE,
1595042879fcSMark Cave-Ayland         .instance_init = esp_init,
1596042879fcSMark Cave-Ayland         .instance_finalize = esp_finalize,
1597eb169c76SMark Cave-Ayland         .instance_size = sizeof(ESPState),
1598eb169c76SMark Cave-Ayland         .class_init = esp_class_init,
1599499f4089SMark Cave-Ayland     },
1600eb169c76SMark Cave-Ayland };
1601eb169c76SMark Cave-Ayland 
1602499f4089SMark Cave-Ayland DEFINE_TYPES(esp_info_types)
1603