16f7e9aecSbellard /* 267e999beSbellard * QEMU ESP/NCR53C9x emulation 36f7e9aecSbellard * 44e9aec74Spbrook * Copyright (c) 2005-2006 Fabrice Bellard 5fabaaf1dSHervé Poussineau * Copyright (c) 2012 Herve Poussineau 678d68f31SMark Cave-Ayland * Copyright (c) 2023 Mark Cave-Ayland 76f7e9aecSbellard * 86f7e9aecSbellard * Permission is hereby granted, free of charge, to any person obtaining a copy 96f7e9aecSbellard * of this software and associated documentation files (the "Software"), to deal 106f7e9aecSbellard * in the Software without restriction, including without limitation the rights 116f7e9aecSbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 126f7e9aecSbellard * copies of the Software, and to permit persons to whom the Software is 136f7e9aecSbellard * furnished to do so, subject to the following conditions: 146f7e9aecSbellard * 156f7e9aecSbellard * The above copyright notice and this permission notice shall be included in 166f7e9aecSbellard * all copies or substantial portions of the Software. 176f7e9aecSbellard * 186f7e9aecSbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 196f7e9aecSbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 206f7e9aecSbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 216f7e9aecSbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 226f7e9aecSbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 236f7e9aecSbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 246f7e9aecSbellard * THE SOFTWARE. 256f7e9aecSbellard */ 265d20fa6bSblueswir1 27a4ab4792SPeter Maydell #include "qemu/osdep.h" 2883c9f4caSPaolo Bonzini #include "hw/sysbus.h" 29d6454270SMarkus Armbruster #include "migration/vmstate.h" 3064552b6bSMarkus Armbruster #include "hw/irq.h" 310d09e41aSPaolo Bonzini #include "hw/scsi/esp.h" 32bf4b9889SBlue Swirl #include "trace.h" 331de7afc9SPaolo Bonzini #include "qemu/log.h" 340b8fa32fSMarkus Armbruster #include "qemu/module.h" 356f7e9aecSbellard 3667e999beSbellard /* 375ad6bb97Sblueswir1 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), 385ad6bb97Sblueswir1 * also produced as NCR89C100. See 3967e999beSbellard * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt 4067e999beSbellard * and 4167e999beSbellard * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt 4274d71ea1SLaurent Vivier * 4374d71ea1SLaurent Vivier * On Macintosh Quadra it is a NCR53C96. 4467e999beSbellard */ 4567e999beSbellard 46c73f96fdSblueswir1 static void esp_raise_irq(ESPState *s) 47c73f96fdSblueswir1 { 48c73f96fdSblueswir1 if (!(s->rregs[ESP_RSTAT] & STAT_INT)) { 49c73f96fdSblueswir1 s->rregs[ESP_RSTAT] |= STAT_INT; 50c73f96fdSblueswir1 qemu_irq_raise(s->irq); 51bf4b9889SBlue Swirl trace_esp_raise_irq(); 52c73f96fdSblueswir1 } 53c73f96fdSblueswir1 } 54c73f96fdSblueswir1 55c73f96fdSblueswir1 static void esp_lower_irq(ESPState *s) 56c73f96fdSblueswir1 { 57c73f96fdSblueswir1 if (s->rregs[ESP_RSTAT] & STAT_INT) { 58c73f96fdSblueswir1 s->rregs[ESP_RSTAT] &= ~STAT_INT; 59c73f96fdSblueswir1 qemu_irq_lower(s->irq); 60bf4b9889SBlue Swirl trace_esp_lower_irq(); 61c73f96fdSblueswir1 } 62c73f96fdSblueswir1 } 63c73f96fdSblueswir1 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 1009c7e23fcSHervé Poussineau void esp_dma_enable(ESPState *s, int irq, int level) 10173d74342SBlue Swirl { 10273d74342SBlue Swirl if (level) { 10373d74342SBlue Swirl s->dma_enabled = 1; 104bf4b9889SBlue Swirl trace_esp_dma_enable(); 10573d74342SBlue Swirl if (s->dma_cb) { 10673d74342SBlue Swirl s->dma_cb(s); 10773d74342SBlue Swirl s->dma_cb = NULL; 10873d74342SBlue Swirl } 10973d74342SBlue Swirl } else { 110bf4b9889SBlue Swirl trace_esp_dma_disable(); 11173d74342SBlue Swirl s->dma_enabled = 0; 11273d74342SBlue Swirl } 11373d74342SBlue Swirl } 11473d74342SBlue Swirl 1159c7e23fcSHervé Poussineau void esp_request_cancelled(SCSIRequest *req) 11694d3f98aSPaolo Bonzini { 117e6810db8SHervé Poussineau ESPState *s = req->hba_private; 11894d3f98aSPaolo Bonzini 11994d3f98aSPaolo Bonzini if (req == s->current_req) { 12094d3f98aSPaolo Bonzini scsi_req_unref(s->current_req); 12194d3f98aSPaolo Bonzini s->current_req = NULL; 12294d3f98aSPaolo Bonzini s->current_dev = NULL; 123324c8809SMark Cave-Ayland s->async_len = 0; 12494d3f98aSPaolo Bonzini } 12594d3f98aSPaolo Bonzini } 12694d3f98aSPaolo Bonzini 127*743d8736SMark Cave-Ayland static void esp_update_drq(ESPState *s) 128*743d8736SMark Cave-Ayland { 129*743d8736SMark Cave-Ayland bool to_device; 130*743d8736SMark Cave-Ayland 131*743d8736SMark Cave-Ayland switch (esp_get_phase(s)) { 132*743d8736SMark Cave-Ayland case STAT_MO: 133*743d8736SMark Cave-Ayland case STAT_CD: 134*743d8736SMark Cave-Ayland case STAT_DO: 135*743d8736SMark Cave-Ayland to_device = true; 136*743d8736SMark Cave-Ayland break; 137*743d8736SMark Cave-Ayland 138*743d8736SMark Cave-Ayland case STAT_DI: 139*743d8736SMark Cave-Ayland case STAT_ST: 140*743d8736SMark Cave-Ayland case STAT_MI: 141*743d8736SMark Cave-Ayland to_device = false; 142*743d8736SMark Cave-Ayland break; 143*743d8736SMark Cave-Ayland 144*743d8736SMark Cave-Ayland default: 145*743d8736SMark Cave-Ayland return; 146*743d8736SMark Cave-Ayland } 147*743d8736SMark Cave-Ayland 148*743d8736SMark Cave-Ayland if (s->dma) { 149*743d8736SMark Cave-Ayland /* DMA request so update DRQ according to transfer direction */ 150*743d8736SMark Cave-Ayland if (to_device) { 151*743d8736SMark Cave-Ayland if (fifo8_num_free(&s->fifo) < 2) { 152*743d8736SMark Cave-Ayland esp_lower_drq(s); 153*743d8736SMark Cave-Ayland } else { 154*743d8736SMark Cave-Ayland esp_raise_drq(s); 155*743d8736SMark Cave-Ayland } 156*743d8736SMark Cave-Ayland } else { 157*743d8736SMark Cave-Ayland if (fifo8_num_used(&s->fifo) < 2) { 158*743d8736SMark Cave-Ayland esp_lower_drq(s); 159*743d8736SMark Cave-Ayland } else { 160*743d8736SMark Cave-Ayland esp_raise_drq(s); 161*743d8736SMark Cave-Ayland } 162*743d8736SMark Cave-Ayland } 163*743d8736SMark Cave-Ayland } else { 164*743d8736SMark Cave-Ayland /* Not a DMA request */ 165*743d8736SMark Cave-Ayland esp_lower_drq(s); 166*743d8736SMark Cave-Ayland } 167*743d8736SMark Cave-Ayland } 168*743d8736SMark 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(); 173042879fcSMark Cave-Ayland return; 174042879fcSMark Cave-Ayland } 175042879fcSMark Cave-Ayland 1760e7dbe29SMark Cave-Ayland fifo8_push(&s->fifo, val); 177042879fcSMark Cave-Ayland } 178c5fef911SMark Cave-Ayland 179266170f9SMark Cave-Ayland static void esp_fifo_push_buf(ESPState *s, uint8_t *buf, int len) 180266170f9SMark Cave-Ayland { 181266170f9SMark Cave-Ayland fifo8_push_all(&s->fifo, buf, len); 182*743d8736SMark Cave-Ayland esp_update_drq(s); 183266170f9SMark Cave-Ayland } 184266170f9SMark Cave-Ayland 18561fa150dSMark Cave-Ayland static uint8_t esp_fifo_pop(ESPState *s) 186042879fcSMark Cave-Ayland { 18761fa150dSMark Cave-Ayland if (fifo8_is_empty(&s->fifo)) { 188042879fcSMark Cave-Ayland return 0; 189042879fcSMark Cave-Ayland } 190042879fcSMark Cave-Ayland 19161fa150dSMark Cave-Ayland return fifo8_pop(&s->fifo); 192023666daSMark Cave-Ayland } 193023666daSMark Cave-Ayland 194d103d0dbSMark Cave-Ayland static uint32_t esp_fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen) 1957b320a8eSMark Cave-Ayland { 1967b320a8eSMark Cave-Ayland const uint8_t *buf; 19749c60d16SMark Cave-Ayland uint32_t n, n2; 19849c60d16SMark Cave-Ayland int len; 1997b320a8eSMark Cave-Ayland 2007b320a8eSMark Cave-Ayland if (maxlen == 0) { 2017b320a8eSMark Cave-Ayland return 0; 2027b320a8eSMark Cave-Ayland } 2037b320a8eSMark Cave-Ayland 20449c60d16SMark Cave-Ayland len = maxlen; 20549c60d16SMark Cave-Ayland buf = fifo8_pop_buf(fifo, len, &n); 2067b320a8eSMark Cave-Ayland if (dest) { 2077b320a8eSMark Cave-Ayland memcpy(dest, buf, n); 2087b320a8eSMark Cave-Ayland } 2097b320a8eSMark Cave-Ayland 21049c60d16SMark Cave-Ayland /* Add FIFO wraparound if needed */ 21149c60d16SMark Cave-Ayland len -= n; 21249c60d16SMark Cave-Ayland len = MIN(len, fifo8_num_used(fifo)); 21349c60d16SMark Cave-Ayland if (len) { 21449c60d16SMark Cave-Ayland buf = fifo8_pop_buf(fifo, len, &n2); 21549c60d16SMark Cave-Ayland if (dest) { 21649c60d16SMark Cave-Ayland memcpy(&dest[n], buf, n2); 21749c60d16SMark Cave-Ayland } 21849c60d16SMark Cave-Ayland n += n2; 21949c60d16SMark Cave-Ayland } 22049c60d16SMark Cave-Ayland 2217b320a8eSMark Cave-Ayland return n; 2227b320a8eSMark Cave-Ayland } 2237b320a8eSMark Cave-Ayland 224da838126SMark Cave-Ayland static uint32_t esp_fifo_pop_buf(ESPState *s, uint8_t *dest, int maxlen) 225d103d0dbSMark Cave-Ayland { 226*743d8736SMark Cave-Ayland uint32_t len = esp_fifo8_pop_buf(&s->fifo, dest, maxlen); 227*743d8736SMark Cave-Ayland 228*743d8736SMark Cave-Ayland esp_update_drq(s); 229*743d8736SMark Cave-Ayland return len; 230d103d0dbSMark Cave-Ayland } 231d103d0dbSMark Cave-Ayland 232c47b5835SMark Cave-Ayland static uint32_t esp_get_tc(ESPState *s) 233c47b5835SMark Cave-Ayland { 234c47b5835SMark Cave-Ayland uint32_t dmalen; 235c47b5835SMark Cave-Ayland 236c47b5835SMark Cave-Ayland dmalen = s->rregs[ESP_TCLO]; 237c47b5835SMark Cave-Ayland dmalen |= s->rregs[ESP_TCMID] << 8; 238c47b5835SMark Cave-Ayland dmalen |= s->rregs[ESP_TCHI] << 16; 239c47b5835SMark Cave-Ayland 240c47b5835SMark Cave-Ayland return dmalen; 241c47b5835SMark Cave-Ayland } 242c47b5835SMark Cave-Ayland 243c47b5835SMark Cave-Ayland static void esp_set_tc(ESPState *s, uint32_t dmalen) 244c47b5835SMark Cave-Ayland { 245c5d7df28SMark Cave-Ayland uint32_t old_tc = esp_get_tc(s); 246c5d7df28SMark Cave-Ayland 247c47b5835SMark Cave-Ayland s->rregs[ESP_TCLO] = dmalen; 248c47b5835SMark Cave-Ayland s->rregs[ESP_TCMID] = dmalen >> 8; 249c47b5835SMark Cave-Ayland s->rregs[ESP_TCHI] = dmalen >> 16; 250c5d7df28SMark Cave-Ayland 251c5d7df28SMark Cave-Ayland if (old_tc && dmalen == 0) { 252c5d7df28SMark Cave-Ayland s->rregs[ESP_RSTAT] |= STAT_TC; 253c5d7df28SMark Cave-Ayland } 254c47b5835SMark Cave-Ayland } 255c47b5835SMark Cave-Ayland 256c04ed569SMark Cave-Ayland static uint32_t esp_get_stc(ESPState *s) 257c04ed569SMark Cave-Ayland { 258c04ed569SMark Cave-Ayland uint32_t dmalen; 259c04ed569SMark Cave-Ayland 260c04ed569SMark Cave-Ayland dmalen = s->wregs[ESP_TCLO]; 261c04ed569SMark Cave-Ayland dmalen |= s->wregs[ESP_TCMID] << 8; 262c04ed569SMark Cave-Ayland dmalen |= s->wregs[ESP_TCHI] << 16; 263c04ed569SMark Cave-Ayland 264c04ed569SMark Cave-Ayland return dmalen; 265c04ed569SMark Cave-Ayland } 266c04ed569SMark Cave-Ayland 267761bef75SMark Cave-Ayland static uint8_t esp_pdma_read(ESPState *s) 268761bef75SMark Cave-Ayland { 2698da90e81SMark Cave-Ayland uint8_t val; 2708da90e81SMark Cave-Ayland 27161fa150dSMark Cave-Ayland val = esp_fifo_pop(s); 2728da90e81SMark Cave-Ayland return val; 273761bef75SMark Cave-Ayland } 274761bef75SMark Cave-Ayland 275761bef75SMark Cave-Ayland static void esp_pdma_write(ESPState *s, uint8_t val) 276761bef75SMark Cave-Ayland { 2778da90e81SMark Cave-Ayland uint32_t dmalen = esp_get_tc(s); 2788da90e81SMark Cave-Ayland 2793c421400SMark Cave-Ayland if (dmalen == 0) { 2808da90e81SMark Cave-Ayland return; 2818da90e81SMark Cave-Ayland } 2828da90e81SMark Cave-Ayland 2830e7dbe29SMark Cave-Ayland esp_fifo_push(s, val); 2848da90e81SMark Cave-Ayland 2858da90e81SMark Cave-Ayland dmalen--; 2868da90e81SMark Cave-Ayland esp_set_tc(s, dmalen); 287761bef75SMark Cave-Ayland } 288761bef75SMark Cave-Ayland 289c7bce09cSMark Cave-Ayland static int esp_select(ESPState *s) 2906130b188SLaurent Vivier { 2916130b188SLaurent Vivier int target; 2926130b188SLaurent Vivier 2936130b188SLaurent Vivier target = s->wregs[ESP_WBUSID] & BUSID_DID; 2946130b188SLaurent Vivier 2956130b188SLaurent Vivier s->ti_size = 0; 2969b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_0; 2976130b188SLaurent Vivier 298cf40a5e4SMark Cave-Ayland if (s->current_req) { 299cf40a5e4SMark Cave-Ayland /* Started a new command before the old one finished. Cancel it. */ 300cf40a5e4SMark Cave-Ayland scsi_req_cancel(s->current_req); 301cf40a5e4SMark Cave-Ayland } 302cf40a5e4SMark Cave-Ayland 3036130b188SLaurent Vivier s->current_dev = scsi_device_find(&s->bus, 0, target, 0); 3046130b188SLaurent Vivier if (!s->current_dev) { 3056130b188SLaurent Vivier /* No such drive */ 3066130b188SLaurent Vivier s->rregs[ESP_RSTAT] = 0; 307cf1a7a9bSMark Cave-Ayland s->rregs[ESP_RINTR] = INTR_DC; 3086130b188SLaurent Vivier esp_raise_irq(s); 3096130b188SLaurent Vivier return -1; 3106130b188SLaurent Vivier } 3114e78f3bfSMark Cave-Ayland 3124e78f3bfSMark Cave-Ayland /* 3134e78f3bfSMark Cave-Ayland * Note that we deliberately don't raise the IRQ here: this will be done 314c90b2792SMark Cave-Ayland * either in esp_transfer_data() or esp_command_complete() 3154e78f3bfSMark Cave-Ayland */ 3166130b188SLaurent Vivier return 0; 3176130b188SLaurent Vivier } 3186130b188SLaurent Vivier 3193ee9a475SMark Cave-Ayland static void esp_do_dma(ESPState *s); 3203ee9a475SMark Cave-Ayland static void esp_do_nodma(ESPState *s); 3213ee9a475SMark Cave-Ayland 3224eb86065SPaolo Bonzini static void do_command_phase(ESPState *s) 3239f149aa9Spbrook { 3247b320a8eSMark Cave-Ayland uint32_t cmdlen; 3259f149aa9Spbrook int32_t datalen; 326f48a7a6eSPaolo Bonzini SCSIDevice *current_lun; 3277b320a8eSMark Cave-Ayland uint8_t buf[ESP_CMDFIFO_SZ]; 3289f149aa9Spbrook 3294eb86065SPaolo Bonzini trace_esp_do_command_phase(s->lun); 330023666daSMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 33199545751SMark Cave-Ayland if (!cmdlen || !s->current_dev) { 33299545751SMark Cave-Ayland return; 33399545751SMark Cave-Ayland } 334f87d0487SMark Cave-Ayland esp_fifo8_pop_buf(&s->cmdfifo, buf, cmdlen); 335023666daSMark Cave-Ayland 3364eb86065SPaolo Bonzini current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun); 337b22f83d8SAlexandra Diupina if (!current_lun) { 338b22f83d8SAlexandra Diupina /* No such drive */ 339b22f83d8SAlexandra Diupina s->rregs[ESP_RSTAT] = 0; 340b22f83d8SAlexandra Diupina s->rregs[ESP_RINTR] = INTR_DC; 341b22f83d8SAlexandra Diupina s->rregs[ESP_RSEQ] = SEQ_0; 342b22f83d8SAlexandra Diupina esp_raise_irq(s); 343b22f83d8SAlexandra Diupina return; 344b22f83d8SAlexandra Diupina } 345b22f83d8SAlexandra Diupina 346fe9d8927SJohn Millikin s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s); 347c39ce112SPaolo Bonzini datalen = scsi_req_enqueue(s->current_req); 34867e999beSbellard s->ti_size = datalen; 349023666daSMark Cave-Ayland fifo8_reset(&s->cmdfifo); 350c90b2792SMark Cave-Ayland s->data_ready = false; 35167e999beSbellard if (datalen != 0) { 3524e78f3bfSMark Cave-Ayland /* 353c90b2792SMark Cave-Ayland * Switch to DATA phase but wait until initial data xfer is 3544e78f3bfSMark Cave-Ayland * complete before raising the command completion interrupt 3554e78f3bfSMark Cave-Ayland */ 356c90b2792SMark Cave-Ayland if (datalen > 0) { 357abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_DI); 3584f6200f0Sbellard } else { 359abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_DO); 3602f275b8fSbellard } 3614e78f3bfSMark Cave-Ayland scsi_req_continue(s->current_req); 3624e78f3bfSMark Cave-Ayland return; 3634e78f3bfSMark Cave-Ayland } 3644e78f3bfSMark Cave-Ayland } 3652f275b8fSbellard 3664eb86065SPaolo Bonzini static void do_message_phase(ESPState *s) 367f2818f22SArtyom Tarasenko { 3684eb86065SPaolo Bonzini if (s->cmdfifo_cdb_offset) { 3691828000bSMark Cave-Ayland uint8_t message = fifo8_is_empty(&s->cmdfifo) ? 0 : 3701828000bSMark Cave-Ayland fifo8_pop(&s->cmdfifo); 371023666daSMark Cave-Ayland 3724eb86065SPaolo Bonzini trace_esp_do_identify(message); 3734eb86065SPaolo Bonzini s->lun = message & 7; 374023666daSMark Cave-Ayland s->cmdfifo_cdb_offset--; 3754eb86065SPaolo Bonzini } 376f2818f22SArtyom Tarasenko 377799d90d8SMark Cave-Ayland /* Ignore extended messages for now */ 378023666daSMark Cave-Ayland if (s->cmdfifo_cdb_offset) { 3794eb86065SPaolo Bonzini int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo)); 3802260402bSMark Cave-Ayland esp_fifo8_pop_buf(&s->cmdfifo, NULL, len); 381023666daSMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 382023666daSMark Cave-Ayland } 3834eb86065SPaolo Bonzini } 384023666daSMark Cave-Ayland 3854eb86065SPaolo Bonzini static void do_cmd(ESPState *s) 3864eb86065SPaolo Bonzini { 3874eb86065SPaolo Bonzini do_message_phase(s); 3884eb86065SPaolo Bonzini assert(s->cmdfifo_cdb_offset == 0); 3894eb86065SPaolo Bonzini do_command_phase(s); 390f2818f22SArtyom Tarasenko } 391f2818f22SArtyom Tarasenko 3929f149aa9Spbrook static void handle_satn(ESPState *s) 3939f149aa9Spbrook { 3941b26eaa1SHervé Poussineau if (s->dma && !s->dma_enabled) { 39573d74342SBlue Swirl s->dma_cb = handle_satn; 39673d74342SBlue Swirl return; 39773d74342SBlue Swirl } 398b46a43a2SMark Cave-Ayland 3991bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4001bcaf71bSMark Cave-Ayland return; 4011bcaf71bSMark Cave-Ayland } 4023ee9a475SMark Cave-Ayland 4033ee9a475SMark Cave-Ayland esp_set_phase(s, STAT_MO); 4043ee9a475SMark Cave-Ayland 4053ee9a475SMark Cave-Ayland if (s->dma) { 4063ee9a475SMark Cave-Ayland esp_do_dma(s); 4073ee9a475SMark Cave-Ayland } else { 408d39592ffSMark Cave-Ayland esp_do_nodma(s); 4099f149aa9Spbrook } 41094d5c79dSMark Cave-Ayland } 4119f149aa9Spbrook 412f2818f22SArtyom Tarasenko static void handle_s_without_atn(ESPState *s) 413f2818f22SArtyom Tarasenko { 4141b26eaa1SHervé Poussineau if (s->dma && !s->dma_enabled) { 41573d74342SBlue Swirl s->dma_cb = handle_s_without_atn; 41673d74342SBlue Swirl return; 41773d74342SBlue Swirl } 418b46a43a2SMark Cave-Ayland 4191bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4201bcaf71bSMark Cave-Ayland return; 4211bcaf71bSMark Cave-Ayland } 4229ff0fd12SMark Cave-Ayland 423abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_CD); 4249ff0fd12SMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 4259ff0fd12SMark Cave-Ayland 4269ff0fd12SMark Cave-Ayland if (s->dma) { 4279ff0fd12SMark Cave-Ayland esp_do_dma(s); 4289ff0fd12SMark Cave-Ayland } else { 429d39592ffSMark Cave-Ayland esp_do_nodma(s); 430f2818f22SArtyom Tarasenko } 431f2818f22SArtyom Tarasenko } 432f2818f22SArtyom Tarasenko 4339f149aa9Spbrook static void handle_satn_stop(ESPState *s) 4349f149aa9Spbrook { 4351b26eaa1SHervé Poussineau if (s->dma && !s->dma_enabled) { 43673d74342SBlue Swirl s->dma_cb = handle_satn_stop; 43773d74342SBlue Swirl return; 43873d74342SBlue Swirl } 439b46a43a2SMark Cave-Ayland 4401bcaf71bSMark Cave-Ayland if (esp_select(s) < 0) { 4411bcaf71bSMark Cave-Ayland return; 4421bcaf71bSMark Cave-Ayland } 443db4d4150SMark Cave-Ayland 444abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_MO); 4455d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 0; 446db4d4150SMark Cave-Ayland 447db4d4150SMark Cave-Ayland if (s->dma) { 448db4d4150SMark Cave-Ayland esp_do_dma(s); 449db4d4150SMark Cave-Ayland } else { 450d39592ffSMark Cave-Ayland esp_do_nodma(s); 4519f149aa9Spbrook } 4529f149aa9Spbrook } 4539f149aa9Spbrook 454a6cad7cdSMark Cave-Ayland static void handle_pad(ESPState *s) 455a6cad7cdSMark Cave-Ayland { 456a6cad7cdSMark Cave-Ayland if (s->dma) { 457a6cad7cdSMark Cave-Ayland esp_do_dma(s); 458a6cad7cdSMark Cave-Ayland } else { 459a6cad7cdSMark Cave-Ayland esp_do_nodma(s); 460a6cad7cdSMark Cave-Ayland } 461a6cad7cdSMark Cave-Ayland } 462a6cad7cdSMark Cave-Ayland 4630fc5c15aSpbrook static void write_response(ESPState *s) 4642f275b8fSbellard { 465bf4b9889SBlue Swirl trace_esp_write_response(s->status); 466042879fcSMark Cave-Ayland 4678baa1472SMark Cave-Ayland if (s->dma) { 4688baa1472SMark Cave-Ayland esp_do_dma(s); 4698baa1472SMark Cave-Ayland } else { 47083428f7aSMark Cave-Ayland esp_do_nodma(s); 4712f275b8fSbellard } 4728baa1472SMark Cave-Ayland } 4734f6200f0Sbellard 4745aa0df40SMark Cave-Ayland static bool esp_cdb_ready(ESPState *s) 4755d02add4SMark Cave-Ayland { 4765aa0df40SMark Cave-Ayland int len = fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset; 4775d02add4SMark Cave-Ayland const uint8_t *pbuf; 4783cc70889SMark Cave-Ayland uint32_t n; 4795aa0df40SMark Cave-Ayland int cdblen; 4805d02add4SMark Cave-Ayland 4815aa0df40SMark Cave-Ayland if (len <= 0) { 4825aa0df40SMark Cave-Ayland return false; 4835d02add4SMark Cave-Ayland } 4845d02add4SMark Cave-Ayland 4853cc70889SMark Cave-Ayland pbuf = fifo8_peek_buf(&s->cmdfifo, len, &n); 4863cc70889SMark Cave-Ayland if (n < len) { 4873cc70889SMark Cave-Ayland /* 4883cc70889SMark Cave-Ayland * In normal use the cmdfifo should never wrap, but include this check 4893cc70889SMark Cave-Ayland * to prevent a malicious guest from reading past the end of the 4903cc70889SMark Cave-Ayland * cmdfifo data buffer below 4913cc70889SMark Cave-Ayland */ 4923cc70889SMark Cave-Ayland return false; 4933cc70889SMark Cave-Ayland } 4943cc70889SMark Cave-Ayland 4955aa0df40SMark Cave-Ayland cdblen = scsi_cdb_length((uint8_t *)&pbuf[s->cmdfifo_cdb_offset]); 4965d02add4SMark Cave-Ayland 4975aa0df40SMark Cave-Ayland return cdblen < 0 ? false : (len >= cdblen); 4985d02add4SMark Cave-Ayland } 4995d02add4SMark Cave-Ayland 500004826d0SMark Cave-Ayland static void esp_dma_ti_check(ESPState *s) 5014d611c9aSpbrook { 502af74b3c1SMark Cave-Ayland if (esp_get_tc(s) == 0 && fifo8_num_used(&s->fifo) < 2) { 503cf47a41eSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 504c73f96fdSblueswir1 esp_raise_irq(s); 505af74b3c1SMark Cave-Ayland esp_lower_drq(s); 506af74b3c1SMark Cave-Ayland } 5074d611c9aSpbrook } 508a917d384Spbrook 509a917d384Spbrook static void esp_do_dma(ESPState *s) 510a917d384Spbrook { 511023666daSMark Cave-Ayland uint32_t len, cmdlen; 512023666daSMark Cave-Ayland uint8_t buf[ESP_CMDFIFO_SZ]; 513a917d384Spbrook 5146cc88d6bSMark Cave-Ayland len = esp_get_tc(s); 515ad2725afSMark Cave-Ayland 516ad2725afSMark Cave-Ayland switch (esp_get_phase(s)) { 517ad2725afSMark Cave-Ayland case STAT_MO: 51846b0c361SMark Cave-Ayland if (s->dma_memory_read) { 51946b0c361SMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->cmdfifo)); 52046b0c361SMark Cave-Ayland s->dma_memory_read(s->dma_opaque, buf, len); 52146b0c361SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 52246b0c361SMark Cave-Ayland } else { 523da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 52467ea170eSMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 52567ea170eSMark Cave-Ayland esp_raise_drq(s); 52646b0c361SMark Cave-Ayland } 52746b0c361SMark Cave-Ayland 52867ea170eSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 52967ea170eSMark Cave-Ayland s->cmdfifo_cdb_offset += len; 53046b0c361SMark Cave-Ayland 5313ee9a475SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 5323ee9a475SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 5333ee9a475SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 5343ee9a475SMark Cave-Ayland /* First byte received, switch to command phase */ 5353ee9a475SMark Cave-Ayland esp_set_phase(s, STAT_CD); 5369b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 5373ee9a475SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 5383ee9a475SMark Cave-Ayland 5393ee9a475SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) > 1) { 5403ee9a475SMark Cave-Ayland /* Process any additional command phase data */ 5413ee9a475SMark Cave-Ayland esp_do_dma(s); 5423ee9a475SMark Cave-Ayland } 5433ee9a475SMark Cave-Ayland } 5443ee9a475SMark Cave-Ayland break; 5453ee9a475SMark Cave-Ayland 546db4d4150SMark Cave-Ayland case CMD_SELATNS | CMD_DMA: 547db4d4150SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) == 1) { 548db4d4150SMark Cave-Ayland /* First byte received, stop in message out phase */ 5499b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 550db4d4150SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 551db4d4150SMark Cave-Ayland 552db4d4150SMark Cave-Ayland /* Raise command completion interrupt */ 553db4d4150SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 554db4d4150SMark Cave-Ayland esp_raise_irq(s); 555db4d4150SMark Cave-Ayland } 556db4d4150SMark Cave-Ayland break; 557db4d4150SMark Cave-Ayland 5583fd325a2SMark Cave-Ayland case CMD_TI | CMD_DMA: 55946b0c361SMark Cave-Ayland /* ATN remains asserted until TC == 0 */ 56046b0c361SMark Cave-Ayland if (esp_get_tc(s) == 0) { 56146b0c361SMark Cave-Ayland esp_set_phase(s, STAT_CD); 562cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 56346b0c361SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 56446b0c361SMark Cave-Ayland esp_raise_irq(s); 56546b0c361SMark Cave-Ayland } 56646b0c361SMark Cave-Ayland break; 5673fd325a2SMark Cave-Ayland } 5683fd325a2SMark Cave-Ayland break; 56946b0c361SMark Cave-Ayland 570ad2725afSMark Cave-Ayland case STAT_CD: 571023666daSMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 572023666daSMark Cave-Ayland trace_esp_do_dma(cmdlen, len); 57374d71ea1SLaurent Vivier if (s->dma_memory_read) { 5740ebb5fd8SMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->cmdfifo)); 575023666daSMark Cave-Ayland s->dma_memory_read(s->dma_opaque, buf, len); 576023666daSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 577a0347651SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 57874d71ea1SLaurent Vivier } else { 579da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 580406e8a3eSMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 581406e8a3eSMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 58274d71ea1SLaurent Vivier esp_raise_drq(s); 5833c7f3c8bSMark Cave-Ayland } 584023666daSMark Cave-Ayland trace_esp_handle_ti_cmd(cmdlen); 58515407433SLaurent Vivier s->ti_size = 0; 58646b0c361SMark Cave-Ayland if (esp_get_tc(s) == 0) { 587799d90d8SMark Cave-Ayland /* Command has been received */ 588c959f218SMark Cave-Ayland do_cmd(s); 589799d90d8SMark Cave-Ayland } 590ad2725afSMark Cave-Ayland break; 5911454dc76SMark Cave-Ayland 5921454dc76SMark Cave-Ayland case STAT_DO: 5930db89536SMark Cave-Ayland if (!s->current_req) { 5940db89536SMark Cave-Ayland return; 5950db89536SMark Cave-Ayland } 5964460b86aSMark Cave-Ayland if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { 597a917d384Spbrook /* Defer until data is available. */ 598a917d384Spbrook return; 599a917d384Spbrook } 600a917d384Spbrook if (len > s->async_len) { 601a917d384Spbrook len = s->async_len; 602a917d384Spbrook } 6030d17ce82SMark Cave-Ayland 604a6cad7cdSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 605a6cad7cdSMark Cave-Ayland case CMD_TI | CMD_DMA: 60674d71ea1SLaurent Vivier if (s->dma_memory_read) { 6078b17de88Sblueswir1 s->dma_memory_read(s->dma_opaque, s->async_buf, len); 608f3666223SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 6090d17ce82SMark Cave-Ayland } else { 6100d17ce82SMark Cave-Ayland /* Copy FIFO data to device */ 6110d17ce82SMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 6120d17ce82SMark Cave-Ayland len = MIN(len, fifo8_num_used(&s->fifo)); 613da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, s->async_buf, len); 6140d17ce82SMark Cave-Ayland esp_raise_drq(s); 6150d17ce82SMark Cave-Ayland } 6160d17ce82SMark Cave-Ayland 617f3666223SMark Cave-Ayland s->async_buf += len; 618f3666223SMark Cave-Ayland s->async_len -= len; 619f3666223SMark Cave-Ayland s->ti_size += len; 620a6cad7cdSMark Cave-Ayland break; 621a6cad7cdSMark Cave-Ayland 622a6cad7cdSMark Cave-Ayland case CMD_PAD | CMD_DMA: 623a6cad7cdSMark Cave-Ayland /* Copy TC zero bytes into the incoming stream */ 624a6cad7cdSMark Cave-Ayland if (!s->dma_memory_read) { 625a6cad7cdSMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 626a6cad7cdSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 627a6cad7cdSMark Cave-Ayland } 628a6cad7cdSMark Cave-Ayland 629a6cad7cdSMark Cave-Ayland memset(s->async_buf, 0, len); 630a6cad7cdSMark Cave-Ayland 631a6cad7cdSMark Cave-Ayland s->async_buf += len; 632a6cad7cdSMark Cave-Ayland s->async_len -= len; 633a6cad7cdSMark Cave-Ayland s->ti_size += len; 634a6cad7cdSMark Cave-Ayland break; 635a6cad7cdSMark Cave-Ayland } 636f3666223SMark Cave-Ayland 637e4e166c8SMark Cave-Ayland if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) { 638e4e166c8SMark Cave-Ayland /* Defer until the scsi layer has completed */ 639f3666223SMark Cave-Ayland scsi_req_continue(s->current_req); 640f3666223SMark Cave-Ayland return; 641f3666223SMark Cave-Ayland } 642f3666223SMark Cave-Ayland 643004826d0SMark Cave-Ayland esp_dma_ti_check(s); 6441454dc76SMark Cave-Ayland break; 6451454dc76SMark Cave-Ayland 6461454dc76SMark Cave-Ayland case STAT_DI: 6471454dc76SMark Cave-Ayland if (!s->current_req) { 6481454dc76SMark Cave-Ayland return; 6491454dc76SMark Cave-Ayland } 6501454dc76SMark Cave-Ayland if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) { 6511454dc76SMark Cave-Ayland /* Defer until data is available. */ 6521454dc76SMark Cave-Ayland return; 6531454dc76SMark Cave-Ayland } 6541454dc76SMark Cave-Ayland if (len > s->async_len) { 6551454dc76SMark Cave-Ayland len = s->async_len; 6561454dc76SMark Cave-Ayland } 657c37cc88eSMark Cave-Ayland 658a6cad7cdSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 659a6cad7cdSMark Cave-Ayland case CMD_TI | CMD_DMA: 66074d71ea1SLaurent Vivier if (s->dma_memory_write) { 6618b17de88Sblueswir1 s->dma_memory_write(s->dma_opaque, s->async_buf, len); 66274d71ea1SLaurent Vivier } else { 66382141c8bSMark Cave-Ayland /* Copy device data to FIFO */ 664042879fcSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 665266170f9SMark Cave-Ayland esp_fifo_push_buf(s, s->async_buf, len); 666c37cc88eSMark Cave-Ayland esp_raise_drq(s); 667c37cc88eSMark Cave-Ayland } 668c37cc88eSMark Cave-Ayland 66982141c8bSMark Cave-Ayland s->async_buf += len; 67082141c8bSMark Cave-Ayland s->async_len -= len; 67182141c8bSMark Cave-Ayland s->ti_size -= len; 67282141c8bSMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 673a6cad7cdSMark Cave-Ayland break; 674a6cad7cdSMark Cave-Ayland 675a6cad7cdSMark Cave-Ayland case CMD_PAD | CMD_DMA: 676a6cad7cdSMark Cave-Ayland /* Drop TC bytes from the incoming stream */ 677a6cad7cdSMark Cave-Ayland if (!s->dma_memory_write) { 678a6cad7cdSMark Cave-Ayland len = MIN(len, fifo8_num_free(&s->fifo)); 679a6cad7cdSMark Cave-Ayland } 680a6cad7cdSMark Cave-Ayland 681a6cad7cdSMark Cave-Ayland s->async_buf += len; 682a6cad7cdSMark Cave-Ayland s->async_len -= len; 683a6cad7cdSMark Cave-Ayland s->ti_size -= len; 684a6cad7cdSMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 685a6cad7cdSMark Cave-Ayland break; 686a6cad7cdSMark Cave-Ayland } 687e4e166c8SMark Cave-Ayland 68802a3ce56SMark Cave-Ayland if (s->async_len == 0 && s->ti_size == 0 && esp_get_tc(s)) { 68902a3ce56SMark Cave-Ayland /* If the guest underflows TC then terminate SCSI request */ 69002a3ce56SMark Cave-Ayland scsi_req_continue(s->current_req); 69102a3ce56SMark Cave-Ayland return; 69202a3ce56SMark Cave-Ayland } 69302a3ce56SMark Cave-Ayland 694e4e166c8SMark Cave-Ayland if (s->async_len == 0 && fifo8_num_used(&s->fifo) < 2) { 695e4e166c8SMark Cave-Ayland /* Defer until the scsi layer has completed */ 696e4e166c8SMark Cave-Ayland scsi_req_continue(s->current_req); 697e4e166c8SMark Cave-Ayland return; 698e4e166c8SMark Cave-Ayland } 699e4e166c8SMark Cave-Ayland 700004826d0SMark Cave-Ayland esp_dma_ti_check(s); 7011454dc76SMark Cave-Ayland break; 7028baa1472SMark Cave-Ayland 7038baa1472SMark Cave-Ayland case STAT_ST: 7048baa1472SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 7058baa1472SMark Cave-Ayland case CMD_ICCS | CMD_DMA: 7068baa1472SMark Cave-Ayland len = MIN(len, 1); 7078baa1472SMark Cave-Ayland 7088baa1472SMark Cave-Ayland if (len) { 7098baa1472SMark Cave-Ayland buf[0] = s->status; 7108baa1472SMark Cave-Ayland 7118baa1472SMark Cave-Ayland if (s->dma_memory_write) { 7128baa1472SMark Cave-Ayland s->dma_memory_write(s->dma_opaque, buf, len); 7138baa1472SMark Cave-Ayland } else { 714266170f9SMark Cave-Ayland esp_fifo_push_buf(s, buf, len); 7158baa1472SMark Cave-Ayland } 7168baa1472SMark Cave-Ayland 717421d1ca5SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 7188baa1472SMark Cave-Ayland esp_set_phase(s, STAT_MI); 7198baa1472SMark Cave-Ayland 7208baa1472SMark Cave-Ayland if (esp_get_tc(s) > 0) { 7218baa1472SMark Cave-Ayland /* Process any message in phase data */ 7228baa1472SMark Cave-Ayland esp_do_dma(s); 7238baa1472SMark Cave-Ayland } 7248baa1472SMark Cave-Ayland } 7258baa1472SMark Cave-Ayland break; 72602a3ce56SMark Cave-Ayland 72702a3ce56SMark Cave-Ayland default: 72802a3ce56SMark Cave-Ayland /* Consume remaining data if the guest underflows TC */ 72902a3ce56SMark Cave-Ayland if (fifo8_num_used(&s->fifo) < 2) { 73002a3ce56SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 73102a3ce56SMark Cave-Ayland esp_raise_irq(s); 73202a3ce56SMark Cave-Ayland esp_lower_drq(s); 73302a3ce56SMark Cave-Ayland } 73402a3ce56SMark Cave-Ayland break; 7358baa1472SMark Cave-Ayland } 7368baa1472SMark Cave-Ayland break; 7378baa1472SMark Cave-Ayland 7388baa1472SMark Cave-Ayland case STAT_MI: 7398baa1472SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 7408baa1472SMark Cave-Ayland case CMD_ICCS | CMD_DMA: 7418baa1472SMark Cave-Ayland len = MIN(len, 1); 7428baa1472SMark Cave-Ayland 7438baa1472SMark Cave-Ayland if (len) { 7448baa1472SMark Cave-Ayland buf[0] = 0; 7458baa1472SMark Cave-Ayland 7468baa1472SMark Cave-Ayland if (s->dma_memory_write) { 7478baa1472SMark Cave-Ayland s->dma_memory_write(s->dma_opaque, buf, len); 7488baa1472SMark Cave-Ayland } else { 749266170f9SMark Cave-Ayland esp_fifo_push_buf(s, buf, len); 7508baa1472SMark Cave-Ayland } 7518baa1472SMark Cave-Ayland 752421d1ca5SMark Cave-Ayland esp_set_tc(s, esp_get_tc(s) - len); 753421d1ca5SMark Cave-Ayland 7548baa1472SMark Cave-Ayland /* Raise end of command interrupt */ 7550ee71db4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_FC; 7568baa1472SMark Cave-Ayland esp_raise_irq(s); 7578baa1472SMark Cave-Ayland } 7588baa1472SMark Cave-Ayland break; 7598baa1472SMark Cave-Ayland } 7608baa1472SMark Cave-Ayland break; 76174d71ea1SLaurent Vivier } 762a917d384Spbrook } 763a917d384Spbrook 764a1b8d389SMark Cave-Ayland static void esp_nodma_ti_dataout(ESPState *s) 765a1b8d389SMark Cave-Ayland { 766a1b8d389SMark Cave-Ayland int len; 767a1b8d389SMark Cave-Ayland 768a1b8d389SMark Cave-Ayland if (!s->current_req) { 769a1b8d389SMark Cave-Ayland return; 770a1b8d389SMark Cave-Ayland } 771a1b8d389SMark Cave-Ayland if (s->async_len == 0) { 772a1b8d389SMark Cave-Ayland /* Defer until data is available. */ 773a1b8d389SMark Cave-Ayland return; 774a1b8d389SMark Cave-Ayland } 775a1b8d389SMark Cave-Ayland len = MIN(s->async_len, ESP_FIFO_SZ); 776a1b8d389SMark Cave-Ayland len = MIN(len, fifo8_num_used(&s->fifo)); 777da838126SMark Cave-Ayland esp_fifo_pop_buf(s, s->async_buf, len); 778a1b8d389SMark Cave-Ayland s->async_buf += len; 779a1b8d389SMark Cave-Ayland s->async_len -= len; 780a1b8d389SMark Cave-Ayland s->ti_size += len; 781a1b8d389SMark Cave-Ayland 782a1b8d389SMark Cave-Ayland if (s->async_len == 0) { 783a1b8d389SMark Cave-Ayland scsi_req_continue(s->current_req); 784a1b8d389SMark Cave-Ayland return; 785a1b8d389SMark Cave-Ayland } 786a1b8d389SMark Cave-Ayland 787a1b8d389SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 788a1b8d389SMark Cave-Ayland esp_raise_irq(s); 789a1b8d389SMark Cave-Ayland } 790a1b8d389SMark Cave-Ayland 7911b9e48a5SMark Cave-Ayland static void esp_do_nodma(ESPState *s) 7921b9e48a5SMark Cave-Ayland { 7932572689bSMark Cave-Ayland uint8_t buf[ESP_FIFO_SZ]; 7947b320a8eSMark Cave-Ayland uint32_t cmdlen; 7955a857339SMark Cave-Ayland int len; 7961b9e48a5SMark Cave-Ayland 79783e803deSMark Cave-Ayland switch (esp_get_phase(s)) { 79883e803deSMark Cave-Ayland case STAT_MO: 799215d2579SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 800215d2579SMark Cave-Ayland case CMD_SELATN: 8012572689bSMark Cave-Ayland /* Copy FIFO into cmdfifo */ 802da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8035a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8045a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 8052572689bSMark Cave-Ayland 8065d02add4SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 8075d02add4SMark Cave-Ayland /* First byte received, switch to command phase */ 8085d02add4SMark Cave-Ayland esp_set_phase(s, STAT_CD); 8099b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 8105d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 8115d02add4SMark Cave-Ayland 8125d02add4SMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) > 1) { 8135d02add4SMark Cave-Ayland /* Process any additional command phase data */ 8145d02add4SMark Cave-Ayland esp_do_nodma(s); 8155d02add4SMark Cave-Ayland } 8165d02add4SMark Cave-Ayland } 8175d02add4SMark Cave-Ayland break; 8185d02add4SMark Cave-Ayland 8195d02add4SMark Cave-Ayland case CMD_SELATNS: 820215d2579SMark Cave-Ayland /* Copy one byte from FIFO into cmdfifo */ 8215a50644eSMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, 8225a50644eSMark Cave-Ayland MIN(fifo8_num_used(&s->fifo), 1)); 8235a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8245a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 825215d2579SMark Cave-Ayland 826d39592ffSMark Cave-Ayland if (fifo8_num_used(&s->cmdfifo) >= 1) { 8275d02add4SMark Cave-Ayland /* First byte received, stop in message out phase */ 8289b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 8295d02add4SMark Cave-Ayland s->cmdfifo_cdb_offset = 1; 8305d02add4SMark Cave-Ayland 8315d02add4SMark Cave-Ayland /* Raise command completion interrupt */ 8325d02add4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 8335d02add4SMark Cave-Ayland esp_raise_irq(s); 8345d02add4SMark Cave-Ayland } 8355d02add4SMark Cave-Ayland break; 8365d02add4SMark Cave-Ayland 8375d02add4SMark Cave-Ayland case CMD_TI: 838215d2579SMark Cave-Ayland /* Copy FIFO into cmdfifo */ 839da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8405a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8415a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 842215d2579SMark Cave-Ayland 8435d02add4SMark Cave-Ayland /* ATN remains asserted until FIFO empty */ 8441b9e48a5SMark Cave-Ayland s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo); 845abc139cdSMark Cave-Ayland esp_set_phase(s, STAT_CD); 846cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 8471b9e48a5SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 8481b9e48a5SMark Cave-Ayland esp_raise_irq(s); 84979a6c7c6SMark Cave-Ayland break; 8505d02add4SMark Cave-Ayland } 8515d02add4SMark Cave-Ayland break; 85279a6c7c6SMark Cave-Ayland 85379a6c7c6SMark Cave-Ayland case STAT_CD: 854acdee66dSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 855acdee66dSMark Cave-Ayland case CMD_TI: 85679a6c7c6SMark Cave-Ayland /* Copy FIFO into cmdfifo */ 857da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8585a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8595a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 86079a6c7c6SMark Cave-Ayland 86179a6c7c6SMark Cave-Ayland cmdlen = fifo8_num_used(&s->cmdfifo); 86279a6c7c6SMark Cave-Ayland trace_esp_handle_ti_cmd(cmdlen); 86379a6c7c6SMark Cave-Ayland 8645d02add4SMark Cave-Ayland /* CDB may be transferred in one or more TI commands */ 8655aa0df40SMark Cave-Ayland if (esp_cdb_ready(s)) { 86679a6c7c6SMark Cave-Ayland /* Command has been received */ 86779a6c7c6SMark Cave-Ayland do_cmd(s); 8685d02add4SMark Cave-Ayland } else { 8695d02add4SMark Cave-Ayland /* 8705d02add4SMark Cave-Ayland * If data was transferred from the FIFO then raise bus 8715d02add4SMark Cave-Ayland * service interrupt to indicate transfer complete. Otherwise 8725d02add4SMark Cave-Ayland * defer until the next FIFO write. 8735d02add4SMark Cave-Ayland */ 8745a857339SMark Cave-Ayland if (len) { 8755d02add4SMark Cave-Ayland /* Raise interrupt to indicate transfer complete */ 8765d02add4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 8775d02add4SMark Cave-Ayland esp_raise_irq(s); 8785d02add4SMark Cave-Ayland } 8795d02add4SMark Cave-Ayland } 8805d02add4SMark Cave-Ayland break; 8815d02add4SMark Cave-Ayland 8828ba32048SMark Cave-Ayland case CMD_SEL | CMD_DMA: 8838ba32048SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 884acdee66dSMark Cave-Ayland /* Copy FIFO into cmdfifo */ 885da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 8865a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 8875a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 888acdee66dSMark Cave-Ayland 8898ba32048SMark Cave-Ayland /* Handle when DMA transfer is terminated by non-DMA FIFO write */ 8905aa0df40SMark Cave-Ayland if (esp_cdb_ready(s)) { 8918ba32048SMark Cave-Ayland /* Command has been received */ 8928ba32048SMark Cave-Ayland do_cmd(s); 8938ba32048SMark Cave-Ayland } 8948ba32048SMark Cave-Ayland break; 8958ba32048SMark Cave-Ayland 8965d02add4SMark Cave-Ayland case CMD_SEL: 8975d02add4SMark Cave-Ayland case CMD_SELATN: 898acdee66dSMark Cave-Ayland /* FIFO already contain entire CDB: copy to cmdfifo and execute */ 899da838126SMark Cave-Ayland len = esp_fifo_pop_buf(s, buf, fifo8_num_used(&s->fifo)); 9005a857339SMark Cave-Ayland len = MIN(fifo8_num_free(&s->cmdfifo), len); 9015a857339SMark Cave-Ayland fifo8_push_all(&s->cmdfifo, buf, len); 902acdee66dSMark Cave-Ayland 9035d02add4SMark Cave-Ayland do_cmd(s); 9045d02add4SMark Cave-Ayland break; 9055d02add4SMark Cave-Ayland } 90683e803deSMark Cave-Ayland break; 9071b9e48a5SMark Cave-Ayland 9089d1aa52bSMark Cave-Ayland case STAT_DO: 9095d02add4SMark Cave-Ayland /* Accumulate data in FIFO until non-DMA TI is executed */ 9109d1aa52bSMark Cave-Ayland break; 9119d1aa52bSMark Cave-Ayland 9129d1aa52bSMark Cave-Ayland case STAT_DI: 9139d1aa52bSMark Cave-Ayland if (!s->current_req) { 9149d1aa52bSMark Cave-Ayland return; 9159d1aa52bSMark Cave-Ayland } 9169d1aa52bSMark Cave-Ayland if (s->async_len == 0) { 9179d1aa52bSMark Cave-Ayland /* Defer until data is available. */ 9189d1aa52bSMark Cave-Ayland return; 9199d1aa52bSMark Cave-Ayland } 9206ef2cabcSMark Cave-Ayland if (fifo8_is_empty(&s->fifo)) { 9211f46d1c3SMark Cave-Ayland esp_fifo_push(s, s->async_buf[0]); 9226ef2cabcSMark Cave-Ayland s->async_buf++; 9236ef2cabcSMark Cave-Ayland s->async_len--; 9246ef2cabcSMark Cave-Ayland s->ti_size--; 9256ef2cabcSMark Cave-Ayland } 9261b9e48a5SMark Cave-Ayland 9271b9e48a5SMark Cave-Ayland if (s->async_len == 0) { 9281b9e48a5SMark Cave-Ayland scsi_req_continue(s->current_req); 9291b9e48a5SMark Cave-Ayland return; 9301b9e48a5SMark Cave-Ayland } 9311b9e48a5SMark Cave-Ayland 9329655f72cSMark Cave-Ayland /* If preloading the FIFO, defer until TI command issued */ 9339655f72cSMark Cave-Ayland if (s->rregs[ESP_CMD] != CMD_TI) { 9349655f72cSMark Cave-Ayland return; 9359655f72cSMark Cave-Ayland } 9369655f72cSMark Cave-Ayland 9371b9e48a5SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 9381b9e48a5SMark Cave-Ayland esp_raise_irq(s); 9399d1aa52bSMark Cave-Ayland break; 94083428f7aSMark Cave-Ayland 94183428f7aSMark Cave-Ayland case STAT_ST: 94283428f7aSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 94383428f7aSMark Cave-Ayland case CMD_ICCS: 9441f46d1c3SMark Cave-Ayland esp_fifo_push(s, s->status); 94583428f7aSMark Cave-Ayland esp_set_phase(s, STAT_MI); 94683428f7aSMark Cave-Ayland 94783428f7aSMark Cave-Ayland /* Process any message in phase data */ 94883428f7aSMark Cave-Ayland esp_do_nodma(s); 94983428f7aSMark Cave-Ayland break; 95083428f7aSMark Cave-Ayland } 95183428f7aSMark Cave-Ayland break; 95283428f7aSMark Cave-Ayland 95383428f7aSMark Cave-Ayland case STAT_MI: 95483428f7aSMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 95583428f7aSMark Cave-Ayland case CMD_ICCS: 9561f46d1c3SMark Cave-Ayland esp_fifo_push(s, 0); 95783428f7aSMark Cave-Ayland 9580ee71db4SMark Cave-Ayland /* Raise end of command interrupt */ 9590ee71db4SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_FC; 96083428f7aSMark Cave-Ayland esp_raise_irq(s); 96183428f7aSMark Cave-Ayland break; 96283428f7aSMark Cave-Ayland } 96383428f7aSMark Cave-Ayland break; 9649d1aa52bSMark Cave-Ayland } 9651b9e48a5SMark Cave-Ayland } 9661b9e48a5SMark Cave-Ayland 9674aaa6ac3SMark Cave-Ayland void esp_command_complete(SCSIRequest *req, size_t resid) 968a917d384Spbrook { 9694aaa6ac3SMark Cave-Ayland ESPState *s = req->hba_private; 9705a83e83eSMark Cave-Ayland int to_device = (esp_get_phase(s) == STAT_DO); 9714aaa6ac3SMark Cave-Ayland 972bf4b9889SBlue Swirl trace_esp_command_complete(); 9736ef2cabcSMark Cave-Ayland 9746ef2cabcSMark Cave-Ayland /* 9756ef2cabcSMark Cave-Ayland * Non-DMA transfers from the target will leave the last byte in 9766ef2cabcSMark Cave-Ayland * the FIFO so don't reset ti_size in this case 9776ef2cabcSMark Cave-Ayland */ 9786ef2cabcSMark Cave-Ayland if (s->dma || to_device) { 979c6df7102SPaolo Bonzini if (s->ti_size != 0) { 980bf4b9889SBlue Swirl trace_esp_command_complete_unexpected(); 981c6df7102SPaolo Bonzini } 9826ef2cabcSMark Cave-Ayland } 9836ef2cabcSMark Cave-Ayland 984a917d384Spbrook s->async_len = 0; 9854aaa6ac3SMark Cave-Ayland if (req->status) { 986bf4b9889SBlue Swirl trace_esp_command_complete_fail(); 987c6df7102SPaolo Bonzini } 9884aaa6ac3SMark Cave-Ayland s->status = req->status; 9896ef2cabcSMark Cave-Ayland 9906ef2cabcSMark Cave-Ayland /* 991cb988199SMark Cave-Ayland * Switch to status phase. For non-DMA transfers from the target the last 992cb988199SMark Cave-Ayland * byte is still in the FIFO 9936ef2cabcSMark Cave-Ayland */ 9948bb22495SMark Cave-Ayland s->ti_size = 0; 9958bb22495SMark Cave-Ayland 9968bb22495SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 9978bb22495SMark Cave-Ayland case CMD_SEL | CMD_DMA: 9988bb22495SMark Cave-Ayland case CMD_SEL: 9998bb22495SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 10008bb22495SMark Cave-Ayland case CMD_SELATN: 1001cb988199SMark Cave-Ayland /* 10028bb22495SMark Cave-Ayland * No data phase for sequencer command so raise deferred bus service 1003c90b2792SMark Cave-Ayland * and function complete interrupt 1004cb988199SMark Cave-Ayland */ 1005c90b2792SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 10069b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 10078bb22495SMark Cave-Ayland break; 1008cb22ce50SMark Cave-Ayland 1009cb22ce50SMark Cave-Ayland case CMD_TI | CMD_DMA: 1010cb22ce50SMark Cave-Ayland case CMD_TI: 1011cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 1012cb22ce50SMark Cave-Ayland break; 10136ef2cabcSMark Cave-Ayland } 10146ef2cabcSMark Cave-Ayland 10158bb22495SMark Cave-Ayland /* Raise bus service interrupt to indicate change to STATUS phase */ 10168bb22495SMark Cave-Ayland esp_set_phase(s, STAT_ST); 10178bb22495SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 10188bb22495SMark Cave-Ayland esp_raise_irq(s); 101902a3ce56SMark Cave-Ayland 102002a3ce56SMark Cave-Ayland /* Ensure DRQ is set correctly for TC underflow or normal completion */ 102102a3ce56SMark Cave-Ayland esp_dma_ti_check(s); 10228bb22495SMark Cave-Ayland 10235c6c0e51SHannes Reinecke if (s->current_req) { 10245c6c0e51SHannes Reinecke scsi_req_unref(s->current_req); 10255c6c0e51SHannes Reinecke s->current_req = NULL; 1026a917d384Spbrook s->current_dev = NULL; 10275c6c0e51SHannes Reinecke } 1028c6df7102SPaolo Bonzini } 1029c6df7102SPaolo Bonzini 10309c7e23fcSHervé Poussineau void esp_transfer_data(SCSIRequest *req, uint32_t len) 1031c6df7102SPaolo Bonzini { 1032e6810db8SHervé Poussineau ESPState *s = req->hba_private; 10336cc88d6bSMark Cave-Ayland uint32_t dmalen = esp_get_tc(s); 1034c6df7102SPaolo Bonzini 10356cc88d6bSMark Cave-Ayland trace_esp_transfer_data(dmalen, s->ti_size); 1036aba1f023SPaolo Bonzini s->async_len = len; 10370c34459bSPaolo Bonzini s->async_buf = scsi_req_get_buf(req); 10384e78f3bfSMark Cave-Ayland 1039c90b2792SMark Cave-Ayland if (!s->data_ready) { 1040a4608fa0SMark Cave-Ayland s->data_ready = true; 1041a4608fa0SMark Cave-Ayland 1042a4608fa0SMark Cave-Ayland switch (s->rregs[ESP_CMD]) { 1043a4608fa0SMark Cave-Ayland case CMD_SEL | CMD_DMA: 1044a4608fa0SMark Cave-Ayland case CMD_SEL: 1045a4608fa0SMark Cave-Ayland case CMD_SELATN | CMD_DMA: 1046a4608fa0SMark Cave-Ayland case CMD_SELATN: 1047c90b2792SMark Cave-Ayland /* 1048c90b2792SMark Cave-Ayland * Initial incoming data xfer is complete for sequencer command 1049c90b2792SMark Cave-Ayland * so raise deferred bus service and function complete interrupt 1050c90b2792SMark Cave-Ayland */ 1051c90b2792SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; 10529b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_CD; 1053c90b2792SMark Cave-Ayland break; 1054c90b2792SMark Cave-Ayland 1055a4608fa0SMark Cave-Ayland case CMD_SELATNS | CMD_DMA: 1056a4608fa0SMark Cave-Ayland case CMD_SELATNS: 10574e78f3bfSMark Cave-Ayland /* 10584e78f3bfSMark Cave-Ayland * Initial incoming data xfer is complete so raise command 10594e78f3bfSMark Cave-Ayland * completion interrupt 10604e78f3bfSMark Cave-Ayland */ 10614e78f3bfSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 10629b2cdca2SMark Cave-Ayland s->rregs[ESP_RSEQ] = SEQ_MO; 1063a4608fa0SMark Cave-Ayland break; 1064a4608fa0SMark Cave-Ayland 1065a4608fa0SMark Cave-Ayland case CMD_TI | CMD_DMA: 1066a4608fa0SMark Cave-Ayland case CMD_TI: 1067a4608fa0SMark Cave-Ayland /* 1068a4608fa0SMark Cave-Ayland * Bus service interrupt raised because of initial change to 1069a4608fa0SMark Cave-Ayland * DATA phase 1070a4608fa0SMark Cave-Ayland */ 1071cb22ce50SMark Cave-Ayland s->rregs[ESP_CMD] = 0; 1072a4608fa0SMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_BS; 1073a4608fa0SMark Cave-Ayland break; 1074a4608fa0SMark Cave-Ayland } 1075c90b2792SMark Cave-Ayland 1076c90b2792SMark Cave-Ayland esp_raise_irq(s); 10774e78f3bfSMark Cave-Ayland } 10784e78f3bfSMark Cave-Ayland 10791b9e48a5SMark Cave-Ayland /* 10801b9e48a5SMark Cave-Ayland * Always perform the initial transfer upon reception of the next TI 10811b9e48a5SMark Cave-Ayland * command to ensure the DMA/non-DMA status of the command is correct. 10821b9e48a5SMark Cave-Ayland * It is not possible to use s->dma directly in the section below as 10831b9e48a5SMark Cave-Ayland * some OSs send non-DMA NOP commands after a DMA transfer. Hence if the 10841b9e48a5SMark Cave-Ayland * async data transfer is delayed then s->dma is set incorrectly. 10851b9e48a5SMark Cave-Ayland */ 10861b9e48a5SMark Cave-Ayland 108782003450SMark Cave-Ayland if (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA)) { 1088a79e767aSMark Cave-Ayland /* When the SCSI layer returns more data, raise deferred INTR_BS */ 1089004826d0SMark Cave-Ayland esp_dma_ti_check(s); 1090a79e767aSMark Cave-Ayland 1091a79e767aSMark Cave-Ayland esp_do_dma(s); 109282003450SMark Cave-Ayland } else if (s->rregs[ESP_CMD] == CMD_TI) { 10931b9e48a5SMark Cave-Ayland esp_do_nodma(s); 10941b9e48a5SMark Cave-Ayland } 1095a917d384Spbrook } 10962e5d83bbSpbrook 10972f275b8fSbellard static void handle_ti(ESPState *s) 10982f275b8fSbellard { 10991b9e48a5SMark Cave-Ayland uint32_t dmalen; 11002f275b8fSbellard 11017246e160SHervé Poussineau if (s->dma && !s->dma_enabled) { 11027246e160SHervé Poussineau s->dma_cb = handle_ti; 11037246e160SHervé Poussineau return; 11047246e160SHervé Poussineau } 11057246e160SHervé Poussineau 11064f6200f0Sbellard if (s->dma) { 11071b9e48a5SMark Cave-Ayland dmalen = esp_get_tc(s); 1108b76624deSMark Cave-Ayland trace_esp_handle_ti(dmalen); 11094d611c9aSpbrook esp_do_dma(s); 1110799d90d8SMark Cave-Ayland } else { 11111b9e48a5SMark Cave-Ayland trace_esp_handle_ti(s->ti_size); 11121b9e48a5SMark Cave-Ayland esp_do_nodma(s); 11135d02add4SMark Cave-Ayland 11145d02add4SMark Cave-Ayland if (esp_get_phase(s) == STAT_DO) { 11155d02add4SMark Cave-Ayland esp_nodma_ti_dataout(s); 11165d02add4SMark Cave-Ayland } 11174f6200f0Sbellard } 11182f275b8fSbellard } 11192f275b8fSbellard 11209c7e23fcSHervé Poussineau void esp_hard_reset(ESPState *s) 11216f7e9aecSbellard { 11225aca8c3bSblueswir1 memset(s->rregs, 0, ESP_REGS); 11235aca8c3bSblueswir1 memset(s->wregs, 0, ESP_REGS); 1124c9cf45c1SHannes Reinecke s->tchi_written = 0; 11254e9aec74Spbrook s->ti_size = 0; 11263f26c975SMark Cave-Ayland s->async_len = 0; 1127042879fcSMark Cave-Ayland fifo8_reset(&s->fifo); 1128023666daSMark Cave-Ayland fifo8_reset(&s->cmdfifo); 11294e9aec74Spbrook s->dma = 0; 113073d74342SBlue Swirl s->dma_cb = NULL; 11318dea1dd4Sblueswir1 11328dea1dd4Sblueswir1 s->rregs[ESP_CFG1] = 7; 11336f7e9aecSbellard } 11346f7e9aecSbellard 1135a391fdbcSHervé Poussineau static void esp_soft_reset(ESPState *s) 113685948643SBlue Swirl { 113785948643SBlue Swirl qemu_irq_lower(s->irq); 11386dec7c0dSMark Cave-Ayland qemu_irq_lower(s->drq_irq); 1139a391fdbcSHervé Poussineau esp_hard_reset(s); 114085948643SBlue Swirl } 114185948643SBlue Swirl 1142c6e51f1bSJohn Millikin static void esp_bus_reset(ESPState *s) 1143c6e51f1bSJohn Millikin { 11444a5fc890SPeter Maydell bus_cold_reset(BUS(&s->bus)); 1145c6e51f1bSJohn Millikin } 1146c6e51f1bSJohn Millikin 1147a391fdbcSHervé Poussineau static void parent_esp_reset(ESPState *s, int irq, int level) 11482d069babSblueswir1 { 114985948643SBlue Swirl if (level) { 1150a391fdbcSHervé Poussineau esp_soft_reset(s); 115185948643SBlue Swirl } 11522d069babSblueswir1 } 11532d069babSblueswir1 1154f21fe39dSMark Cave-Ayland static void esp_run_cmd(ESPState *s) 1155f21fe39dSMark Cave-Ayland { 1156f21fe39dSMark Cave-Ayland uint8_t cmd = s->rregs[ESP_CMD]; 1157f21fe39dSMark Cave-Ayland 1158f21fe39dSMark Cave-Ayland if (cmd & CMD_DMA) { 1159f21fe39dSMark Cave-Ayland s->dma = 1; 1160f21fe39dSMark Cave-Ayland /* Reload DMA counter. */ 1161f21fe39dSMark Cave-Ayland if (esp_get_stc(s) == 0) { 1162f21fe39dSMark Cave-Ayland esp_set_tc(s, 0x10000); 1163f21fe39dSMark Cave-Ayland } else { 1164f21fe39dSMark Cave-Ayland esp_set_tc(s, esp_get_stc(s)); 1165f21fe39dSMark Cave-Ayland } 1166f21fe39dSMark Cave-Ayland } else { 1167f21fe39dSMark Cave-Ayland s->dma = 0; 1168f21fe39dSMark Cave-Ayland } 1169f21fe39dSMark Cave-Ayland switch (cmd & CMD_CMD) { 1170f21fe39dSMark Cave-Ayland case CMD_NOP: 1171f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_nop(cmd); 1172f21fe39dSMark Cave-Ayland break; 1173f21fe39dSMark Cave-Ayland case CMD_FLUSH: 1174f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_flush(cmd); 1175f21fe39dSMark Cave-Ayland fifo8_reset(&s->fifo); 1176f21fe39dSMark Cave-Ayland break; 1177f21fe39dSMark Cave-Ayland case CMD_RESET: 1178f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_reset(cmd); 1179f21fe39dSMark Cave-Ayland esp_soft_reset(s); 1180f21fe39dSMark Cave-Ayland break; 1181f21fe39dSMark Cave-Ayland case CMD_BUSRESET: 1182f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_bus_reset(cmd); 1183f21fe39dSMark Cave-Ayland esp_bus_reset(s); 1184f21fe39dSMark Cave-Ayland if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { 1185f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_RST; 1186f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1187f21fe39dSMark Cave-Ayland } 1188f21fe39dSMark Cave-Ayland break; 1189f21fe39dSMark Cave-Ayland case CMD_TI: 1190f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_ti(cmd); 1191f21fe39dSMark Cave-Ayland handle_ti(s); 1192f21fe39dSMark Cave-Ayland break; 1193f21fe39dSMark Cave-Ayland case CMD_ICCS: 1194f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_iccs(cmd); 1195f21fe39dSMark Cave-Ayland write_response(s); 1196f21fe39dSMark Cave-Ayland break; 1197f21fe39dSMark Cave-Ayland case CMD_MSGACC: 1198f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_msgacc(cmd); 1199f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] |= INTR_DC; 1200f21fe39dSMark Cave-Ayland s->rregs[ESP_RSEQ] = 0; 1201f21fe39dSMark Cave-Ayland s->rregs[ESP_RFLAGS] = 0; 1202f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1203f21fe39dSMark Cave-Ayland break; 1204f21fe39dSMark Cave-Ayland case CMD_PAD: 1205f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_pad(cmd); 1206a6cad7cdSMark Cave-Ayland handle_pad(s); 1207f21fe39dSMark Cave-Ayland break; 1208f21fe39dSMark Cave-Ayland case CMD_SATN: 1209f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_satn(cmd); 1210f21fe39dSMark Cave-Ayland break; 1211f21fe39dSMark Cave-Ayland case CMD_RSTATN: 1212f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_rstatn(cmd); 1213f21fe39dSMark Cave-Ayland break; 1214f21fe39dSMark Cave-Ayland case CMD_SEL: 1215f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_sel(cmd); 1216f21fe39dSMark Cave-Ayland handle_s_without_atn(s); 1217f21fe39dSMark Cave-Ayland break; 1218f21fe39dSMark Cave-Ayland case CMD_SELATN: 1219f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_selatn(cmd); 1220f21fe39dSMark Cave-Ayland handle_satn(s); 1221f21fe39dSMark Cave-Ayland break; 1222f21fe39dSMark Cave-Ayland case CMD_SELATNS: 1223f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_selatns(cmd); 1224f21fe39dSMark Cave-Ayland handle_satn_stop(s); 1225f21fe39dSMark Cave-Ayland break; 1226f21fe39dSMark Cave-Ayland case CMD_ENSEL: 1227f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_ensel(cmd); 1228f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] = 0; 1229f21fe39dSMark Cave-Ayland break; 1230f21fe39dSMark Cave-Ayland case CMD_DISSEL: 1231f21fe39dSMark Cave-Ayland trace_esp_mem_writeb_cmd_dissel(cmd); 1232f21fe39dSMark Cave-Ayland s->rregs[ESP_RINTR] = 0; 1233f21fe39dSMark Cave-Ayland esp_raise_irq(s); 1234f21fe39dSMark Cave-Ayland break; 1235f21fe39dSMark Cave-Ayland default: 1236f21fe39dSMark Cave-Ayland trace_esp_error_unhandled_command(cmd); 1237f21fe39dSMark Cave-Ayland break; 1238f21fe39dSMark Cave-Ayland } 1239f21fe39dSMark Cave-Ayland } 1240f21fe39dSMark Cave-Ayland 12419c7e23fcSHervé Poussineau uint64_t esp_reg_read(ESPState *s, uint32_t saddr) 124273d74342SBlue Swirl { 1243b630c075SMark Cave-Ayland uint32_t val; 124473d74342SBlue Swirl 12456f7e9aecSbellard switch (saddr) { 12465ad6bb97Sblueswir1 case ESP_FIFO: 124761fa150dSMark Cave-Ayland s->rregs[ESP_FIFO] = esp_fifo_pop(s); 1248b630c075SMark Cave-Ayland val = s->rregs[ESP_FIFO]; 12494f6200f0Sbellard break; 12505ad6bb97Sblueswir1 case ESP_RINTR: 125194d5c79dSMark Cave-Ayland /* 125294d5c79dSMark Cave-Ayland * Clear sequence step, interrupt register and all status bits 125394d5c79dSMark Cave-Ayland * except TC 125494d5c79dSMark Cave-Ayland */ 1255b630c075SMark Cave-Ayland val = s->rregs[ESP_RINTR]; 12562814df28SBlue Swirl s->rregs[ESP_RINTR] = 0; 1257d294b77aSMark Cave-Ayland esp_lower_irq(s); 1258d68212cdSMark Cave-Ayland s->rregs[ESP_RSTAT] &= STAT_TC | 7; 1259af947a3dSMark Cave-Ayland /* 1260af947a3dSMark Cave-Ayland * According to the datasheet ESP_RSEQ should be cleared, but as the 1261af947a3dSMark Cave-Ayland * emulation currently defers information transfers to the next TI 1262af947a3dSMark Cave-Ayland * command leave it for now so that pedantic guests such as the old 1263af947a3dSMark Cave-Ayland * Linux 2.6 driver see the correct flags before the next SCSI phase 1264af947a3dSMark Cave-Ayland * transition. 1265af947a3dSMark Cave-Ayland * 1266af947a3dSMark Cave-Ayland * s->rregs[ESP_RSEQ] = SEQ_0; 1267af947a3dSMark Cave-Ayland */ 1268b630c075SMark Cave-Ayland break; 1269c9cf45c1SHannes Reinecke case ESP_TCHI: 1270c9cf45c1SHannes Reinecke /* Return the unique id if the value has never been written */ 1271c9cf45c1SHannes Reinecke if (!s->tchi_written) { 1272b630c075SMark Cave-Ayland val = s->chip_id; 1273b630c075SMark Cave-Ayland } else { 1274b630c075SMark Cave-Ayland val = s->rregs[saddr]; 1275c9cf45c1SHannes Reinecke } 1276b630c075SMark Cave-Ayland break; 1277238ec4d7SMark Cave-Ayland case ESP_RFLAGS: 1278238ec4d7SMark Cave-Ayland /* Bottom 5 bits indicate number of bytes in FIFO */ 1279238ec4d7SMark Cave-Ayland val = fifo8_num_used(&s->fifo); 1280238ec4d7SMark Cave-Ayland break; 12816f7e9aecSbellard default: 1282b630c075SMark Cave-Ayland val = s->rregs[saddr]; 12836f7e9aecSbellard break; 12846f7e9aecSbellard } 1285b630c075SMark Cave-Ayland 1286b630c075SMark Cave-Ayland trace_esp_mem_readb(saddr, val); 1287b630c075SMark Cave-Ayland return val; 12886f7e9aecSbellard } 12896f7e9aecSbellard 12909c7e23fcSHervé Poussineau void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) 12916f7e9aecSbellard { 1292bf4b9889SBlue Swirl trace_esp_mem_writeb(saddr, s->wregs[saddr], val); 12936f7e9aecSbellard switch (saddr) { 1294c9cf45c1SHannes Reinecke case ESP_TCHI: 1295c9cf45c1SHannes Reinecke s->tchi_written = true; 1296c9cf45c1SHannes Reinecke /* fall through */ 12975ad6bb97Sblueswir1 case ESP_TCLO: 12985ad6bb97Sblueswir1 case ESP_TCMID: 12995ad6bb97Sblueswir1 s->rregs[ESP_RSTAT] &= ~STAT_TC; 13004f6200f0Sbellard break; 13015ad6bb97Sblueswir1 case ESP_FIFO: 13022572689bSMark Cave-Ayland if (!fifo8_is_full(&s->fifo)) { 13030e7dbe29SMark Cave-Ayland esp_fifo_push(s, val); 13042572689bSMark Cave-Ayland } 13055d02add4SMark Cave-Ayland esp_do_nodma(s); 13064f6200f0Sbellard break; 13075ad6bb97Sblueswir1 case ESP_CMD: 13084f6200f0Sbellard s->rregs[saddr] = val; 1309f21fe39dSMark Cave-Ayland esp_run_cmd(s); 13106f7e9aecSbellard break; 13115ad6bb97Sblueswir1 case ESP_WBUSID ... ESP_WSYNO: 13124f6200f0Sbellard break; 13135ad6bb97Sblueswir1 case ESP_CFG1: 13149ea73f8bSPaolo Bonzini case ESP_CFG2: case ESP_CFG3: 13159ea73f8bSPaolo Bonzini case ESP_RES3: case ESP_RES4: 13164f6200f0Sbellard s->rregs[saddr] = val; 13174f6200f0Sbellard break; 13185ad6bb97Sblueswir1 case ESP_WCCF ... ESP_WTEST: 13194f6200f0Sbellard break; 13206f7e9aecSbellard default: 13213af4e9aaSHervé Poussineau trace_esp_error_invalid_write(val, saddr); 13228dea1dd4Sblueswir1 return; 13236f7e9aecSbellard } 13242f275b8fSbellard s->wregs[saddr] = val; 13256f7e9aecSbellard } 13266f7e9aecSbellard 1327a8170e5eSAvi Kivity static bool esp_mem_accepts(void *opaque, hwaddr addr, 13288372d383SPeter Maydell unsigned size, bool is_write, 13298372d383SPeter Maydell MemTxAttrs attrs) 133067bb5314SAvi Kivity { 133167bb5314SAvi Kivity return (size == 1) || (is_write && size == 4); 133267bb5314SAvi Kivity } 13336f7e9aecSbellard 13346cc88d6bSMark Cave-Ayland static bool esp_is_before_version_5(void *opaque, int version_id) 13356cc88d6bSMark Cave-Ayland { 13366cc88d6bSMark Cave-Ayland ESPState *s = ESP(opaque); 13376cc88d6bSMark Cave-Ayland 13386cc88d6bSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13396cc88d6bSMark Cave-Ayland return version_id < 5; 13406cc88d6bSMark Cave-Ayland } 13416cc88d6bSMark Cave-Ayland 13424e78f3bfSMark Cave-Ayland static bool esp_is_version_5(void *opaque, int version_id) 13434e78f3bfSMark Cave-Ayland { 13444e78f3bfSMark Cave-Ayland ESPState *s = ESP(opaque); 13454e78f3bfSMark Cave-Ayland 13464e78f3bfSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13470bcd5a18SMark Cave-Ayland return version_id >= 5; 13484e78f3bfSMark Cave-Ayland } 13494e78f3bfSMark Cave-Ayland 13504eb86065SPaolo Bonzini static bool esp_is_version_6(void *opaque, int version_id) 13514eb86065SPaolo Bonzini { 13524eb86065SPaolo Bonzini ESPState *s = ESP(opaque); 13534eb86065SPaolo Bonzini 13544eb86065SPaolo Bonzini version_id = MIN(version_id, s->mig_version_id); 13554eb86065SPaolo Bonzini return version_id >= 6; 13564eb86065SPaolo Bonzini } 13574eb86065SPaolo Bonzini 135882003450SMark Cave-Ayland static bool esp_is_between_version_5_and_6(void *opaque, int version_id) 135982003450SMark Cave-Ayland { 136082003450SMark Cave-Ayland ESPState *s = ESP(opaque); 136182003450SMark Cave-Ayland 136282003450SMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 136382003450SMark Cave-Ayland return version_id >= 5 && version_id <= 6; 136482003450SMark Cave-Ayland } 136582003450SMark Cave-Ayland 1366ff4a1dabSMark Cave-Ayland int esp_pre_save(void *opaque) 13670bd005beSMark Cave-Ayland { 1368ff4a1dabSMark Cave-Ayland ESPState *s = ESP(object_resolve_path_component( 1369ff4a1dabSMark Cave-Ayland OBJECT(opaque), "esp")); 13700bd005beSMark Cave-Ayland 13710bd005beSMark Cave-Ayland s->mig_version_id = vmstate_esp.version_id; 13720bd005beSMark Cave-Ayland return 0; 13730bd005beSMark Cave-Ayland } 13740bd005beSMark Cave-Ayland 13750bd005beSMark Cave-Ayland static int esp_post_load(void *opaque, int version_id) 13760bd005beSMark Cave-Ayland { 13770bd005beSMark Cave-Ayland ESPState *s = ESP(opaque); 1378042879fcSMark Cave-Ayland int len, i; 13790bd005beSMark Cave-Ayland 13806cc88d6bSMark Cave-Ayland version_id = MIN(version_id, s->mig_version_id); 13816cc88d6bSMark Cave-Ayland 13826cc88d6bSMark Cave-Ayland if (version_id < 5) { 13836cc88d6bSMark Cave-Ayland esp_set_tc(s, s->mig_dma_left); 1384042879fcSMark Cave-Ayland 1385042879fcSMark Cave-Ayland /* Migrate ti_buf to fifo */ 1386042879fcSMark Cave-Ayland len = s->mig_ti_wptr - s->mig_ti_rptr; 1387042879fcSMark Cave-Ayland for (i = 0; i < len; i++) { 1388042879fcSMark Cave-Ayland fifo8_push(&s->fifo, s->mig_ti_buf[i]); 1389042879fcSMark Cave-Ayland } 1390023666daSMark Cave-Ayland 1391023666daSMark Cave-Ayland /* Migrate cmdbuf to cmdfifo */ 1392023666daSMark Cave-Ayland for (i = 0; i < s->mig_cmdlen; i++) { 1393023666daSMark Cave-Ayland fifo8_push(&s->cmdfifo, s->mig_cmdbuf[i]); 1394023666daSMark Cave-Ayland } 13956cc88d6bSMark Cave-Ayland } 13966cc88d6bSMark Cave-Ayland 13970bd005beSMark Cave-Ayland s->mig_version_id = vmstate_esp.version_id; 13980bd005beSMark Cave-Ayland return 0; 13990bd005beSMark Cave-Ayland } 14000bd005beSMark Cave-Ayland 14019c7e23fcSHervé Poussineau const VMStateDescription vmstate_esp = { 1402cc9952f3SBlue Swirl .name = "esp", 140382003450SMark Cave-Ayland .version_id = 7, 1404cc9952f3SBlue Swirl .minimum_version_id = 3, 14050bd005beSMark Cave-Ayland .post_load = esp_post_load, 14062d7b39a6SRichard Henderson .fields = (const VMStateField[]) { 1407cc9952f3SBlue Swirl VMSTATE_BUFFER(rregs, ESPState), 1408cc9952f3SBlue Swirl VMSTATE_BUFFER(wregs, ESPState), 1409cc9952f3SBlue Swirl VMSTATE_INT32(ti_size, ESPState), 1410042879fcSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_ti_rptr, ESPState, esp_is_before_version_5), 1411042879fcSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_ti_wptr, ESPState, esp_is_before_version_5), 1412042879fcSMark Cave-Ayland VMSTATE_BUFFER_TEST(mig_ti_buf, ESPState, esp_is_before_version_5), 14133944966dSPaolo Bonzini VMSTATE_UINT32(status, ESPState), 14144aaa6ac3SMark Cave-Ayland VMSTATE_UINT32_TEST(mig_deferred_status, ESPState, 14154aaa6ac3SMark Cave-Ayland esp_is_before_version_5), 14164aaa6ac3SMark Cave-Ayland VMSTATE_BOOL_TEST(mig_deferred_complete, ESPState, 14174aaa6ac3SMark Cave-Ayland esp_is_before_version_5), 1418cc9952f3SBlue Swirl VMSTATE_UINT32(dma, ESPState), 1419023666daSMark Cave-Ayland VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 0, 1420023666daSMark Cave-Ayland esp_is_before_version_5, 0, 16), 1421023666daSMark Cave-Ayland VMSTATE_STATIC_BUFFER(mig_cmdbuf, ESPState, 4, 1422023666daSMark Cave-Ayland esp_is_before_version_5, 16, 1423023666daSMark Cave-Ayland sizeof(typeof_field(ESPState, mig_cmdbuf))), 1424023666daSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_cmdlen, ESPState, esp_is_before_version_5), 1425cc9952f3SBlue Swirl VMSTATE_UINT32(do_cmd, ESPState), 14266cc88d6bSMark Cave-Ayland VMSTATE_UINT32_TEST(mig_dma_left, ESPState, esp_is_before_version_5), 14278dded6deSMark Cave-Ayland VMSTATE_BOOL_TEST(data_ready, ESPState, esp_is_version_5), 1428023666daSMark Cave-Ayland VMSTATE_UINT8_TEST(cmdfifo_cdb_offset, ESPState, esp_is_version_5), 1429042879fcSMark Cave-Ayland VMSTATE_FIFO8_TEST(fifo, ESPState, esp_is_version_5), 1430023666daSMark Cave-Ayland VMSTATE_FIFO8_TEST(cmdfifo, ESPState, esp_is_version_5), 143182003450SMark Cave-Ayland VMSTATE_UINT8_TEST(mig_ti_cmd, ESPState, 143282003450SMark Cave-Ayland esp_is_between_version_5_and_6), 14334eb86065SPaolo Bonzini VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6), 1434442de89aSMark Cave-Ayland VMSTATE_BOOL(drq_state, ESPState), 1435cc9952f3SBlue Swirl VMSTATE_END_OF_LIST() 143674d71ea1SLaurent Vivier }, 1437cc9952f3SBlue Swirl }; 14386f7e9aecSbellard 1439a8170e5eSAvi Kivity static void sysbus_esp_mem_write(void *opaque, hwaddr addr, 1440a391fdbcSHervé Poussineau uint64_t val, unsigned int size) 1441a391fdbcSHervé Poussineau { 1442a391fdbcSHervé Poussineau SysBusESPState *sysbus = opaque; 1443eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1444a391fdbcSHervé Poussineau uint32_t saddr; 1445a391fdbcSHervé Poussineau 1446a391fdbcSHervé Poussineau saddr = addr >> sysbus->it_shift; 1447eb169c76SMark Cave-Ayland esp_reg_write(s, saddr, val); 1448a391fdbcSHervé Poussineau } 1449a391fdbcSHervé Poussineau 1450a8170e5eSAvi Kivity static uint64_t sysbus_esp_mem_read(void *opaque, hwaddr addr, 1451a391fdbcSHervé Poussineau unsigned int size) 1452a391fdbcSHervé Poussineau { 1453a391fdbcSHervé Poussineau SysBusESPState *sysbus = opaque; 1454eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1455a391fdbcSHervé Poussineau uint32_t saddr; 1456a391fdbcSHervé Poussineau 1457a391fdbcSHervé Poussineau saddr = addr >> sysbus->it_shift; 1458eb169c76SMark Cave-Ayland return esp_reg_read(s, saddr); 1459a391fdbcSHervé Poussineau } 1460a391fdbcSHervé Poussineau 1461a391fdbcSHervé Poussineau static const MemoryRegionOps sysbus_esp_mem_ops = { 1462a391fdbcSHervé Poussineau .read = sysbus_esp_mem_read, 1463a391fdbcSHervé Poussineau .write = sysbus_esp_mem_write, 1464a391fdbcSHervé Poussineau .endianness = DEVICE_NATIVE_ENDIAN, 1465a391fdbcSHervé Poussineau .valid.accepts = esp_mem_accepts, 1466a391fdbcSHervé Poussineau }; 1467a391fdbcSHervé Poussineau 146874d71ea1SLaurent Vivier static void sysbus_esp_pdma_write(void *opaque, hwaddr addr, 146974d71ea1SLaurent Vivier uint64_t val, unsigned int size) 147074d71ea1SLaurent Vivier { 147174d71ea1SLaurent Vivier SysBusESPState *sysbus = opaque; 1472eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 147374d71ea1SLaurent Vivier 1474960ebfd9SMark Cave-Ayland trace_esp_pdma_write(size); 1475960ebfd9SMark Cave-Ayland 147674d71ea1SLaurent Vivier switch (size) { 147774d71ea1SLaurent Vivier case 1: 1478761bef75SMark Cave-Ayland esp_pdma_write(s, val); 147974d71ea1SLaurent Vivier break; 148074d71ea1SLaurent Vivier case 2: 1481761bef75SMark Cave-Ayland esp_pdma_write(s, val >> 8); 1482761bef75SMark Cave-Ayland esp_pdma_write(s, val); 148374d71ea1SLaurent Vivier break; 148474d71ea1SLaurent Vivier } 1485b46a43a2SMark Cave-Ayland esp_do_dma(s); 148674d71ea1SLaurent Vivier } 148774d71ea1SLaurent Vivier 148874d71ea1SLaurent Vivier static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr, 148974d71ea1SLaurent Vivier unsigned int size) 149074d71ea1SLaurent Vivier { 149174d71ea1SLaurent Vivier SysBusESPState *sysbus = opaque; 1492eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 149374d71ea1SLaurent Vivier uint64_t val = 0; 149474d71ea1SLaurent Vivier 1495960ebfd9SMark Cave-Ayland trace_esp_pdma_read(size); 1496960ebfd9SMark Cave-Ayland 149774d71ea1SLaurent Vivier switch (size) { 149874d71ea1SLaurent Vivier case 1: 1499761bef75SMark Cave-Ayland val = esp_pdma_read(s); 150074d71ea1SLaurent Vivier break; 150174d71ea1SLaurent Vivier case 2: 1502761bef75SMark Cave-Ayland val = esp_pdma_read(s); 1503761bef75SMark Cave-Ayland val = (val << 8) | esp_pdma_read(s); 150474d71ea1SLaurent Vivier break; 150574d71ea1SLaurent Vivier } 1506b46a43a2SMark Cave-Ayland esp_do_dma(s); 150774d71ea1SLaurent Vivier return val; 150874d71ea1SLaurent Vivier } 150974d71ea1SLaurent Vivier 1510a7a22088SMark Cave-Ayland static void *esp_load_request(QEMUFile *f, SCSIRequest *req) 1511a7a22088SMark Cave-Ayland { 1512a7a22088SMark Cave-Ayland ESPState *s = container_of(req->bus, ESPState, bus); 1513a7a22088SMark Cave-Ayland 1514a7a22088SMark Cave-Ayland scsi_req_ref(req); 1515a7a22088SMark Cave-Ayland s->current_req = req; 1516a7a22088SMark Cave-Ayland return s; 1517a7a22088SMark Cave-Ayland } 1518a7a22088SMark Cave-Ayland 151974d71ea1SLaurent Vivier static const MemoryRegionOps sysbus_esp_pdma_ops = { 152074d71ea1SLaurent Vivier .read = sysbus_esp_pdma_read, 152174d71ea1SLaurent Vivier .write = sysbus_esp_pdma_write, 152274d71ea1SLaurent Vivier .endianness = DEVICE_NATIVE_ENDIAN, 152374d71ea1SLaurent Vivier .valid.min_access_size = 1, 1524cf1b8286SMark Cave-Ayland .valid.max_access_size = 4, 1525cf1b8286SMark Cave-Ayland .impl.min_access_size = 1, 1526cf1b8286SMark Cave-Ayland .impl.max_access_size = 2, 152774d71ea1SLaurent Vivier }; 152874d71ea1SLaurent Vivier 1529afd4030cSPaolo Bonzini static const struct SCSIBusInfo esp_scsi_info = { 1530afd4030cSPaolo Bonzini .tcq = false, 15317e0380b9SPaolo Bonzini .max_target = ESP_MAX_DEVS, 15327e0380b9SPaolo Bonzini .max_lun = 7, 1533afd4030cSPaolo Bonzini 1534a7a22088SMark Cave-Ayland .load_request = esp_load_request, 1535c6df7102SPaolo Bonzini .transfer_data = esp_transfer_data, 153694d3f98aSPaolo Bonzini .complete = esp_command_complete, 153794d3f98aSPaolo Bonzini .cancel = esp_request_cancelled 1538cfdc1bb0SPaolo Bonzini }; 1539cfdc1bb0SPaolo Bonzini 1540a391fdbcSHervé Poussineau static void sysbus_esp_gpio_demux(void *opaque, int irq, int level) 1541cfb9de9cSPaul Brook { 154284fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(opaque); 1543eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1544a391fdbcSHervé Poussineau 1545a391fdbcSHervé Poussineau switch (irq) { 1546a391fdbcSHervé Poussineau case 0: 1547a391fdbcSHervé Poussineau parent_esp_reset(s, irq, level); 1548a391fdbcSHervé Poussineau break; 1549a391fdbcSHervé Poussineau case 1: 1550b86dc5cbSMark Cave-Ayland esp_dma_enable(s, irq, level); 1551a391fdbcSHervé Poussineau break; 1552a391fdbcSHervé Poussineau } 1553a391fdbcSHervé Poussineau } 1554a391fdbcSHervé Poussineau 1555b09318caSHu Tao static void sysbus_esp_realize(DeviceState *dev, Error **errp) 1556a391fdbcSHervé Poussineau { 1557b09318caSHu Tao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 155884fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(dev); 1559eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1560eb169c76SMark Cave-Ayland 1561eb169c76SMark Cave-Ayland if (!qdev_realize(DEVICE(s), NULL, errp)) { 1562eb169c76SMark Cave-Ayland return; 1563eb169c76SMark Cave-Ayland } 15646f7e9aecSbellard 1565b09318caSHu Tao sysbus_init_irq(sbd, &s->irq); 15666dec7c0dSMark Cave-Ayland sysbus_init_irq(sbd, &s->drq_irq); 1567a391fdbcSHervé Poussineau assert(sysbus->it_shift != -1); 15686f7e9aecSbellard 1569d32e4b3dSHervé Poussineau s->chip_id = TCHI_FAS100A; 157029776739SPaolo Bonzini memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops, 157174d71ea1SLaurent Vivier sysbus, "esp-regs", ESP_REGS << sysbus->it_shift); 1572b09318caSHu Tao sysbus_init_mmio(sbd, &sysbus->iomem); 157374d71ea1SLaurent Vivier memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_ops, 1574cf1b8286SMark Cave-Ayland sysbus, "esp-pdma", 4); 157574d71ea1SLaurent Vivier sysbus_init_mmio(sbd, &sysbus->pdma); 15766f7e9aecSbellard 1577b09318caSHu Tao qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2); 15782d069babSblueswir1 1579739e95f5SPeter Maydell scsi_bus_init(&s->bus, sizeof(s->bus), dev, &esp_scsi_info); 158067e999beSbellard } 1581cfb9de9cSPaul Brook 1582a391fdbcSHervé Poussineau static void sysbus_esp_hard_reset(DeviceState *dev) 1583a391fdbcSHervé Poussineau { 158484fbefedSMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(dev); 1585eb169c76SMark Cave-Ayland ESPState *s = ESP(&sysbus->esp); 1586eb169c76SMark Cave-Ayland 1587eb169c76SMark Cave-Ayland esp_hard_reset(s); 1588eb169c76SMark Cave-Ayland } 1589eb169c76SMark Cave-Ayland 1590eb169c76SMark Cave-Ayland static void sysbus_esp_init(Object *obj) 1591eb169c76SMark Cave-Ayland { 1592eb169c76SMark Cave-Ayland SysBusESPState *sysbus = SYSBUS_ESP(obj); 1593eb169c76SMark Cave-Ayland 1594eb169c76SMark Cave-Ayland object_initialize_child(obj, "esp", &sysbus->esp, TYPE_ESP); 1595a391fdbcSHervé Poussineau } 1596a391fdbcSHervé Poussineau 1597a391fdbcSHervé Poussineau static const VMStateDescription vmstate_sysbus_esp_scsi = { 1598a391fdbcSHervé Poussineau .name = "sysbusespscsi", 15990bd005beSMark Cave-Ayland .version_id = 2, 1600ea84a442SGuenter Roeck .minimum_version_id = 1, 1601ff4a1dabSMark Cave-Ayland .pre_save = esp_pre_save, 16022d7b39a6SRichard Henderson .fields = (const VMStateField[]) { 16030bd005beSMark Cave-Ayland VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2), 1604a391fdbcSHervé Poussineau VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState), 1605a391fdbcSHervé Poussineau VMSTATE_END_OF_LIST() 1606a391fdbcSHervé Poussineau } 1607999e12bbSAnthony Liguori }; 1608999e12bbSAnthony Liguori 1609a391fdbcSHervé Poussineau static void sysbus_esp_class_init(ObjectClass *klass, void *data) 1610999e12bbSAnthony Liguori { 161139bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 1612999e12bbSAnthony Liguori 1613b09318caSHu Tao dc->realize = sysbus_esp_realize; 1614a391fdbcSHervé Poussineau dc->reset = sysbus_esp_hard_reset; 1615a391fdbcSHervé Poussineau dc->vmsd = &vmstate_sysbus_esp_scsi; 1616125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 161763235df8SBlue Swirl } 1618999e12bbSAnthony Liguori 1619042879fcSMark Cave-Ayland static void esp_finalize(Object *obj) 1620042879fcSMark Cave-Ayland { 1621042879fcSMark Cave-Ayland ESPState *s = ESP(obj); 1622042879fcSMark Cave-Ayland 1623042879fcSMark Cave-Ayland fifo8_destroy(&s->fifo); 1624023666daSMark Cave-Ayland fifo8_destroy(&s->cmdfifo); 1625042879fcSMark Cave-Ayland } 1626042879fcSMark Cave-Ayland 1627042879fcSMark Cave-Ayland static void esp_init(Object *obj) 1628042879fcSMark Cave-Ayland { 1629042879fcSMark Cave-Ayland ESPState *s = ESP(obj); 1630042879fcSMark Cave-Ayland 1631042879fcSMark Cave-Ayland fifo8_create(&s->fifo, ESP_FIFO_SZ); 1632023666daSMark Cave-Ayland fifo8_create(&s->cmdfifo, ESP_CMDFIFO_SZ); 1633042879fcSMark Cave-Ayland } 1634042879fcSMark Cave-Ayland 1635eb169c76SMark Cave-Ayland static void esp_class_init(ObjectClass *klass, void *data) 1636eb169c76SMark Cave-Ayland { 1637eb169c76SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(klass); 1638eb169c76SMark Cave-Ayland 1639eb169c76SMark Cave-Ayland /* internal device for sysbusesp/pciespscsi, not user-creatable */ 1640eb169c76SMark Cave-Ayland dc->user_creatable = false; 1641eb169c76SMark Cave-Ayland set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1642eb169c76SMark Cave-Ayland } 1643eb169c76SMark Cave-Ayland 1644499f4089SMark Cave-Ayland static const TypeInfo esp_info_types[] = { 1645499f4089SMark Cave-Ayland { 1646499f4089SMark Cave-Ayland .name = TYPE_SYSBUS_ESP, 1647499f4089SMark Cave-Ayland .parent = TYPE_SYS_BUS_DEVICE, 1648499f4089SMark Cave-Ayland .instance_init = sysbus_esp_init, 1649499f4089SMark Cave-Ayland .instance_size = sizeof(SysBusESPState), 1650499f4089SMark Cave-Ayland .class_init = sysbus_esp_class_init, 1651499f4089SMark Cave-Ayland }, 1652499f4089SMark Cave-Ayland { 1653eb169c76SMark Cave-Ayland .name = TYPE_ESP, 1654eb169c76SMark Cave-Ayland .parent = TYPE_DEVICE, 1655042879fcSMark Cave-Ayland .instance_init = esp_init, 1656042879fcSMark Cave-Ayland .instance_finalize = esp_finalize, 1657eb169c76SMark Cave-Ayland .instance_size = sizeof(ESPState), 1658eb169c76SMark Cave-Ayland .class_init = esp_class_init, 1659499f4089SMark Cave-Ayland }, 1660eb169c76SMark Cave-Ayland }; 1661eb169c76SMark Cave-Ayland 1662499f4089SMark Cave-Ayland DEFINE_TYPES(esp_info_types) 1663