Annotation of qemu/hw/esp.c, revision 1.1.1.13

1.1       root        1: /*
1.1.1.5   root        2:  * QEMU ESP/NCR53C9x emulation
1.1.1.6   root        3:  *
1.1.1.3   root        4:  * Copyright (c) 2005-2006 Fabrice Bellard
1.1.1.6   root        5:  *
1.1       root        6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
1.1.1.7   root       24: 
1.1.1.8   root       25: #include "sysbus.h"
1.1.1.7   root       26: #include "scsi.h"
1.1.1.9   root       27: #include "esp.h"
1.1.1.13! root       28: #include "trace.h"
1.1       root       29: 
1.1.1.5   root       30: /*
1.1.1.6   root       31:  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
                     32:  * also produced as NCR89C100. See
1.1.1.5   root       33:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
                     34:  * and
                     35:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
                     36:  */
                     37: 
1.1.1.8   root       38: #define ESP_ERROR(fmt, ...)                                             \
                     39:     do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
1.1.1.7   root       40: 
1.1.1.6   root       41: #define ESP_REGS 16
1.1.1.7   root       42: #define TI_BUFSZ 16
1.1.1.5   root       43: 
1.1.1.3   root       44: typedef struct ESPState ESPState;
1.1       root       45: 
1.1.1.3   root       46: struct ESPState {
1.1.1.8   root       47:     SysBusDevice busdev;
1.1.1.6   root       48:     uint8_t rregs[ESP_REGS];
                     49:     uint8_t wregs[ESP_REGS];
1.1.1.13! root       50:     qemu_irq irq;
        !            51:     uint32_t it_shift;
1.1.1.5   root       52:     int32_t ti_size;
1.1.1.2   root       53:     uint32_t ti_rptr, ti_wptr;
1.1.1.12  root       54:     uint32_t status;
1.1.1.7   root       55:     uint32_t dma;
1.1.1.13! root       56:     uint8_t ti_buf[TI_BUFSZ];
1.1.1.9   root       57:     SCSIBus bus;
1.1.1.4   root       58:     SCSIDevice *current_dev;
1.1.1.12  root       59:     SCSIRequest *current_req;
1.1.1.4   root       60:     uint8_t cmdbuf[TI_BUFSZ];
1.1.1.7   root       61:     uint32_t cmdlen;
                     62:     uint32_t do_cmd;
1.1.1.5   root       63: 
                     64:     /* The amount of data left in the current DMA transfer.  */
                     65:     uint32_t dma_left;
                     66:     /* The size of the current DMA transfer.  Zero if no transfer is in
                     67:        progress.  */
                     68:     uint32_t dma_counter;
1.1.1.13! root       69:     int dma_enabled;
        !            70: 
1.1.1.5   root       71:     uint32_t async_len;
1.1.1.13! root       72:     uint8_t *async_buf;
1.1.1.7   root       73: 
1.1.1.10  root       74:     ESPDMAMemoryReadWriteFunc dma_memory_read;
                     75:     ESPDMAMemoryReadWriteFunc dma_memory_write;
1.1.1.5   root       76:     void *dma_opaque;
1.1.1.11  root       77:     void (*dma_cb)(ESPState *s);
1.1.1.3   root       78: };
1.1       root       79: 
1.1.1.6   root       80: #define ESP_TCLO   0x0
                     81: #define ESP_TCMID  0x1
                     82: #define ESP_FIFO   0x2
                     83: #define ESP_CMD    0x3
                     84: #define ESP_RSTAT  0x4
                     85: #define ESP_WBUSID 0x4
                     86: #define ESP_RINTR  0x5
                     87: #define ESP_WSEL   0x5
                     88: #define ESP_RSEQ   0x6
                     89: #define ESP_WSYNTP 0x6
                     90: #define ESP_RFLAGS 0x7
                     91: #define ESP_WSYNO  0x7
                     92: #define ESP_CFG1   0x8
                     93: #define ESP_RRES1  0x9
                     94: #define ESP_WCCF   0x9
                     95: #define ESP_RRES2  0xa
                     96: #define ESP_WTEST  0xa
                     97: #define ESP_CFG2   0xb
                     98: #define ESP_CFG3   0xc
                     99: #define ESP_RES3   0xd
                    100: #define ESP_TCHI   0xe
                    101: #define ESP_RES4   0xf
                    102: 
                    103: #define CMD_DMA 0x80
                    104: #define CMD_CMD 0x7f
                    105: 
                    106: #define CMD_NOP      0x00
                    107: #define CMD_FLUSH    0x01
                    108: #define CMD_RESET    0x02
                    109: #define CMD_BUSRESET 0x03
                    110: #define CMD_TI       0x10
                    111: #define CMD_ICCS     0x11
                    112: #define CMD_MSGACC   0x12
