xref: /qemu/hw/scsi/esp.c (revision d39592ff)
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
649ab747fSPaolo Bonzini  *
749ab747fSPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
849ab747fSPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
949ab747fSPaolo Bonzini  * in the Software without restriction, including without limitation the rights
1049ab747fSPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1149ab747fSPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1249ab747fSPaolo Bonzini  * furnished to do so, subject to the following conditions:
1349ab747fSPaolo Bonzini  *
1449ab747fSPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1549ab747fSPaolo Bonzini  * all copies or substantial portions of the Software.
1649ab747fSPaolo Bonzini  *
1749ab747fSPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1849ab747fSPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1949ab747fSPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2049ab747fSPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2149ab747fSPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2249ab747fSPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2349ab747fSPaolo Bonzini  * THE SOFTWARE.
2449ab747fSPaolo Bonzini  */
2549ab747fSPaolo Bonzini 
26a4ab4792SPeter Maydell #include "qemu/osdep.h"
2749ab747fSPaolo Bonzini #include "hw/sysbus.h"
28d6454270SMarkus Armbruster #include "migration/vmstate.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
3049ab747fSPaolo Bonzini #include "hw/scsi/esp.h"
3149ab747fSPaolo Bonzini #include "trace.h"
3249ab747fSPaolo Bonzini #include "qemu/log.h"
330b8fa32fSMarkus Armbruster #include "qemu/module.h"
3449ab747fSPaolo Bonzini 
3549ab747fSPaolo Bonzini /*
3649ab747fSPaolo Bonzini  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
3749ab747fSPaolo Bonzini  * also produced as NCR89C100. See
3849ab747fSPaolo Bonzini  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
3949ab747fSPaolo Bonzini  * and
4049ab747fSPaolo Bonzini  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
4174d71ea1SLaurent Vivier  *
4274d71ea1SLaurent Vivier  * On Macintosh Quadra it is a NCR53C96.
4349ab747fSPaolo Bonzini  */
4449ab747fSPaolo Bonzini 
4549ab747fSPaolo Bonzini static void esp_raise_irq(ESPState *s)
4649ab747fSPaolo Bonzini {
4749ab747fSPaolo Bonzini     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
4849ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] |= STAT_INT;
4949ab747fSPaolo Bonzini         qemu_irq_raise(s->irq);
5049ab747fSPaolo Bonzini         trace_esp_raise_irq();
5149ab747fSPaolo Bonzini     }
5249ab747fSPaolo Bonzini }
5349ab747fSPaolo Bonzini 
5449ab747fSPaolo Bonzini static void esp_lower_irq(ESPState *s)
5549ab747fSPaolo Bonzini {
5649ab747fSPaolo Bonzini     if (s->rregs[ESP_RSTAT] & STAT_INT) {
5749ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] &= ~STAT_INT;
5849ab747fSPaolo Bonzini         qemu_irq_lower(s->irq);
5949ab747fSPaolo Bonzini         trace_esp_lower_irq();
6049ab747fSPaolo Bonzini     }
6149ab747fSPaolo Bonzini }
6249ab747fSPaolo Bonzini 
6374d71ea1SLaurent Vivier static void esp_raise_drq(ESPState *s)
6474d71ea1SLaurent Vivier {
6574d71ea1SLaurent Vivier     qemu_irq_raise(s->irq_data);
66960ebfd9SMark Cave-Ayland     trace_esp_raise_drq();
6774d71ea1SLaurent Vivier }
6874d71ea1SLaurent Vivier 
6974d71ea1SLaurent Vivier static void esp_lower_drq(ESPState *s)
7074d71ea1SLaurent Vivier {
7174d71ea1SLaurent Vivier     qemu_irq_lower(s->irq_data);
72960ebfd9SMark Cave-Ayland     trace_esp_lower_drq();
7374d71ea1SLaurent Vivier }
7474d71ea1SLaurent Vivier 
7549ab747fSPaolo Bonzini void esp_dma_enable(ESPState *s, int irq, int level)
7649ab747fSPaolo Bonzini {
7749ab747fSPaolo Bonzini     if (level) {
7849ab747fSPaolo Bonzini         s->dma_enabled = 1;
7949ab747fSPaolo Bonzini         trace_esp_dma_enable();
8049ab747fSPaolo Bonzini         if (s->dma_cb) {
8149ab747fSPaolo Bonzini             s->dma_cb(s);
8249ab747fSPaolo Bonzini             s->dma_cb = NULL;
8349ab747fSPaolo Bonzini         }
8449ab747fSPaolo Bonzini     } else {
8549ab747fSPaolo Bonzini         trace_esp_dma_disable();
8649ab747fSPaolo Bonzini         s->dma_enabled = 0;
8749ab747fSPaolo Bonzini     }
8849ab747fSPaolo Bonzini }
8949ab747fSPaolo Bonzini 
9049ab747fSPaolo Bonzini void esp_request_cancelled(SCSIRequest *req)
9149ab747fSPaolo Bonzini {
9249ab747fSPaolo Bonzini     ESPState *s = req->hba_private;
9349ab747fSPaolo Bonzini 
9449ab747fSPaolo Bonzini     if (req == s->current_req) {
9549ab747fSPaolo Bonzini         scsi_req_unref(s->current_req);
9649ab747fSPaolo Bonzini         s->current_req = NULL;
9749ab747fSPaolo Bonzini         s->current_dev = NULL;
98324c8809SMark Cave-Ayland         s->async_len = 0;
9949ab747fSPaolo Bonzini     }
10049ab747fSPaolo Bonzini }
10149ab747fSPaolo Bonzini 
102e5455b8cSMark Cave-Ayland static void esp_fifo_push(Fifo8 *fifo, uint8_t val)
103042879fcSMark Cave-Ayland {
104e5455b8cSMark Cave-Ayland     if (fifo8_num_used(fifo) == fifo->capacity) {
105042879fcSMark Cave-Ayland         trace_esp_error_fifo_overrun();
106042879fcSMark Cave-Ayland         return;
107042879fcSMark Cave-Ayland     }
108042879fcSMark Cave-Ayland 
109e5455b8cSMark Cave-Ayland     fifo8_push(fifo, val);
110042879fcSMark Cave-Ayland }
111c5fef911SMark Cave-Ayland 
112c5fef911SMark Cave-Ayland static uint8_t esp_fifo_pop(Fifo8 *fifo)
113042879fcSMark Cave-Ayland {
114c5fef911SMark Cave-Ayland     if (fifo8_is_empty(fifo)) {
115042879fcSMark Cave-Ayland         return 0;
116042879fcSMark Cave-Ayland     }
117042879fcSMark Cave-Ayland 
118c5fef911SMark Cave-Ayland     return fifo8_pop(fifo);
119023666daSMark Cave-Ayland }
120023666daSMark Cave-Ayland 
1217b320a8eSMark Cave-Ayland static uint32_t esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen)
1227b320a8eSMark Cave-Ayland {
1237b320a8eSMark Cave-Ayland     const uint8_t *buf;
12449c60d16SMark Cave-Ayland     uint32_t n, n2;
12549c60d16SMark Cave-Ayland     int len;
1267b320a8eSMark Cave-Ayland 
1277b320a8eSMark Cave-Ayland     if (maxlen == 0) {
1287b320a8eSMark Cave-Ayland         return 0;
1297b320a8eSMark Cave-Ayland     }
1307b320a8eSMark Cave-Ayland 
13149c60d16SMark Cave-Ayland     len = maxlen;
13249c60d16SMark Cave-Ayland     buf = fifo8_pop_buf(fifo, len, &n);
1337b320a8eSMark Cave-Ayland     if (dest) {
1347b320a8eSMark Cave-Ayland         memcpy(dest, buf, n);
1357b320a8eSMark Cave-Ayland     }
1367b320a8eSMark Cave-Ayland 
13749c60d16SMark Cave-Ayland     /* Add FIFO wraparound if needed */
13849c60d16SMark Cave-Ayland     len -= n;
13949c60d16SMark Cave-Ayland     len = MIN(len, fifo8_num_used(fifo));
14049c60d16SMark Cave-Ayland     if (len) {
14149c60d16SMark Cave-Ayland         buf = fifo8_pop_buf(fifo, len, &n2);
14249c60d16SMark Cave-Ayland         if (dest) {
14349c60d16SMark Cave-Ayland             memcpy(&dest[n], buf, n2);
14449c60d16SMark Cave-Ayland         }
14549c60d16SMark Cave-Ayland         n += n2;
14649c60d16SMark Cave-Ayland     }
14749c60d16SMark Cave-Ayland 
1487b320a8eSMark Cave-Ayland     return n;
1497b320a8eSMark Cave-Ayland }
1507b320a8eSMark Cave-Ayland 
151c47b5835SMark Cave-Ayland static uint32_t esp_get_tc(ESPState *s)
152c47b5835SMark Cave-Ayland {
153c47b5835SMark Cave-Ayland     uint32_t dmalen;
154c47b5835SMark Cave-Ayland 
155c47b5835SMark Cave-Ayland     dmalen = s->rregs[ESP_TCLO];
156c47b5835SMark Cave-Ayland     dmalen |= s->rregs[ESP_TCMID] << 8;
157c47b5835SMark Cave-Ayland     dmalen |= s->rregs[ESP_TCHI] << 16;
158c47b5835SMark Cave-Ayland 
159c47b5835SMark Cave-Ayland     return dmalen;
160c47b5835SMark Cave-Ayland }
161c47b5835SMark Cave-Ayland 
162c47b5835SMark Cave-Ayland static void esp_set_tc(ESPState *s, uint32_t dmalen)
163c47b5835SMark Cave-Ayland {
164c5d7df28SMark Cave-Ayland     uint32_t old_tc = esp_get_tc(s);
165c5d7df28SMark Cave-Ayland 
166c47b5835SMark Cave-Ayland     s->rregs[ESP_TCLO] = dmalen;
167c47b5835SMark Cave-Ayland     s->rregs[ESP_TCMID] = dmalen >> 8;
168c47b5835SMark Cave-Ayland     s->rregs[ESP_TCHI] = dmalen >> 16;
169c5d7df28SMark Cave-Ayland 
170c5d7df28SMark Cave-Ayland     if (old_tc && dmalen == 0) {
171c5d7df28SMark Cave-Ayland         s->rregs[ESP_RSTAT] |= STAT_TC;
172c5d7df28SMark Cave-Ayland     }
173c47b5835SMark Cave-Ayland }
174c47b5835SMark Cave-Ayland 
175c04ed569SMark Cave-Ayland static uint32_t esp_get_stc(ESPState *s)
176c04ed569SMark Cave-Ayland {
177c04ed569SMark Cave-Ayland     uint32_t dmalen;
178c04ed569SMark Cave-Ayland 
179c04ed569SMark Cave-Ayland     dmalen = s->wregs[ESP_TCLO];
180c04ed569SMark Cave-Ayland     dmalen |= s->wregs[ESP_TCMID] << 8;
181c04ed569SMark Cave-Ayland     dmalen |= s->wregs[ESP_TCHI] << 16;
182c04ed569SMark Cave-Ayland 
183c04ed569SMark Cave-Ayland     return dmalen;
184c04ed569SMark Cave-Ayland }
185c04ed569SMark Cave-Ayland 
186abc139cdSMark Cave-Ayland static const char *esp_phase_names[8] = {
187abc139cdSMark Cave-Ayland     "DATA OUT", "DATA IN", "COMMAND", "STATUS",
188abc139cdSMark Cave-Ayland     "(reserved)", "(reserved)", "MESSAGE OUT", "MESSAGE IN"
189abc139cdSMark Cave-Ayland };
190abc139cdSMark Cave-Ayland 
191abc139cdSMark Cave-Ayland static void esp_set_phase(ESPState *s, uint8_t phase)
192abc139cdSMark Cave-Ayland {
193abc139cdSMark Cave-Ayland     s->rregs[ESP_RSTAT] &= ~7;
194abc139cdSMark Cave-Ayland     s->rregs[ESP_RSTAT] |= phase;
195abc139cdSMark Cave-Ayland 
196abc139cdSMark Cave-Ayland     trace_esp_set_phase(esp_phase_names[phase]);
197abc139cdSMark Cave-Ayland }
198abc139cdSMark Cave-Ayland 
1995a83e83eSMark Cave-Ayland static uint8_t esp_get_phase(ESPState *s)
2005a83e83eSMark Cave-Ayland {
2015a83e83eSMark Cave-Ayland     return s->rregs[ESP_RSTAT] & 7;
2025a83e83eSMark Cave-Ayland }
2035a83e83eSMark Cave-Ayland 
204761bef75SMark Cave-Ayland static uint8_t esp_pdma_read(ESPState *s)
205761bef75SMark Cave-Ayland {
2068da90e81SMark Cave-Ayland     uint8_t val;
2078da90e81SMark Cave-Ayland 
208c5fef911SMark Cave-Ayland     val = esp_fifo_pop(&s->fifo);
2098da90e81SMark Cave-Ayland     return val;
210761bef75SMark Cave-Ayland }
211761bef75SMark Cave-Ayland 
212761bef75SMark Cave-Ayland static void esp_pdma_write(ESPState *s, uint8_t val)
213761bef75SMark Cave-Ayland {
2148da90e81SMark Cave-Ayland     uint32_t dmalen = esp_get_tc(s);
2158da90e81SMark Cave-Ayland 
2163c421400SMark Cave-Ayland     if (dmalen == 0) {
2178da90e81SMark Cave-Ayland         return;
2188da90e81SMark Cave-Ayland     }
2198da90e81SMark Cave-Ayland 
220e5455b8cSMark Cave-Ayland     esp_fifo_push(&s->fifo, val);
2218da90e81SMark Cave-Ayland 
2228da90e81SMark Cave-Ayland     dmalen--;
2238da90e81SMark Cave-Ayland     esp_set_tc(s, dmalen);
224761bef75SMark Cave-Ayland }
225761bef75SMark Cave-Ayland 
226c7bce09cSMark Cave-Ayland static int esp_select(ESPState *s)
2276130b188SLaurent Vivier {
2286130b188SLaurent Vivier     int target;
2296130b188SLaurent Vivier 
2306130b188SLaurent Vivier     target = s->wregs[ESP_WBUSID] & BUSID_DID;
2316130b188SLaurent Vivier 
2326130b188SLaurent Vivier     s->ti_size = 0;
2336130b188SLaurent Vivier 
234cf40a5e4SMark Cave-Ayland     if (s->current_req) {
235cf40a5e4SMark Cave-Ayland         /* Started a new command before the old one finished. Cancel it. */
236cf40a5e4SMark Cave-Ayland         scsi_req_cancel(s->current_req);
237cf40a5e4SMark Cave-Ayland     }
238cf40a5e4SMark Cave-Ayland 
2396130b188SLaurent Vivier     s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
2406130b188SLaurent Vivier     if (!s->current_dev) {
2416130b188SLaurent Vivier         /* No such drive */
2426130b188SLaurent Vivier         s->rregs[ESP_RSTAT] = 0;
243cf1a7a9bSMark Cave-Ayland         s->rregs[ESP_RINTR] = INTR_DC;
2446130b188SLaurent Vivier         s->rregs[ESP_RSEQ] = SEQ_0;
2456130b188SLaurent Vivier         esp_raise_irq(s);
2466130b188SLaurent Vivier         return -1;
2476130b188SLaurent Vivier     }
2484e78f3bfSMark Cave-Ayland 
2494e78f3bfSMark Cave-Ayland     /*
2504e78f3bfSMark Cave-Ayland      * Note that we deliberately don't raise the IRQ here: this will be done
251c90b2792SMark Cave-Ayland      * either in esp_transfer_data() or esp_command_complete()
2524e78f3bfSMark Cave-Ayland      */
2534e78f3bfSMark Cave-Ayland     s->rregs[ESP_RSEQ] = SEQ_CD;
2546130b188SLaurent Vivier     return 0;
2556130b188SLaurent Vivier }
2566130b188SLaurent Vivier 
2573ee9a475SMark Cave-Ayland static void esp_do_dma(ESPState *s);
2583ee9a475SMark Cave-Ayland static void esp_do_nodma(ESPState *s);
2593ee9a475SMark Cave-Ayland 
2604eb86065SPaolo Bonzini static void do_command_phase(ESPState *s)
26149ab747fSPaolo Bonzini {
2627b320a8eSMark Cave-Ayland     uint32_t cmdlen;
26349ab747fSPaolo Bonzini     int32_t datalen;
26449ab747fSPaolo Bonzini     SCSIDevice *current_lun;
2657b320a8eSMark Cave-Ayland     uint8_t buf[ESP_CMDFIFO_SZ];
26649ab747fSPaolo Bonzini 
2674eb86065SPaolo Bonzini     trace_esp_do_command_phase(s->lun);
268023666daSMark Cave-Ayland     cmdlen = fifo8_num_used(&s->cmdfifo);
26999545751SMark Cave-Ayland     if (!cmdlen || !s->current_dev) {
27099545751SMark Cave-Ayland         return;
27199545751SMark Cave-Ayland     }
2727b320a8eSMark Cave-Ayland     esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen);
273023666daSMark Cave-Ayland 
2744eb86065SPaolo Bonzini     current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
275b22f83d8SAlexandra Diupina     if (!current_lun) {
276b22f83d8SAlexandra Diupina         /* No such drive */
277b22f83d8SAlexandra Diupina         s->rregs[ESP_RSTAT] = 0;
278b22f83d8SAlexandra Diupina         s->rregs[ESP_RINTR] = INTR_DC;
279b22f83d8SAlexandra Diupina         s->rregs[ESP_RSEQ] = SEQ_0;
280b22f83d8SAlexandra Diupina         esp_raise_irq(s);
281b22f83d8SAlexandra Diupina         return;
282b22f83d8SAlexandra Diupina     }
283b22f83d8SAlexandra Diupina 
284fe9d8927SJohn Millikin     s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s);
28549ab747fSPaolo Bonzini     datalen = scsi_req_enqueue(s->current_req);
28649ab747fSPaolo Bonzini     s->ti_size = datalen;
287023666daSMark Cave-Ayland     fifo8_reset(&s->cmdfifo);
288c90b2792SMark Cave-Ayland     s->data_ready = false;
28949ab747fSPaolo Bonzini     if (datalen != 0) {
2904e78f3bfSMark Cave-Ayland         /*
291c90b2792SMark Cave-Ayland          * Switch to DATA phase but wait until initial data xfer is
2924e78f3bfSMark Cave-Ayland          * complete before raising the command completion interrupt
2934e78f3bfSMark Cave-Ayland          */
294c90b2792SMark Cave-Ayland         if (datalen > 0) {
295abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_DI);
29649ab747fSPaolo Bonzini         } else {
297abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_DO);
29849ab747fSPaolo Bonzini         }
2994e78f3bfSMark Cave-Ayland         scsi_req_continue(s->current_req);
3004e78f3bfSMark Cave-Ayland         return;
3014e78f3bfSMark Cave-Ayland     }
3024e78f3bfSMark Cave-Ayland }
30349ab747fSPaolo Bonzini 
3044eb86065SPaolo Bonzini static void do_message_phase(ESPState *s)
30549ab747fSPaolo Bonzini {
3064eb86065SPaolo Bonzini     if (s->cmdfifo_cdb_offset) {
3074eb86065SPaolo Bonzini         uint8_t message = esp_fifo_pop(&s->cmdfifo);
308023666daSMark Cave-Ayland 
3094eb86065SPaolo Bonzini         trace_esp_do_identify(message);
3104eb86065SPaolo Bonzini         s->lun = message & 7;
311023666daSMark Cave-Ayland         s->cmdfifo_cdb_offset--;
3124eb86065SPaolo Bonzini     }
31349ab747fSPaolo Bonzini 
314799d90d8SMark Cave-Ayland     /* Ignore extended messages for now */
315023666daSMark Cave-Ayland     if (s->cmdfifo_cdb_offset) {
3164eb86065SPaolo Bonzini         int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
317fa7505c1SMark Cave-Ayland         esp_fifo_pop_buf(&s->cmdfifo, NULL, len);
318023666daSMark Cave-Ayland         s->cmdfifo_cdb_offset = 0;
319023666daSMark Cave-Ayland     }
3204eb86065SPaolo Bonzini }
321023666daSMark Cave-Ayland 
3224eb86065SPaolo Bonzini static void do_cmd(ESPState *s)
3234eb86065SPaolo Bonzini {
3244eb86065SPaolo Bonzini     do_message_phase(s);
3254eb86065SPaolo Bonzini     assert(s->cmdfifo_cdb_offset == 0);
3264eb86065SPaolo Bonzini     do_command_phase(s);
32749ab747fSPaolo Bonzini }
32849ab747fSPaolo Bonzini 
32949ab747fSPaolo Bonzini static void handle_satn(ESPState *s)
33049ab747fSPaolo Bonzini {
33149ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
33249ab747fSPaolo Bonzini         s->dma_cb = handle_satn;
33349ab747fSPaolo Bonzini         return;
33449ab747fSPaolo Bonzini     }
335b46a43a2SMark Cave-Ayland 
3361bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3371bcaf71bSMark Cave-Ayland         return;
3381bcaf71bSMark Cave-Ayland     }
3393ee9a475SMark Cave-Ayland 
3403ee9a475SMark Cave-Ayland     esp_set_phase(s, STAT_MO);
3413ee9a475SMark Cave-Ayland 
3423ee9a475SMark Cave-Ayland     if (s->dma) {
3433ee9a475SMark Cave-Ayland         esp_do_dma(s);
3443ee9a475SMark Cave-Ayland     } else {
345*d39592ffSMark Cave-Ayland         esp_do_nodma(s);
34649ab747fSPaolo Bonzini     }
34794d5c79dSMark Cave-Ayland }
34849ab747fSPaolo Bonzini 
34949ab747fSPaolo Bonzini static void handle_s_without_atn(ESPState *s)
35049ab747fSPaolo Bonzini {
35149ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
35249ab747fSPaolo Bonzini         s->dma_cb = handle_s_without_atn;
35349ab747fSPaolo Bonzini         return;
35449ab747fSPaolo Bonzini     }
355b46a43a2SMark Cave-Ayland 
3561bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3571bcaf71bSMark Cave-Ayland         return;
3581bcaf71bSMark Cave-Ayland     }
3599ff0fd12SMark Cave-Ayland 
360abc139cdSMark Cave-Ayland     esp_set_phase(s, STAT_CD);
3619ff0fd12SMark Cave-Ayland     s->rregs[ESP_RSEQ] = SEQ_CD;
3629ff0fd12SMark Cave-Ayland     s->cmdfifo_cdb_offset = 0;
3639ff0fd12SMark Cave-Ayland 
3649ff0fd12SMark Cave-Ayland     if (s->dma) {
3659ff0fd12SMark Cave-Ayland         esp_do_dma(s);
3669ff0fd12SMark Cave-Ayland     } else {
367*d39592ffSMark Cave-Ayland         esp_do_nodma(s);
36849ab747fSPaolo Bonzini     }
36949ab747fSPaolo Bonzini }
37049ab747fSPaolo Bonzini 
37149ab747fSPaolo Bonzini static void handle_satn_stop(ESPState *s)
37249ab747fSPaolo Bonzini {
37349ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
37449ab747fSPaolo Bonzini         s->dma_cb = handle_satn_stop;
37549ab747fSPaolo Bonzini         return;
37649ab747fSPaolo Bonzini     }
377b46a43a2SMark Cave-Ayland 
3781bcaf71bSMark Cave-Ayland     if (esp_select(s) < 0) {
3791bcaf71bSMark Cave-Ayland         return;
3801bcaf71bSMark Cave-Ayland     }
381db4d4150SMark Cave-Ayland 
382abc139cdSMark Cave-Ayland     esp_set_phase(s, STAT_MO);
383db4d4150SMark Cave-Ayland     s->rregs[ESP_RSEQ] = SEQ_MO;
3845d02add4SMark Cave-Ayland     s->cmdfifo_cdb_offset = 0;
385db4d4150SMark Cave-Ayland 
386db4d4150SMark Cave-Ayland     if (s->dma) {
387db4d4150SMark Cave-Ayland         esp_do_dma(s);
388db4d4150SMark Cave-Ayland     } else {
389*d39592ffSMark Cave-Ayland         esp_do_nodma(s);
39049ab747fSPaolo Bonzini     }
39149ab747fSPaolo Bonzini }
39249ab747fSPaolo Bonzini 
39349ab747fSPaolo Bonzini static void write_response(ESPState *s)
39449ab747fSPaolo Bonzini {
395e3922557SMark Cave-Ayland     uint8_t buf[2];
396042879fcSMark Cave-Ayland 
39749ab747fSPaolo Bonzini     trace_esp_write_response(s->status);
398042879fcSMark Cave-Ayland 
3998baa1472SMark Cave-Ayland     if (s->dma) {
4008baa1472SMark Cave-Ayland         esp_do_dma(s);
4018baa1472SMark Cave-Ayland     } else {
402e3922557SMark Cave-Ayland         buf[0] = s->status;
403e3922557SMark Cave-Ayland         buf[1] = 0;
404042879fcSMark Cave-Ayland 
405e3922557SMark Cave-Ayland         fifo8_reset(&s->fifo);
406e3922557SMark Cave-Ayland         fifo8_push_all(&s->fifo, buf, 2);
40749ab747fSPaolo Bonzini         s->rregs[ESP_RFLAGS] = 2;
40849ab747fSPaolo Bonzini         esp_raise_irq(s);
40949ab747fSPaolo Bonzini     }
4108baa1472SMark Cave-Ayland }
41149ab747fSPaolo Bonzini 
4125d02add4SMark Cave-Ayland static int esp_cdb_length(ESPState *s)
4135d02add4SMark Cave-Ayland {
4145d02add4SMark Cave-Ayland     const uint8_t *pbuf;
4155d02add4SMark Cave-Ayland     int cmdlen, len;
4165d02add4SMark Cave-Ayland 
4175d02add4SMark Cave-Ayland     cmdlen = fifo8_num_used(&s->cmdfifo);
4185d02add4SMark Cave-Ayland     if (cmdlen < s->cmdfifo_cdb_offset) {
4195d02add4SMark Cave-Ayland         return 0;
4205d02add4SMark Cave-Ayland     }
4215d02add4SMark Cave-Ayland 
4225d02add4SMark Cave-Ayland     pbuf = fifo8_peek_buf(&s->cmdfifo, cmdlen, NULL);
4235d02add4SMark Cave-Ayland     len = scsi_cdb_length((uint8_t *)&pbuf[s->cmdfifo_cdb_offset]);
4245d02add4SMark Cave-Ayland 
4255d02add4SMark Cave-Ayland     return len;
4265d02add4SMark Cave-Ayland }
4275d02add4SMark Cave-Ayland 
428004826d0SMark Cave-Ayland static void esp_dma_ti_check(ESPState *s)
42949ab747fSPaolo Bonzini {
430af74b3c1SMark Cave-Ayland     if (esp_get_tc(s) == 0 && fifo8_num_used(&s->fifo) < 2) {
431cf47a41eSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS;
43249ab747fSPaolo Bonzini         esp_raise_irq(s);
433af74b3c1SMark Cave-Ayland         esp_lower_drq(s);
434af74b3c1SMark Cave-Ayland     }
43549ab747fSPaolo Bonzini }
43649ab747fSPaolo Bonzini 
43749ab747fSPaolo Bonzini static void esp_do_dma(ESPState *s)
43849ab747fSPaolo Bonzini {
439023666daSMark Cave-Ayland     uint32_t len, cmdlen;
440023666daSMark Cave-Ayland     uint8_t buf[ESP_CMDFIFO_SZ];
44119e9afb1SMark Cave-Ayland     int n;
44249ab747fSPaolo Bonzini 
4436cc88d6bSMark Cave-Ayland     len = esp_get_tc(s);
444ad2725afSMark Cave-Ayland 
445ad2725afSMark Cave-Ayland     switch (esp_get_phase(s)) {
446ad2725afSMark Cave-Ayland     case STAT_MO:
44746b0c361SMark Cave-Ayland         if (s->dma_memory_read) {
44846b0c361SMark Cave-Ayland             len = MIN(len, fifo8_num_free(&s->cmdfifo));
44946b0c361SMark Cave-Ayland             s->dma_memory_read(s->dma_opaque, buf, len);
45046b0c361SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
45146b0c361SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
45246b0c361SMark Cave-Ayland             s->cmdfifo_cdb_offset += len;
45346b0c361SMark Cave-Ayland         } else {
45446b0c361SMark Cave-Ayland             n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
45546b0c361SMark Cave-Ayland             n = MIN(fifo8_num_free(&s->cmdfifo), n);
45646b0c361SMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, n);
45746b0c361SMark Cave-Ayland             s->cmdfifo_cdb_offset += n;
45846b0c361SMark Cave-Ayland         }
45946b0c361SMark Cave-Ayland 
46046b0c361SMark Cave-Ayland         esp_raise_drq(s);
46146b0c361SMark Cave-Ayland 
4623ee9a475SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
4633ee9a475SMark Cave-Ayland         case CMD_SELATN | CMD_DMA:
4643ee9a475SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
4653ee9a475SMark Cave-Ayland                 /* First byte received, switch to command phase */
4663ee9a475SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
4673ee9a475SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
4683ee9a475SMark Cave-Ayland 
4693ee9a475SMark Cave-Ayland                 if (fifo8_num_used(&s->cmdfifo) > 1) {
4703ee9a475SMark Cave-Ayland                     /* Process any additional command phase data */
4713ee9a475SMark Cave-Ayland                     esp_do_dma(s);
4723ee9a475SMark Cave-Ayland                 }
4733ee9a475SMark Cave-Ayland             }
4743ee9a475SMark Cave-Ayland             break;
4753ee9a475SMark Cave-Ayland 
476db4d4150SMark Cave-Ayland         case CMD_SELATNS | CMD_DMA:
477db4d4150SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) == 1) {
478db4d4150SMark Cave-Ayland                 /* First byte received, stop in message out phase */
479db4d4150SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
480db4d4150SMark Cave-Ayland 
481db4d4150SMark Cave-Ayland                 /* Raise command completion interrupt */
482db4d4150SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
483db4d4150SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_CD;
484db4d4150SMark Cave-Ayland                 esp_raise_irq(s);
485db4d4150SMark Cave-Ayland             }
486db4d4150SMark Cave-Ayland             break;
487db4d4150SMark Cave-Ayland 
4883fd325a2SMark Cave-Ayland         case CMD_TI | CMD_DMA:
48946b0c361SMark Cave-Ayland             /* ATN remains asserted until TC == 0 */
49046b0c361SMark Cave-Ayland             if (esp_get_tc(s) == 0) {
49146b0c361SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
492cb22ce50SMark Cave-Ayland                 s->rregs[ESP_CMD] = 0;
49346b0c361SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_CD;
49446b0c361SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS;
49546b0c361SMark Cave-Ayland                 esp_raise_irq(s);
49646b0c361SMark Cave-Ayland             }
49746b0c361SMark Cave-Ayland             break;
4983fd325a2SMark Cave-Ayland         }
4993fd325a2SMark Cave-Ayland         break;
50046b0c361SMark Cave-Ayland 
501ad2725afSMark Cave-Ayland     case STAT_CD:
502023666daSMark Cave-Ayland         cmdlen = fifo8_num_used(&s->cmdfifo);
503023666daSMark Cave-Ayland         trace_esp_do_dma(cmdlen, len);
50474d71ea1SLaurent Vivier         if (s->dma_memory_read) {
5050ebb5fd8SMark Cave-Ayland             len = MIN(len, fifo8_num_free(&s->cmdfifo));
506023666daSMark Cave-Ayland             s->dma_memory_read(s->dma_opaque, buf, len);
507023666daSMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, len);
508a0347651SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
50974d71ea1SLaurent Vivier         } else {
5103c7f3c8bSMark Cave-Ayland             n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
5113c7f3c8bSMark Cave-Ayland             n = MIN(fifo8_num_free(&s->cmdfifo), n);
5123c7f3c8bSMark Cave-Ayland             fifo8_push_all(&s->cmdfifo, buf, n);
5133c7f3c8bSMark Cave-Ayland 
51474d71ea1SLaurent Vivier             esp_raise_drq(s);
5153c7f3c8bSMark Cave-Ayland         }
516023666daSMark Cave-Ayland         trace_esp_handle_ti_cmd(cmdlen);
51715407433SLaurent Vivier         s->ti_size = 0;
51846b0c361SMark Cave-Ayland         if (esp_get_tc(s) == 0) {
519799d90d8SMark Cave-Ayland             /* Command has been received */
520c959f218SMark Cave-Ayland             do_cmd(s);
521799d90d8SMark Cave-Ayland         }
522ad2725afSMark Cave-Ayland         break;
5231454dc76SMark Cave-Ayland 
5241454dc76SMark Cave-Ayland     case STAT_DO:
5250db89536SMark Cave-Ayland         if (!s->current_req) {
5260db89536SMark Cave-Ayland             return;
5270db89536SMark Cave-Ayland         }
5284460b86aSMark Cave-Ayland         if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
52949ab747fSPaolo Bonzini             /* Defer until data is available.  */
53049ab747fSPaolo Bonzini             return;
53149ab747fSPaolo Bonzini         }
53249ab747fSPaolo Bonzini         if (len > s->async_len) {
53349ab747fSPaolo Bonzini             len = s->async_len;
53449ab747fSPaolo Bonzini         }
53574d71ea1SLaurent Vivier         if (s->dma_memory_read) {
53649ab747fSPaolo Bonzini             s->dma_memory_read(s->dma_opaque, s->async_buf, len);
537f3666223SMark Cave-Ayland 
538f3666223SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
539f3666223SMark Cave-Ayland             s->async_buf += len;
540f3666223SMark Cave-Ayland             s->async_len -= len;
541f3666223SMark Cave-Ayland             s->ti_size += len;
542f3666223SMark Cave-Ayland 
543e4e166c8SMark Cave-Ayland             if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
544e4e166c8SMark Cave-Ayland                 /* Defer until the scsi layer has completed */
545f3666223SMark Cave-Ayland                 scsi_req_continue(s->current_req);
546f3666223SMark Cave-Ayland                 return;
547f3666223SMark Cave-Ayland             }
548f3666223SMark Cave-Ayland 
549004826d0SMark Cave-Ayland             esp_dma_ti_check(s);
55049ab747fSPaolo Bonzini         } else {
55119e9afb1SMark Cave-Ayland             /* Copy FIFO data to device */
55219e9afb1SMark Cave-Ayland             len = MIN(s->async_len, ESP_FIFO_SZ);
55319e9afb1SMark Cave-Ayland             len = MIN(len, fifo8_num_used(&s->fifo));
55419e9afb1SMark Cave-Ayland             n = esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
55519e9afb1SMark Cave-Ayland             s->async_buf += n;
55619e9afb1SMark Cave-Ayland             s->async_len -= n;
55719e9afb1SMark Cave-Ayland             s->ti_size += n;
55819e9afb1SMark Cave-Ayland 
55974d71ea1SLaurent Vivier             esp_raise_drq(s);
560e4e166c8SMark Cave-Ayland 
561e4e166c8SMark Cave-Ayland             if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
562e4e166c8SMark Cave-Ayland                 /* Defer until the scsi layer has completed */
563e4e166c8SMark Cave-Ayland                 scsi_req_continue(s->current_req);
564e4e166c8SMark Cave-Ayland                 return;
565e4e166c8SMark Cave-Ayland             }
566e4e166c8SMark Cave-Ayland 
567004826d0SMark Cave-Ayland             esp_dma_ti_check(s);
56874d71ea1SLaurent Vivier         }
5691454dc76SMark Cave-Ayland         break;
5701454dc76SMark Cave-Ayland 
5711454dc76SMark Cave-Ayland     case STAT_DI:
5721454dc76SMark Cave-Ayland         if (!s->current_req) {
5731454dc76SMark Cave-Ayland             return;
5741454dc76SMark Cave-Ayland         }
5751454dc76SMark Cave-Ayland         if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
5761454dc76SMark Cave-Ayland             /* Defer until data is available.  */
5771454dc76SMark Cave-Ayland             return;
5781454dc76SMark Cave-Ayland         }
5791454dc76SMark Cave-Ayland         if (len > s->async_len) {
5801454dc76SMark Cave-Ayland             len = s->async_len;
5811454dc76SMark Cave-Ayland         }
58274d71ea1SLaurent Vivier         if (s->dma_memory_write) {
58349ab747fSPaolo Bonzini             s->dma_memory_write(s->dma_opaque, s->async_buf, len);
584f3666223SMark Cave-Ayland 
585f3666223SMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
586f3666223SMark Cave-Ayland             s->async_buf += len;
587f3666223SMark Cave-Ayland             s->async_len -= len;
588f3666223SMark Cave-Ayland             s->ti_size -= len;
589f3666223SMark Cave-Ayland 
590e4e166c8SMark Cave-Ayland             if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
591e4e166c8SMark Cave-Ayland                 /* Defer until the scsi layer has completed */
592f3666223SMark Cave-Ayland                 scsi_req_continue(s->current_req);
593fabcba49SMark Cave-Ayland                 return;
594f3666223SMark Cave-Ayland             }
595f3666223SMark Cave-Ayland 
596004826d0SMark Cave-Ayland             esp_dma_ti_check(s);
59774d71ea1SLaurent Vivier         } else {
59882141c8bSMark Cave-Ayland             /* Copy device data to FIFO */
599042879fcSMark Cave-Ayland             len = MIN(len, fifo8_num_free(&s->fifo));
600042879fcSMark Cave-Ayland             fifo8_push_all(&s->fifo, s->async_buf, len);
60182141c8bSMark Cave-Ayland             s->async_buf += len;
60282141c8bSMark Cave-Ayland             s->async_len -= len;
60382141c8bSMark Cave-Ayland             s->ti_size -= len;
60482141c8bSMark Cave-Ayland             esp_set_tc(s, esp_get_tc(s) - len);
60574d71ea1SLaurent Vivier             esp_raise_drq(s);
606e4e166c8SMark Cave-Ayland 
607e4e166c8SMark Cave-Ayland             if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) {
608e4e166c8SMark Cave-Ayland                 /* Defer until the scsi layer has completed */
609e4e166c8SMark Cave-Ayland                 scsi_req_continue(s->current_req);
610e4e166c8SMark Cave-Ayland                 return;
611e4e166c8SMark Cave-Ayland             }
612e4e166c8SMark Cave-Ayland 
613004826d0SMark Cave-Ayland             esp_dma_ti_check(s);
614e4e166c8SMark Cave-Ayland         }
6151454dc76SMark Cave-Ayland         break;
6168baa1472SMark Cave-Ayland 
6178baa1472SMark Cave-Ayland     case STAT_ST:
6188baa1472SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
6198baa1472SMark Cave-Ayland         case CMD_ICCS | CMD_DMA:
6208baa1472SMark Cave-Ayland             len = MIN(len, 1);
6218baa1472SMark Cave-Ayland 
6228baa1472SMark Cave-Ayland             if (len) {
6238baa1472SMark Cave-Ayland                 buf[0] = s->status;
6248baa1472SMark Cave-Ayland 
6258baa1472SMark Cave-Ayland                 if (s->dma_memory_write) {
6268baa1472SMark Cave-Ayland                     s->dma_memory_write(s->dma_opaque, buf, len);
6278baa1472SMark Cave-Ayland                     esp_set_tc(s, esp_get_tc(s) - len);
6288baa1472SMark Cave-Ayland                 } else {
6298baa1472SMark Cave-Ayland                     fifo8_push_all(&s->fifo, buf, len);
6308baa1472SMark Cave-Ayland                     esp_set_tc(s, esp_get_tc(s) - len);
6318baa1472SMark Cave-Ayland                 }
6328baa1472SMark Cave-Ayland 
6338baa1472SMark Cave-Ayland                 esp_set_phase(s, STAT_MI);
6348baa1472SMark Cave-Ayland 
6358baa1472SMark Cave-Ayland                 if (esp_get_tc(s) > 0) {
6368baa1472SMark Cave-Ayland                     /* Process any message in phase data */
6378baa1472SMark Cave-Ayland                     esp_do_dma(s);
6388baa1472SMark Cave-Ayland                 }
6398baa1472SMark Cave-Ayland             }
6408baa1472SMark Cave-Ayland             break;
6418baa1472SMark Cave-Ayland         }
6428baa1472SMark Cave-Ayland         break;
6438baa1472SMark Cave-Ayland 
6448baa1472SMark Cave-Ayland     case STAT_MI:
6458baa1472SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
6468baa1472SMark Cave-Ayland         case CMD_ICCS | CMD_DMA:
6478baa1472SMark Cave-Ayland             len = MIN(len, 1);
6488baa1472SMark Cave-Ayland 
6498baa1472SMark Cave-Ayland             if (len) {
6508baa1472SMark Cave-Ayland                 buf[0] = 0;
6518baa1472SMark Cave-Ayland 
6528baa1472SMark Cave-Ayland                 if (s->dma_memory_write) {
6538baa1472SMark Cave-Ayland                     s->dma_memory_write(s->dma_opaque, buf, len);
6548baa1472SMark Cave-Ayland                     esp_set_tc(s, esp_get_tc(s) - len);
6558baa1472SMark Cave-Ayland                 } else {
6568baa1472SMark Cave-Ayland                     fifo8_push_all(&s->fifo, buf, len);
6578baa1472SMark Cave-Ayland                     esp_set_tc(s, esp_get_tc(s) - len);
6588baa1472SMark Cave-Ayland                 }
6598baa1472SMark Cave-Ayland 
6608baa1472SMark Cave-Ayland                 /* Raise end of command interrupt */
6618baa1472SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
6628baa1472SMark Cave-Ayland                 s->rregs[ESP_RSEQ] = SEQ_CD;
6638baa1472SMark Cave-Ayland                 esp_raise_irq(s);
6648baa1472SMark Cave-Ayland             }
6658baa1472SMark Cave-Ayland             break;
6668baa1472SMark Cave-Ayland         }
6678baa1472SMark Cave-Ayland         break;
66874d71ea1SLaurent Vivier     }
66949ab747fSPaolo Bonzini }
67049ab747fSPaolo Bonzini 
671a1b8d389SMark Cave-Ayland static void esp_nodma_ti_dataout(ESPState *s)
672a1b8d389SMark Cave-Ayland {
673a1b8d389SMark Cave-Ayland     int len;
674a1b8d389SMark Cave-Ayland 
675a1b8d389SMark Cave-Ayland     if (!s->current_req) {
676a1b8d389SMark Cave-Ayland         return;
677a1b8d389SMark Cave-Ayland     }
678a1b8d389SMark Cave-Ayland     if (s->async_len == 0) {
679a1b8d389SMark Cave-Ayland         /* Defer until data is available.  */
680a1b8d389SMark Cave-Ayland         return;
681a1b8d389SMark Cave-Ayland     }
682a1b8d389SMark Cave-Ayland     len = MIN(s->async_len, ESP_FIFO_SZ);
683a1b8d389SMark Cave-Ayland     len = MIN(len, fifo8_num_used(&s->fifo));
684a1b8d389SMark Cave-Ayland     esp_fifo_pop_buf(&s->fifo, s->async_buf, len);
685a1b8d389SMark Cave-Ayland     s->async_buf += len;
686a1b8d389SMark Cave-Ayland     s->async_len -= len;
687a1b8d389SMark Cave-Ayland     s->ti_size += len;
688a1b8d389SMark Cave-Ayland 
689a1b8d389SMark Cave-Ayland     if (s->async_len == 0) {
690a1b8d389SMark Cave-Ayland         scsi_req_continue(s->current_req);
691a1b8d389SMark Cave-Ayland         return;
692a1b8d389SMark Cave-Ayland     }
693a1b8d389SMark Cave-Ayland 
694a1b8d389SMark Cave-Ayland     s->rregs[ESP_RINTR] |= INTR_BS;
695a1b8d389SMark Cave-Ayland     esp_raise_irq(s);
696a1b8d389SMark Cave-Ayland }
697a1b8d389SMark Cave-Ayland 
6981b9e48a5SMark Cave-Ayland static void esp_do_nodma(ESPState *s)
6991b9e48a5SMark Cave-Ayland {
7002572689bSMark Cave-Ayland     uint8_t buf[ESP_FIFO_SZ];
7017b320a8eSMark Cave-Ayland     uint32_t cmdlen;
702a1b8d389SMark Cave-Ayland     int n;
7031b9e48a5SMark Cave-Ayland 
70483e803deSMark Cave-Ayland     switch (esp_get_phase(s)) {
70583e803deSMark Cave-Ayland     case STAT_MO:
7062572689bSMark Cave-Ayland         /* Copy FIFO into cmdfifo */
7072572689bSMark Cave-Ayland         n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
7082572689bSMark Cave-Ayland         n = MIN(fifo8_num_free(&s->cmdfifo), n);
7092572689bSMark Cave-Ayland         fifo8_push_all(&s->cmdfifo, buf, n);
71079a6c7c6SMark Cave-Ayland         s->cmdfifo_cdb_offset += n;
7112572689bSMark Cave-Ayland 
7125d02add4SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
7135d02add4SMark Cave-Ayland         case CMD_SELATN:
7145d02add4SMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
7155d02add4SMark Cave-Ayland                 /* First byte received, switch to command phase */
7165d02add4SMark Cave-Ayland                 esp_set_phase(s, STAT_CD);
7175d02add4SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
7185d02add4SMark Cave-Ayland 
7195d02add4SMark Cave-Ayland                 if (fifo8_num_used(&s->cmdfifo) > 1) {
7205d02add4SMark Cave-Ayland                     /* Process any additional command phase data */
7215d02add4SMark Cave-Ayland                     esp_do_nodma(s);
7225d02add4SMark Cave-Ayland                 }
7235d02add4SMark Cave-Ayland             }
7245d02add4SMark Cave-Ayland             break;
7255d02add4SMark Cave-Ayland 
7265d02add4SMark Cave-Ayland         case CMD_SELATNS:
727*d39592ffSMark Cave-Ayland             if (fifo8_num_used(&s->cmdfifo) >= 1) {
7285d02add4SMark Cave-Ayland                 /* First byte received, stop in message out phase */
7295d02add4SMark Cave-Ayland                 s->cmdfifo_cdb_offset = 1;
7305d02add4SMark Cave-Ayland 
7315d02add4SMark Cave-Ayland                 /* Raise command completion interrupt */
7325d02add4SMark Cave-Ayland                 s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
7335d02add4SMark Cave-Ayland                 esp_raise_irq(s);
7345d02add4SMark Cave-Ayland             }
7355d02add4SMark Cave-Ayland             break;
7365d02add4SMark Cave-Ayland 
7375d02add4SMark Cave-Ayland         case CMD_TI:
7385d02add4SMark Cave-Ayland             /* ATN remains asserted until FIFO empty */
7391b9e48a5SMark Cave-Ayland             s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo);
740abc139cdSMark Cave-Ayland             esp_set_phase(s, STAT_CD);
741cb22ce50SMark Cave-Ayland             s->rregs[ESP_CMD] = 0;
7421b9e48a5SMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_BS;
7431b9e48a5SMark Cave-Ayland             esp_raise_irq(s);
74479a6c7c6SMark Cave-Ayland             break;
7455d02add4SMark Cave-Ayland         }
7465d02add4SMark Cave-Ayland         break;
74779a6c7c6SMark Cave-Ayland 
74879a6c7c6SMark Cave-Ayland     case STAT_CD:
74979a6c7c6SMark Cave-Ayland         /* Copy FIFO into cmdfifo */
75079a6c7c6SMark Cave-Ayland         n = esp_fifo_pop_buf(&s->fifo, buf, fifo8_num_used(&s->fifo));
75179a6c7c6SMark Cave-Ayland         n = MIN(fifo8_num_free(&s->cmdfifo), n);
75279a6c7c6SMark Cave-Ayland         fifo8_push_all(&s->cmdfifo, buf, n);
75379a6c7c6SMark Cave-Ayland 
7545d02add4SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
7555d02add4SMark Cave-Ayland         case CMD_TI:
75679a6c7c6SMark Cave-Ayland             cmdlen = fifo8_num_used(&s->cmdfifo);
75779a6c7c6SMark Cave-Ayland             trace_esp_handle_ti_cmd(cmdlen);
75879a6c7c6SMark Cave-Ayland 
7595d02add4SMark Cave-Ayland             /* CDB may be transferred in one or more TI commands */
7605d02add4SMark Cave-Ayland             if (esp_cdb_length(s) && esp_cdb_length(s) ==
7615d02add4SMark Cave-Ayland                 fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset) {
76279a6c7c6SMark Cave-Ayland                     /* Command has been received */
76379a6c7c6SMark Cave-Ayland                     do_cmd(s);
7645d02add4SMark Cave-Ayland             } else {
7655d02add4SMark Cave-Ayland                 /*
7665d02add4SMark Cave-Ayland                  * If data was transferred from the FIFO then raise bus
7675d02add4SMark Cave-Ayland                  * service interrupt to indicate transfer complete. Otherwise
7685d02add4SMark Cave-Ayland                  * defer until the next FIFO write.
7695d02add4SMark Cave-Ayland                  */
7705d02add4SMark Cave-Ayland                 if (n) {
7715d02add4SMark Cave-Ayland                     /* Raise interrupt to indicate transfer complete */
7725d02add4SMark Cave-Ayland                     s->rregs[ESP_RINTR] |= INTR_BS;
7735d02add4SMark Cave-Ayland                     esp_raise_irq(s);
7745d02add4SMark Cave-Ayland                 }
7755d02add4SMark Cave-Ayland             }
7765d02add4SMark Cave-Ayland             break;
7775d02add4SMark Cave-Ayland 
7785d02add4SMark Cave-Ayland         case CMD_SEL:
7795d02add4SMark Cave-Ayland         case CMD_SELATN:
7805d02add4SMark Cave-Ayland             /* FIFO already contain entire CDB */
7815d02add4SMark Cave-Ayland             do_cmd(s);
7825d02add4SMark Cave-Ayland             break;
7835d02add4SMark Cave-Ayland         }
78483e803deSMark Cave-Ayland         break;
7851b9e48a5SMark Cave-Ayland 
7869d1aa52bSMark Cave-Ayland     case STAT_DO:
7875d02add4SMark Cave-Ayland         /* Accumulate data in FIFO until non-DMA TI is executed */
7889d1aa52bSMark Cave-Ayland         break;
7899d1aa52bSMark Cave-Ayland 
7909d1aa52bSMark Cave-Ayland     case STAT_DI:
7919d1aa52bSMark Cave-Ayland         if (!s->current_req) {
7929d1aa52bSMark Cave-Ayland             return;
7939d1aa52bSMark Cave-Ayland         }
7949d1aa52bSMark Cave-Ayland         if (s->async_len == 0) {
7959d1aa52bSMark Cave-Ayland             /* Defer until data is available.  */
7969d1aa52bSMark Cave-Ayland             return;
7979d1aa52bSMark Cave-Ayland         }
7986ef2cabcSMark Cave-Ayland         if (fifo8_is_empty(&s->fifo)) {
7996ef2cabcSMark Cave-Ayland             fifo8_push(&s->fifo, s->async_buf[0]);
8006ef2cabcSMark Cave-Ayland             s->async_buf++;
8016ef2cabcSMark Cave-Ayland             s->async_len--;
8026ef2cabcSMark Cave-Ayland             s->ti_size--;
8036ef2cabcSMark Cave-Ayland         }
8041b9e48a5SMark Cave-Ayland 
8051b9e48a5SMark Cave-Ayland         if (s->async_len == 0) {
8061b9e48a5SMark Cave-Ayland             scsi_req_continue(s->current_req);
8071b9e48a5SMark Cave-Ayland             return;
8081b9e48a5SMark Cave-Ayland         }
8091b9e48a5SMark Cave-Ayland 
8109655f72cSMark Cave-Ayland         /* If preloading the FIFO, defer until TI command issued */
8119655f72cSMark Cave-Ayland         if (s->rregs[ESP_CMD] != CMD_TI) {
8129655f72cSMark Cave-Ayland             return;
8139655f72cSMark Cave-Ayland         }
8149655f72cSMark Cave-Ayland 
8151b9e48a5SMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS;
8161b9e48a5SMark Cave-Ayland         esp_raise_irq(s);
8179d1aa52bSMark Cave-Ayland         break;
8189d1aa52bSMark Cave-Ayland     }
8191b9e48a5SMark Cave-Ayland }
8201b9e48a5SMark Cave-Ayland 
8214aaa6ac3SMark Cave-Ayland void esp_command_complete(SCSIRequest *req, size_t resid)
82249ab747fSPaolo Bonzini {
8234aaa6ac3SMark Cave-Ayland     ESPState *s = req->hba_private;
8245a83e83eSMark Cave-Ayland     int to_device = (esp_get_phase(s) == STAT_DO);
8254aaa6ac3SMark Cave-Ayland 
82649ab747fSPaolo Bonzini     trace_esp_command_complete();
8276ef2cabcSMark Cave-Ayland 
8286ef2cabcSMark Cave-Ayland     /*
8296ef2cabcSMark Cave-Ayland      * Non-DMA transfers from the target will leave the last byte in
8306ef2cabcSMark Cave-Ayland      * the FIFO so don't reset ti_size in this case
8316ef2cabcSMark Cave-Ayland      */
8326ef2cabcSMark Cave-Ayland     if (s->dma || to_device) {
83349ab747fSPaolo Bonzini         if (s->ti_size != 0) {
83449ab747fSPaolo Bonzini             trace_esp_command_complete_unexpected();
83549ab747fSPaolo Bonzini         }
8366ef2cabcSMark Cave-Ayland     }
8376ef2cabcSMark Cave-Ayland 
83849ab747fSPaolo Bonzini     s->async_len = 0;
8394aaa6ac3SMark Cave-Ayland     if (req->status) {
84049ab747fSPaolo Bonzini         trace_esp_command_complete_fail();
84149ab747fSPaolo Bonzini     }
8424aaa6ac3SMark Cave-Ayland     s->status = req->status;
8436ef2cabcSMark Cave-Ayland 
8446ef2cabcSMark Cave-Ayland     /*
845cb988199SMark Cave-Ayland      * Switch to status phase. For non-DMA transfers from the target the last
846cb988199SMark Cave-Ayland      * byte is still in the FIFO
8476ef2cabcSMark Cave-Ayland      */
8488bb22495SMark Cave-Ayland     s->ti_size = 0;
8498bb22495SMark Cave-Ayland 
8508bb22495SMark Cave-Ayland     switch (s->rregs[ESP_CMD]) {
8518bb22495SMark Cave-Ayland     case CMD_SEL | CMD_DMA:
8528bb22495SMark Cave-Ayland     case CMD_SEL:
8538bb22495SMark Cave-Ayland     case CMD_SELATN | CMD_DMA:
8548bb22495SMark Cave-Ayland     case CMD_SELATN:
855cb988199SMark Cave-Ayland         /*
8568bb22495SMark Cave-Ayland          * No data phase for sequencer command so raise deferred bus service
857c90b2792SMark Cave-Ayland          * and function complete interrupt
858cb988199SMark Cave-Ayland          */
859c90b2792SMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
8608bb22495SMark Cave-Ayland         break;
861cb22ce50SMark Cave-Ayland 
862cb22ce50SMark Cave-Ayland     case CMD_TI | CMD_DMA:
863cb22ce50SMark Cave-Ayland     case CMD_TI:
864cb22ce50SMark Cave-Ayland         s->rregs[ESP_CMD] = 0;
865cb22ce50SMark Cave-Ayland         break;
8666ef2cabcSMark Cave-Ayland     }
8676ef2cabcSMark Cave-Ayland 
8688bb22495SMark Cave-Ayland     /* Raise bus service interrupt to indicate change to STATUS phase */
8698bb22495SMark Cave-Ayland     esp_set_phase(s, STAT_ST);
8708bb22495SMark Cave-Ayland     s->rregs[ESP_RINTR] |= INTR_BS;
8718bb22495SMark Cave-Ayland     esp_raise_irq(s);
8728bb22495SMark Cave-Ayland     esp_lower_drq(s);
8738bb22495SMark Cave-Ayland 
87449ab747fSPaolo Bonzini     if (s->current_req) {
87549ab747fSPaolo Bonzini         scsi_req_unref(s->current_req);
87649ab747fSPaolo Bonzini         s->current_req = NULL;
87749ab747fSPaolo Bonzini         s->current_dev = NULL;
87849ab747fSPaolo Bonzini     }
87949ab747fSPaolo Bonzini }
88049ab747fSPaolo Bonzini 
88149ab747fSPaolo Bonzini void esp_transfer_data(SCSIRequest *req, uint32_t len)
88249ab747fSPaolo Bonzini {
88349ab747fSPaolo Bonzini     ESPState *s = req->hba_private;
8846cc88d6bSMark Cave-Ayland     uint32_t dmalen = esp_get_tc(s);
88549ab747fSPaolo Bonzini 
8866cc88d6bSMark Cave-Ayland     trace_esp_transfer_data(dmalen, s->ti_size);
88749ab747fSPaolo Bonzini     s->async_len = len;
88849ab747fSPaolo Bonzini     s->async_buf = scsi_req_get_buf(req);
8894e78f3bfSMark Cave-Ayland 
890c90b2792SMark Cave-Ayland     if (!s->data_ready) {
891a4608fa0SMark Cave-Ayland         s->data_ready = true;
892a4608fa0SMark Cave-Ayland 
893a4608fa0SMark Cave-Ayland         switch (s->rregs[ESP_CMD]) {
894a4608fa0SMark Cave-Ayland         case CMD_SEL | CMD_DMA:
895a4608fa0SMark Cave-Ayland         case CMD_SEL:
896a4608fa0SMark Cave-Ayland         case CMD_SELATN | CMD_DMA:
897a4608fa0SMark Cave-Ayland         case CMD_SELATN:
898c90b2792SMark Cave-Ayland             /*
899c90b2792SMark Cave-Ayland              * Initial incoming data xfer is complete for sequencer command
900c90b2792SMark Cave-Ayland              * so raise deferred bus service and function complete interrupt
901c90b2792SMark Cave-Ayland              */
902c90b2792SMark Cave-Ayland              s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC;
903c90b2792SMark Cave-Ayland              break;
904c90b2792SMark Cave-Ayland 
905a4608fa0SMark Cave-Ayland         case CMD_SELATNS | CMD_DMA:
906a4608fa0SMark Cave-Ayland         case CMD_SELATNS:
9074e78f3bfSMark Cave-Ayland             /*
9084e78f3bfSMark Cave-Ayland              * Initial incoming data xfer is complete so raise command
9094e78f3bfSMark Cave-Ayland              * completion interrupt
9104e78f3bfSMark Cave-Ayland              */
9114e78f3bfSMark Cave-Ayland              s->rregs[ESP_RINTR] |= INTR_BS;
912a4608fa0SMark Cave-Ayland              break;
913a4608fa0SMark Cave-Ayland 
914a4608fa0SMark Cave-Ayland         case CMD_TI | CMD_DMA:
915a4608fa0SMark Cave-Ayland         case CMD_TI:
916a4608fa0SMark Cave-Ayland             /*
917a4608fa0SMark Cave-Ayland              * Bus service interrupt raised because of initial change to
918a4608fa0SMark Cave-Ayland              * DATA phase
919a4608fa0SMark Cave-Ayland              */
920cb22ce50SMark Cave-Ayland             s->rregs[ESP_CMD] = 0;
921a4608fa0SMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_BS;
922a4608fa0SMark Cave-Ayland             break;
923a4608fa0SMark Cave-Ayland         }
924c90b2792SMark Cave-Ayland 
925c90b2792SMark Cave-Ayland         esp_raise_irq(s);
9264e78f3bfSMark Cave-Ayland     }
9274e78f3bfSMark Cave-Ayland 
9281b9e48a5SMark Cave-Ayland     /*
9291b9e48a5SMark Cave-Ayland      * Always perform the initial transfer upon reception of the next TI
9301b9e48a5SMark Cave-Ayland      * command to ensure the DMA/non-DMA status of the command is correct.
9311b9e48a5SMark Cave-Ayland      * It is not possible to use s->dma directly in the section below as
9321b9e48a5SMark Cave-Ayland      * some OSs send non-DMA NOP commands after a DMA transfer. Hence if the
9331b9e48a5SMark Cave-Ayland      * async data transfer is delayed then s->dma is set incorrectly.
9341b9e48a5SMark Cave-Ayland      */
9351b9e48a5SMark Cave-Ayland 
93682003450SMark Cave-Ayland     if (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA)) {
937a79e767aSMark Cave-Ayland         /* When the SCSI layer returns more data, raise deferred INTR_BS */
938004826d0SMark Cave-Ayland         esp_dma_ti_check(s);
939a79e767aSMark Cave-Ayland 
940a79e767aSMark Cave-Ayland         esp_do_dma(s);
94182003450SMark Cave-Ayland     } else if (s->rregs[ESP_CMD] == CMD_TI) {
9421b9e48a5SMark Cave-Ayland         esp_do_nodma(s);
9431b9e48a5SMark Cave-Ayland     }
94449ab747fSPaolo Bonzini }
94549ab747fSPaolo Bonzini 
94649ab747fSPaolo Bonzini static void handle_ti(ESPState *s)
94749ab747fSPaolo Bonzini {
9481b9e48a5SMark Cave-Ayland     uint32_t dmalen;
94949ab747fSPaolo Bonzini 
95049ab747fSPaolo Bonzini     if (s->dma && !s->dma_enabled) {
95149ab747fSPaolo Bonzini         s->dma_cb = handle_ti;
95249ab747fSPaolo Bonzini         return;
95349ab747fSPaolo Bonzini     }
95449ab747fSPaolo Bonzini 
95549ab747fSPaolo Bonzini     if (s->dma) {
9561b9e48a5SMark Cave-Ayland         dmalen = esp_get_tc(s);
957b76624deSMark Cave-Ayland         trace_esp_handle_ti(dmalen);
95849ab747fSPaolo Bonzini         esp_do_dma(s);
959799d90d8SMark Cave-Ayland     } else {
9601b9e48a5SMark Cave-Ayland         trace_esp_handle_ti(s->ti_size);
9611b9e48a5SMark Cave-Ayland         esp_do_nodma(s);
9625d02add4SMark Cave-Ayland 
9635d02add4SMark Cave-Ayland         if (esp_get_phase(s) == STAT_DO) {
9645d02add4SMark Cave-Ayland             esp_nodma_ti_dataout(s);
9655d02add4SMark Cave-Ayland         }
96649ab747fSPaolo Bonzini     }
96749ab747fSPaolo Bonzini }
96849ab747fSPaolo Bonzini 
96949ab747fSPaolo Bonzini void esp_hard_reset(ESPState *s)
97049ab747fSPaolo Bonzini {
97149ab747fSPaolo Bonzini     memset(s->rregs, 0, ESP_REGS);
97249ab747fSPaolo Bonzini     memset(s->wregs, 0, ESP_REGS);
973c9cf45c1SHannes Reinecke     s->tchi_written = 0;
97449ab747fSPaolo Bonzini     s->ti_size = 0;
9753f26c975SMark Cave-Ayland     s->async_len = 0;
976042879fcSMark Cave-Ayland     fifo8_reset(&s->fifo);
977023666daSMark Cave-Ayland     fifo8_reset(&s->cmdfifo);
97849ab747fSPaolo Bonzini     s->dma = 0;
97949ab747fSPaolo Bonzini     s->dma_cb = NULL;
98049ab747fSPaolo Bonzini 
98149ab747fSPaolo Bonzini     s->rregs[ESP_CFG1] = 7;
98249ab747fSPaolo Bonzini }
98349ab747fSPaolo Bonzini 
98449ab747fSPaolo Bonzini static void esp_soft_reset(ESPState *s)
98549ab747fSPaolo Bonzini {
98649ab747fSPaolo Bonzini     qemu_irq_lower(s->irq);
98774d71ea1SLaurent Vivier     qemu_irq_lower(s->irq_data);
98849ab747fSPaolo Bonzini     esp_hard_reset(s);
98949ab747fSPaolo Bonzini }
99049ab747fSPaolo Bonzini 
991c6e51f1bSJohn Millikin static void esp_bus_reset(ESPState *s)
992c6e51f1bSJohn Millikin {
9934a5fc890SPeter Maydell     bus_cold_reset(BUS(&s->bus));
994c6e51f1bSJohn Millikin }
995c6e51f1bSJohn Millikin 
99649ab747fSPaolo Bonzini static void parent_esp_reset(ESPState *s, int irq, int level)
99749ab747fSPaolo Bonzini {
99849ab747fSPaolo Bonzini     if (level) {
99949ab747fSPaolo Bonzini         esp_soft_reset(s);
100049ab747fSPaolo Bonzini     }
100149ab747fSPaolo Bonzini }
100249ab747fSPaolo Bonzini 
1003f21fe39dSMark Cave-Ayland static void esp_run_cmd(ESPState *s)
1004f21fe39dSMark Cave-Ayland {
1005f21fe39dSMark Cave-Ayland     uint8_t cmd = s->rregs[ESP_CMD];
1006f21fe39dSMark Cave-Ayland 
1007f21fe39dSMark Cave-Ayland     if (cmd & CMD_DMA) {
1008f21fe39dSMark Cave-Ayland         s->dma = 1;
1009f21fe39dSMark Cave-Ayland         /* Reload DMA counter.  */
1010f21fe39dSMark Cave-Ayland         if (esp_get_stc(s) == 0) {
1011f21fe39dSMark Cave-Ayland             esp_set_tc(s, 0x10000);
1012f21fe39dSMark Cave-Ayland         } else {
1013f21fe39dSMark Cave-Ayland             esp_set_tc(s, esp_get_stc(s));
1014f21fe39dSMark Cave-Ayland         }
1015f21fe39dSMark Cave-Ayland     } else {
1016f21fe39dSMark Cave-Ayland         s->dma = 0;
1017f21fe39dSMark Cave-Ayland     }
1018f21fe39dSMark Cave-Ayland     switch (cmd & CMD_CMD) {
1019f21fe39dSMark Cave-Ayland     case CMD_NOP:
1020f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_nop(cmd);
1021f21fe39dSMark Cave-Ayland         break;
1022f21fe39dSMark Cave-Ayland     case CMD_FLUSH:
1023f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_flush(cmd);
1024f21fe39dSMark Cave-Ayland         fifo8_reset(&s->fifo);
1025f21fe39dSMark Cave-Ayland         break;
1026f21fe39dSMark Cave-Ayland     case CMD_RESET:
1027f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_reset(cmd);
1028f21fe39dSMark Cave-Ayland         esp_soft_reset(s);
1029f21fe39dSMark Cave-Ayland         break;
1030f21fe39dSMark Cave-Ayland     case CMD_BUSRESET:
1031f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_bus_reset(cmd);
1032f21fe39dSMark Cave-Ayland         esp_bus_reset(s);
1033f21fe39dSMark Cave-Ayland         if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1034f21fe39dSMark Cave-Ayland             s->rregs[ESP_RINTR] |= INTR_RST;
1035f21fe39dSMark Cave-Ayland             esp_raise_irq(s);
1036f21fe39dSMark Cave-Ayland         }
1037f21fe39dSMark Cave-Ayland         break;
1038f21fe39dSMark Cave-Ayland     case CMD_TI:
1039f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_ti(cmd);
1040f21fe39dSMark Cave-Ayland         handle_ti(s);
1041f21fe39dSMark Cave-Ayland         break;
1042f21fe39dSMark Cave-Ayland     case CMD_ICCS:
1043f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_iccs(cmd);
1044f21fe39dSMark Cave-Ayland         write_response(s);
1045f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_FC;
1046abc139cdSMark Cave-Ayland         esp_set_phase(s, STAT_MI);
1047f21fe39dSMark Cave-Ayland         break;
1048f21fe39dSMark Cave-Ayland     case CMD_MSGACC:
1049f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_msgacc(cmd);
1050f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_DC;
1051f21fe39dSMark Cave-Ayland         s->rregs[ESP_RSEQ] = 0;
1052f21fe39dSMark Cave-Ayland         s->rregs[ESP_RFLAGS] = 0;
1053f21fe39dSMark Cave-Ayland         esp_raise_irq(s);
1054f21fe39dSMark Cave-Ayland         break;
1055f21fe39dSMark Cave-Ayland     case CMD_PAD:
1056f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_pad(cmd);
1057f21fe39dSMark Cave-Ayland         s->rregs[ESP_RSTAT] = STAT_TC;
1058f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] |= INTR_FC;
1059f21fe39dSMark Cave-Ayland         s->rregs[ESP_RSEQ] = 0;
1060f21fe39dSMark Cave-Ayland         break;
1061f21fe39dSMark Cave-Ayland     case CMD_SATN:
1062f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_satn(cmd);
1063f21fe39dSMark Cave-Ayland         break;
1064f21fe39dSMark Cave-Ayland     case CMD_RSTATN:
1065f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_rstatn(cmd);
1066f21fe39dSMark Cave-Ayland         break;
1067f21fe39dSMark Cave-Ayland     case CMD_SEL:
1068f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_sel(cmd);
1069f21fe39dSMark Cave-Ayland         handle_s_without_atn(s);
1070f21fe39dSMark Cave-Ayland         break;
1071f21fe39dSMark Cave-Ayland     case CMD_SELATN:
1072f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_selatn(cmd);
1073f21fe39dSMark Cave-Ayland         handle_satn(s);
1074f21fe39dSMark Cave-Ayland         break;
1075f21fe39dSMark Cave-Ayland     case CMD_SELATNS:
1076f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_selatns(cmd);
1077f21fe39dSMark Cave-Ayland         handle_satn_stop(s);
1078f21fe39dSMark Cave-Ayland         break;
1079f21fe39dSMark Cave-Ayland     case CMD_ENSEL:
1080f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_ensel(cmd);
1081f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] = 0;
1082f21fe39dSMark Cave-Ayland         break;
1083f21fe39dSMark Cave-Ayland     case CMD_DISSEL:
1084f21fe39dSMark Cave-Ayland         trace_esp_mem_writeb_cmd_dissel(cmd);
1085f21fe39dSMark Cave-Ayland         s->rregs[ESP_RINTR] = 0;
1086f21fe39dSMark Cave-Ayland         esp_raise_irq(s);
1087f21fe39dSMark Cave-Ayland         break;
1088f21fe39dSMark Cave-Ayland     default:
1089f21fe39dSMark Cave-Ayland         trace_esp_error_unhandled_command(cmd);
1090f21fe39dSMark Cave-Ayland         break;
1091f21fe39dSMark Cave-Ayland     }
1092f21fe39dSMark Cave-Ayland }
1093f21fe39dSMark Cave-Ayland 
109449ab747fSPaolo Bonzini uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
109549ab747fSPaolo Bonzini {
1096b630c075SMark Cave-Ayland     uint32_t val;
109749ab747fSPaolo Bonzini 
109849ab747fSPaolo Bonzini     switch (saddr) {
109949ab747fSPaolo Bonzini     case ESP_FIFO:
11001b9e48a5SMark Cave-Ayland         if (s->dma_memory_read && s->dma_memory_write &&
11011b9e48a5SMark Cave-Ayland                 (s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
110249ab747fSPaolo Bonzini             /* Data out.  */
1103ff589551SPrasad J Pandit             qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
110449ab747fSPaolo Bonzini             s->rregs[ESP_FIFO] = 0;
1105042879fcSMark Cave-Ayland         } else {
1106c5fef911SMark Cave-Ayland             s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo);
110749ab747fSPaolo Bonzini         }
1108b630c075SMark Cave-Ayland         val = s->rregs[ESP_FIFO];
110949ab747fSPaolo Bonzini         break;
111049ab747fSPaolo Bonzini     case ESP_RINTR:
111194d5c79dSMark Cave-Ayland         /*
111294d5c79dSMark Cave-Ayland          * Clear sequence step, interrupt register and all status bits
111394d5c79dSMark Cave-Ayland          * except TC
111494d5c79dSMark Cave-Ayland          */
1115b630c075SMark Cave-Ayland         val = s->rregs[ESP_RINTR];
111649ab747fSPaolo Bonzini         s->rregs[ESP_RINTR] = 0;
111749ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1118af947a3dSMark Cave-Ayland         /*
1119af947a3dSMark Cave-Ayland          * According to the datasheet ESP_RSEQ should be cleared, but as the
1120af947a3dSMark Cave-Ayland          * emulation currently defers information transfers to the next TI
1121af947a3dSMark Cave-Ayland          * command leave it for now so that pedantic guests such as the old
1122af947a3dSMark Cave-Ayland          * Linux 2.6 driver see the correct flags before the next SCSI phase
1123af947a3dSMark Cave-Ayland          * transition.
1124af947a3dSMark Cave-Ayland          *
1125af947a3dSMark Cave-Ayland          * s->rregs[ESP_RSEQ] = SEQ_0;
1126af947a3dSMark Cave-Ayland          */
112749ab747fSPaolo Bonzini         esp_lower_irq(s);
1128b630c075SMark Cave-Ayland         break;
1129c9cf45c1SHannes Reinecke     case ESP_TCHI:
1130c9cf45c1SHannes Reinecke         /* Return the unique id if the value has never been written */
1131c9cf45c1SHannes Reinecke         if (!s->tchi_written) {
1132b630c075SMark Cave-Ayland             val = s->chip_id;
1133b630c075SMark Cave-Ayland         } else {
1134b630c075SMark Cave-Ayland             val = s->rregs[saddr];
1135c9cf45c1SHannes Reinecke         }
1136b630c075SMark Cave-Ayland         break;
1137238ec4d7SMark Cave-Ayland      case ESP_RFLAGS:
1138238ec4d7SMark Cave-Ayland         /* Bottom 5 bits indicate number of bytes in FIFO */
1139238ec4d7SMark Cave-Ayland         val = fifo8_num_used(&s->fifo);
1140238ec4d7SMark Cave-Ayland         break;
114149ab747fSPaolo Bonzini     default:
1142b630c075SMark Cave-Ayland         val = s->rregs[saddr];
114349ab747fSPaolo Bonzini         break;
114449ab747fSPaolo Bonzini     }
1145b630c075SMark Cave-Ayland 
1146b630c075SMark Cave-Ayland     trace_esp_mem_readb(saddr, val);
1147b630c075SMark Cave-Ayland     return val;
114849ab747fSPaolo Bonzini }
114949ab747fSPaolo Bonzini 
115049ab747fSPaolo Bonzini void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
115149ab747fSPaolo Bonzini {
115249ab747fSPaolo Bonzini     trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
115349ab747fSPaolo Bonzini     switch (saddr) {
1154c9cf45c1SHannes Reinecke     case ESP_TCHI:
1155c9cf45c1SHannes Reinecke         s->tchi_written = true;
1156c9cf45c1SHannes Reinecke         /* fall through */
115749ab747fSPaolo Bonzini     case ESP_TCLO:
115849ab747fSPaolo Bonzini     case ESP_TCMID:
115949ab747fSPaolo Bonzini         s->rregs[ESP_RSTAT] &= ~STAT_TC;
116049ab747fSPaolo Bonzini         break;
116149ab747fSPaolo Bonzini     case ESP_FIFO:
11622572689bSMark Cave-Ayland         if (!fifo8_is_full(&s->fifo)) {
11632572689bSMark Cave-Ayland             esp_fifo_push(&s->fifo, val);
11642572689bSMark Cave-Ayland         }
11655d02add4SMark Cave-Ayland         esp_do_nodma(s);
116649ab747fSPaolo Bonzini         break;
116749ab747fSPaolo Bonzini     case ESP_CMD:
116849ab747fSPaolo Bonzini         s->rregs[saddr] = val;
1169f21fe39dSMark Cave-Ayland         esp_run_cmd(s);
117049ab747fSPaolo Bonzini         break;
117149ab747fSPaolo Bonzini     case ESP_WBUSID ... ESP_WSYNO:
117249ab747fSPaolo Bonzini         break;
117349ab747fSPaolo Bonzini     case ESP_CFG1:
117449ab747fSPaolo Bonzini     case ESP_CFG2: case ESP_CFG3:
117549ab747fSPaolo Bonzini     case ESP_RES3: case ESP_RES4:
117649ab747fSPaolo Bonzini         s->rregs[saddr] = val;
117749ab747fSPaolo Bonzini         break;
117849ab747fSPaolo Bonzini     case ESP_WCCF ... ESP_WTEST:
117949ab747fSPaolo Bonzini         break;
118049ab747fSPaolo Bonzini     default:
118149ab747fSPaolo Bonzini         trace_esp_error_invalid_write(val, saddr);
118249ab747fSPaolo Bonzini         return;
118349ab747fSPaolo Bonzini     }
118449ab747fSPaolo Bonzini     s->wregs[saddr] = val;
118549ab747fSPaolo Bonzini }
118649ab747fSPaolo Bonzini 
118749ab747fSPaolo Bonzini static bool esp_mem_accepts(void *opaque, hwaddr addr,
11888372d383SPeter Maydell                             unsigned size, bool is_write,
11898372d383SPeter Maydell                             MemTxAttrs attrs)
119049ab747fSPaolo Bonzini {
119149ab747fSPaolo Bonzini     return (size == 1) || (is_write && size == 4);
119249ab747fSPaolo Bonzini }
119349ab747fSPaolo Bonzini 
11946cc88d6bSMark Cave-Ayland static bool esp_is_before_version_5(void *opaque, int version_id)
11956cc88d6bSMark Cave-Ayland {
11966cc88d6bSMark Cave-Ayland     ESPState *s = ESP(opaque);
11976cc88d6bSMark Cave-Ayland 
11986cc88d6bSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
11996cc88d6bSMark Cave-Ayland     return version_id < 5;
12006cc88d6bSMark Cave-Ayland }
12016cc88d6bSMark Cave-Ayland 
12024e78f3bfSMark Cave-Ayland static bool esp_is_version_5(void *opaque, int version_id)
12034e78f3bfSMark Cave-Ayland {
12044e78f3bfSMark Cave-Ayland     ESPState *s = ESP(opaque);
12054e78f3bfSMark Cave-Ayland 
12064e78f3bfSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
12070bcd5a18SMark Cave-Ayland     return version_id >= 5;
12084e78f3bfSMark Cave-Ayland }
12094e78f3bfSMark Cave-Ayland 
12104eb86065SPaolo Bonzini static bool esp_is_version_6(void *opaque, int version_id)
12114eb86065SPaolo Bonzini {
12124eb86065SPaolo Bonzini     ESPState *s = ESP(opaque);
12134eb86065SPaolo Bonzini 
12144eb86065SPaolo Bonzini     version_id = MIN(version_id, s->mig_version_id);
12154eb86065SPaolo Bonzini     return version_id >= 6;
12164eb86065SPaolo Bonzini }
12174eb86065SPaolo Bonzini 
121882003450SMark Cave-Ayland static bool esp_is_between_version_5_and_6(void *opaque, int version_id)
121982003450SMark Cave-Ayland {
122082003450SMark Cave-Ayland     ESPState *s = ESP(opaque);
122182003450SMark Cave-Ayland 
122282003450SMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
122382003450SMark Cave-Ayland     return version_id >= 5 && version_id <= 6;
122482003450SMark Cave-Ayland }
122582003450SMark Cave-Ayland 
1226ff4a1dabSMark Cave-Ayland int esp_pre_save(void *opaque)
12270bd005beSMark Cave-Ayland {
1228ff4a1dabSMark Cave-Ayland     ESPState *s = ESP(object_resolve_path_component(
1229ff4a1dabSMark Cave-Ayland                       OBJECT(opaque), "esp"));
12300bd005beSMark Cave-Ayland 
12310bd005beSMark Cave-Ayland     s->mig_version_id = vmstate_esp.version_id;
12320bd005beSMark Cave-Ayland     return 0;
12330bd005beSMark Cave-Ayland }
12340bd005beSMark Cave-Ayland 
12350bd005beSMark Cave-Ayland static int esp_post_load(void *opaque, int version_id)
12360bd005beSMark Cave-Ayland {
12370bd005beSMark Cave-Ayland     ESPState *s = ESP(opaque);
1238042879fcSMark Cave-Ayland     int len, i;
12390bd005beSMark Cave-Ayland 
12406cc88d6bSMark Cave-Ayland     version_id = MIN(version_id, s->mig_version_id);
12416cc88d6bSMark Cave-Ayland 
12426cc88d6bSMark Cave-Ayland     if (version_id < 5) {
12436cc88d6bSMark Cave-Ayland         esp_set_tc(s, s->mig_dma_left);
1244042879fcSMark Cave-Ayland 
1245042879fcSMark Cave-Ayland         /* Migrate ti_buf to fifo */
1246042879fcSMark Cave-Ayland         len = s->mig_ti_wptr - s->mig_ti_rptr;
1247042879fcSMark Cave-Ayland         for (i = 0; i < len; i++) {
1248042879fcSMark Cave-Ayland             fifo8_push(&s->fifo, s->mig_ti_buf[i]);
1249042879fcSMark Cave-Ayland         }
1250023666daSMark Cave-Ayland 
1251023666daSMark Cave-Ayland         /* Migrate cmdbuf to cmdfifo */
1252023666daSMark Cave-Ayland         for (i = 0; i < s->mig_cmdlen; i++) {
1253023666daSMark Cave-Ayland             fifo8_push(&s->cmdfifo, s->mig_cmdbuf[i]);
1254023666daSMark Cave-Ayland         }
12556cc88d6bSMark Cave-Ayland     }
12566cc88d6bSMark Cave-Ayland 
12570bd005beSMark Cave-Ayland     s->mig_version_id = vmstate_esp.version_id;
12580bd005beSMark Cave-Ayland     return 0;
12590bd005beSMark Cave-Ayland }
12600bd005beSMark Cave-Ayland 
126149ab747fSPaolo Bonzini const VMStateDescription vmstate_esp = {
126249ab747fSPaolo Bonzini     .name = "esp",
126382003450SMark Cave-Ayland     .version_id = 7,
126449ab747fSPaolo Bonzini     .minimum_version_id = 3,
12650bd005beSMark Cave-Ayland     .post_load = esp_post_load,
12662d7b39a6SRichard Henderson     .fields = (const VMStateField[]) {
126749ab747fSPaolo Bonzini         VMSTATE_BUFFER(rregs, ESPState),
126849ab747fSPaolo Bonzini         VMSTATE_BUFFER(wregs, ESPState),
126949ab747fSPaolo Bonzini         VMSTATE_INT32(ti_size, ESPState),
1270042879fcSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_ti_rptr, ESPState, esp_is_before_version_5),
1271042879fcSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_ti_wptr, ESPState, esp_is_before_version_5),
1272042879fcSMark Cave-Ayland         VMSTATE_BUFFER_TEST(mig_ti_buf, ESPState, esp_is_before_version_5),
127349ab747fSPaolo Bonzini         VMSTATE_UINT32(status, ESPState),
12744aaa6ac3SMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_deferred_status, ESPState,
12754aaa6ac3SMark Cave-Ayland                             esp_is_before_version_5),
12764aaa6ac3SMark Cave-Ayland         VMSTATE_BOOL_TEST(mig_deferred_complete, ESPState,
12774aaa6ac3SMark Cave-Ayland                           esp_is_before_version_5),
127849ab747fSPaolo Bonzini         VMSTATE_UINT32(dma, ESPState),
1279023666daSMark Cave-Ayland         VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 0,
1280023666daSMark Cave-Ayland                               esp_is_before_version_5, 0, 16),
1281023666daSMark Cave-Ayland         VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 4,
1282023666daSMark Cave-Ayland                               esp_is_before_version_5, 16,
1283023666daSMark Cave-Ayland                               sizeof(typeof_field(ESPState, mig_cmdbuf))),
1284023666daSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_cmdlen, ESPState, esp_is_before_version_5),
128549ab747fSPaolo Bonzini         VMSTATE_UINT32(do_cmd, ESPState),
12866cc88d6bSMark Cave-Ayland         VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5),
12878dded6deSMark Cave-Ayland         VMSTATE_BOOL_TEST(data_ready, ESPState, esp_is_version_5),
1288023666daSMark Cave-Ayland         VMSTATE_UINT8_TEST(cmdfifo_cdb_offset, ESPState, esp_is_version_5),
1289042879fcSMark Cave-Ayland         VMSTATE_FIFO8_TEST(fifo, ESPState, esp_is_version_5),
1290023666daSMark Cave-Ayland         VMSTATE_FIFO8_TEST(cmdfifo, ESPState, esp_is_version_5),
129182003450SMark Cave-Ayland         VMSTATE_UINT8_TEST(mig_ti_cmd, ESPState,
129282003450SMark Cave-Ayland                            esp_is_between_version_5_and_6),
12934eb86065SPaolo Bonzini         VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6),
129449ab747fSPaolo Bonzini         VMSTATE_END_OF_LIST()
129574d71ea1SLaurent Vivier     },
129649ab747fSPaolo Bonzini };
129749ab747fSPaolo Bonzini 
129849ab747fSPaolo Bonzini static void sysbus_esp_mem_write(void *opaque, hwaddr addr,
129949ab747fSPaolo Bonzini                                  uint64_t val, unsigned int size)
130049ab747fSPaolo Bonzini {
130149ab747fSPaolo Bonzini     SysBusESPState *sysbus = opaque;
1302eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
130349ab747fSPaolo Bonzini     uint32_t saddr;
130449ab747fSPaolo Bonzini 
130549ab747fSPaolo Bonzini     saddr = addr >> sysbus->it_shift;
1306eb169c76SMark Cave-Ayland     esp_reg_write(s, saddr, val);
130749ab747fSPaolo Bonzini }
130849ab747fSPaolo Bonzini 
130949ab747fSPaolo Bonzini static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr,
131049ab747fSPaolo Bonzini                                     unsigned int size)
131149ab747fSPaolo Bonzini {
131249ab747fSPaolo Bonzini     SysBusESPState *sysbus = opaque;
1313eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
131449ab747fSPaolo Bonzini     uint32_t saddr;
131549ab747fSPaolo Bonzini 
131649ab747fSPaolo Bonzini     saddr = addr >> sysbus->it_shift;
1317eb169c76SMark Cave-Ayland     return esp_reg_read(s, saddr);
131849ab747fSPaolo Bonzini }
131949ab747fSPaolo Bonzini 
132049ab747fSPaolo Bonzini static const MemoryRegionOps sysbus_esp_mem_ops = {
132149ab747fSPaolo Bonzini     .read = sysbus_esp_mem_read,
132249ab747fSPaolo Bonzini     .write = sysbus_esp_mem_write,
132349ab747fSPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
132449ab747fSPaolo Bonzini     .valid.accepts = esp_mem_accepts,
132549ab747fSPaolo Bonzini };
132649ab747fSPaolo Bonzini 
132774d71ea1SLaurent Vivier static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
132874d71ea1SLaurent Vivier                                   uint64_t val, unsigned int size)
132974d71ea1SLaurent Vivier {
133074d71ea1SLaurent Vivier     SysBusESPState *sysbus = opaque;
1331eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
133274d71ea1SLaurent Vivier 
1333960ebfd9SMark Cave-Ayland     trace_esp_pdma_write(size);
1334960ebfd9SMark Cave-Ayland 
133574d71ea1SLaurent Vivier     switch (size) {
133674d71ea1SLaurent Vivier     case 1:
1337761bef75SMark Cave-Ayland         esp_pdma_write(s, val);
133874d71ea1SLaurent Vivier         break;
133974d71ea1SLaurent Vivier     case 2:
1340761bef75SMark Cave-Ayland         esp_pdma_write(s, val >> 8);
1341761bef75SMark Cave-Ayland         esp_pdma_write(s, val);
134274d71ea1SLaurent Vivier         break;
134374d71ea1SLaurent Vivier     }
1344b46a43a2SMark Cave-Ayland     esp_do_dma(s);
134574d71ea1SLaurent Vivier }
134674d71ea1SLaurent Vivier 
134774d71ea1SLaurent Vivier static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr,
134874d71ea1SLaurent Vivier                                      unsigned int size)
134974d71ea1SLaurent Vivier {
135074d71ea1SLaurent Vivier     SysBusESPState *sysbus = opaque;
1351eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
135274d71ea1SLaurent Vivier     uint64_t val = 0;
135374d71ea1SLaurent Vivier 
1354960ebfd9SMark Cave-Ayland     trace_esp_pdma_read(size);
1355960ebfd9SMark Cave-Ayland 
135674d71ea1SLaurent Vivier     switch (size) {
135774d71ea1SLaurent Vivier     case 1:
1358761bef75SMark Cave-Ayland         val = esp_pdma_read(s);
135974d71ea1SLaurent Vivier         break;
136074d71ea1SLaurent Vivier     case 2:
1361761bef75SMark Cave-Ayland         val = esp_pdma_read(s);
1362761bef75SMark Cave-Ayland         val = (val << 8) | esp_pdma_read(s);
136374d71ea1SLaurent Vivier         break;
136474d71ea1SLaurent Vivier     }
1365b46a43a2SMark Cave-Ayland     esp_do_dma(s);
136674d71ea1SLaurent Vivier     return val;
136774d71ea1SLaurent Vivier }
136874d71ea1SLaurent Vivier 
1369a7a22088SMark Cave-Ayland static void *esp_load_request(QEMUFile *f, SCSIRequest *req)
1370a7a22088SMark Cave-Ayland {
1371a7a22088SMark Cave-Ayland     ESPState *s = container_of(req->bus, ESPState, bus);
1372a7a22088SMark Cave-Ayland 
1373a7a22088SMark Cave-Ayland     scsi_req_ref(req);
1374a7a22088SMark Cave-Ayland     s->current_req = req;
1375a7a22088SMark Cave-Ayland     return s;
1376a7a22088SMark Cave-Ayland }
1377a7a22088SMark Cave-Ayland 
137874d71ea1SLaurent Vivier static const MemoryRegionOps sysbus_esp_pdma_ops = {
137974d71ea1SLaurent Vivier     .read = sysbus_esp_pdma_read,
138074d71ea1SLaurent Vivier     .write = sysbus_esp_pdma_write,
138174d71ea1SLaurent Vivier     .endianness = DEVICE_NATIVE_ENDIAN,
138274d71ea1SLaurent Vivier     .valid.min_access_size = 1,
1383cf1b8286SMark Cave-Ayland     .valid.max_access_size = 4,
1384cf1b8286SMark Cave-Ayland     .impl.min_access_size = 1,
1385cf1b8286SMark Cave-Ayland     .impl.max_access_size = 2,
138674d71ea1SLaurent Vivier };
138774d71ea1SLaurent Vivier 
138849ab747fSPaolo Bonzini static const struct SCSIBusInfo esp_scsi_info = {
138949ab747fSPaolo Bonzini     .tcq = false,
139049ab747fSPaolo Bonzini     .max_target = ESP_MAX_DEVS,
139149ab747fSPaolo Bonzini     .max_lun = 7,
139249ab747fSPaolo Bonzini 
1393a7a22088SMark Cave-Ayland     .load_request = esp_load_request,
139449ab747fSPaolo Bonzini     .transfer_data = esp_transfer_data,
139549ab747fSPaolo Bonzini     .complete = esp_command_complete,
139649ab747fSPaolo Bonzini     .cancel = esp_request_cancelled
139749ab747fSPaolo Bonzini };
139849ab747fSPaolo Bonzini 
139949ab747fSPaolo Bonzini static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
140049ab747fSPaolo Bonzini {
140184fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(opaque);
1402eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
140349ab747fSPaolo Bonzini 
140449ab747fSPaolo Bonzini     switch (irq) {
140549ab747fSPaolo Bonzini     case 0:
140649ab747fSPaolo Bonzini         parent_esp_reset(s, irq, level);
140749ab747fSPaolo Bonzini         break;
140849ab747fSPaolo Bonzini     case 1:
1409b86dc5cbSMark Cave-Ayland         esp_dma_enable(s, irq, level);
141049ab747fSPaolo Bonzini         break;
141149ab747fSPaolo Bonzini     }
141249ab747fSPaolo Bonzini }
141349ab747fSPaolo Bonzini 
1414b09318caSHu Tao static void sysbus_esp_realize(DeviceState *dev, Error **errp)
141549ab747fSPaolo Bonzini {
1416b09318caSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
141784fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(dev);
1418eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
1419eb169c76SMark Cave-Ayland 
1420eb169c76SMark Cave-Ayland     if (!qdev_realize(DEVICE(s), NULL, errp)) {
1421eb169c76SMark Cave-Ayland         return;
1422eb169c76SMark Cave-Ayland     }
142349ab747fSPaolo Bonzini 
1424b09318caSHu Tao     sysbus_init_irq(sbd, &s->irq);
142574d71ea1SLaurent Vivier     sysbus_init_irq(sbd, &s->irq_data);
142649ab747fSPaolo Bonzini     assert(sysbus->it_shift != -1);
142749ab747fSPaolo Bonzini 
142849ab747fSPaolo Bonzini     s->chip_id = TCHI_FAS100A;
142929776739SPaolo Bonzini     memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops,
143074d71ea1SLaurent Vivier                           sysbus, "esp-regs", ESP_REGS << sysbus->it_shift);
1431b09318caSHu Tao     sysbus_init_mmio(sbd, &sysbus->iomem);
143274d71ea1SLaurent Vivier     memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_ops,
1433cf1b8286SMark Cave-Ayland                           sysbus, "esp-pdma", 4);
143474d71ea1SLaurent Vivier     sysbus_init_mmio(sbd, &sysbus->pdma);
143549ab747fSPaolo Bonzini 
1436b09318caSHu Tao     qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
143749ab747fSPaolo Bonzini 
1438739e95f5SPeter Maydell     scsi_bus_init(&s->bus, sizeof(s->bus), dev, &esp_scsi_info);
143949ab747fSPaolo Bonzini }
144049ab747fSPaolo Bonzini 
144149ab747fSPaolo Bonzini static void sysbus_esp_hard_reset(DeviceState *dev)
144249ab747fSPaolo Bonzini {
144384fbefedSMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(dev);
1444eb169c76SMark Cave-Ayland     ESPState *s = ESP(&sysbus->esp);
1445eb169c76SMark Cave-Ayland 
1446eb169c76SMark Cave-Ayland     esp_hard_reset(s);
1447eb169c76SMark Cave-Ayland }
1448eb169c76SMark Cave-Ayland 
1449eb169c76SMark Cave-Ayland static void sysbus_esp_init(Object *obj)
1450eb169c76SMark Cave-Ayland {
1451eb169c76SMark Cave-Ayland     SysBusESPState *sysbus = SYSBUS_ESP(obj);
1452eb169c76SMark Cave-Ayland 
1453eb169c76SMark Cave-Ayland     object_initialize_child(obj, "esp", &sysbus->esp, TYPE_ESP);
145449ab747fSPaolo Bonzini }
145549ab747fSPaolo Bonzini 
145649ab747fSPaolo Bonzini static const VMStateDescription vmstate_sysbus_esp_scsi = {
145749ab747fSPaolo Bonzini     .name = "sysbusespscsi",
14580bd005beSMark Cave-Ayland     .version_id = 2,
1459ea84a442SGuenter Roeck     .minimum_version_id = 1,
1460ff4a1dabSMark Cave-Ayland     .pre_save = esp_pre_save,
14612d7b39a6SRichard Henderson     .fields = (const VMStateField[]) {
14620bd005beSMark Cave-Ayland         VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2),
146349ab747fSPaolo Bonzini         VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
146449ab747fSPaolo Bonzini         VMSTATE_END_OF_LIST()
146549ab747fSPaolo Bonzini     }
146649ab747fSPaolo Bonzini };
146749ab747fSPaolo Bonzini 
146849ab747fSPaolo Bonzini static void sysbus_esp_class_init(ObjectClass *klass, void *data)
146949ab747fSPaolo Bonzini {
147049ab747fSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
147149ab747fSPaolo Bonzini 
1472b09318caSHu Tao     dc->realize = sysbus_esp_realize;
147349ab747fSPaolo Bonzini     dc->reset = sysbus_esp_hard_reset;
147449ab747fSPaolo Bonzini     dc->vmsd = &vmstate_sysbus_esp_scsi;
1475125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
147649ab747fSPaolo Bonzini }
147749ab747fSPaolo Bonzini 
147849ab747fSPaolo Bonzini static const TypeInfo sysbus_esp_info = {
147984fbefedSMark Cave-Ayland     .name          = TYPE_SYSBUS_ESP,
148049ab747fSPaolo Bonzini     .parent        = TYPE_SYS_BUS_DEVICE,
1481eb169c76SMark Cave-Ayland     .instance_init = sysbus_esp_init,
148249ab747fSPaolo Bonzini     .instance_size = sizeof(SysBusESPState),
148349ab747fSPaolo Bonzini     .class_init    = sysbus_esp_class_init,
148449ab747fSPaolo Bonzini };
148549ab747fSPaolo Bonzini 
1486042879fcSMark Cave-Ayland static void esp_finalize(Object *obj)
1487042879fcSMark Cave-Ayland {
1488042879fcSMark Cave-Ayland     ESPState *s = ESP(obj);
1489042879fcSMark Cave-Ayland 
1490042879fcSMark Cave-Ayland     fifo8_destroy(&s->fifo);
1491023666daSMark Cave-Ayland     fifo8_destroy(&s->cmdfifo);
1492042879fcSMark Cave-Ayland }
1493042879fcSMark Cave-Ayland 
1494042879fcSMark Cave-Ayland static void esp_init(Object *obj)
1495042879fcSMark Cave-Ayland {
1496042879fcSMark Cave-Ayland     ESPState *s = ESP(obj);
1497042879fcSMark Cave-Ayland 
1498042879fcSMark Cave-Ayland     fifo8_create(&s->fifo, ESP_FIFO_SZ);
1499023666daSMark Cave-Ayland     fifo8_create(&s->cmdfifo, ESP_CMDFIFO_SZ);
1500042879fcSMark Cave-Ayland }
1501042879fcSMark Cave-Ayland 
1502eb169c76SMark Cave-Ayland static void esp_class_init(ObjectClass *klass, void *data)
1503eb169c76SMark Cave-Ayland {
1504eb169c76SMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(klass);
1505eb169c76SMark Cave-Ayland 
1506eb169c76SMark Cave-Ayland     /* internal device for sysbusesp/pciespscsi, not user-creatable */
1507eb169c76SMark Cave-Ayland     dc->user_creatable = false;
1508eb169c76SMark Cave-Ayland     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
1509eb169c76SMark Cave-Ayland }
1510eb169c76SMark Cave-Ayland 
1511eb169c76SMark Cave-Ayland static const TypeInfo esp_info = {
1512eb169c76SMark Cave-Ayland     .name = TYPE_ESP,
1513eb169c76SMark Cave-Ayland     .parent = TYPE_DEVICE,
1514042879fcSMark Cave-Ayland     .instance_init = esp_init,
1515042879fcSMark Cave-Ayland     .instance_finalize = esp_finalize,
1516eb169c76SMark Cave-Ayland     .instance_size = sizeof(ESPState),
1517eb169c76SMark Cave-Ayland     .class_init = esp_class_init,
1518eb169c76SMark Cave-Ayland };
1519eb169c76SMark Cave-Ayland 
152049ab747fSPaolo Bonzini static void esp_register_types(void)
152149ab747fSPaolo Bonzini {
152249ab747fSPaolo Bonzini     type_register_static(&sysbus_esp_info);
1523eb169c76SMark Cave-Ayland     type_register_static(&esp_info);
152449ab747fSPaolo Bonzini }
152549ab747fSPaolo Bonzini 
152649ab747fSPaolo Bonzini type_init(esp_register_types)
1527