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

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       root       28: 
                     29: /* debug ESP card */
                     30: //#define DEBUG_ESP
                     31: 
1.1.1.5   root       32: /*
1.1.1.6   root       33:  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
                     34:  * also produced as NCR89C100. See
1.1.1.5   root       35:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
                     36:  * and
                     37:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
                     38:  */
                     39: 
1.1       root       40: #ifdef DEBUG_ESP
1.1.1.8   root       41: #define DPRINTF(fmt, ...)                                       \
                     42:     do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0)
1.1       root       43: #else
1.1.1.8   root       44: #define DPRINTF(fmt, ...) do {} while (0)
1.1       root       45: #endif
                     46: 
1.1.1.8   root       47: #define ESP_ERROR(fmt, ...)                                             \
                     48:     do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
1.1.1.7   root       49: 
1.1.1.6   root       50: #define ESP_REGS 16
1.1.1.7   root       51: #define TI_BUFSZ 16
1.1.1.5   root       52: 
1.1.1.3   root       53: typedef struct ESPState ESPState;
1.1       root       54: 
1.1.1.3   root       55: struct ESPState {
1.1.1.8   root       56:     SysBusDevice busdev;
1.1.1.7   root       57:     uint32_t it_shift;
1.1.1.6   root       58:     qemu_irq irq;
                     59:     uint8_t rregs[ESP_REGS];
                     60:     uint8_t wregs[ESP_REGS];
1.1.1.5   root       61:     int32_t ti_size;
1.1.1.2   root       62:     uint32_t ti_rptr, ti_wptr;
                     63:     uint8_t ti_buf[TI_BUFSZ];
1.1.1.7   root       64:     uint32_t sense;
                     65:     uint32_t dma;
1.1.1.9   root       66:     SCSIBus bus;
1.1.1.4   root       67:     SCSIDevice *current_dev;
                     68:     uint8_t cmdbuf[TI_BUFSZ];
1.1.1.7   root       69:     uint32_t cmdlen;
                     70:     uint32_t do_cmd;
1.1.1.5   root       71: 
                     72:     /* The amount of data left in the current DMA transfer.  */
                     73:     uint32_t dma_left;
                     74:     /* The size of the current DMA transfer.  Zero if no transfer is in
                     75:        progress.  */
                     76:     uint32_t dma_counter;
                     77:     uint8_t *async_buf;
                     78:     uint32_t async_len;
1.1.1.7   root       79: 
1.1.1.10! root       80:     ESPDMAMemoryReadWriteFunc dma_memory_read;
        !            81:     ESPDMAMemoryReadWriteFunc dma_memory_write;
1.1.1.5   root       82:     void *dma_opaque;
1.1.1.3   root       83: };
1.1       root       84: 
1.1.1.6   root       85: #define ESP_TCLO   0x0
                     86: #define ESP_TCMID  0x1
                     87: #define ESP_FIFO   0x2
                     88: #define ESP_CMD    0x3
                     89: #define ESP_RSTAT  0x4
                     90: #define ESP_WBUSID 0x4
                     91: #define ESP_RINTR  0x5
                     92: #define ESP_WSEL   0x5
                     93: #define ESP_RSEQ   0x6
                     94: #define ESP_WSYNTP 0x6
                     95: #define ESP_RFLAGS 0x7
                     96: #define ESP_WSYNO  0x7
                     97: #define ESP_CFG1   0x8
                     98: #define ESP_RRES1  0x9
                     99: #define ESP_WCCF   0x9
                    100: #define ESP_RRES2  0xa
                    101: #define ESP_WTEST  0xa
                    102: #define ESP_CFG2   0xb
                    103: #define ESP_CFG3   0xc
                    104: #define ESP_RES3   0xd
                    105: #define ESP_TCHI   0xe
                    106: #define ESP_RES4   0xf
                    107: 
                    108: #define CMD_DMA 0x80
                    109: #define CMD_CMD 0x7f
                    110: 
                    111: #define CMD_NOP      0x00
                    112: #define CMD_FLUSH    0x01
                    113: #define CMD_RESET    0x02
                    114: #define CMD_BUSRESET 0x03
                    115: #define CMD_TI       0x10
                    116: #define CMD_ICCS     0x11
                    117: #define CMD_MSGACC   0x12