1.1.1.9   root      113: #define CMD_PAD      0x18
1.1.1.6   root      114: #define CMD_SATN     0x1a
1.1.1.9   root      115: #define CMD_SEL      0x41
1.1.1.6   root      116: #define CMD_SELATN   0x42
                    117: #define CMD_SELATNS  0x43
                    118: #define CMD_ENSEL    0x44
                    119: 
1.1       root      120: #define STAT_DO 0x00
                    121: #define STAT_DI 0x01
                    122: #define STAT_CD 0x02
                    123: #define STAT_ST 0x03
1.1.1.7   root      124: #define STAT_MO 0x06
                    125: #define STAT_MI 0x07
1.1.1.6   root      126: #define STAT_PIO_MASK 0x06
1.1       root      127: 
                    128: #define STAT_TC 0x10
1.1.1.5   root      129: #define STAT_PE 0x20
                    130: #define STAT_GE 0x40
1.1.1.7   root      131: #define STAT_INT 0x80
                    132: 
                    133: #define BUSID_DID 0x07
1.1       root      134: 
                    135: #define INTR_FC 0x08
                    136: #define INTR_BS 0x10
                    137: #define INTR_DC 0x20
1.1.1.2   root      138: #define INTR_RST 0x80
1.1       root      139: 
                    140: #define SEQ_0 0x0
                    141: #define SEQ_CD 0x4
                    142: 
1.1.1.6   root      143: #define CFG1_RESREPT 0x40
                    144: 
                    145: #define TCHI_FAS100A 0x4
                    146: 
1.1.1.7   root      147: static void esp_raise_irq(ESPState *s)
                    148: {
                    149:     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
                    150:         s->rregs[ESP_RSTAT] |= STAT_INT;
                    151:         qemu_irq_raise(s->irq);
1.1.1.13! root      152:         trace_esp_raise_irq();
1.1.1.7   root      153:     }
                    154: }
                    155: 
                    156: static void esp_lower_irq(ESPState *s)
                    157: {
                    158:     if (s->rregs[ESP_RSTAT] & STAT_INT) {
                    159:         s->rregs[ESP_RSTAT] &= ~STAT_INT;
                    160:         qemu_irq_lower(s->irq);
1.1.1.13! root      161:         trace_esp_lower_irq();
1.1.1.7   root      162:     }
                    163: }
                    164: 
1.1.1.11  root      165: static void esp_dma_enable(void *opaque, int irq, int level)
                    166: {
                    167:     DeviceState *d = opaque;
                    168:     ESPState *s = container_of(d, ESPState, busdev.qdev);
                    169: 
                    170:     if (level) {
                    171:         s->dma_enabled = 1;
1.1.1.13! root      172:         trace_esp_dma_enable();
1.1.1.11  root      173:         if (s->dma_cb) {
                    174:             s->dma_cb(s);
                    175:             s->dma_cb = NULL;
                    176:         }
                    177:     } else {
1.1.1.13! root      178:         trace_esp_dma_disable();
1.1.1.11  root      179:         s->dma_enabled = 0;
                    180:     }
                    181: }
                    182: 
1.1.1.12  root      183: static void esp_request_cancelled(SCSIRequest *req)
                    184: {
                    185:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
                    186: 
                    187:     if (req == s->current_req) {
                    188:         scsi_req_unref(s->current_req);
                    189:         s->current_req = NULL;
                    190:         s->current_dev = NULL;
                    191:     }
                    192: }
                    193: 
