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 822c1017bfSMark Cave-Ayland static const char *esp_phase_names[8] = { 832c1017bfSMark Cave-Ayland "DATA OUT", "DATA IN", "COMMAND", "STATUS", 842c1017bfSMark Cave-Ayland "(reserved)", "(reserved)", "MESSAGE OUT", "MESSAGE IN" 852c1017bfSMark Cave-Ayland }; 862c1017bfSMark Cave-Ayland 872c1017bfSMark Cave-Ayland static void esp_set_phase(ESPState *s, uint8_t phase) 882c1017bfSMark Cave-Ayland { 892c1017bfSMark Cave-Ayland s->rregs[ESP_RSTAT] &= ~7; 902c1017bfSMark Cave-Ayland s->rregs[ESP_RSTAT] |= phase; 912c1017bfSMark Cave-Ayland 922c1017bfSMark Cave-Ayland trace_esp_set_phase(esp_phase_names[phase]); 932c1017bfSMark Cave-Ayland } 942c1017bfSMark Cave-Ayland 952c1017bfSMark Cave-Ayland static uint8_t esp_get_phase(ESPState *s) 962c1017bfSMark Cave-Ayland { 972c1017bfSMark Cave-Ayland return s->rregs[ESP_RSTAT] & 7; 982c1017bfSMark Cave-Ayland } 992c1017bfSMark Cave-Ayland 10049ab747fSPaolo Bonzini void esp_dma_enable(ESPState *s, int irq, int level) 10149ab747fSPaolo Bonzini { 10249ab747fSPaolo Bonzini if (level) { 10349ab747fSPaolo Bonzini s->dma_enabled = 1; 10449ab747fSPaolo Bonzini trace_esp_dma_enable(); 10549ab747fSPaolo Bonzini if (s->dma_cb) { 10649ab747fSPaolo Bonzini s->dma_cb(s); 10749ab747fSPaolo Bonzini s->dma_cb = NULL; 10849ab747fSPaolo Bonzini } 10949ab747fSPaolo Bonzini } else { 11049ab747fSPaolo Bonzini trace_esp_dma_disable(); 11149ab747fSPaolo Bonzini s->dma_enabled = 0; 11249ab747fSPaolo Bonzini } 11349ab747fSPaolo Bonzini } 11449ab747fSPaolo Bonzini 11549ab747fSPaolo Bonzini void esp_request_cancelled(SCSIRequest *req) 11649ab747fSPaolo Bonzini { 11749ab747fSPaolo Bonzini ESPState *s = req->hba_private; 11849ab747fSPaolo Bonzini 11949ab747fSPaolo Bonzini if (req == s->current_req) { 12049ab747fSPaolo Bonzini scsi_req_unref(s->current_req); 12149ab747fSPaolo Bonzini s->current_req = NULL; 12249ab747fSPaolo Bonzini s->current_dev = NULL; 123324c8809SMark Cave-Ayland s->async_len = 0; 12449ab747fSPaolo Bonzini } 12549ab747fSPaolo Bonzini } 12649ab747fSPaolo Bonzini 127743d8736SMark Cave-Ayland static void esp_update_drq(ESPState *s) 128743d8736SMark Cave-Ayland { 129743d8736SMark Cave-Ayland bool to_device; 130743d8736SMark Cave-Ayland 131743d8736SMark Cave-Ayland switch (esp_get_phase(s)) { 132743d8736SMark Cave-Ayland case STAT_MO: 133743d8736SMark Cave-Ayland case STAT_CD: 134743d8736SMark Cave-Ayland case STAT_DO: 135743d8736SMark Cave-Ayland to_device = true; 136743d8736SMark Cave-Ayland break; 137743d8736SMark Cave-Ayland 138743d8736SMark Cave-Ayland case STAT_DI: 139743d8736SMark Cave-Ayland case STAT_ST: 140743d8736SMark Cave-Ayland case STAT_MI: 141743d8736SMark Cave-Ayland to_device = false; 142743d8736SMark Cave-Ayland break; 143743d8736SMark Cave-Ayland 144743d8736SMark Cave-Ayland default: 145743d8736SMark Cave-Ayland return; 146743d8736SMark Cave-Ayland } 147743d8736SMark Cave-Ayland 148743d8736SMark Cave-Ayland if (s->dma) { 149743d8736SMark Cave-Ayland /* DMA request so update DRQ according to transfer direction */ 150743d8736SMark Cave-Ayland if (to_device) { 151743d8736SMark Cave-Ayland if (fifo8_num_free(&s->fifo) < 2) { 152743d8736SMark Cave-Ayland esp_lower_drq(s); 153743d8736SMark Cave-Ayland } else { 154743d8736SMark Cave-Ayland esp_raise_drq(s); 155743d8736SMark Cave-Ayland } 156743d8736SMark Cave-Ayland } else { 157743d8736SMark Cave-Ayland if (fifo8_num_used(&s->fifo) < 2) { 158743d8736SMark Cave-Ayland esp_lower_drq(s); 159743d8736SMark Cave-Ayland } else { 160743d8736SMark Cave-Ayland esp_raise_drq(s); 161743d8736SMark Cave-Ayland } 162743d8736SMark Cave-Ayland } 163743d8736SMark Cave-Ayland } else { 164743d8736SMark Cave-Ayland /* Not a DMA request */ 165743d8736SMark Cave-Ayland esp_lower_drq(s); 166743d8736SMark Cave-Ayland } 167743d8736SMark Cave-Ayland } 168743d8736SMark Cave-Ayland 1690e7dbe29SMark Cave-Ayland static void esp_fifo_push(ESPState *s, uint8_t val) 170042879fcSMark Cave-Ayland { 1710e7dbe29SMark Cave-Ayland if (fifo8_num_used(&s->fifo) == s->fifo.capacity) { 172042879fcSMark Cave-Ayland trace_esp_error_fifo_overrun(); 173*ffa3a5f2SMark Cave-Ayland } else { 174*ffa3a5f2SMark Cave-Ayland fifo8_push(&s->fifo, val); 175042879fcSMark Cave-Ayland } 176042879fcSMark Cave-Ayland 177*ffa3a5f2SMark Cave-Ayland esp_update_drq(s); 178042879fcSMark Cave-Ayland } 179c5fef911SMark Cave-Ayland 180266170f9SMark Cave-Ayland static void esp_fifo_push_buf(ESPState *s, uint8_t *buf, int len) 181266170f9SMark Cave-Ayland { 182266170f9SMark Cave-Ayland fifo8_push_all(&s->fifo, buf, len); 183743d8736SMark Cave-Ayland esp_update_drq(s); 184266170f9SMark Cave-Ayland } 185266170f9SMark Cave-Ayland 18661fa150dSMark Cave-Ayland static uint8_t esp_fifo_pop(ESPState *s) 187042879fcSMark Cave-Ayland { 188*ffa3a5f2SMark Cave-Ayland uint8_t val; 189*ffa3a5f2SMark Cave-Ayland 19061fa150dSMark Cave-Ayland if (fifo8_is_empty(&s->fifo)) { 191*ffa3a5f2SMark Cave-Ayland val = 0; 192*ffa3a5f2SMark Cave-Ayland } else { 193*ffa3a5f2SMark Cave-Ayland val = fifo8_pop(&s->fifo); 194042879fcSMark Cave-Ayland } 195042879fcSMark Cave-Ayland 196*ffa3a5f2SMark Cave-Ayland esp_update_drq(s); 197*ffa3a5f2SMark Cave-Ayland return val; 198023666daSMark Cave-Ayland } 199023666daSMark Cave-Ayland 200d103d0dbSMark Cave-Ayland static uint32_t esp_fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen) 2017b320a8eSMark Cave-Ayland { 2027b320a8eSMark Cave-Ayland const uint8_t *buf; 20349c60d16SMark Cave-Ayland uint32_t n, n2; 20449c60d16SMark Cave-Ayland int len; 2057b320a8eSMark Cave-Ayland 2067b320a8eSMark Cave-Ayland if (maxlen == 0) { 2077b320a8eSMark Cave-Ayland return 0; 2087b320a8eSMark Cave-Ayland } 2097b320a8eSMark Cave-Ayland 21049c60d16SMark Cave-Ayland len = maxlen; 21149c60d16SMark Cave-Ayland buf = fifo8_pop_buf(fifo, len, &n); 2127b320a8eSMark Cave-Ayland if (dest) { 2137b320a8eSMark Cave-Ayland memcpy(dest, buf, n); 2147b320a8eSMark Cave-Ayland } 2157b320a8eSMark Cave-Ayland 21649c60d16SMark Cave-Ayland /* Add FIFO wraparound if needed */ 21749c60d16SMark Cave-Ayland len -= n; 21849c60d16SMark Cave-Ayland len = MIN(len, fifo8_num_used(fifo)); 21949c60d16SMark Cave-Ayland if (len) { 22049c60d16SMark Cave-Ayland buf = fifo8_pop_buf(fifo, len, &n2); 22149c60d16SMark Cave-Ayland if (dest) { 22249c60d16SMark Cave-Ayland memcpy(&dest[n], buf, n2); 22349c60d16SMark Cave-Ayland } 22449c60d16SMark Cave-Ayland n += n2; 22549c60d16SMark Cave-Ayland } 22649c60d16SMark Cave-Ayland 2277b320a8eSMark Cave-Ayland return n; 2287b320a8eSMark Cave-Ayland } 2297b320a8eSMark Cave-Ayland 230da838126SMark Cave-Ayland static uint32_t esp_fifo_pop_buf(ESPState *s, uint8_t *dest, int maxlen) 231d103d0dbSMark Cave-Ayland { 232743d8736SMark Cave-Ayland uint32_t len = esp_fifo8_pop_buf(&s->fifo, dest, maxlen); 233743d8736SMark Cave-Ayland 234743d8736SMark Cave-Ayland esp_update_drq(s); 235743d8736SMark Cave-Ayland return len; 236d103d0dbSMark Cave-Ayland } 237d103d0dbSMark Cave-Ayland 238c47b5835SMark Cave-Ayland static uint32_t esp_get_tc(ESPState *s) 239c47b5835SMark Cave-Ayland { 240c47b5835SMark Cave-Ayland uint32_t dmalen; 241c47b5835SMark Cave-Ayland 242c47b5835SMark Cave-Ayland dmalen = s->rregs[ESP_TCLO]; 243c47b5835SMark Cave-Ayland dmalen |= s->rregs[ESP_TCMID] << 8; 244c47b5835SMark Cave-Ayland dmalen |= s->rregs[ESP_TCHI] << 16; 245c47b5835SMark Cave-Ayland 246c47b5835SMark Cave-Ayland return dmalen; 247c47b5835SMark Cave-Ayland } 248c47b5835SMark Cave-Ayland 249c47b5835SMark Cave-Ayland static void esp_set_tc(ESPState *s, uint32_t dmalen) 250c47b5835SMark Cave-Ayland { 251c5d7df28SMark Cave-Ayland uint32_t old_tc = esp_get_tc(s); 252c5d7df28SMark Cave-Ayland 253c47b5835SMark Cave-Ayland s->rregs[ESP_TCLO] = dmalen; 254c47b5835SMark Cave-Ayland s->rregs[ESP_TCMID] = dmalen >> 8; 255c47b5835SMark Cave-Ayland s->rregs[ESP_TCHI] = dmalen >> 16; 256c5d7df28SMark Cave-Ayland 257c5d7df28SMark Cave-Ayland if (old_tc && dmalen == 0) { 258c5d7df28SMark Cave-Ayland s->rregs[ESP_RSTAT] |= STAT_TC; 259c5d7df28SMark Cave-Ayland } 260c47b5835SMark Cave-Ayland } 261c47b5835SMark Cave-Ayland 262c04ed569SMark Cave-Ayland static uint32_t esp_get_stc(ESPState *s) 263c04ed569SMark Cave-Ayland { 264c04ed569SMark Cave-Ayland uint32_t dmalen; 265c04ed569SMark Cave-Ayland 266c04ed569SMark Cave-Ayland dmalen = s->wregs[ESP_TCLO]; 267c04ed569SMark Cave-Ayland dmalen |= s->wregs[ESP_TCMID] << 8; 268c04ed569SMark Cave-Ayland dmalen |= s->wregs[ESP_TCHI] << 16; 269c04ed569SMark Cave-Ayland 270c04ed569SMark Cave-Ayland return dmalen; 271c04ed569SMark Cave-Ayland } 272c04ed569SMark Cave-Ayland 273761bef75SMark Cave-Ayland static uint8_t esp_pdma_read(ESPState *s) 274761bef75SMark Cave-Ayland { 2758da90e81SMark Cave-Ayland uint8_t val; 2768da90e81SMark Cave-Ayland 27761fa150dSMark Cave-Ayland val = esp_fifo_pop(s); 2788da90e81SMark Cave-Ayland return val; 279761bef75SMark Cave-Ayland } 280761bef75SMark Cave-Ayland 281761bef75SMark Cave-Ayland static void esp_pdma_write(ESPState *s, uint8_t val) 282761bef75SMark Cave-Ayland { 2838da90e81SMark Cave-Ayland uint32_t dmalen = esp_get_tc(s); 2848da90e81SMark Cave-Ayland 2853c421400SMark Cave-Ayland if (dmalen == 0) { 2868da90e81SMark Cave-Ayland return; 2878da90e81SMark Cave-Ayland } 2888da90e81SMark Cave-Ayland 2890e7dbe29SMark Cave-Ayland esp_fifo_push(s, val); 2908da90e81SMark Cave-Ayland 2918da90e81SMark Cave-Ayland dmalen--; 2928da90e81SMark Cave-Ayland esp_set_tc(s, dmalen); 293761bef75SMark Cave-Ayland } 294761bef75SMark Cave-Ayland 295c7bce09cSMark Cave-Ayland static int esp_select(ESPState *s) 2966130b188SLaurent Vivier { 2976130b188SLaurent Vivier int target; 2986130b188SLaurent Vivier 2996130b188SLaurent Vivier target = s->wregs[ESP_WBUSID] & BUSID_DID; 3006130b188SLaurent Vivier 3016130b188SLaurent Vivier s->ti_size = 0; 3029b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_0; 3036130b188SLaurent Vivier 304cf40a5e4SMark Cave-Ayland if (s->current_req) { 305cf40a5e4SMark Cave-Ayland /* Started a new command before the old one finished. Cancel it. */ 306cf40a5e4SMark Cave-Ayland scsi_req_cancel(s->current_req); 307cf40a5e4SMark Cave-Ayland } 308cf40a5e4SMark Cave-Ayland 3096130b188SLaurent Vivier s->current_dev = scsi_device_find(&s->bus, 0, target, 0); 3106130b188SLaurent Vivier if (!s->current_dev) { 3116130b188SLaurent Vivier /* No such drive */ 3126130b188SLaurent Vivier s->rregs[ESP_RSTAT] = 0; 313cf1a7a9bSMark Cave-Ayland s->rregs[ESP_RINTR] = INTR_DC; 3146130b188SLaurent Vivier esp_raise_irq(s); 3156130b188SLaurent Vivier return -1; 3166130b188SLaurent Vivier } 3174e78f3bfSMark Cave-Ayland 3184e78f3bfSMark Cave-Ayland /* 3194e78f3bfSMark Cave-Ayland * Note that we deliberately don't raise the IRQ here: this will be done 320c90b2792SMark Cave-Ayland * either in esp_transfer_data() or esp_command_complete() 3214e78f3bfSMark Cave-Ayland */ 3226130b188SLaurent Vivier return 0; 3236130b188SLaurent Vivier } 3246130b188SLaurent Vivier 3253ee9a475SMark Cave-Ayland static void esp_do_dma(ESPState *s); 3263ee9a475SMark Cave-Ayland static void esp_do_nodma(ESPState *s); 3273ee9a475SMark Cave-Ayland 3284eb86065SPaolo Bonzini static void do_command_phase(ESPState *s) 32949ab747fSPaolo Bonzini { 3307b320a8eSMark Cave-Ayland uint32_t cmdlen; 33149ab747fSPaolo Bonzini int32_t datalen; 33249ab747fSPaolo Bonzini SCSIDevice *current_lun; 3337b320a8eSMark Cave-Ayland uint8_t buf[ESP_CMDFIFO_SZ]; 33449ab747fSPaolo Bonzini 3354eb86065SPaolo Bonzini trace_esp_do_command_phase(s->lun); 336023666daSMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 33799545751SMark Cave-Ayland if (!cmdlen || !s->current_dev) { 33899545751SMark Cave-Ayland return; 33999545751SMark Cave-Ayland } 340f87d0487SMark Cave-Ayland esp_fifo8_pop_buf(&s->cmdfifo, buf, cmdlen); 341023666daSMark Cave-Ayland 3424eb86065SPaolo Bonzini current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun); 343b22f83d8SAlexandra Diupina if (!current_lun) { 344b22f83d8SAlexandra Diupina /* No such drive */ 345b22f83d8SAlexandra Diupina s->rregs[ESP_RSTAT] = 0; 346b22f83d8SAlexandra Diupina s->rregs[ESP_RINTR] = INTR_DC; 347b22f83d8SAlexandra Diupina s->rregs[ESP_RSEQ] = SEQ_0; 348b22f83d8SAlexandra Diupina esp_raise_irq(s); 349b22f83d8SAlexandra Diupina return; 350b22f83d8SAlexandra Diupina } 351b22f83d8SAlexandra Diupina 352fe9d8927SJohn Millikin s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s); 35349ab747fSPaolo Bonzini datalen = scsi_req_enqueue(s->current_req); 35449ab747fSPaolo Bonzini s->ti_size = datalen; 355023666daSMark Cave-Ayland fifo8_reset(&s->cmdfifo); 356c90b2792SMark Cave-Ayland s->data_ready = false; 35749ab747fSPaolo Bonzini if (datalen != 0) { 3584e78f3bfSMark Cave-Ayland /* 359c90b2792SMark Cave-Ayland * Switch to DATA phase but wait until initial data xfer is 3604e78f3bfSMark Cave-Ayland * complete before raising the command completion interrupt 3614e78f3bfSMark Cave-Ayland */ 362c90b2792SMark Cave-Ayland if (datalen > 0) { 363abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_DI); 36449ab747fSPaolo Bonzini } else { 365abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_DO); 36649ab747fSPaolo Bonzini } 3674e78f3bfSMark Cave-Ayland scsi_req_continue(s->current_req); 3684e78f3bfSMark Cave-Ayland return; 3694e78f3bfSMark Cave-Ayland } 3704e78f3bfSMark Cave-Ayland } 37149ab747fSPaolo Bonzini 3724eb86065SPaolo Bonzini static void do_message_phase(ESPState *s) 37349ab747fSPaolo Bonzini { 3744eb86065SPaolo Bonzini if (s->cmdfifo_cdb_offset) { 3751828000bSMark Cave-Ayland uint8_t message = fifo8_is_empty(&s->cmdfifo) ? 0 : 3761828000bSMark Cave-Ayland fifo8_pop(&s->cmdfifo); 377023666daSMark Cave-Ayland 3784eb86065SPaolo Bonzini trace_esp_do_identify(message); 3794eb86065SPaolo Bonzini s->lun = message & 7; 380023666daSMark Cave-Ayland s->cmdfifo_cdb_offset--; 3814eb86065SPaolo Bonzini } 38249ab747fSPaolo Bonzini 383799d90d8SMark Cave-Ayland /* Ignore extended messages for now */ 384023666daSMark Cave-Ayland if (s->cmdfifo_cdb_offset) { 3854eb86065SPaolo Bonzini int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo)); 3862260402bSMark Cave-Ayland esp_fifo8_pop_buf(&s->cmdfifo, NULL, len); 387023666daSMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 388023666daSMark Cave-Ayland } 3894eb86065SPaolo Bonzini } 390023666daSMark Cave-Ayland 3914eb86065SPaolo Bonzini static void do_cmd(ESPState *s) 3924eb86065SPaolo Bonzini { 3934eb86065SPaolo Bonzini do_message_phase(s); 3944eb86065SPaolo Bonzini assert(s->cmdfifo_cdb_offset == 0); 3954eb86065SPaolo Bonzini do_command_phase(s); 39649ab747fSPaolo Bonzini } 39749ab747fSPaolo Bonzini 39849ab747fSPaolo Bonzini static void handle_satn(ESPState *s) 39949ab747fSPaolo Bonzini { 40049ab747fSPaolo Bonzini if (s->dma && !s->dma_enabled) { 40149ab747fSPaolo Bonzini s->dma_cb = handle_satn; 40249ab747fSPaolo Bonzini return; 40349ab747fSPaolo Bonzini } 404b46a43a2SMark Cave-Ayland 4051bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4061bcaf71bSMark Cave-Ayland return; 4071bcaf71bSMark Cave-Ayland } 4083ee9a475SMark Cave-Ayland 4093ee9a475SMark Cave-Ayland esp_set_phase(s, STAT_MO); 4103ee9a475SMark Cave-Ayland 4113ee9a475SMark Cave-Ayland if (s->dma) { 4123ee9a475SMark Cave-Ayland esp_do_dma(s); 4133ee9a475SMark Cave-Ayland } else { 414d39592ffSMark Cave-Ayland esp_do_nodma(s); 41549ab747fSPaolo Bonzini } 41694d5c79dSMark Cave-Ayland } 41749ab747fSPaolo Bonzini 41849ab747fSPaolo Bonzini static void handle_s_without_atn(ESPState *s) 41949ab747fSPaolo Bonzini { 42049ab747fSPaolo Bonzini if (s->dma && !s->dma_enabled) { 42149ab747fSPaolo Bonzini s->dma_cb = handle_s_without_atn; 42249ab747fSPaolo Bonzini return; 42349ab747fSPaolo Bonzini } 424b46a43a2SMark Cave-Ayland 4251bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4261bcaf71bSMark Cave-Ayland return; 4271bcaf71bSMark Cave-Ayland } 4289ff0fd12SMark Cave-Ayland 429abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_CD); 4309ff0fd12SMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 4319ff0fd12SMark Cave-Ayland 4329ff0fd12SMark Cave-Ayland if (s->dma) { 4339ff0fd12SMark Cave-Ayland esp_do_dma(s); 4349ff0fd12SMark Cave-Ayland } else { 435d39592ffSMark Cave-Ayland esp_do_nodma(s); 43649ab747fSPaolo Bonzini } 43749ab747fSPaolo Bonzini } 43849ab747fSPaolo Bonzini 43949ab747fSPaolo Bonzini static void handle_satn_stop(ESPState *s) 44049ab747fSPaolo Bonzini { 44149ab747fSPaolo Bonzini if (s->dma && !s->dma_enabled) { 44249ab747fSPaolo Bonzini s->dma_cb = handle_satn_stop; 44349ab747fSPaolo Bonzini return; 44449ab747fSPaolo Bonzini } 445b46a43a2SMark Cave-Ayland 4461bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4471bcaf71bSMark Cave-Ayland return; 4481bcaf71bSMark Cave-Ayland } 449db4d4150SMark Cave-Ayland 450abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_MO); 4515d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 452db4d4150SMark Cave-Ayland 453db4d4150SMark Cave-Ayland if (s->dma) { 454db4d4150SMark Cave-Ayland esp_do_dma(s); 455db4d4150SMark Cave-Ayland } else { 456d39592ffSMark Cave-Ayland esp_do_nodma(s); 45749ab747fSPaolo Bonzini } 45849ab747fSPaolo Bonzini } 45949ab747fSPaolo Bonzini 460a6cad7cdSMark Cave-Ayland static void handle_pad(ESPState *s) 461a6cad7cdSMark Cave-Ayland { 462a6cad7cdSMark Cave-Ayland if (s->dma) { 463a6cad7cdSMark Cave-Ayland esp_do_dma(s); 464a6cad7cdSMark Cave-Ayland } else { 465a6cad7cdSMark Cave-Ayland esp_do_nodma(s); 466a6cad7cdSMark Cave-Ayland } 467a6cad7cdSMark Cave-Ayland } 468a6cad7cdSMark Cave-Ayland 46949ab747fSPaolo Bonzini static void write_response(ESPState *s) 47049ab747fSPaolo Bonzini { 47149ab747fSPaolo Bonzini trace_esp_write_response(s->status); 472042879fcSMark Cave-Ayland 4738baa1472SMark Cave-Ayland if (s->dma) { 4748baa1472SMark Cave-Ayland esp_do_dma(s); 4758baa1472SMark Cave-Ayland } else { 47683428f7aSMark Cave-Ayland esp_do_nodma(s); 47749ab747fSPaolo Bonzini } 4788baa1472SMark Cave-Ayland } 47949ab747fSPaolo Bonzini 4805aa0df40SMark Cave-Ayland static bool esp_cdb_ready(ESPState *s) 4815d02add4SMark Cave-Ayland { 4825aa0df40SMark Cave-Ayland int len = fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset; 4835d02add4SMark Cave-Ayland const uint8_t *pbuf; 4843cc70889SMark Cave-Ayland uint32_t n; 4855aa0df40SMark Cave-Ayland int cdblen; 4865d02add4SMark Cave-Ayland 4875aa0df40SMark Cave-Ayland if (len <= 0) { 4885aa0df40SMark Cave-Ayland return false; 4895d02add4SMark Cave-Ayland } 4905d02add4SMark Cave-Ayland 4913cc70889SMark Cave-Ayland pbuf = fifo8_peek_buf(&s->cmdfifo, len, &n); 4923cc70889SMark Cave-Ayland if (n < len) { 4933cc70889SMark Cave-Ayland /* 4943cc70889SMark Cave-Ayland * In normal use the cmdfifo should never wrap, but include this check 4953cc70889SMark Cave-Ayland * to prevent a malicious guest from reading past the end of the 4963cc70889SMark Cave-Ayland * cmdfifo data buffer below 4973cc70889SMark Cave-Ayland */ 4983cc70889SMark Cave-Ayland return false; 4993cc70889SMark Cave-Ayland } 5003cc70889SMark Cave-Ayland 5015aa0df40SMark Cave-Ayland cdblen = scsi_cdb_length((uint8_t *)&pbuf[s->cmdfifo_cdb_offset]); 5025d02add4SMark Cave-Ayland 5035aa0df40SMark Cave-Ayland return cdblen < 0 ? false : (len >= cdblen); 5045d02add4SMark Cave-Ayland } 5055d02add4SMark Cave-Ayland 506004826d0SMark Cave-Ayland static void esp_dma_ti_check(ESPState *s) 50749ab747fSPaolo Bonzini { 508af74b3c1SMark Cave-Ayland if (esp_get_tc(s) == 0 && fifo8_num_used(&s->fifo) < 2) { 509cf47a41eSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 51049ab747fSPaolo Bonzini esp_raise_irq(s); 511af74b3c1SMark Cave-Ayland esp_lower_drq(s); 512af74b3c1SMark Cave-Ayland } 51349ab747fSPaolo Bonzini } 51449ab747fSPaolo Bonzini 51549ab747fSPaolo Bonzini static void esp_do_dma(ESPState *s) 51649ab747fSPaolo Bonzini { 517023666daSMark Cave-Ayland uint32_t len, cmdlen; 518023666daSMark Cave-Ayland uint8_t buf[ESP_CMDFIFO_SZ]; 51949ab747fSPaolo Bonzini 5206cc88d6bSMark Cave-Ayland len = esp_get_tc(s); 521ad2725afSMark Cave-Ayland 522ad2725afSMark Cave-Ayland switch (esp_get_phase(s)) { 523ad2725afSMark Cave-Ayland case STAT_MO: 52446b0c361SMark Cave-Ayland if (s->dma_memory_read) { 52546b0c361SMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->cmdfifo)); 52646b0c361SMark Cave-Ayland s->dma_memory_read(s->dma_opaque, buf, len); 52746b0c361SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 52846b0c361SMark Cave-Ayland } else { 529da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 53067ea170eSMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 53167ea170eSMark Cave-Ayland esp_raise_drq(s); 53246b0c361SMark Cave-Ayland } 53346b0c361SMark Cave-Ayland 53467ea170eSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 53567ea170eSMark Cave-Ayland s->cmdfifo_cdb_offset += len; 53646b0c361SMark Cave-Ayland 5373ee9a475SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 5383ee9a475SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 5393ee9a475SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 5403ee9a475SMark Cave-Ayland /* First byte received, switch to command phase */ 5413ee9a475SMark Cave-Ayland esp_set_phase(s, STAT_CD); 5429b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 5433ee9a475SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 5443ee9a475SMark Cave-Ayland 5453ee9a475SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) > 1) { 5463ee9a475SMark Cave-Ayland /* Process any additional command phase data */ 5473ee9a475SMark Cave-Ayland esp_do_dma(s); 5483ee9a475SMark Cave-Ayland } 5493ee9a475SMark Cave-Ayland } 5503ee9a475SMark Cave-Ayland break; 5513ee9a475SMark Cave-Ayland 552db4d4150SMark Cave-Ayland case CMD_SELATNS | CMD_DMA: 553db4d4150SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) == 1) { 554db4d4150SMark Cave-Ayland /* First byte received, stop in message out phase */ 5559b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 556db4d4150SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 557db4d4150SMark Cave-Ayland 558db4d4150SMark Cave-Ayland /* Raise command completion interrupt */ 559db4d4150SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 560db4d4150SMark Cave-Ayland esp_raise_irq(s); 561db4d4150SMark Cave-Ayland } 562db4d4150SMark Cave-Ayland break; 563db4d4150SMark Cave-Ayland 5643fd325a2SMark Cave-Ayland case CMD_TI | CMD_DMA: 56546b0c361SMark Cave-Ayland /* ATN remains asserted until TC == 0 */ 56646b0c361SMark Cave-Ayland if (esp_get_tc(s) == 0) { 56746b0c361SMark Cave-Ayland esp_set_phase(s, STAT_CD); 568cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 56946b0c361SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 57046b0c361SMark Cave-Ayland esp_raise_irq(s); 57146b0c361SMark Cave-Ayland } 57246b0c361SMark Cave-Ayland break; 5733fd325a2SMark Cave-Ayland } 5743fd325a2SMark Cave-Ayland break; 57546b0c361SMark Cave-Ayland 576ad2725afSMark Cave-Ayland case STAT_CD: 577023666daSMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 578023666daSMark Cave-Ayland trace_esp_do_dma(cmdlen, len); 57974d71ea1SLaurent Vivier if (s->dma_memory_read) { 5800ebb5fd8SMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->cmdfifo)); 581023666daSMark Cave-Ayland s->dma_memory_read(s->dma_opaque, buf, len); 582023666daSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 583a0347651SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 58474d71ea1SLaurent Vivier } else { 585da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 586406e8a3eSMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 587406e8a3eSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 58874d71ea1SLaurent Vivier esp_raise_drq(s); 5893c7f3c8bSMark Cave-Ayland } 590023666daSMark Cave-Ayland trace_esp_handle_ti_cmd(cmdlen); 59115407433SLaurent Vivier s->ti_size = 0; 59246b0c361SMark Cave-Ayland if (esp_get_tc(s) == 0) { 593799d90d8SMark Cave-Ayland /* Command has been received */ 594c959f218SMark Cave-Ayland do_cmd(s); 595799d90d8SMark Cave-Ayland } 596ad2725afSMark Cave-Ayland break; 5971454dc76SMark Cave-Ayland 5981454dc76SMark Cave-Ayland case STAT_DO: 5990db89536SMark Cave-Ayland if (!s->current_req) { 6000db89536SMark Cave-Ayland return; 6010db89536SMark Cave-Ayland } 6024460b86aSMark Cave-Ayland if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { 60349ab747fSPaolo Bonzini /* Defer until data is available. */ 60449ab747fSPaolo Bonzini return; 60549ab747fSPaolo Bonzini } 60649ab747fSPaolo Bonzini if (len > s->async_len) { 60749ab747fSPaolo Bonzini len = s->async_len; 60849ab747fSPaolo Bonzini } 6090d17ce82SMark Cave-Ayland 610a6cad7cdSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 611a6cad7cdSMark Cave-Ayland case CMD_TI | CMD_DMA: 61274d71ea1SLaurent Vivier if (s->dma_memory_read) { 61349ab747fSPaolo Bonzini s->dma_memory_read(s->dma_opaque, s->async_buf, len); 614f3666223SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 6150d17ce82SMark Cave-Ayland } else { 6160d17ce82SMark Cave-Ayland /* Copy FIFO data to device */ 6170d17ce82SMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 6180d17ce82SMark Cave-Ayland len = MIN(len, fifo8_num_used(&s->fifo)); 619da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, s->async_buf, len); 6200d17ce82SMark Cave-Ayland esp_raise_drq(s); 6210d17ce82SMark Cave-Ayland } 6220d17ce82SMark Cave-Ayland 623f3666223SMark Cave-Ayland s->async_buf += len; 624f3666223SMark Cave-Ayland s->async_len -= len; 625f3666223SMark Cave-Ayland s->ti_size += len; 626a6cad7cdSMark Cave-Ayland break; 627a6cad7cdSMark Cave-Ayland 628a6cad7cdSMark Cave-Ayland case CMD_PAD | CMD_DMA: 629a6cad7cdSMark Cave-Ayland /* Copy TC zero bytes into the incoming stream */ 630a6cad7cdSMark Cave-Ayland if (!s->dma_memory_read) { 631a6cad7cdSMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 632a6cad7cdSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 633a6cad7cdSMark Cave-Ayland } 634a6cad7cdSMark Cave-Ayland 635a6cad7cdSMark Cave-Ayland memset(s->async_buf, 0, len); 636a6cad7cdSMark Cave-Ayland 637a6cad7cdSMark Cave-Ayland s->async_buf += len; 638a6cad7cdSMark Cave-Ayland s->async_len -= len; 639a6cad7cdSMark Cave-Ayland s->ti_size += len; 640a6cad7cdSMark Cave-Ayland break; 641a6cad7cdSMark Cave-Ayland } 642f3666223SMark Cave-Ayland 643e4e166c8SMark Cave-Ayland if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) { 644e4e166c8SMark Cave-Ayland /* Defer until the scsi layer has completed */ 645f3666223SMark Cave-Ayland scsi_req_continue(s->current_req); 646f3666223SMark Cave-Ayland return; 647f3666223SMark Cave-Ayland } 648f3666223SMark Cave-Ayland 649004826d0SMark Cave-Ayland esp_dma_ti_check(s); 6501454dc76SMark Cave-Ayland break; 6511454dc76SMark Cave-Ayland 6521454dc76SMark Cave-Ayland case STAT_DI: 6531454dc76SMark Cave-Ayland if (!s->current_req) { 6541454dc76SMark Cave-Ayland return; 6551454dc76SMark Cave-Ayland } 6561454dc76SMark Cave-Ayland if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { 6571454dc76SMark Cave-Ayland /* Defer until data is available. */ 6581454dc76SMark Cave-Ayland return; 6591454dc76SMark Cave-Ayland } 6601454dc76SMark Cave-Ayland if (len > s->async_len) { 6611454dc76SMark Cave-Ayland len = s->async_len; 6621454dc76SMark Cave-Ayland } 663c37cc88eSMark Cave-Ayland 664a6cad7cdSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 665a6cad7cdSMark Cave-Ayland case CMD_TI | CMD_DMA: 66674d71ea1SLaurent Vivier if (s->dma_memory_write) { 66749ab747fSPaolo Bonzini s->dma_memory_write(s->dma_opaque, s->async_buf, len); 66874d71ea1SLaurent Vivier } else { 66982141c8bSMark Cave-Ayland /* Copy device data to FIFO */ 670042879fcSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 671266170f9SMark Cave-Ayland esp_fifo_push_buf(s, s->async_buf, len); 672c37cc88eSMark Cave-Ayland esp_raise_drq(s); 673c37cc88eSMark Cave-Ayland } 674c37cc88eSMark Cave-Ayland 67582141c8bSMark Cave-Ayland s->async_buf += len; 67682141c8bSMark Cave-Ayland s->async_len -= len; 67782141c8bSMark Cave-Ayland s->ti_size -= len; 67882141c8bSMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 679a6cad7cdSMark Cave-Ayland break; 680a6cad7cdSMark Cave-Ayland 681a6cad7cdSMark Cave-Ayland case CMD_PAD | CMD_DMA: 682a6cad7cdSMark Cave-Ayland /* Drop TC bytes from the incoming stream */ 683a6cad7cdSMark Cave-Ayland if (!s->dma_memory_write) { 684a6cad7cdSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 685a6cad7cdSMark Cave-Ayland } 686a6cad7cdSMark Cave-Ayland 687a6cad7cdSMark Cave-Ayland s->async_buf += len; 688a6cad7cdSMark Cave-Ayland s->async_len -= len; 689a6cad7cdSMark Cave-Ayland s->ti_size -= len; 690a6cad7cdSMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 691a6cad7cdSMark Cave-Ayland break; 692a6cad7cdSMark Cave-Ayland } 693e4e166c8SMark Cave-Ayland 69402a3ce56SMark Cave-Ayland if (s->async_len == 0 && s->ti_size == 0 && esp_get_tc(s)) { 69502a3ce56SMark Cave-Ayland /* If the guest underflows TC then terminate SCSI request */ 69602a3ce56SMark Cave-Ayland scsi_req_continue(s->current_req); 69702a3ce56SMark Cave-Ayland return; 69802a3ce56SMark Cave-Ayland } 69902a3ce56SMark Cave-Ayland 700e4e166c8SMark Cave-Ayland if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) { 701e4e166c8SMark Cave-Ayland /* Defer until the scsi layer has completed */ 702e4e166c8SMark Cave-Ayland scsi_req_continue(s->current_req); 703e4e166c8SMark Cave-Ayland return; 704e4e166c8SMark Cave-Ayland } 705e4e166c8SMark Cave-Ayland 706004826d0SMark Cave-Ayland esp_dma_ti_check(s); 7071454dc76SMark Cave-Ayland break; 7088baa1472SMark Cave-Ayland 7098baa1472SMark Cave-Ayland case STAT_ST: 7108baa1472SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 7118baa1472SMark Cave-Ayland case CMD_ICCS | CMD_DMA: 7128baa1472SMark Cave-Ayland len = MIN(len, 1); 7138baa1472SMark Cave-Ayland 7148baa1472SMark Cave-Ayland if (len) { 7158baa1472SMark Cave-Ayland buf[0] = s->status; 7168baa1472SMark Cave-Ayland 7178baa1472SMark Cave-Ayland if (s->dma_memory_write) { 7188baa1472SMark Cave-Ayland s->dma_memory_write(s->dma_opaque, buf, len); 7198baa1472SMark Cave-Ayland } else { 720266170f9SMark Cave-Ayland esp_fifo_push_buf(s, buf, len); 7218baa1472SMark Cave-Ayland } 7228baa1472SMark Cave-Ayland 723421d1ca5SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 7248baa1472SMark Cave-Ayland esp_set_phase(s, STAT_MI); 7258baa1472SMark Cave-Ayland 7268baa1472SMark Cave-Ayland if (esp_get_tc(s) > 0) { 7278baa1472SMark Cave-Ayland /* Process any message in phase data */ 7288baa1472SMark Cave-Ayland esp_do_dma(s); 7298baa1472SMark Cave-Ayland } 7308baa1472SMark Cave-Ayland } 7318baa1472SMark Cave-Ayland break; 73202a3ce56SMark Cave-Ayland 73302a3ce56SMark Cave-Ayland default: 73402a3ce56SMark Cave-Ayland /* Consume remaining data if the guest underflows TC */ 73502a3ce56SMark Cave-Ayland if (fifo8_num_used(&s->fifo) < 2) { 73602a3ce56SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 73702a3ce56SMark Cave-Ayland esp_raise_irq(s); 73802a3ce56SMark Cave-Ayland esp_lower_drq(s); 73902a3ce56SMark Cave-Ayland } 74002a3ce56SMark Cave-Ayland break; 7418baa1472SMark Cave-Ayland } 7428baa1472SMark Cave-Ayland break; 7438baa1472SMark Cave-Ayland 7448baa1472SMark Cave-Ayland case STAT_MI: 7458baa1472SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 7468baa1472SMark Cave-Ayland case CMD_ICCS | CMD_DMA: 7478baa1472SMark Cave-Ayland len = MIN(len, 1); 7488baa1472SMark Cave-Ayland 7498baa1472SMark Cave-Ayland if (len) { 7508baa1472SMark Cave-Ayland buf[0] = 0; 7518baa1472SMark Cave-Ayland 7528baa1472SMark Cave-Ayland if (s->dma_memory_write) { 7538baa1472SMark Cave-Ayland s->dma_memory_write(s->dma_opaque, buf, len); 7548baa1472SMark Cave-Ayland } else { 755266170f9SMark Cave-Ayland esp_fifo_push_buf(s, buf, len); 7568baa1472SMark Cave-Ayland } 7578baa1472SMark Cave-Ayland 758421d1ca5SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 759421d1ca5SMark Cave-Ayland 7608baa1472SMark Cave-Ayland /* Raise end of command interrupt */ 7610ee71db4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_FC; 7628baa1472SMark Cave-Ayland esp_raise_irq(s); 7638baa1472SMark Cave-Ayland } 7648baa1472SMark Cave-Ayland break; 7658baa1472SMark Cave-Ayland } 7668baa1472SMark Cave-Ayland break; 76774d71ea1SLaurent Vivier } 76849ab747fSPaolo Bonzini } 76949ab747fSPaolo Bonzini 770a1b8d389SMark Cave-Ayland static void esp_nodma_ti_dataout(ESPState *s) 771a1b8d389SMark Cave-Ayland { 772a1b8d389SMark Cave-Ayland int len; 773a1b8d389SMark Cave-Ayland 774a1b8d389SMark Cave-Ayland if (!s->current_req) { 775a1b8d389SMark Cave-Ayland return; 776a1b8d389SMark Cave-Ayland } 777a1b8d389SMark Cave-Ayland if (s->async_len == 0) { 778a1b8d389SMark Cave-Ayland /* Defer until data is available. */ 779a1b8d389SMark Cave-Ayland return; 780a1b8d389SMark Cave-Ayland } 781a1b8d389SMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 782a1b8d389SMark Cave-Ayland len = MIN(len, fifo8_num_used(&s->fifo)); 783da838126SMark Cave-Ayland esp_fifo_pop_buf(s, s->async_buf, len); 784a1b8d389SMark Cave-Ayland s->async_buf += len; 785a1b8d389SMark Cave-Ayland s->async_len -= len; 786a1b8d389SMark Cave-Ayland s->ti_size += len; 787a1b8d389SMark Cave-Ayland 788a1b8d389SMark Cave-Ayland if (s->async_len == 0) { 789a1b8d389SMark Cave-Ayland scsi_req_continue(s->current_req); 790a1b8d389SMark Cave-Ayland return; 791a1b8d389SMark Cave-Ayland } 792a1b8d389SMark Cave-Ayland 793a1b8d389SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 794a1b8d389SMark Cave-Ayland esp_raise_irq(s); 795a1b8d389SMark Cave-Ayland } 796a1b8d389SMark Cave-Ayland 7971b9e48a5SMark Cave-Ayland static void esp_do_nodma(ESPState *s) 7981b9e48a5SMark Cave-Ayland { 7992572689bSMark Cave-Ayland uint8_t buf[ESP_FIFO_SZ]; 8007b320a8eSMark Cave-Ayland uint32_t cmdlen; 8015a857339SMark Cave-Ayland int len; 8021b9e48a5SMark Cave-Ayland 80383e803deSMark Cave-Ayland switch (esp_get_phase(s)) { 80483e803deSMark Cave-Ayland case STAT_MO: 805215d2579SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 806215d2579SMark Cave-Ayland case CMD_SELATN: 8072572689bSMark Cave-Ayland /* Copy FIFO into cmdfifo */ 808da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8095a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8105a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 8112572689bSMark Cave-Ayland 8125d02add4SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 8135d02add4SMark Cave-Ayland /* First byte received, switch to command phase */ 8145d02add4SMark Cave-Ayland esp_set_phase(s, STAT_CD); 8159b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 8165d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 8175d02add4SMark Cave-Ayland 8185d02add4SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) > 1) { 8195d02add4SMark Cave-Ayland /* Process any additional command phase data */ 8205d02add4SMark Cave-Ayland esp_do_nodma(s); 8215d02add4SMark Cave-Ayland } 8225d02add4SMark Cave-Ayland } 8235d02add4SMark Cave-Ayland break; 8245d02add4SMark Cave-Ayland 8255d02add4SMark Cave-Ayland case CMD_SELATNS: 826215d2579SMark Cave-Ayland /* Copy one byte from FIFO into cmdfifo */ 8275a50644eSMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, 8285a50644eSMark Cave-Ayland MIN(fifo8_num_used(&s->fifo), 1)); 8295a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8305a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 831215d2579SMark Cave-Ayland 832d39592ffSMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 8335d02add4SMark Cave-Ayland /* First byte received, stop in message out phase */ 8349b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 8355d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 8365d02add4SMark Cave-Ayland 8375d02add4SMark Cave-Ayland /* Raise command completion interrupt */ 8385d02add4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 8395d02add4SMark Cave-Ayland esp_raise_irq(s); 8405d02add4SMark Cave-Ayland } 8415d02add4SMark Cave-Ayland break; 8425d02add4SMark Cave-Ayland 8435d02add4SMark Cave-Ayland case CMD_TI: 844215d2579SMark Cave-Ayland /* Copy FIFO into cmdfifo */ 845da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8465a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8475a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 848215d2579SMark Cave-Ayland 8495d02add4SMark Cave-Ayland /* ATN remains asserted until FIFO empty */ 8501b9e48a5SMark Cave-Ayland s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo); 851abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_CD); 852cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 8531b9e48a5SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 8541b9e48a5SMark Cave-Ayland esp_raise_irq(s); 85579a6c7c6SMark Cave-Ayland break; 8565d02add4SMark Cave-Ayland } 8575d02add4SMark Cave-Ayland break; 85879a6c7c6SMark Cave-Ayland 85979a6c7c6SMark Cave-Ayland case STAT_CD: 860acdee66dSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 861acdee66dSMark Cave-Ayland case CMD_TI: 86279a6c7c6SMark Cave-Ayland /* Copy FIFO into cmdfifo */ 863da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8645a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8655a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 86679a6c7c6SMark Cave-Ayland 86779a6c7c6SMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 86879a6c7c6SMark Cave-Ayland trace_esp_handle_ti_cmd(cmdlen); 86979a6c7c6SMark Cave-Ayland 8705d02add4SMark Cave-Ayland /* CDB may be transferred in one or more TI commands */ 8715aa0df40SMark Cave-Ayland if (esp_cdb_ready(s)) { 87279a6c7c6SMark Cave-Ayland /* Command has been received */ 87379a6c7c6SMark Cave-Ayland do_cmd(s); 8745d02add4SMark Cave-Ayland } else { 8755d02add4SMark Cave-Ayland /* 8765d02add4SMark Cave-Ayland * If data was transferred from the FIFO then raise bus 8775d02add4SMark Cave-Ayland * service interrupt to indicate transfer complete. Otherwise 8785d02add4SMark Cave-Ayland * defer until the next FIFO write. 8795d02add4SMark Cave-Ayland */ 8805a857339SMark Cave-Ayland if (len) { 8815d02add4SMark Cave-Ayland /* Raise interrupt to indicate transfer complete */ 8825d02add4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 8835d02add4SMark Cave-Ayland esp_raise_irq(s); 8845d02add4SMark Cave-Ayland } 8855d02add4SMark Cave-Ayland } 8865d02add4SMark Cave-Ayland break; 8875d02add4SMark Cave-Ayland 8888ba32048SMark Cave-Ayland case CMD_SEL | CMD_DMA: 8898ba32048SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 890acdee66dSMark Cave-Ayland /* Copy FIFO into cmdfifo */ 891da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8925a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8935a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 894acdee66dSMark Cave-Ayland 8958ba32048SMark Cave-Ayland /* Handle when DMA transfer is terminated by non-DMA FIFO write */ 8965aa0df40SMark Cave-Ayland if (esp_cdb_ready(s)) { 8978ba32048SMark Cave-Ayland /* Command has been received */ 8988ba32048SMark Cave-Ayland do_cmd(s); 8998ba32048SMark Cave-Ayland } 9008ba32048SMark Cave-Ayland break; 9018ba32048SMark Cave-Ayland 9025d02add4SMark Cave-Ayland case CMD_SEL: 9035d02add4SMark Cave-Ayland case CMD_SELATN: 904acdee66dSMark Cave-Ayland /* FIFO already contain entire CDB: copy to cmdfifo and execute */ 905da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 9065a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 9075a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 908acdee66dSMark Cave-Ayland 9095d02add4SMark Cave-Ayland do_cmd(s); 9105d02add4SMark Cave-Ayland break; 9115d02add4SMark Cave-Ayland } 91283e803deSMark Cave-Ayland break; 9131b9e48a5SMark Cave-Ayland 9149d1aa52bSMark Cave-Ayland case STAT_DO: 9155d02add4SMark Cave-Ayland /* Accumulate data in FIFO until non-DMA TI is executed */ 9169d1aa52bSMark Cave-Ayland break; 9179d1aa52bSMark Cave-Ayland 9189d1aa52bSMark Cave-Ayland case STAT_DI: 9199d1aa52bSMark Cave-Ayland if (!s->current_req) { 9209d1aa52bSMark Cave-Ayland return; 9219d1aa52bSMark Cave-Ayland } 9229d1aa52bSMark Cave-Ayland if (s->async_len == 0) { 9239d1aa52bSMark Cave-Ayland /* Defer until data is available. */ 9249d1aa52bSMark Cave-Ayland return; 9259d1aa52bSMark Cave-Ayland } 9266ef2cabcSMark Cave-Ayland if (fifo8_is_empty(&s->fifo)) { 9271f46d1c3SMark Cave-Ayland esp_fifo_push(s, s->async_buf[0]); 9286ef2cabcSMark Cave-Ayland s->async_buf++; 9296ef2cabcSMark Cave-Ayland s->async_len--; 9306ef2cabcSMark Cave-Ayland s->ti_size--; 9316ef2cabcSMark Cave-Ayland } 9321b9e48a5SMark Cave-Ayland 9331b9e48a5SMark Cave-Ayland if (s->async_len == 0) { 9341b9e48a5SMark Cave-Ayland scsi_req_continue(s->current_req); 9351b9e48a5SMark Cave-Ayland return; 9361b9e48a5SMark Cave-Ayland } 9371b9e48a5SMark Cave-Ayland 9389655f72cSMark Cave-Ayland /* If preloading the FIFO, defer until TI command issued */ 9399655f72cSMark Cave-Ayland if (s->rregs[ESP_CMD] != CMD_TI) { 9409655f72cSMark Cave-Ayland return; 9419655f72cSMark Cave-Ayland } 9429655f72cSMark Cave-Ayland 9431b9e48a5SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 9441b9e48a5SMark Cave-Ayland esp_raise_irq(s); 9459d1aa52bSMark Cave-Ayland break; 94683428f7aSMark Cave-Ayland 94783428f7aSMark Cave-Ayland case STAT_ST: 94883428f7aSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 94983428f7aSMark Cave-Ayland case CMD_ICCS: 9501f46d1c3SMark Cave-Ayland esp_fifo_push(s, s->status); 95183428f7aSMark Cave-Ayland esp_set_phase(s, STAT_MI); 95283428f7aSMark Cave-Ayland 95383428f7aSMark Cave-Ayland /* Process any message in phase data */ 95483428f7aSMark Cave-Ayland esp_do_nodma(s); 95583428f7aSMark Cave-Ayland break; 95683428f7aSMark Cave-Ayland } 95783428f7aSMark Cave-Ayland break; 95883428f7aSMark Cave-Ayland 95983428f7aSMark Cave-Ayland case STAT_MI: 96083428f7aSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 96183428f7aSMark Cave-Ayland case CMD_ICCS: 9621f46d1c3SMark Cave-Ayland esp_fifo_push(s, 0); 96383428f7aSMark Cave-Ayland 9640ee71db4SMark Cave-Ayland /* Raise end of command interrupt */ 9650ee71db4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_FC; 96683428f7aSMark Cave-Ayland esp_raise_irq(s); 96783428f7aSMark Cave-Ayland break; 96883428f7aSMark Cave-Ayland } 96983428f7aSMark Cave-Ayland break; 9709d1aa52bSMark Cave-Ayland } 9711b9e48a5SMark Cave-Ayland } 9721b9e48a5SMark Cave-Ayland 9734aaa6ac3SMark Cave-Ayland void esp_command_complete(SCSIRequest *req, size_t resid) 97449ab747fSPaolo Bonzini { 9754aaa6ac3SMark Cave-Ayland ESPState *s = req->hba_private; 9765a83e83eSMark Cave-Ayland int to_device = (esp_get_phase(s) == STAT_DO); 9774aaa6ac3SMark Cave-Ayland 97849ab747fSPaolo Bonzini trace_esp_command_complete(); 9796ef2cabcSMark Cave-Ayland 9806ef2cabcSMark Cave-Ayland /* 9816ef2cabcSMark Cave-Ayland * Non-DMA transfers from the target will leave the last byte in 9826ef2cabcSMark Cave-Ayland * the FIFO so don't reset ti_size in this case 9836ef2cabcSMark Cave-Ayland */ 9846ef2cabcSMark Cave-Ayland if (s->dma || to_device) { 98549ab747fSPaolo Bonzini if (s->ti_size != 0) { 98649ab747fSPaolo Bonzini trace_esp_command_complete_unexpected(); 98749ab747fSPaolo Bonzini } 9886ef2cabcSMark Cave-Ayland } 9896ef2cabcSMark Cave-Ayland 99049ab747fSPaolo Bonzini s->async_len = 0; 9914aaa6ac3SMark Cave-Ayland if (req->status) { 99249ab747fSPaolo Bonzini trace_esp_command_complete_fail(); 99349ab747fSPaolo Bonzini } 9944aaa6ac3SMark Cave-Ayland s->status = req->status; 9956ef2cabcSMark Cave-Ayland 9966ef2cabcSMark Cave-Ayland /* 997cb988199SMark Cave-Ayland * Switch to status phase. For non-DMA transfers from the target the last 998cb988199SMark Cave-Ayland * byte is still in the FIFO 9996ef2cabcSMark Cave-Ayland */ 10008bb22495SMark Cave-Ayland s->ti_size = 0; 10018bb22495SMark Cave-Ayland 10028bb22495SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 10038bb22495SMark Cave-Ayland case CMD_SEL | CMD_DMA: 10048bb22495SMark Cave-Ayland case CMD_SEL: 10058bb22495SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 10068bb22495SMark Cave-Ayland case CMD_SELATN: 1007cb988199SMark Cave-Ayland /* 10088bb22495SMark Cave-Ayland * No data phase for sequencer command so raise deferred bus service 1009c90b2792SMark Cave-Ayland * and function complete interrupt 1010cb988199SMark Cave-Ayland */ 1011c90b2792SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 10129b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 10138bb22495SMark Cave-Ayland break; 1014cb22ce50SMark Cave-Ayland 1015cb22ce50SMark Cave-Ayland case CMD_TI | CMD_DMA: 1016cb22ce50SMark Cave-Ayland case CMD_TI: 1017cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 1018cb22ce50SMark Cave-Ayland break; 10196ef2cabcSMark Cave-Ayland } 10206ef2cabcSMark Cave-Ayland 10218bb22495SMark Cave-Ayland /* Raise bus service interrupt to indicate change to STATUS phase */ 10228bb22495SMark Cave-Ayland esp_set_phase(s, STAT_ST); 10238bb22495SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 10248bb22495SMark Cave-Ayland esp_raise_irq(s); 102502a3ce56SMark Cave-Ayland 102602a3ce56SMark Cave-Ayland /* Ensure DRQ is set correctly for TC underflow or normal completion */ 102702a3ce56SMark Cave-Ayland esp_dma_ti_check(s); 10288bb22495SMark Cave-Ayland 102949ab747fSPaolo Bonzini if (s->current_req) { 103049ab747fSPaolo Bonzini scsi_req_unref(s->current_req); 103149ab747fSPaolo Bonzini s->current_req = NULL; 103249ab747fSPaolo Bonzini s->current_dev = NULL; 103349ab747fSPaolo Bonzini } 103449ab747fSPaolo Bonzini } 103549ab747fSPaolo Bonzini 103649ab747fSPaolo Bonzini void esp_transfer_data(SCSIRequest *req, uint32_t len) 103749ab747fSPaolo Bonzini { 103849ab747fSPaolo Bonzini ESPState *s = req->hba_private; 10396cc88d6bSMark Cave-Ayland uint32_t dmalen = esp_get_tc(s); 104049ab747fSPaolo Bonzini 10416cc88d6bSMark Cave-Ayland trace_esp_transfer_data(dmalen, s->ti_size); 104249ab747fSPaolo Bonzini s->async_len = len; 104349ab747fSPaolo Bonzini s->async_buf = scsi_req_get_buf(req); 10444e78f3bfSMark Cave-Ayland 1045c90b2792SMark Cave-Ayland if (!s->data_ready) { 1046a4608fa0SMark Cave-Ayland s->data_ready = true; 1047a4608fa0SMark Cave-Ayland 1048a4608fa0SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 1049a4608fa0SMark Cave-Ayland case CMD_SEL | CMD_DMA: 1050a4608fa0SMark Cave-Ayland case CMD_SEL: 1051a4608fa0SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 1052a4608fa0SMark Cave-Ayland case CMD_SELATN: 1053c90b2792SMark Cave-Ayland /* 1054c90b2792SMark Cave-Ayland * Initial incoming data xfer is complete for sequencer command 1055c90b2792SMark Cave-Ayland * so raise deferred bus service and function complete interrupt 1056c90b2792SMark Cave-Ayland */ 1057c90b2792SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 10589b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 1059c90b2792SMark Cave-Ayland break; 1060c90b2792SMark Cave-Ayland 1061a4608fa0SMark Cave-Ayland case CMD_SELATNS | CMD_DMA: 1062a4608fa0SMark Cave-Ayland case CMD_SELATNS: 10634e78f3bfSMark Cave-Ayland /* 10644e78f3bfSMark Cave-Ayland * Initial incoming data xfer is complete so raise command 10654e78f3bfSMark Cave-Ayland * completion interrupt 10664e78f3bfSMark Cave-Ayland */ 10674e78f3bfSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 10689b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 1069a4608fa0SMark Cave-Ayland break; 1070a4608fa0SMark Cave-Ayland 1071a4608fa0SMark Cave-Ayland case CMD_TI | CMD_DMA: 1072a4608fa0SMark Cave-Ayland case CMD_TI: 1073a4608fa0SMark Cave-Ayland /* 1074a4608fa0SMark Cave-Ayland * Bus service interrupt raised because of initial change to 1075a4608fa0SMark Cave-Ayland * DATA phase 1076a4608fa0SMark Cave-Ayland */ 1077cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 1078a4608fa0SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 1079a4608fa0SMark Cave-Ayland break; 1080a4608fa0SMark Cave-Ayland } 1081c90b2792SMark Cave-Ayland 1082c90b2792SMark Cave-Ayland esp_raise_irq(s); 10834e78f3bfSMark Cave-Ayland } 10844e78f3bfSMark Cave-Ayland 10851b9e48a5SMark Cave-Ayland /* 10861b9e48a5SMark Cave-Ayland * Always perform the initial transfer upon reception of the next TI 10871b9e48a5SMark Cave-Ayland * command to ensure the DMA/non-DMA status of the command is correct. 10881b9e48a5SMark Cave-Ayland * It is not possible to use s->dma directly in the section below as 10891b9e48a5SMark Cave-Ayland * some OSs send non-DMA NOP commands after a DMA transfer. Hence if the 10901b9e48a5SMark Cave-Ayland * async data transfer is delayed then s->dma is set incorrectly. 10911b9e48a5SMark Cave-Ayland */ 10921b9e48a5SMark Cave-Ayland 109382003450SMark Cave-Ayland if (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA)) { 1094a79e767aSMark Cave-Ayland /* When the SCSI layer returns more data, raise deferred INTR_BS */ 1095004826d0SMark Cave-Ayland esp_dma_ti_check(s); 1096a79e767aSMark Cave-Ayland 1097a79e767aSMark Cave-Ayland esp_do_dma(s); 109882003450SMark Cave-Ayland } else if (s->rregs[ESP_CMD] == CMD_TI) { 10991b9e48a5SMark Cave-Ayland esp_do_nodma(s); 11001b9e48a5SMark Cave-Ayland } 110149ab747fSPaolo Bonzini } 110249ab747fSPaolo Bonzini 110349ab747fSPaolo Bonzini static void handle_ti(ESPState *s) 110449ab747fSPaolo Bonzini { 11051b9e48a5SMark Cave-Ayland uint32_t dmalen; 110649ab747fSPaolo Bonzini 110749ab747fSPaolo Bonzini if (s->dma && !s->dma_enabled) { 110849ab747fSPaolo Bonzini s->dma_cb = handle_ti; 110949ab747fSPaolo Bonzini return; 111049ab747fSPaolo Bonzini } 111149ab747fSPaolo Bonzini 111249ab747fSPaolo Bonzini if (s->dma) { 11131b9e48a5SMark Cave-Ayland dmalen = esp_get_tc(s); 1114b76624deSMark Cave-Ayland trace_esp_handle_ti(dmalen); 111549ab747fSPaolo Bonzini esp_do_dma(s); 1116799d90d8SMark Cave-Ayland } else { 11171b9e48a5SMark Cave-Ayland trace_esp_handle_ti(s->ti_size); 11181b9e48a5SMark Cave-Ayland esp_do_nodma(s); 11195d02add4SMark Cave-Ayland 11205d02add4SMark Cave-Ayland if (esp_get_phase(s) == STAT_DO) { 11215d02add4SMark Cave-Ayland esp_nodma_ti_dataout(s); 11225d02add4SMark Cave-Ayland } 112349ab747fSPaolo Bonzini } 112449ab747fSPaolo Bonzini } 112549ab747fSPaolo Bonzini 112649ab747fSPaolo Bonzini void esp_hard_reset(ESPState *s) 112749ab747fSPaolo Bonzini { 112849ab747fSPaolo Bonzini memset(s->rregs, 0, ESP_REGS); 112949ab747fSPaolo Bonzini memset(s->wregs, 0, ESP_REGS); 1130c9cf45c1SHannes Reinecke s->tchi_written = 0; 113149ab747fSPaolo Bonzini s->ti_size = 0; 11323f26c975SMark Cave-Ayland s->async_len = 0; 1133042879fcSMark Cave-Ayland fifo8_reset(&s->fifo); 1134023666daSMark Cave-Ayland fifo8_reset(&s->cmdfifo); 113549ab747fSPaolo Bonzini s->dma = 0; 113649ab747fSPaolo Bonzini s->dma_cb = NULL; 113749ab747fSPaolo Bonzini 113849ab747fSPaolo Bonzini s->rregs[ESP_CFG1] = 7; 113949ab747fSPaolo Bonzini } 114049ab747fSPaolo Bonzini 114149ab747fSPaolo Bonzini static void esp_soft_reset(ESPState *s) 114249ab747fSPaolo Bonzini { 114349ab747fSPaolo Bonzini qemu_irq_lower(s->irq); 11446dec7c0dSMark Cave-Ayland qemu_irq_lower(s->drq_irq); 114549ab747fSPaolo Bonzini esp_hard_reset(s); 114649ab747fSPaolo Bonzini } 114749ab747fSPaolo Bonzini 1148c6e51f1bSJohn Millikin static void esp_bus_reset(ESPState *s) 1149c6e51f1bSJohn Millikin { 11504a5fc890SPeter Maydell bus_cold_reset(BUS(&s->bus)); 1151c6e51f1bSJohn Millikin } 1152c6e51f1bSJohn Millikin 115349ab747fSPaolo Bonzini static void parent_esp_reset(ESPState *s, int irq, int level) 115449ab747fSPaolo Bonzini { 115549ab747fSPaolo Bonzini if (level) { 115649ab747fSPaolo Bonzini esp_soft_reset(s); 115749ab747fSPaolo Bonzini } 115849ab747fSPaolo Bonzini } 115949ab747fSPaolo Bonzini 1160f21fe39dSMark Cave-Ayland static void esp_run_cmd(ESPState *s) 1161f21fe39dSMark Cave-Ayland { 1162f21fe39dSMark Cave-Ayland uint8_t cmd = s->rregs[ESP_CMD]; 1163f21fe39dSMark Cave-Ayland 1164f21fe39dSMark Cave-Ayland if (cmd & CMD_DMA) { 1165f21fe39dSMark Cave-Ayland s->dma = 1; 1166f21fe39dSMark Cave-Ayland /* Reload DMA counter. */ 1167f21fe39dSMark Cave-Ayland if (esp_get_stc(s) == 0) { 1168f21fe39dSMark Cave-Ayland esp_set_tc(s, 0x10000); 1169f21fe39dSMark Cave-Ayland } else { 1170f21fe39dSMark Cave-Ayland esp_set_tc(s, esp_get_stc(s)); 1171f21fe39dSMark Cave-Ayland } 1172f21fe39dSMark Cave-Ayland } else { 1173f21fe39dSMark Cave-Ayland s->dma = 0; 1174f21fe39dSMark Cave-Ayland } 1175f21fe39dSMark Cave-Ayland switch (cmd & CMD_CMD) { 1176f21fe39dSMark Cave-Ayland case CMD_NOP: 1177f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_nop(cmd); 1178f21fe39dSMark Cave-Ayland break; 1179f21fe39dSMark Cave-Ayland case CMD_FLUSH: 1180f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_flush(cmd); 1181f21fe39dSMark Cave-Ayland fifo8_reset(&s->fifo); 1182f21fe39dSMark Cave-Ayland break; 1183f21fe39dSMark Cave-Ayland case CMD_RESET: 1184f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_reset(cmd); 1185f21fe39dSMark Cave-Ayland esp_soft_reset(s); 1186f21fe39dSMark Cave-Ayland break; 1187f21fe39dSMark Cave-Ayland case CMD_BUSRESET: 1188f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_bus_reset(cmd); 1189f21fe39dSMark Cave-Ayland esp_bus_reset(s); 1190f21fe39dSMark Cave-Ayland if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { 1191f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_RST; 1192f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1193f21fe39dSMark Cave-Ayland } 1194f21fe39dSMark Cave-Ayland break; 1195f21fe39dSMark Cave-Ayland case CMD_TI: 1196f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_ti(cmd); 1197f21fe39dSMark Cave-Ayland handle_ti(s); 1198f21fe39dSMark Cave-Ayland break; 1199f21fe39dSMark Cave-Ayland case CMD_ICCS: 1200f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_iccs(cmd); 1201f21fe39dSMark Cave-Ayland write_response(s); 1202f21fe39dSMark Cave-Ayland break; 1203f21fe39dSMark Cave-Ayland case CMD_MSGACC: 1204f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_msgacc(cmd); 1205f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_DC; 1206f21fe39dSMark Cave-Ayland s->rregs[ESP_RSEQ] = 0; 1207f21fe39dSMark Cave-Ayland s->rregs[ESP_RFLAGS] = 0; 1208f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1209f21fe39dSMark Cave-Ayland break; 1210f21fe39dSMark Cave-Ayland case CMD_PAD: 1211f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_pad(cmd); 1212a6cad7cdSMark Cave-Ayland handle_pad(s); 1213f21fe39dSMark Cave-Ayland break; 1214f21fe39dSMark Cave-Ayland case CMD_SATN: 1215f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_satn(cmd); 1216f21fe39dSMark Cave-Ayland break; 1217f21fe39dSMark Cave-Ayland case CMD_RSTATN: 1218f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_rstatn(cmd); 1219f21fe39dSMark Cave-Ayland break; 1220f21fe39dSMark Cave-Ayland case CMD_SEL: 1221f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_sel(cmd); 1222f21fe39dSMark Cave-Ayland handle_s_without_atn(s); 1223f21fe39dSMark Cave-Ayland break; 1224f21fe39dSMark Cave-Ayland case CMD_SELATN: 1225f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_selatn(cmd); 1226f21fe39dSMark Cave-Ayland handle_satn(s); 1227f21fe39dSMark Cave-Ayland break; 1228f21fe39dSMark Cave-Ayland case CMD_SELATNS: 1229f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_selatns(cmd); 1230f21fe39dSMark Cave-Ayland handle_satn_stop(s); 1231f21fe39dSMark Cave-Ayland break; 1232f21fe39dSMark Cave-Ayland case CMD_ENSEL: 1233f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_ensel(cmd); 1234f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] = 0; 1235f21fe39dSMark Cave-Ayland break; 1236f21fe39dSMark Cave-Ayland case CMD_DISSEL: 1237f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_dissel(cmd); 1238f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] = 0; 1239f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1240f21fe39dSMark Cave-Ayland break; 1241f21fe39dSMark Cave-Ayland default: 1242f21fe39dSMark Cave-Ayland trace_esp_error_unhandled_command(cmd); 1243f21fe39dSMark Cave-Ayland break; 1244f21fe39dSMark Cave-Ayland } 1245f21fe39dSMark Cave-Ayland } 1246f21fe39dSMark Cave-Ayland 124749ab747fSPaolo Bonzini uint64_t esp_reg_read(ESPState *s, uint32_t saddr) 124849ab747fSPaolo Bonzini { 1249b630c075SMark Cave-Ayland uint32_t val; 125049ab747fSPaolo Bonzini 125149ab747fSPaolo Bonzini switch (saddr) { 125249ab747fSPaolo Bonzini case ESP_FIFO: 125361fa150dSMark Cave-Ayland s->rregs[ESP_FIFO] = esp_fifo_pop(s); 1254b630c075SMark Cave-Ayland val = s->rregs[ESP_FIFO]; 125549ab747fSPaolo Bonzini break; 125649ab747fSPaolo Bonzini case ESP_RINTR: 125794d5c79dSMark Cave-Ayland /* 125894d5c79dSMark Cave-Ayland * Clear sequence step, interrupt register and all status bits 125994d5c79dSMark Cave-Ayland * except TC 126094d5c79dSMark Cave-Ayland */ 1261b630c075SMark Cave-Ayland val = s->rregs[ESP_RINTR]; 126249ab747fSPaolo Bonzini s->rregs[ESP_RINTR] = 0; 1263d294b77aSMark Cave-Ayland esp_lower_irq(s); 1264d68212cdSMark Cave-Ayland s->rregs[ESP_RSTAT] &= STAT_TC | 7; 1265af947a3dSMark Cave-Ayland /* 1266af947a3dSMark Cave-Ayland * According to the datasheet ESP_RSEQ should be cleared, but as the 1267af947a3dSMark Cave-Ayland * emulation currently defers information transfers to the next TI 1268af947a3dSMark Cave-Ayland * command leave it for now so that pedantic guests such as the old 1269af947a3dSMark Cave-Ayland * Linux 2.6 driver see the correct flags before the next SCSI phase 1270af947a3dSMark Cave-Ayland * transition. 1271af947a3dSMark Cave-Ayland * 1272af947a3dSMark Cave-Ayland * s->rregs[ESP_RSEQ] = SEQ_0; 1273af947a3dSMark Cave-Ayland */ 1274b630c075SMark Cave-Ayland break; 1275c9cf45c1SHannes Reinecke case ESP_TCHI: 1276c9cf45c1SHannes Reinecke /* Return the unique id if the value has never been written */ 1277c9cf45c1SHannes Reinecke if (!s->tchi_written) { 1278b630c075SMark Cave-Ayland val = s->chip_id; 1279b630c075SMark Cave-Ayland } else { 1280b630c075SMark Cave-Ayland val = s->rregs[saddr]; 1281c9cf45c1SHannes Reinecke } 1282b630c075SMark Cave-Ayland break; 1283238ec4d7SMark Cave-Ayland case ESP_RFLAGS: 1284238ec4d7SMark Cave-Ayland /* Bottom 5 bits indicate number of bytes in FIFO */ 1285238ec4d7SMark Cave-Ayland val = fifo8_num_used(&s->fifo); 1286238ec4d7SMark Cave-Ayland break; 128749ab747fSPaolo Bonzini default: 1288b630c075SMark Cave-Ayland val = s->rregs[saddr]; 128949ab747fSPaolo Bonzini break; 129049ab747fSPaolo Bonzini } 1291b630c075SMark Cave-Ayland 1292b630c075SMark Cave-Ayland trace_esp_mem_readb(saddr, val); 1293b630c075SMark Cave-Ayland return val; 129449ab747fSPaolo Bonzini } 129549ab747fSPaolo Bonzini 129649ab747fSPaolo Bonzini void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) 129749ab747fSPaolo Bonzini { 129849ab747fSPaolo Bonzini trace_esp_mem_writeb(saddr, s->wregs[saddr], val); 129949ab747fSPaolo Bonzini switch (saddr) { 1300c9cf45c1SHannes Reinecke case ESP_TCHI: 1301c9cf45c1SHannes Reinecke s->tchi_written = true; 1302c9cf45c1SHannes Reinecke /* fall through */ 130349ab747fSPaolo Bonzini case ESP_TCLO: 130449ab747fSPaolo Bonzini case ESP_TCMID: 130549ab747fSPaolo Bonzini s->rregs[ESP_RSTAT] &= ~STAT_TC; 130649ab747fSPaolo Bonzini break; 130749ab747fSPaolo Bonzini case ESP_FIFO: 13082572689bSMark Cave-Ayland if (!fifo8_is_full(&s->fifo)) { 13090e7dbe29SMark Cave-Ayland esp_fifo_push(s, val); 13102572689bSMark Cave-Ayland } 13115d02add4SMark Cave-Ayland esp_do_nodma(s); 131249ab747fSPaolo Bonzini break; 131349ab747fSPaolo Bonzini case ESP_CMD: 131449ab747fSPaolo Bonzini s->rregs[saddr] = val; 1315f21fe39dSMark Cave-Ayland esp_run_cmd(s); 131649ab747fSPaolo Bonzini break; 131749ab747fSPaolo Bonzini case ESP_WBUSID ... ESP_WSYNO: 131849ab747fSPaolo Bonzini break; 131949ab747fSPaolo Bonzini case ESP_CFG1: 132049ab747fSPaolo Bonzini case ESP_CFG2: case ESP_CFG3: 132149ab747fSPaolo Bonzini case ESP_RES3: case ESP_RES4: 132249ab747fSPaolo Bonzini s->rregs[saddr] = val; 132349ab747fSPaolo Bonzini break; 132449ab747fSPaolo Bonzini case ESP_WCCF ... ESP_WTEST: 132549ab747fSPaolo Bonzini break; 132649ab747fSPaolo Bonzini default: 132749ab747fSPaolo Bonzini trace_esp_error_invalid_write(val, saddr); 132849ab747fSPaolo Bonzini return; 132949ab747fSPaolo Bonzini } 133049ab747fSPaolo Bonzini s->wregs[saddr] = val; 133149ab747fSPaolo Bonzini } 133249ab747fSPaolo Bonzini 133349ab747fSPaolo Bonzini static bool esp_mem_accepts(void *opaque, hwaddr addr, 13348372d383SPeter Maydell unsigned size, bool is_write, 13358372d383SPeter Maydell MemTxAttrs attrs) 133649ab747fSPaolo Bonzini { 133749ab747fSPaolo Bonzini return (size == 1) || (is_write && size == 4); 133849ab747fSPaolo Bonzini } 133949ab747fSPaolo Bonzini 13406cc88d6bSMark Cave-Ayland static bool esp_is_before_version_5(void *opaque, int version_id) 13416cc88d6bSMark Cave-Ayland { 13426cc88d6bSMark Cave-Ayland ESPState *s = ESP(opaque); 13436cc88d6bSMark Cave-Ayland 13446cc88d6bSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13456cc88d6bSMark Cave-Ayland return version_id < 5; 13466cc88d6bSMark Cave-Ayland } 13476cc88d6bSMark Cave-Ayland 13484e78f3bfSMark Cave-Ayland static bool esp_is_version_5(void *opaque, int version_id) 13494e78f3bfSMark Cave-Ayland { 13504e78f3bfSMark Cave-Ayland ESPState *s = ESP(opaque); 13514e78f3bfSMark Cave-Ayland 13524e78f3bfSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13530bcd5a18SMark Cave-Ayland return version_id >= 5; 13544e78f3bfSMark Cave-Ayland } 13554e78f3bfSMark Cave-Ayland 13564eb86065SPaolo Bonzini static bool esp_is_version_6(void *opaque, int version_id) 13574eb86065SPaolo Bonzini { 13584eb86065SPaolo Bonzini ESPState *s = ESP(opaque); 13594eb86065SPaolo Bonzini 13604eb86065SPaolo Bonzini version_id = MIN(version_id, s->mig_version_id); 13614eb86065SPaolo Bonzini return version_id >= 6; 13624eb86065SPaolo Bonzini } 13634eb86065SPaolo Bonzini 136482003450SMark Cave-Ayland static bool esp_is_between_version_5_and_6(void *opaque, int version_id) 136582003450SMark Cave-Ayland { 136682003450SMark Cave-Ayland ESPState *s = ESP(opaque); 136782003450SMark Cave-Ayland 136882003450SMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 136982003450SMark Cave-Ayland return version_id >= 5 && version_id <= 6; 137082003450SMark Cave-Ayland } 137182003450SMark Cave-Ayland 1372ff4a1dabSMark Cave-Ayland int esp_pre_save(void *opaque) 13730bd005beSMark Cave-Ayland { 1374ff4a1dabSMark Cave-Ayland ESPState *s = ESP(object_resolve_path_component( 1375ff4a1dabSMark Cave-Ayland OBJECT(opaque), "esp")); 13760bd005beSMark Cave-Ayland 13770bd005beSMark Cave-Ayland s->mig_version_id = vmstate_esp.version_id; 13780bd005beSMark Cave-Ayland return 0; 13790bd005beSMark Cave-Ayland } 13800bd005beSMark Cave-Ayland 13810bd005beSMark Cave-Ayland static int esp_post_load(void *opaque, int version_id) 13820bd005beSMark Cave-Ayland { 13830bd005beSMark Cave-Ayland ESPState *s = ESP(opaque); 1384042879fcSMark Cave-Ayland int len, i; 13850bd005beSMark Cave-Ayland 13866cc88d6bSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13876cc88d6bSMark Cave-Ayland 13886cc88d6bSMark Cave-Ayland if (version_id < 5) { 13896cc88d6bSMark Cave-Ayland esp_set_tc(s, s->mig_dma_left); 1390042879fcSMark Cave-Ayland 1391042879fcSMark Cave-Ayland /* Migrate ti_buf to fifo */ 1392042879fcSMark Cave-Ayland len = s->mig_ti_wptr - s->mig_ti_rptr; 1393042879fcSMark Cave-Ayland for (i = 0; i < len; i++) { 1394042879fcSMark Cave-Ayland fifo8_push(&s->fifo, s->mig_ti_buf[i]); 1395042879fcSMark Cave-Ayland } 1396023666daSMark Cave-Ayland 1397023666daSMark Cave-Ayland /* Migrate cmdbuf to cmdfifo */ 1398023666daSMark Cave-Ayland for (i = 0; i < s->mig_cmdlen; i++) { 1399023666daSMark Cave-Ayland fifo8_push(&s->cmdfifo, s->mig_cmdbuf[i]); 1400023666daSMark Cave-Ayland } 14016cc88d6bSMark Cave-Ayland } 14026cc88d6bSMark Cave-Ayland 14030bd005beSMark Cave-Ayland s->mig_version_id = vmstate_esp.version_id; 14040bd005beSMark Cave-Ayland return 0; 14050bd005beSMark Cave-Ayland } 14060bd005beSMark Cave-Ayland 140749ab747fSPaolo Bonzini const VMStateDescription vmstate_esp = { 140849ab747fSPaolo Bonzini .name = "esp", 140982003450SMark Cave-Ayland .version_id = 7, 141049ab747fSPaolo Bonzini .minimum_version_id = 3, 14110bd005beSMark Cave-Ayland .post_load = esp_post_load, 14122d7b39a6SRichard Henderson .fields = (const VMStateField[]) { 141349ab747fSPaolo Bonzini VMSTATE_BUFFER(rregs, ESPState), 141449ab747fSPaolo Bonzini VMSTATE_BUFFER(wregs, ESPState), 141549ab747fSPaolo Bonzini VMSTATE_INT32(ti_size, ESPState), 1416042879fcSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_ti_rptr, ESPState, esp_is_before_version_5), 1417042879fcSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_ti_wptr, ESPState, esp_is_before_version_5), 1418042879fcSMark Cave-Ayland VMSTATE_BUFFER_TEST(mig_ti_buf, ESPState, esp_is_before_version_5), 141949ab747fSPaolo Bonzini VMSTATE_UINT32(status, ESPState), 14204aaa6ac3SMark Cave-Ayland VMSTATE_UINT32_TEST(mig_deferred_status, ESPState, 14214aaa6ac3SMark Cave-Ayland esp_is_before_version_5), 14224aaa6ac3SMark Cave-Ayland VMSTATE_BOOL_TEST(mig_deferred_complete, ESPState, 14234aaa6ac3SMark Cave-Ayland esp_is_before_version_5), 142449ab747fSPaolo Bonzini VMSTATE_UINT32(dma, ESPState), 1425023666daSMark Cave-Ayland VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 0, 1426023666daSMark Cave-Ayland esp_is_before_version_5, 0, 16), 1427023666daSMark Cave-Ayland VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 4, 1428023666daSMark Cave-Ayland esp_is_before_version_5, 16, 1429023666daSMark Cave-Ayland sizeof(typeof_field(ESPState, mig_cmdbuf))), 1430023666daSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_cmdlen, ESPState, esp_is_before_version_5), 143149ab747fSPaolo Bonzini VMSTATE_UINT32(do_cmd, ESPState), 14326cc88d6bSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5), 14338dded6deSMark Cave-Ayland VMSTATE_BOOL_TEST(data_ready, ESPState, esp_is_version_5), 1434023666daSMark Cave-Ayland VMSTATE_UINT8_TEST(cmdfifo_cdb_offset, ESPState, esp_is_version_5), 1435042879fcSMark Cave-Ayland VMSTATE_FIFO8_TEST(fifo, ESPState, esp_is_version_5), 1436023666daSMark Cave-Ayland VMSTATE_FIFO8_TEST(cmdfifo, ESPState, esp_is_version_5), 143782003450SMark Cave-Ayland VMSTATE_UINT8_TEST(mig_ti_cmd, ESPState, 143882003450SMark Cave-Ayland esp_is_between_version_5_and_6), 14394eb86065SPaolo Bonzini VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6), 1440442de89aSMark Cave-Ayland VMSTATE_BOOL(drq_state, ESPState), 144149ab747fSPaolo Bonzini VMSTATE_END_OF_LIST() 144274d71ea1SLaurent Vivier }, 144349ab747fSPaolo Bonzini }; 144449ab747fSPaolo Bonzini 144549ab747fSPaolo Bonzini static void sysbus_esp_mem_write(void *opaque, hwaddr addr, 144649ab747fSPaolo Bonzini uint64_t val, unsigned int size) 144749ab747fSPaolo Bonzini { 144849ab747fSPaolo Bonzini SysBusESPState *sysbus = opaque; 1449eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 145049ab747fSPaolo Bonzini uint32_t saddr; 145149ab747fSPaolo Bonzini 145249ab747fSPaolo Bonzini saddr = addr >> sysbus->it_shift; 1453eb169c76SMark Cave-Ayland esp_reg_write(s, saddr, val); 145449ab747fSPaolo Bonzini } 145549ab747fSPaolo Bonzini 145649ab747fSPaolo Bonzini static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr, 145749ab747fSPaolo Bonzini unsigned int size) 145849ab747fSPaolo Bonzini { 145949ab747fSPaolo Bonzini SysBusESPState *sysbus = opaque; 1460eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 146149ab747fSPaolo Bonzini uint32_t saddr; 146249ab747fSPaolo Bonzini 146349ab747fSPaolo Bonzini saddr = addr >> sysbus->it_shift; 1464eb169c76SMark Cave-Ayland return esp_reg_read(s, saddr); 146549ab747fSPaolo Bonzini } 146649ab747fSPaolo Bonzini 146749ab747fSPaolo Bonzini static const MemoryRegionOps sysbus_esp_mem_ops = { 146849ab747fSPaolo Bonzini .read = sysbus_esp_mem_read, 146949ab747fSPaolo Bonzini .write = sysbus_esp_mem_write, 147049ab747fSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 147149ab747fSPaolo Bonzini .valid.accepts = esp_mem_accepts, 147249ab747fSPaolo Bonzini }; 147349ab747fSPaolo Bonzini 147474d71ea1SLaurent Vivier static void sysbus_esp_pdma_write(void *opaque, hwaddr addr, 147574d71ea1SLaurent Vivier uint64_t val, unsigned int size) 147674d71ea1SLaurent Vivier { 147774d71ea1SLaurent Vivier SysBusESPState *sysbus = opaque; 1478eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 147974d71ea1SLaurent Vivier 1480960ebfd9SMark Cave-Ayland trace_esp_pdma_write(size); 1481960ebfd9SMark Cave-Ayland 148274d71ea1SLaurent Vivier switch (size) { 148374d71ea1SLaurent Vivier case 1: 1484761bef75SMark Cave-Ayland esp_pdma_write(s, val); 148574d71ea1SLaurent Vivier break; 148674d71ea1SLaurent Vivier case 2: 1487761bef75SMark Cave-Ayland esp_pdma_write(s, val >> 8); 1488761bef75SMark Cave-Ayland esp_pdma_write(s, val); 148974d71ea1SLaurent Vivier break; 149074d71ea1SLaurent Vivier } 1491b46a43a2SMark Cave-Ayland esp_do_dma(s); 149274d71ea1SLaurent Vivier } 149374d71ea1SLaurent Vivier 149474d71ea1SLaurent Vivier static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr, 149574d71ea1SLaurent Vivier unsigned int size) 149674d71ea1SLaurent Vivier { 149774d71ea1SLaurent Vivier SysBusESPState *sysbus = opaque; 1498eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 149974d71ea1SLaurent Vivier uint64_t val = 0; 150074d71ea1SLaurent Vivier 1501960ebfd9SMark Cave-Ayland trace_esp_pdma_read(size); 1502960ebfd9SMark Cave-Ayland 150374d71ea1SLaurent Vivier switch (size) { 150474d71ea1SLaurent Vivier case 1: 1505761bef75SMark Cave-Ayland val = esp_pdma_read(s); 150674d71ea1SLaurent Vivier break; 150774d71ea1SLaurent Vivier case 2: 1508761bef75SMark Cave-Ayland val = esp_pdma_read(s); 1509761bef75SMark Cave-Ayland val = (val << 8) | esp_pdma_read(s); 151074d71ea1SLaurent Vivier break; 151174d71ea1SLaurent Vivier } 1512b46a43a2SMark Cave-Ayland esp_do_dma(s); 151374d71ea1SLaurent Vivier return val; 151474d71ea1SLaurent Vivier } 151574d71ea1SLaurent Vivier 1516a7a22088SMark Cave-Ayland static void *esp_load_request(QEMUFile *f, SCSIRequest *req) 1517a7a22088SMark Cave-Ayland { 1518a7a22088SMark Cave-Ayland ESPState *s = container_of(req->bus, ESPState, bus); 1519a7a22088SMark Cave-Ayland 1520a7a22088SMark Cave-Ayland scsi_req_ref(req); 1521a7a22088SMark Cave-Ayland s->current_req = req; 1522a7a22088SMark Cave-Ayland return s; 1523a7a22088SMark Cave-Ayland } 1524a7a22088SMark Cave-Ayland 152574d71ea1SLaurent Vivier static const MemoryRegionOps sysbus_esp_pdma_ops = { 152674d71ea1SLaurent Vivier .read = sysbus_esp_pdma_read, 152774d71ea1SLaurent Vivier .write = sysbus_esp_pdma_write, 152874d71ea1SLaurent Vivier .endianness = DEVICE_NATIVE_ENDIAN, 152974d71ea1SLaurent Vivier .valid.min_access_size = 1, 1530cf1b8286SMark Cave-Ayland .valid.max_access_size = 4, 1531cf1b8286SMark Cave-Ayland .impl.min_access_size = 1, 1532cf1b8286SMark Cave-Ayland .impl.max_access_size = 2, 153374d71ea1SLaurent Vivier }; 153474d71ea1SLaurent Vivier 153549ab747fSPaolo Bonzini static const struct SCSIBusInfo esp_scsi_info = { 153649ab747fSPaolo Bonzini .tcq = false, 153749ab747fSPaolo Bonzini .max_target = ESP_MAX_DEVS, 153849ab747fSPaolo Bonzini .max_lun = 7, 153949ab747fSPaolo Bonzini 1540a7a22088SMark Cave-Ayland .load_request = esp_load_request, 154149ab747fSPaolo Bonzini .transfer_data = esp_transfer_data, 154249ab747fSPaolo Bonzini .complete = esp_command_complete, 154349ab747fSPaolo Bonzini .cancel = esp_request_cancelled 154449ab747fSPaolo Bonzini }; 154549ab747fSPaolo Bonzini 154649ab747fSPaolo Bonzini static void sysbus_esp_gpio_demux(void *opaque, int irq, int level) 154749ab747fSPaolo Bonzini { 154884fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(opaque); 1549eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 155049ab747fSPaolo Bonzini 155149ab747fSPaolo Bonzini switch (irq) { 155249ab747fSPaolo Bonzini case 0: 155349ab747fSPaolo Bonzini parent_esp_reset(s, irq, level); 155449ab747fSPaolo Bonzini break; 155549ab747fSPaolo Bonzini case 1: 1556b86dc5cbSMark Cave-Ayland esp_dma_enable(s, irq, level); 155749ab747fSPaolo Bonzini break; 155849ab747fSPaolo Bonzini } 155949ab747fSPaolo Bonzini } 156049ab747fSPaolo Bonzini 1561b09318caSHu Tao static void sysbus_esp_realize(DeviceState *dev, Error **errp) 156249ab747fSPaolo Bonzini { 1563b09318caSHu Tao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 156484fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(dev); 1565eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1566eb169c76SMark Cave-Ayland 1567eb169c76SMark Cave-Ayland if (!qdev_realize(DEVICE(s), NULL, errp)) { 1568eb169c76SMark Cave-Ayland return; 1569eb169c76SMark Cave-Ayland } 157049ab747fSPaolo Bonzini 1571b09318caSHu Tao sysbus_init_irq(sbd, &s->irq); 15726dec7c0dSMark Cave-Ayland sysbus_init_irq(sbd, &s->drq_irq); 157349ab747fSPaolo Bonzini assert(sysbus->it_shift != -1); 157449ab747fSPaolo Bonzini 157549ab747fSPaolo Bonzini s->chip_id = TCHI_FAS100A; 157629776739SPaolo Bonzini memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops, 157774d71ea1SLaurent Vivier sysbus, "esp-regs", ESP_REGS << sysbus->it_shift); 1578b09318caSHu Tao sysbus_init_mmio(sbd, &sysbus->iomem); 157974d71ea1SLaurent Vivier memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_ops, 1580cf1b8286SMark Cave-Ayland sysbus, "esp-pdma", 4); 158174d71ea1SLaurent Vivier sysbus_init_mmio(sbd, &sysbus->pdma); 158249ab747fSPaolo Bonzini 1583b09318caSHu Tao qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2); 158449ab747fSPaolo Bonzini 1585739e95f5SPeter Maydell scsi_bus_init(&s->bus, sizeof(s->bus), dev, &esp_scsi_info); 158649ab747fSPaolo Bonzini } 158749ab747fSPaolo Bonzini 158849ab747fSPaolo Bonzini static void sysbus_esp_hard_reset(DeviceState *dev) 158949ab747fSPaolo Bonzini { 159084fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(dev); 1591eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1592eb169c76SMark Cave-Ayland 1593eb169c76SMark Cave-Ayland esp_hard_reset(s); 1594eb169c76SMark Cave-Ayland } 1595eb169c76SMark Cave-Ayland 1596eb169c76SMark Cave-Ayland static void sysbus_esp_init(Object *obj) 1597eb169c76SMark Cave-Ayland { 1598eb169c76SMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(obj); 1599eb169c76SMark Cave-Ayland 1600eb169c76SMark Cave-Ayland object_initialize_child(obj, "esp", &sysbus->esp, TYPE_ESP); 160149ab747fSPaolo Bonzini } 160249ab747fSPaolo Bonzini 160349ab747fSPaolo Bonzini static const VMStateDescription vmstate_sysbus_esp_scsi = { 160449ab747fSPaolo Bonzini .name = "sysbusespscsi", 16050bd005beSMark Cave-Ayland .version_id = 2, 1606ea84a442SGuenter Roeck .minimum_version_id = 1, 1607ff4a1dabSMark Cave-Ayland .pre_save = esp_pre_save, 16082d7b39a6SRichard Henderson .fields = (const VMStateField[]) { 16090bd005beSMark Cave-Ayland VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2), 161049ab747fSPaolo Bonzini VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState), 161149ab747fSPaolo Bonzini VMSTATE_END_OF_LIST() 161249ab747fSPaolo Bonzini } 161349ab747fSPaolo Bonzini }; 161449ab747fSPaolo Bonzini 161549ab747fSPaolo Bonzini static void sysbus_esp_class_init(ObjectClass *klass, void *data) 161649ab747fSPaolo Bonzini { 161749ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 161849ab747fSPaolo Bonzini 1619b09318caSHu Tao dc->realize = sysbus_esp_realize; 162049ab747fSPaolo Bonzini dc->reset = sysbus_esp_hard_reset; 162149ab747fSPaolo Bonzini dc->vmsd = &vmstate_sysbus_esp_scsi; 1622125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 162349ab747fSPaolo Bonzini } 162449ab747fSPaolo Bonzini 1625042879fcSMark Cave-Ayland static void esp_finalize(Object *obj) 1626042879fcSMark Cave-Ayland { 1627042879fcSMark Cave-Ayland ESPState *s = ESP(obj); 1628042879fcSMark Cave-Ayland 1629042879fcSMark Cave-Ayland fifo8_destroy(&s->fifo); 1630023666daSMark Cave-Ayland fifo8_destroy(&s->cmdfifo); 1631042879fcSMark Cave-Ayland } 1632042879fcSMark Cave-Ayland 1633042879fcSMark Cave-Ayland static void esp_init(Object *obj) 1634042879fcSMark Cave-Ayland { 1635042879fcSMark Cave-Ayland ESPState *s = ESP(obj); 1636042879fcSMark Cave-Ayland 1637042879fcSMark Cave-Ayland fifo8_create(&s->fifo, ESP_FIFO_SZ); 1638023666daSMark Cave-Ayland fifo8_create(&s->cmdfifo, ESP_CMDFIFO_SZ); 1639042879fcSMark Cave-Ayland } 1640042879fcSMark Cave-Ayland 1641eb169c76SMark Cave-Ayland static void esp_class_init(ObjectClass *klass, void *data) 1642eb169c76SMark Cave-Ayland { 1643eb169c76SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(klass); 1644eb169c76SMark Cave-Ayland 1645eb169c76SMark Cave-Ayland /* internal device for sysbusesp/pciespscsi, not user-creatable */ 1646eb169c76SMark Cave-Ayland dc->user_creatable = false; 1647eb169c76SMark Cave-Ayland set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1648eb169c76SMark Cave-Ayland } 1649eb169c76SMark Cave-Ayland 1650499f4089SMark Cave-Ayland static const TypeInfo esp_info_types[] = { 1651499f4089SMark Cave-Ayland { 1652499f4089SMark Cave-Ayland .name = TYPE_SYSBUS_ESP, 1653499f4089SMark Cave-Ayland .parent = TYPE_SYS_BUS_DEVICE, 1654499f4089SMark Cave-Ayland .instance_init = sysbus_esp_init, 1655499f4089SMark Cave-Ayland .instance_size = sizeof(SysBusESPState), 1656499f4089SMark Cave-Ayland .class_init = sysbus_esp_class_init, 1657499f4089SMark Cave-Ayland }, 1658499f4089SMark Cave-Ayland { 1659eb169c76SMark Cave-Ayland .name = TYPE_ESP, 1660eb169c76SMark Cave-Ayland .parent = TYPE_DEVICE, 1661042879fcSMark Cave-Ayland .instance_init = esp_init, 1662042879fcSMark Cave-Ayland .instance_finalize = esp_finalize, 1663eb169c76SMark Cave-Ayland .instance_size = sizeof(ESPState), 1664eb169c76SMark Cave-Ayland .class_init = esp_class_init, 1665499f4089SMark Cave-Ayland }, 1666eb169c76SMark Cave-Ayland }; 1667eb169c76SMark Cave-Ayland 1668499f4089SMark Cave-Ayland DEFINE_TYPES(esp_info_types) 1669