1.1.1.9   root      118: #define CMD_PAD      0x18
1.1.1.6   root      119: #define CMD_SATN     0x1a
1.1.1.9   root      120: #define CMD_SEL      0x41
1.1.1.6   root      121: #define CMD_SELATN   0x42
                    122: #define CMD_SELATNS  0x43
                    123: #define CMD_ENSEL    0x44
                    124: 
1.1       root      125: #define STAT_DO 0x00
                    126: #define STAT_DI 0x01
                    127: #define STAT_CD 0x02
                    128: #define STAT_ST 0x03
1.1.1.7   root      129: #define STAT_MO 0x06
                    130: #define STAT_MI 0x07
1.1.1.6   root      131: #define STAT_PIO_MASK 0x06
1.1       root      132: 
                    133: #define STAT_TC 0x10
1.1.1.5   root      134: #define STAT_PE 0x20
                    135: #define STAT_GE 0x40
1.1.1.7   root      136: #define STAT_INT 0x80
                    137: 
                    138: #define BUSID_DID 0x07
1.1       root      139: 
                    140: #define INTR_FC 0x08
                    141: #define INTR_BS 0x10
                    142: #define INTR_DC 0x20
1.1.1.2   root      143: #define INTR_RST 0x80
1.1       root      144: 
                    145: #define SEQ_0 0x0
                    146: #define SEQ_CD 0x4
                    147: 
1.1.1.6   root      148: #define CFG1_RESREPT 0x40
                    149: 
                    150: #define TCHI_FAS100A 0x4
                    151: 
1.1.1.7   root      152: static void esp_raise_irq(ESPState *s)
                    153: {
                    154:     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
                    155:         s->rregs[ESP_RSTAT] |= STAT_INT;
                    156:         qemu_irq_raise(s->irq);
1.1.1.10! root      157:         DPRINTF("Raise IRQ\n");
1.1.1.7   root      158:     }
                    159: }
                    160: 
                    161: static void esp_lower_irq(ESPState *s)
                    162: {
                    163:     if (s->rregs[ESP_RSTAT] & STAT_INT) {
                    164:         s->rregs[ESP_RSTAT] &= ~STAT_INT;
                    165:         qemu_irq_lower(s->irq);
1.1.1.10! root      166:         DPRINTF("Lower IRQ\n");
1.1.1.7   root      167:     }
                    168: }
                    169: 
                    170: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1       root      171: {
1.1.1.5   root      172:     uint32_t dmalen;
1.1       root      173:     int target;
                    174: 
1.1.1.7   root      175:     target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2   root      176:     if (s->dma) {
1.1.1.7   root      177:         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
                    178:         s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2   root      179:     } else {
1.1.1.7   root      180:         dmalen = s->ti_size;
                    181:         memcpy(buf, s->ti_buf, dmalen);
1.1.1.6   root      182:         buf[0] = 0;
1.1.1.2   root      183:     }
1.1.1.7   root      184:     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.4   root      185: 
1.1       root      186:     s->ti_size = 0;
1.1.1.2   root      187:     s->ti_rptr = 0;
                    188:     s->ti_wptr = 0;
1.1       root      189: 
1.1.1.5   root      190:     if (s->current_dev) {
                    191:         /* Started a new command before the old one finished.  Cancel it.  */
1.1.1.9   root      192:         s->current_dev->info->cancel_io(s->current_dev, 0);
1.1.1.5   root      193:         s->async_len = 0;
                    194:     }
                    195: 
1.1.1.9   root      196:     if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
1.1.1.4   root      197:         // No such drive
1.1.1.7   root      198:         s->rregs[ESP_RSTAT] = 0;
1.1.1.6   root      199:         s->rregs[ESP_RINTR] = INTR_DC;
                    200:         s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7   root      201:         esp_raise_irq(s);
1.1.1.6   root      202:         return 0;
1.1       root      203:     }
1.1.1.9   root      204:     s->current_dev = s->bus.devs[target];
1.1.1.4   root      205:     return dmalen;
                    206: }
                    207: 
1.1.1.9   root      208: static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
1.1.1.4   root      209: {
                    210:     int32_t datalen;
                    211:     int lun;
                    212: 
1.1.1.9   root      213:     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
                    214:     lun = busid & 7;
                    215:     datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun);