1.1.1.7   root      194: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1       root      195: {
1.1.1.5   root      196:     uint32_t dmalen;
1.1       root      197:     int target;
                    198: 
1.1.1.7   root      199:     target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2   root      200:     if (s->dma) {
1.1.1.7   root      201:         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
                    202:         s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2   root      203:     } else {
1.1.1.7   root      204:         dmalen = s->ti_size;
                    205:         memcpy(buf, s->ti_buf, dmalen);
1.1.1.12  root      206:         buf[0] = buf[2] >> 5;
1.1.1.2   root      207:     }
1.1.1.13! root      208:     trace_esp_get_cmd(dmalen, target);
1.1.1.4   root      209: 
1.1       root      210:     s->ti_size = 0;
1.1.1.2   root      211:     s->ti_rptr = 0;
                    212:     s->ti_wptr = 0;
1.1       root      213: 
1.1.1.12  root      214:     if (s->current_req) {
1.1.1.5   root      215:         /* Started a new command before the old one finished.  Cancel it.  */
1.1.1.12  root      216:         scsi_req_cancel(s->current_req);
1.1.1.5   root      217:         s->async_len = 0;
                    218:     }
                    219: 
1.1.1.13! root      220:     s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
        !           221:     if (!s->current_dev) {
1.1.1.4   root      222:         // No such drive
1.1.1.7   root      223:         s->rregs[ESP_RSTAT] = 0;
1.1.1.6   root      224:         s->rregs[ESP_RINTR] = INTR_DC;
                    225:         s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7   root      226:         esp_raise_irq(s);
1.1.1.6   root      227:         return 0;
1.1       root      228:     }
1.1.1.4   root      229:     return dmalen;
                    230: }
                    231: 
1.1.1.9   root      232: static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
1.1.1.4   root      233: {
                    234:     int32_t datalen;
                    235:     int lun;
1.1.1.13! root      236:     SCSIDevice *current_lun;
1.1.1.4   root      237: 
1.1.1.13! root      238:     trace_esp_do_busid_cmd(busid);
1.1.1.9   root      239:     lun = busid & 7;
1.1.1.13! root      240:     current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
        !           241:     s->current_req = scsi_req_new(current_lun, 0, lun, buf, NULL);
        !           242:     datalen = scsi_req_enqueue(s->current_req);
1.1.1.5   root      243:     s->ti_size = datalen;
                    244:     if (datalen != 0) {
1.1.1.7   root      245:         s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5   root      246:         s->dma_left = 0;
                    247:         s->dma_counter = 0;
1.1.1.4   root      248:         if (datalen > 0) {
1.1.1.6   root      249:             s->rregs[ESP_RSTAT] |= STAT_DI;
1.1.1.4   root      250:         } else {
1.1.1.6   root      251:             s->rregs[ESP_RSTAT] |= STAT_DO;
1.1.1.2   root      252:         }
1.1.1.12  root      253:         scsi_req_continue(s->current_req);
1.1       root      254:     }
1.1.1.6   root      255:     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    256:     s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      257:     esp_raise_irq(s);
1.1       root      258: }
                    259: 
1.1.1.9   root      260: static void do_cmd(ESPState *s, uint8_t *buf)
                    261: {
                    262:     uint8_t busid = buf[0];
                    263: 
                    264:     do_busid_cmd(s, &buf[1], busid);
                    265: }
                    266: 
1.1.1.4   root      267: static void handle_satn(ESPState *s)
                    268: {
                    269:     uint8_t buf[32];
                    270:     int len;
                    271: 
1.1.1.11  root      272:     if (!s->dma_enabled) {
                    273:         s->dma_cb = handle_satn;
                    274:         return;
                    275:     }
1.1.1.4   root      276:     len = get_cmd(s, buf);
                    277:     if (len)
                    278:         do_cmd(s, buf);
                    279: }
                    280: 
1.1.1.9   root      281: static void handle_s_without_atn(ESPState *s)
                    282: {
                    283:     uint8_t buf[32];
                    284:     int len;
                    285: 
1.1.1.11  root      286:     if (!s->dma_enabled) {
                    287:         s->dma_cb = handle_s_without_atn;
                    288:         return;
                    289:     }
1.1.1.9   root      290:     len = get_cmd(s, buf);
                    291:     if (len) {
                    292:         do_busid_cmd(s, buf, 0);
                    293:     }
                    294: }
                    295: 
1.1.1.4   root      296: static void handle_satn_stop(ESPState *s)
1.1       root      297: {
1.1.1.11  root      298:     if (!s->dma_enabled) {
                    299:         s->dma_cb = handle_satn_stop;
                    300:         return;
                    301:     }
1.1.1.4   root      302:     s->cmdlen = get_cmd(s, s->cmdbuf);
                    303:     if (s->cmdlen) {
1.1.1.13! root      304:         trace_esp_handle_satn_stop(s->cmdlen);
1.1.1.4   root      305:         s->do_cmd = 1;
1.1.1.7   root      306:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6   root      307:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    308:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      309:         esp_raise_irq(s);
1.1.1.4   root      310:     }
                    311: }
