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

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

unix.superglobalmegacorp.com