1.1.1.5   root      216:     s->ti_size = datalen;
                    217:     if (datalen != 0) {
1.1.1.7   root      218:         s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5   root      219:         s->dma_left = 0;
                    220:         s->dma_counter = 0;
1.1.1.4   root      221:         if (datalen > 0) {
1.1.1.6   root      222:             s->rregs[ESP_RSTAT] |= STAT_DI;
1.1.1.9   root      223:             s->current_dev->info->read_data(s->current_dev, 0);
1.1.1.4   root      224:         } else {
1.1.1.6   root      225:             s->rregs[ESP_RSTAT] |= STAT_DO;
1.1.1.9   root      226:             s->current_dev->info->write_data(s->current_dev, 0);
1.1.1.2   root      227:         }
1.1       root      228:     }
1.1.1.6   root      229:     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    230:     s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      231:     esp_raise_irq(s);
1.1       root      232: }
                    233: 
1.1.1.9   root      234: static void do_cmd(ESPState *s, uint8_t *buf)
                    235: {
                    236:     uint8_t busid = buf[0];
                    237: 
                    238:     do_busid_cmd(s, &buf[1], busid);
                    239: }
                    240: 
1.1.1.4   root      241: static void handle_satn(ESPState *s)
                    242: {
                    243:     uint8_t buf[32];
                    244:     int len;
                    245: 
                    246:     len = get_cmd(s, buf);
                    247:     if (len)
                    248:         do_cmd(s, buf);
                    249: }
                    250: 
1.1.1.9   root      251: static void handle_s_without_atn(ESPState *s)
                    252: {
                    253:     uint8_t buf[32];
                    254:     int len;
                    255: 
                    256:     len = get_cmd(s, buf);
                    257:     if (len) {
                    258:         do_busid_cmd(s, buf, 0);
                    259:     }
                    260: }
                    261: 
1.1.1.4   root      262: static void handle_satn_stop(ESPState *s)
1.1       root      263: {
1.1.1.4   root      264:     s->cmdlen = get_cmd(s, s->cmdbuf);
                    265:     if (s->cmdlen) {
                    266:         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
                    267:         s->do_cmd = 1;
1.1.1.7   root      268:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6   root      269:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    270:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      271:         esp_raise_irq(s);
1.1.1.4   root      272:     }
                    273: }
1.1       root      274: 
1.1.1.4   root      275: static void write_response(ESPState *s)
                    276: {
                    277:     DPRINTF("Transfer status (sense=%d)\n", s->sense);
                    278:     s->ti_buf[0] = s->sense;
                    279:     s->ti_buf[1] = 0;
1.1.1.2   root      280:     if (s->dma) {
1.1.1.7   root      281:         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
                    282:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6   root      283:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    284:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2   root      285:     } else {
1.1.1.6   root      286:         s->ti_size = 2;
                    287:         s->ti_rptr = 0;
                    288:         s->ti_wptr = 0;
                    289:         s->rregs[ESP_RFLAGS] = 2;
1.1.1.2   root      290:     }
1.1.1.7   root      291:     esp_raise_irq(s);
1.1.1.5   root      292: }
1.1       root      293: 
1.1.1.5   root      294: static void esp_dma_done(ESPState *s)
                    295: {
1.1.1.7   root      296:     s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6   root      297:     s->rregs[ESP_RINTR] = INTR_BS;
                    298:     s->rregs[ESP_RSEQ] = 0;
                    299:     s->rregs[ESP_RFLAGS] = 0;
                    300:     s->rregs[ESP_TCLO] = 0;
                    301:     s->rregs[ESP_TCMID] = 0;
1.1.1.7   root      302:     esp_raise_irq(s);
1.1       root      303: }
1.1.1.2   root      304: 
1.1.1.5   root      305: static void esp_do_dma(ESPState *s)
                    306: {
                    307:     uint32_t len;
                    308:     int to_device;
                    309: 
                    310:     to_device = (s->ti_size < 0);
                    311:     len = s->dma_left;
                    312:     if (s->do_cmd) {
                    313:         DPRINTF("command len %d + %d\n", s->cmdlen, len);
1.1.1.7   root      314:         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5   root      315:         s->ti_size = 0;
                    316:         s->cmdlen = 0;
                    317:         s->do_cmd = 0;
                    318:         do_cmd(s, s->cmdbuf);
                    319:         return;
                    320:     }
                    321:     if (s->async_len == 0) {
                    322:         /* Defer until data is available.  */
                    323:         return;
                    324:     }
                    325:     if (len > s->async_len) {
                    326:         len = s->async_len;
                    327:     }
                    328:     if (to_device) {
1.1.1.7   root      329:         s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      330:     } else {
1.1.1.7   root      331:         s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      332:     }
                    333:     s->dma_left -= len;
                    334:     s->async_buf += len;
                    335:     s->async_len -= len;
                    336:     if (to_device)
                    337:         s->ti_size += len;
                    338:     else
                    339:         s->ti_size -= len;
                    340:     if (s->async_len == 0) {
                    341:         if (to_device) {
                    342:             // ti_size is negative
1.1.1.9   root      343:             s->current_dev->info->write_data(s->current_dev, 0);
1.1.1.5   root      344:         } else {
1.1.1.9   root      345:             s->current_dev->info->read_data(s->current_dev, 0);
1.1.1.5   root      346:             /* If there is still data to be read from the device then
1.1.1.7   root      347:                complete the DMA operation immediately.  Otherwise defer
1.1.1.5   root      348:                until the scsi layer has completed.  */
                    349:             if (s->dma_left == 0 && s->ti_size > 0) {
                    350:                 esp_dma_done(s);
                    351:             }
                    352:         }
                    353:     } else {
                    354:         /* Partially filled a scsi buffer. Complete immediately.  */
                    355:         esp_dma_done(s);
                    356:     }
                    357: }
                    358: 