1.1       root      312: 
1.1.1.4   root      313: static void write_response(ESPState *s)
                    314: {
1.1.1.13! root      315:     trace_esp_write_response(s->status);
1.1.1.12  root      316:     s->ti_buf[0] = s->status;
1.1.1.4   root      317:     s->ti_buf[1] = 0;
1.1.1.2   root      318:     if (s->dma) {
1.1.1.7   root      319:         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
                    320:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6   root      321:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    322:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2   root      323:     } else {
1.1.1.6   root      324:         s->ti_size = 2;
                    325:         s->ti_rptr = 0;
                    326:         s->ti_wptr = 0;
                    327:         s->rregs[ESP_RFLAGS] = 2;
1.1.1.2   root      328:     }
1.1.1.7   root      329:     esp_raise_irq(s);
1.1.1.5   root      330: }
1.1       root      331: 
1.1.1.5   root      332: static void esp_dma_done(ESPState *s)
                    333: {
1.1.1.7   root      334:     s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6   root      335:     s->rregs[ESP_RINTR] = INTR_BS;
                    336:     s->rregs[ESP_RSEQ] = 0;
                    337:     s->rregs[ESP_RFLAGS] = 0;
                    338:     s->rregs[ESP_TCLO] = 0;
                    339:     s->rregs[ESP_TCMID] = 0;
1.1.1.7   root      340:     esp_raise_irq(s);
1.1       root      341: }
1.1.1.2   root      342: 
1.1.1.5   root      343: static void esp_do_dma(ESPState *s)
                    344: {
                    345:     uint32_t len;
                    346:     int to_device;
                    347: 
                    348:     to_device = (s->ti_size < 0);
                    349:     len = s->dma_left;
                    350:     if (s->do_cmd) {
1.1.1.13! root      351:         trace_esp_do_dma(s->cmdlen, len);
1.1.1.7   root      352:         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5   root      353:         s->ti_size = 0;
                    354:         s->cmdlen = 0;
                    355:         s->do_cmd = 0;
                    356:         do_cmd(s, s->cmdbuf);
                    357:         return;
                    358:     }
                    359:     if (s->async_len == 0) {
                    360:         /* Defer until data is available.  */
                    361:         return;
                    362:     }
                    363:     if (len > s->async_len) {
                    364:         len = s->async_len;
                    365:     }
                    366:     if (to_device) {
1.1.1.7   root      367:         s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      368:     } else {
1.1.1.7   root      369:         s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      370:     }
                    371:     s->dma_left -= len;
                    372:     s->async_buf += len;
                    373:     s->async_len -= len;
                    374:     if (to_device)
                    375:         s->ti_size += len;
                    376:     else
                    377:         s->ti_size -= len;
                    378:     if (s->async_len == 0) {
1.1.1.12  root      379:         scsi_req_continue(s->current_req);
                    380:         /* If there is still data to be read from the device then
                    381:            complete the DMA operation immediately.  Otherwise defer
                    382:            until the scsi layer has completed.  */
                    383:         if (to_device || s->dma_left != 0 || s->ti_size == 0) {
                    384:             return;
1.1.1.5   root      385:         }
                    386:     }
1.1.1.12  root      387: 
                    388:     /* Partially filled a scsi buffer. Complete immediately.  */
                    389:     esp_dma_done(s);
1.1.1.5   root      390: }
                    391: 
1.1.1.12  root      392: static void esp_command_complete(SCSIRequest *req, uint32_t status)
1.1.1.4   root      393: {
1.1.1.12  root      394:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
1.1.1.4   root      395: 
1.1.1.13! root      396:     trace_esp_command_complete();
1.1.1.12  root      397:     if (s->ti_size != 0) {
1.1.1.13! root      398:         trace_esp_command_complete_unexpected();
1.1.1.12  root      399:     }
                    400:     s->ti_size = 0;
                    401:     s->dma_left = 0;
                    402:     s->async_len = 0;
                    403:     if (status) {
1.1.1.13! root      404:         trace_esp_command_complete_fail();
1.1.1.12  root      405:     }
                    406:     s->status = status;
                    407:     s->rregs[ESP_RSTAT] = STAT_ST;
                    408:     esp_dma_done(s);
                    409:     if (s->current_req) {
                    410:         scsi_req_unref(s->current_req);
                    411:         s->current_req = NULL;
1.1.1.5   root      412:         s->current_dev = NULL;
1.1.1.12  root      413:     }
                    414: }
                    415: 
                    416: static void esp_transfer_data(SCSIRequest *req, uint32_t len)
                    417: {
                    418:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
                    419: 
1.1.1.13! root      420:     trace_esp_transfer_data(s->dma_left, s->ti_size);
1.1.1.12  root      421:     s->async_len = len;
                    422:     s->async_buf = scsi_req_get_buf(req);
                    423:     if (s->dma_left) {
                    424:         esp_do_dma(s);
                    425:     } else if (s->dma_counter != 0 && s->ti_size <= 0) {
                    426:         /* If this was the last part of a DMA transfer then the
                    427:            completion interrupt is deferred to here.  */
                    428:         esp_dma_done(s);
1.1.1.5   root      429:     }
1.1.1.4   root      430: }
1.1       root      431: 
                    432: static void handle_ti(ESPState *s)
                    433: {
1.1.1.5   root      434:     uint32_t dmalen, minlen;
1.1       root      435: 
1.1.1.6   root      436:     dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4   root      437:     if (dmalen==0) {
                    438:       dmalen=0x10000;
                    439:     }
1.1.1.5   root      440:     s->dma_counter = dmalen;
1.1.1.4   root      441: 
                    442:     if (s->do_cmd)
                    443:         minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5   root      444:     else if (s->ti_size < 0)
                    445:         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4   root      446:     else
                    447:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
1.1.1.13! root      448:     trace_esp_handle_ti(minlen);
1.1.1.2   root      449:     if (s->dma) {
1.1.1.5   root      450:         s->dma_left = minlen;
1.1.1.6   root      451:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5   root      452:         esp_do_dma(s);
1.1.1.4   root      453:     } else if (s->do_cmd) {
1.1.1.13! root      454:         trace_esp_handle_ti_cmd(s->cmdlen);
1.1.1.4   root      455:         s->ti_size = 0;
                    456:         s->cmdlen = 0;
                    457:         s->do_cmd = 0;
                    458:         do_cmd(s, s->cmdbuf);
                    459:         return;
                    460:     }
1.1       root      461: }
                    462: 
1.1.1.10  root      463: static void esp_hard_reset(DeviceState *d)
1.1       root      464: {
1.1.1.9   root      465:     ESPState *s = container_of(d, ESPState, busdev.qdev);
1.1.1.5   root      466: 
1.1.1.6   root      467:     memset(s->rregs, 0, ESP_REGS);
                    468:     memset(s->wregs, 0, ESP_REGS);
                    469:     s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3   root      470:     s->ti_size = 0;
                    471:     s->ti_rptr = 0;
                    472:     s->ti_wptr = 0;
                    473:     s->dma = 0;
1.1.1.4   root      474:     s->do_cmd = 0;
1.1.1.11  root      475:     s->dma_cb = NULL;
1.1.1.7   root      476: 
                    477:     s->rregs[ESP_CFG1] = 7;
1.1       root      478: }
                    479: 
1.1.1.10  root      480: static void esp_soft_reset(DeviceState *d)
                    481: {
                    482:     ESPState *s = container_of(d, ESPState, busdev.qdev);
                    483: 
                    484:     qemu_irq_lower(s->irq);
                    485:     esp_hard_reset(d);
                    486: }
                    487: 
1.1.1.6   root      488: static void parent_esp_reset(void *opaque, int irq, int level)
                    489: {
1.1.1.10  root      490:     if (level) {
                    491:         esp_soft_reset(opaque);
                    492:     }
1.1.1.6   root      493: }
                    494: 
1.1.1.11  root      495: static void esp_gpio_demux(void *opaque, int irq, int level)
                    496: {
                    497:     switch (irq) {
                    498:     case 0:
                    499:         parent_esp_reset(opaque, irq, level);
                    500:         break;
                    501:     case 1:
                    502:         esp_dma_enable(opaque, irq, level);
                    503:         break;
                    504:     }
                    505: }
                    506: 