1.1.1.9   root      359: static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,
1.1.1.5   root      360:                                  uint32_t arg)
1.1.1.4   root      361: {
1.1.1.9   root      362:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);
1.1.1.4   root      363: 
1.1.1.5   root      364:     if (reason == SCSI_REASON_DONE) {
                    365:         DPRINTF("SCSI Command complete\n");
                    366:         if (s->ti_size != 0)
                    367:             DPRINTF("SCSI command completed unexpectedly\n");
                    368:         s->ti_size = 0;
                    369:         s->dma_left = 0;
                    370:         s->async_len = 0;
                    371:         if (arg)
                    372:             DPRINTF("Command failed\n");
                    373:         s->sense = arg;
1.1.1.6   root      374:         s->rregs[ESP_RSTAT] = STAT_ST;
1.1.1.5   root      375:         esp_dma_done(s);
                    376:         s->current_dev = NULL;
                    377:     } else {
                    378:         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
                    379:         s->async_len = arg;
1.1.1.9   root      380:         s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);
1.1.1.5   root      381:         if (s->dma_left) {
                    382:             esp_do_dma(s);
                    383:         } else if (s->dma_counter != 0 && s->ti_size <= 0) {
                    384:             /* If this was the last part of a DMA transfer then the
                    385:                completion interrupt is deferred to here.  */
                    386:             esp_dma_done(s);
                    387:         }
                    388:     }
1.1.1.4   root      389: }
1.1       root      390: 
                    391: static void handle_ti(ESPState *s)
                    392: {
1.1.1.5   root      393:     uint32_t dmalen, minlen;
1.1       root      394: 
1.1.1.6   root      395:     dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4   root      396:     if (dmalen==0) {
                    397:       dmalen=0x10000;
                    398:     }
1.1.1.5   root      399:     s->dma_counter = dmalen;
1.1.1.4   root      400: 
                    401:     if (s->do_cmd)
                    402:         minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5   root      403:     else if (s->ti_size < 0)
                    404:         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4   root      405:     else
                    406:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
                    407:     DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2   root      408:     if (s->dma) {
1.1.1.5   root      409:         s->dma_left = minlen;
1.1.1.6   root      410:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5   root      411:         esp_do_dma(s);
1.1.1.4   root      412:     } else if (s->do_cmd) {
                    413:         DPRINTF("command len %d\n", s->cmdlen);
                    414:         s->ti_size = 0;
                    415:         s->cmdlen = 0;
                    416:         s->do_cmd = 0;
                    417:         do_cmd(s, s->cmdbuf);
                    418:         return;
                    419:     }
1.1       root      420: }
                    421: 
1.1.1.10! root      422: static void esp_hard_reset(DeviceState *d)
1.1       root      423: {
1.1.1.9   root      424:     ESPState *s = container_of(d, ESPState, busdev.qdev);
1.1.1.5   root      425: 
1.1.1.6   root      426:     memset(s->rregs, 0, ESP_REGS);
                    427:     memset(s->wregs, 0, ESP_REGS);
                    428:     s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3   root      429:     s->ti_size = 0;
                    430:     s->ti_rptr = 0;
                    431:     s->ti_wptr = 0;
                    432:     s->dma = 0;
1.1.1.4   root      433:     s->do_cmd = 0;
1.1.1.7   root      434: 
                    435:     s->rregs[ESP_CFG1] = 7;
1.1       root      436: }
                    437: 
1.1.1.10! root      438: static void esp_soft_reset(DeviceState *d)
        !           439: {
        !           440:     ESPState *s = container_of(d, ESPState, busdev.qdev);
        !           441: 
        !           442:     qemu_irq_lower(s->irq);
        !           443:     esp_hard_reset(d);
        !           444: }
        !           445: 
1.1.1.6   root      446: static void parent_esp_reset(void *opaque, int irq, int level)
                    447: {
1.1.1.10! root      448:     if (level) {
        !           449:         esp_soft_reset(opaque);
        !           450:     }
1.1.1.6   root      451: }
                    452: 
1.1       root      453: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    454: {
                    455:     ESPState *s = opaque;
1.1.1.8   root      456:     uint32_t saddr, old_val;
1.1       root      457: 
1.1.1.7   root      458:     saddr = addr >> s->it_shift;
1.1.1.2   root      459:     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1       root      460:     switch (saddr) {
1.1.1.6   root      461:     case ESP_FIFO:
                    462:         if (s->ti_size > 0) {
                    463:             s->ti_size--;
                    464:             if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7   root      465:                 /* Data out.  */
                    466:                 ESP_ERROR("PIO data read not implemented\n");
1.1.1.6   root      467:                 s->rregs[ESP_FIFO] = 0;
1.1.1.4   root      468:             } else {
1.1.1.6   root      469:                 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4   root      470:             }
1.1.1.7   root      471:             esp_raise_irq(s);
1.1.1.6   root      472:         }
                    473:         if (s->ti_size == 0) {
1.1.1.2   root      474:             s->ti_rptr = 0;
                    475:             s->ti_wptr = 0;
                    476:         }
1.1.1.6   root      477:         break;
                    478:     case ESP_RINTR:
1.1.1.8   root      479:         /* Clear sequence step, interrupt register and all status bits
                    480:            except TC */
                    481:         old_val = s->rregs[ESP_RINTR];
                    482:         s->rregs[ESP_RINTR] = 0;
                    483:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
                    484:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      485:         esp_lower_irq(s);
1.1.1.8   root      486: 
                    487:         return old_val;
1.1       root      488:     default:
1.1.1.6   root      489:         break;
1.1       root      490:     }
                    491:     return s->rregs[saddr];
                    492: }
                    493: 
                    494: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    495: {
                    496:     ESPState *s = opaque;
                    497:     uint32_t saddr;
                    498: 
1.1.1.7   root      499:     saddr = addr >> s->it_shift;
1.1.1.6   root      500:     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
                    501:             val);