1.1       root      507: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    508: {
                    509:     ESPState *s = opaque;
1.1.1.8   root      510:     uint32_t saddr, old_val;
1.1       root      511: 
1.1.1.7   root      512:     saddr = addr >> s->it_shift;
1.1.1.13! root      513:     trace_esp_mem_readb(saddr, s->rregs[saddr]);
1.1       root      514:     switch (saddr) {
1.1.1.6   root      515:     case ESP_FIFO:
                    516:         if (s->ti_size > 0) {
                    517:             s->ti_size--;
                    518:             if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7   root      519:                 /* Data out.  */
                    520:                 ESP_ERROR("PIO data read not implemented\n");
1.1.1.6   root      521:                 s->rregs[ESP_FIFO] = 0;
1.1.1.4   root      522:             } else {
1.1.1.6   root      523:                 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4   root      524:             }
1.1.1.7   root      525:             esp_raise_irq(s);
1.1.1.6   root      526:         }
                    527:         if (s->ti_size == 0) {
1.1.1.2   root      528:             s->ti_rptr = 0;
                    529:             s->ti_wptr = 0;
                    530:         }
1.1.1.6   root      531:         break;
                    532:     case ESP_RINTR:
1.1.1.8   root      533:         /* Clear sequence step, interrupt register and all status bits
                    534:            except TC */
                    535:         old_val = s->rregs[ESP_RINTR];
                    536:         s->rregs[ESP_RINTR] = 0;
                    537:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
                    538:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      539:         esp_lower_irq(s);
1.1.1.8   root      540: 
                    541:         return old_val;
1.1       root      542:     default:
1.1.1.6   root      543:         break;
1.1       root      544:     }
                    545:     return s->rregs[saddr];
                    546: }
                    547: 
                    548: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    549: {
                    550:     ESPState *s = opaque;
                    551:     uint32_t saddr;
                    552: 
1.1.1.7   root      553:     saddr = addr >> s->it_shift;
1.1.1.13! root      554:     trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
1.1       root      555:     switch (saddr) {
1.1.1.6   root      556:     case ESP_TCLO:
                    557:     case ESP_TCMID:
                    558:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2   root      559:         break;
1.1.1.6   root      560:     case ESP_FIFO:
1.1.1.4   root      561:         if (s->do_cmd) {
                    562:             s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7   root      563:         } else if (s->ti_size == TI_BUFSZ - 1) {
                    564:             ESP_ERROR("fifo overrun\n");
1.1.1.4   root      565:         } else {
                    566:             s->ti_size++;
                    567:             s->ti_buf[s->ti_wptr++] = val & 0xff;
                    568:         }
1.1.1.6   root      569:         break;
                    570:     case ESP_CMD:
1.1.1.2   root      571:         s->rregs[saddr] = val;
1.1.1.6   root      572:         if (val & CMD_DMA) {
                    573:             s->dma = 1;
1.1.1.5   root      574:             /* Reload DMA counter.  */
1.1.1.6   root      575:             s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
                    576:             s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
                    577:         } else {
                    578:             s->dma = 0;
                    579:         }
                    580:         switch(val & CMD_CMD) {
                    581:         case CMD_NOP:
1.1.1.13! root      582:             trace_esp_mem_writeb_cmd_nop(val);
1.1.1.6   root      583:             break;
                    584:         case CMD_FLUSH:
1.1.1.13! root      585:             trace_esp_mem_writeb_cmd_flush(val);
1.1.1.2   root      586:             //s->ti_size = 0;
1.1.1.6   root      587:             s->rregs[ESP_RINTR] = INTR_FC;
                    588:             s->rregs[ESP_RSEQ] = 0;
1.1.1.7   root      589:             s->rregs[ESP_RFLAGS] = 0;
1.1.1.6   root      590:             break;
                    591:         case CMD_RESET:
1.1.1.13! root      592:             trace_esp_mem_writeb_cmd_reset(val);
1.1.1.10  root      593:             esp_soft_reset(&s->busdev.qdev);
1.1.1.6   root      594:             break;
                    595:         case CMD_BUSRESET:
1.1.1.13! root      596:             trace_esp_mem_writeb_cmd_bus_reset(val);
1.1.1.6   root      597:             s->rregs[ESP_RINTR] = INTR_RST;
                    598:             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7   root      599:                 esp_raise_irq(s);
1.1.1.2   root      600:             }
1.1.1.6   root      601:             break;
                    602:         case CMD_TI:
                    603:             handle_ti(s);
                    604:             break;
                    605:         case CMD_ICCS:
1.1.1.13! root      606:             trace_esp_mem_writeb_cmd_iccs(val);
1.1.1.6   root      607:             write_response(s);
1.1.1.7   root      608:             s->rregs[ESP_RINTR] = INTR_FC;
                    609:             s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6   root      610:             break;
                    611:         case CMD_MSGACC:
1.1.1.13! root      612:             trace_esp_mem_writeb_cmd_msgacc(val);
1.1.1.6   root      613:             s->rregs[ESP_RINTR] = INTR_DC;
                    614:             s->rregs[ESP_RSEQ] = 0;
1.1.1.9   root      615:             s->rregs[ESP_RFLAGS] = 0;
                    616:             esp_raise_irq(s);
                    617:             break;
                    618:         case CMD_PAD:
1.1.1.13! root      619:             trace_esp_mem_writeb_cmd_pad(val);
1.1.1.9   root      620:             s->rregs[ESP_RSTAT] = STAT_TC;
                    621:             s->rregs[ESP_RINTR] = INTR_FC;
                    622:             s->rregs[ESP_RSEQ] = 0;
1.1.1.6   root      623:             break;
                    624:         case CMD_SATN:
1.1.1.13! root      625:             trace_esp_mem_writeb_cmd_satn(val);
1.1.1.6   root      626:             break;
1.1.1.9   root      627:         case CMD_SEL:
1.1.1.13! root      628:             trace_esp_mem_writeb_cmd_sel(val);
1.1.1.9   root      629:             handle_s_without_atn(s);
                    630:             break;
1.1.1.6   root      631:         case CMD_SELATN:
1.1.1.13! root      632:             trace_esp_mem_writeb_cmd_selatn(val);
1.1.1.6   root      633:             handle_satn(s);
                    634:             break;
                    635:         case CMD_SELATNS:
1.1.1.13! root      636:             trace_esp_mem_writeb_cmd_selatns(val);
1.1.1.6   root      637:             handle_satn_stop(s);
                    638:             break;
                    639:         case CMD_ENSEL:
1.1.1.13! root      640:             trace_esp_mem_writeb_cmd_ensel(val);
1.1.1.7   root      641:             s->rregs[ESP_RINTR] = 0;
1.1.1.6   root      642:             break;
                    643:         default:
1.1.1.7   root      644:             ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6   root      645:             break;
                    646:         }
                    647:         break;
                    648:     case ESP_WBUSID ... ESP_WSYNO:
                    649:         break;
                    650:     case ESP_CFG1:
1.1.1.2   root      651:         s->rregs[saddr] = val;
                    652:         break;
1.1.1.6   root      653:     case ESP_WCCF ... ESP_WTEST:
1.1.1.2   root      654:         break;
1.1.1.7   root      655:     case ESP_CFG2 ... ESP_RES4:
1.1.1.2   root      656:         s->rregs[saddr] = val;
                    657:         break;
1.1       root      658:     default:
1.1.1.7   root      659:         ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
                    660:         return;
1.1       root      661:     }
                    662:     s->wregs[saddr] = val;
                    663: }
                    664: 