1.1       root      502:     switch (saddr) {
1.1.1.6   root      503:     case ESP_TCLO:
                    504:     case ESP_TCMID:
                    505:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2   root      506:         break;
1.1.1.6   root      507:     case ESP_FIFO:
1.1.1.4   root      508:         if (s->do_cmd) {
                    509:             s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7   root      510:         } else if (s->ti_size == TI_BUFSZ - 1) {
                    511:             ESP_ERROR("fifo overrun\n");
1.1.1.4   root      512:         } else {
                    513:             s->ti_size++;
                    514:             s->ti_buf[s->ti_wptr++] = val & 0xff;
                    515:         }
1.1.1.6   root      516:         break;
                    517:     case ESP_CMD:
1.1.1.2   root      518:         s->rregs[saddr] = val;
1.1.1.6   root      519:         if (val & CMD_DMA) {
                    520:             s->dma = 1;
1.1.1.5   root      521:             /* Reload DMA counter.  */
1.1.1.6   root      522:             s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
                    523:             s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
                    524:         } else {
                    525:             s->dma = 0;
                    526:         }
                    527:         switch(val & CMD_CMD) {
                    528:         case CMD_NOP:
                    529:             DPRINTF("NOP (%2.2x)\n", val);
                    530:             break;
                    531:         case CMD_FLUSH:
                    532:             DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2   root      533:             //s->ti_size = 0;
1.1.1.6   root      534:             s->rregs[ESP_RINTR] = INTR_FC;
                    535:             s->rregs[ESP_RSEQ] = 0;
1.1.1.7   root      536:             s->rregs[ESP_RFLAGS] = 0;
1.1.1.6   root      537:             break;
                    538:         case CMD_RESET:
                    539:             DPRINTF("Chip reset (%2.2x)\n", val);
1.1.1.10! root      540:             esp_soft_reset(&s->busdev.qdev);
1.1.1.6   root      541:             break;
                    542:         case CMD_BUSRESET:
                    543:             DPRINTF("Bus reset (%2.2x)\n", val);
                    544:             s->rregs[ESP_RINTR] = INTR_RST;
                    545:             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7   root      546:                 esp_raise_irq(s);
1.1.1.2   root      547:             }
1.1.1.6   root      548:             break;
                    549:         case CMD_TI:
                    550:             handle_ti(s);
                    551:             break;
                    552:         case CMD_ICCS:
                    553:             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
                    554:             write_response(s);
1.1.1.7   root      555:             s->rregs[ESP_RINTR] = INTR_FC;
                    556:             s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6   root      557:             break;
                    558:         case CMD_MSGACC:
                    559:             DPRINTF("Message Accepted (%2.2x)\n", val);
                    560:             s->rregs[ESP_RINTR] = INTR_DC;
                    561:             s->rregs[ESP_RSEQ] = 0;
1.1.1.9   root      562:             s->rregs[ESP_RFLAGS] = 0;
                    563:             esp_raise_irq(s);
                    564:             break;
                    565:         case CMD_PAD:
                    566:             DPRINTF("Transfer padding (%2.2x)\n", val);
                    567:             s->rregs[ESP_RSTAT] = STAT_TC;
                    568:             s->rregs[ESP_RINTR] = INTR_FC;
                    569:             s->rregs[ESP_RSEQ] = 0;
1.1.1.6   root      570:             break;
                    571:         case CMD_SATN:
                    572:             DPRINTF("Set ATN (%2.2x)\n", val);
                    573:             break;
1.1.1.9   root      574:         case CMD_SEL:
                    575:             DPRINTF("Select without ATN (%2.2x)\n", val);
                    576:             handle_s_without_atn(s);
                    577:             break;
1.1.1.6   root      578:         case CMD_SELATN:
1.1.1.9   root      579:             DPRINTF("Select with ATN (%2.2x)\n", val);
1.1.1.6   root      580:             handle_satn(s);
                    581:             break;
                    582:         case CMD_SELATNS:
1.1.1.9   root      583:             DPRINTF("Select with ATN & stop (%2.2x)\n", val);
1.1.1.6   root      584:             handle_satn_stop(s);
                    585:             break;
                    586:         case CMD_ENSEL:
                    587:             DPRINTF("Enable selection (%2.2x)\n", val);
1.1.1.7   root      588:             s->rregs[ESP_RINTR] = 0;
1.1.1.6   root      589:             break;
                    590:         default:
1.1.1.7   root      591:             ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6   root      592:             break;
                    593:         }
                    594:         break;
                    595:     case ESP_WBUSID ... ESP_WSYNO:
                    596:         break;
                    597:     case ESP_CFG1:
1.1.1.2   root      598:         s->rregs[saddr] = val;
                    599:         break;
1.1.1.6   root      600:     case ESP_WCCF ... ESP_WTEST:
1.1.1.2   root      601:         break;
1.1.1.7   root      602:     case ESP_CFG2 ... ESP_RES4:
1.1.1.2   root      603:         s->rregs[saddr] = val;
                    604:         break;
1.1       root      605:     default:
1.1.1.7   root      606:         ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
                    607:         return;
1.1       root      608:     }
                    609:     s->wregs[saddr] = val;
                    610: }
                    611: 
1.1.1.9   root      612: static CPUReadMemoryFunc * const esp_mem_read[3] = {
1.1       root      613:     esp_mem_readb,
1.1.1.6   root      614:     NULL,
                    615:     NULL,
1.1       root      616: };
                    617: 
1.1.1.9   root      618: static CPUWriteMemoryFunc * const esp_mem_write[3] = {
1.1       root      619:     esp_mem_writeb,
1.1.1.6   root      620:     NULL,
1.1.1.7   root      621:     esp_mem_writeb,
1.1       root      622: };
                    623: 
1.1.1.9   root      624: static const VMStateDescription vmstate_esp = {
                    625:     .name ="esp",
                    626:     .version_id = 3,
                    627:     .minimum_version_id = 3,
                    628:     .minimum_version_id_old = 3,
                    629:     .fields      = (VMStateField []) {
                    630:         VMSTATE_BUFFER(rregs, ESPState),
                    631:         VMSTATE_BUFFER(wregs, ESPState),
                    632:         VMSTATE_INT32(ti_size, ESPState),
                    633:         VMSTATE_UINT32(ti_rptr, ESPState),
                    634:         VMSTATE_UINT32(ti_wptr, ESPState),
                    635:         VMSTATE_BUFFER(ti_buf, ESPState),
                    636:         VMSTATE_UINT32(sense, ESPState),
                    637:         VMSTATE_UINT32(dma, ESPState),
                    638:         VMSTATE_BUFFER(cmdbuf, ESPState),
                    639:         VMSTATE_UINT32(cmdlen, ESPState),
                    640:         VMSTATE_UINT32(do_cmd, ESPState),
                    641:         VMSTATE_UINT32(dma_left, ESPState),
                    642:         VMSTATE_END_OF_LIST()
1.1.1.5   root      643:     }
1.1.1.9   root      644: };
1.1.1.5   root      645: 
1.1.1.8   root      646: void esp_init(target_phys_addr_t espaddr, int it_shift,
1.1.1.10! root      647:               ESPDMAMemoryReadWriteFunc dma_memory_read,
        !           648:               ESPDMAMemoryReadWriteFunc dma_memory_write,
1.1.1.8   root      649:               void *dma_opaque, qemu_irq irq, qemu_irq *reset)
                    650: {
                    651:     DeviceState *dev;
                    652:     SysBusDevice *s;
                    653:     ESPState *esp;
                    654: 
                    655:     dev = qdev_create(NULL, "esp");
                    656:     esp = DO_UPCAST(ESPState, busdev.qdev, dev);
                    657:     esp->dma_memory_read = dma_memory_read;
                    658:     esp->dma_memory_write = dma_memory_write;
                    659:     esp->dma_opaque = dma_opaque;
                    660:     esp->it_shift = it_shift;
1.1.1.9   root      661:     qdev_init_nofail(dev);
1.1.1.8   root      662:     s = sysbus_from_qdev(dev);
                    663:     sysbus_connect_irq(s, 0, irq);
                    664:     sysbus_mmio_map(s, 0, espaddr);
1.1.1.9   root      665:     *reset = qdev_get_gpio_in(dev, 0);
1.1.1.8   root      666: }
                    667: 
1.1.1.9   root      668: static int esp_init1(SysBusDevice *dev)
1.1       root      669: {
1.1.1.8   root      670:     ESPState *s = FROM_SYSBUS(ESPState, dev);
1.1.1.5   root      671:     int esp_io_memory;
1.1       root      672: 
1.1.1.8   root      673:     sysbus_init_irq(dev, &s->irq);
                    674:     assert(s->it_shift != -1);
1.1       root      675: 
1.1.1.8   root      676:     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
                    677:     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
1.1       root      678: 
1.1.1.8   root      679:     qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1);
1.1.1.6   root      680: 
1.1.1.9   root      681:     scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete);
1.1.1.10! root      682:     return scsi_bus_legacy_handle_cmdline(&s->bus);
1.1.1.5   root      683: }
1.1.1.8   root      684: 
1.1.1.9   root      685: static SysBusDeviceInfo esp_info = {
                    686:     .init = esp_init1,
                    687:     .qdev.name  = "esp",
                    688:     .qdev.size  = sizeof(ESPState),
                    689:     .qdev.vmsd  = &vmstate_esp,
1.1.1.10! root      690:     .qdev.reset = esp_hard_reset,
1.1.1.9   root      691:     .qdev.props = (Property[]) {
                    692:         {.name = NULL}
                    693:     }
                    694: };
                    695: 
1.1.1.8   root      696: static void esp_register_devices(void)
                    697: {
1.1.1.9   root      698:     sysbus_register_withprop(&esp_info);
1.1.1.8   root      699: }
                    700: 
                    701: device_init(esp_register_devices)

unix.superglobalmegacorp.com