1.1.1.9   root      665: static CPUReadMemoryFunc * const esp_mem_read[3] = {
1.1       root      666:     esp_mem_readb,
1.1.1.6   root      667:     NULL,
                    668:     NULL,
1.1       root      669: };
                    670: 
1.1.1.9   root      671: static CPUWriteMemoryFunc * const esp_mem_write[3] = {
1.1       root      672:     esp_mem_writeb,
1.1.1.6   root      673:     NULL,
1.1.1.7   root      674:     esp_mem_writeb,
1.1       root      675: };
                    676: 
1.1.1.9   root      677: static const VMStateDescription vmstate_esp = {
                    678:     .name ="esp",
                    679:     .version_id = 3,
                    680:     .minimum_version_id = 3,
                    681:     .minimum_version_id_old = 3,
                    682:     .fields      = (VMStateField []) {
                    683:         VMSTATE_BUFFER(rregs, ESPState),
                    684:         VMSTATE_BUFFER(wregs, ESPState),
                    685:         VMSTATE_INT32(ti_size, ESPState),
                    686:         VMSTATE_UINT32(ti_rptr, ESPState),
                    687:         VMSTATE_UINT32(ti_wptr, ESPState),
                    688:         VMSTATE_BUFFER(ti_buf, ESPState),
1.1.1.12  root      689:         VMSTATE_UINT32(status, ESPState),
1.1.1.9   root      690:         VMSTATE_UINT32(dma, ESPState),
                    691:         VMSTATE_BUFFER(cmdbuf, ESPState),
                    692:         VMSTATE_UINT32(cmdlen, ESPState),
                    693:         VMSTATE_UINT32(do_cmd, ESPState),
                    694:         VMSTATE_UINT32(dma_left, ESPState),
                    695:         VMSTATE_END_OF_LIST()
1.1.1.5   root      696:     }
1.1.1.9   root      697: };
1.1.1.5   root      698: 
1.1.1.8   root      699: void esp_init(target_phys_addr_t espaddr, int it_shift,
1.1.1.10  root      700:               ESPDMAMemoryReadWriteFunc dma_memory_read,
                    701:               ESPDMAMemoryReadWriteFunc dma_memory_write,
1.1.1.11  root      702:               void *dma_opaque, qemu_irq irq, qemu_irq *reset,
                    703:               qemu_irq *dma_enable)
1.1.1.8   root      704: {
                    705:     DeviceState *dev;
                    706:     SysBusDevice *s;
                    707:     ESPState *esp;
                    708: 
                    709:     dev = qdev_create(NULL, "esp");
                    710:     esp = DO_UPCAST(ESPState, busdev.qdev, dev);
                    711:     esp->dma_memory_read = dma_memory_read;
                    712:     esp->dma_memory_write = dma_memory_write;
                    713:     esp->dma_opaque = dma_opaque;
                    714:     esp->it_shift = it_shift;
1.1.1.11  root      715:     /* XXX for now until rc4030 has been changed to use DMA enable signal */
                    716:     esp->dma_enabled = 1;
1.1.1.9   root      717:     qdev_init_nofail(dev);
1.1.1.8   root      718:     s = sysbus_from_qdev(dev);
                    719:     sysbus_connect_irq(s, 0, irq);
                    720:     sysbus_mmio_map(s, 0, espaddr);
1.1.1.9   root      721:     *reset = qdev_get_gpio_in(dev, 0);
1.1.1.11  root      722:     *dma_enable = qdev_get_gpio_in(dev, 1);
1.1.1.8   root      723: }
                    724: 
1.1.1.13! root      725: static const struct SCSIBusInfo esp_scsi_info = {
        !           726:     .tcq = false,
        !           727:     .max_target = ESP_MAX_DEVS,
        !           728:     .max_lun = 7,
        !           729: 
1.1.1.12  root      730:     .transfer_data = esp_transfer_data,
                    731:     .complete = esp_command_complete,
                    732:     .cancel = esp_request_cancelled
                    733: };
                    734: 
1.1.1.9   root      735: static int esp_init1(SysBusDevice *dev)
1.1       root      736: {
1.1.1.8   root      737:     ESPState *s = FROM_SYSBUS(ESPState, dev);
1.1.1.5   root      738:     int esp_io_memory;
1.1       root      739: 
1.1.1.8   root      740:     sysbus_init_irq(dev, &s->irq);
                    741:     assert(s->it_shift != -1);
1.1       root      742: 
1.1.1.11  root      743:     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
                    744:                                            DEVICE_NATIVE_ENDIAN);
1.1.1.8   root      745:     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
1.1       root      746: 
1.1.1.11  root      747:     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
1.1.1.6   root      748: 
1.1.1.13! root      749:     scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
1.1.1.10  root      750:     return scsi_bus_legacy_handle_cmdline(&s->bus);
1.1.1.5   root      751: }
1.1.1.8   root      752: 
1.1.1.9   root      753: static SysBusDeviceInfo esp_info = {
                    754:     .init = esp_init1,
                    755:     .qdev.name  = "esp",
                    756:     .qdev.size  = sizeof(ESPState),
                    757:     .qdev.vmsd  = &vmstate_esp,
1.1.1.10  root      758:     .qdev.reset = esp_hard_reset,
1.1.1.9   root      759:     .qdev.props = (Property[]) {
                    760:         {.name = NULL}
                    761:     }
                    762: };
                    763: 
1.1.1.8   root      764: static void esp_register_devices(void)
                    765: {
1.1.1.9   root      766:     sysbus_register_withprop(&esp_info);
1.1.1.8   root      767: }
                    768: 
                    769: device_init(esp_register_devices)

unix.superglobalmegacorp.com