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

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.6   root       26: #include "scsi-disk.h"
1.1.1.7   root       27: #include "scsi.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.6   root       66:     SCSIDevice *scsi_dev[ESP_MAX_DEVS];
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: 
                     80:     espdma_memory_read_write dma_memory_read;
                     81:     espdma_memory_read_write 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
                    118: #define CMD_SATN     0x1a
                    119: #define CMD_SELATN   0x42
                    120: #define CMD_SELATNS  0x43
                    121: #define CMD_ENSEL    0x44
                    122: 
1.1       root      123: #define STAT_DO 0x00
                    124: #define STAT_DI 0x01
                    125: #define STAT_CD 0x02
                    126: #define STAT_ST 0x03
1.1.1.7   root      127: #define STAT_MO 0x06
                    128: #define STAT_MI 0x07
1.1.1.6   root      129: #define STAT_PIO_MASK 0x06
1.1       root      130: 
                    131: #define STAT_TC 0x10
1.1.1.5   root      132: #define STAT_PE 0x20
                    133: #define STAT_GE 0x40
1.1.1.7   root      134: #define STAT_INT 0x80
                    135: 
                    136: #define BUSID_DID 0x07
1.1       root      137: 
                    138: #define INTR_FC 0x08
                    139: #define INTR_BS 0x10
                    140: #define INTR_DC 0x20
1.1.1.2   root      141: #define INTR_RST 0x80
1.1       root      142: 
                    143: #define SEQ_0 0x0
                    144: #define SEQ_CD 0x4
                    145: 
1.1.1.6   root      146: #define CFG1_RESREPT 0x40
                    147: 
                    148: #define TCHI_FAS100A 0x4
                    149: 
1.1.1.7   root      150: static void esp_raise_irq(ESPState *s)
                    151: {
                    152:     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
                    153:         s->rregs[ESP_RSTAT] |= STAT_INT;
                    154:         qemu_irq_raise(s->irq);
                    155:     }
                    156: }
                    157: 
                    158: static void esp_lower_irq(ESPState *s)
                    159: {
                    160:     if (s->rregs[ESP_RSTAT] & STAT_INT) {
                    161:         s->rregs[ESP_RSTAT] &= ~STAT_INT;
                    162:         qemu_irq_lower(s->irq);
                    163:     }
                    164: }
                    165: 
                    166: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1       root      167: {
1.1.1.5   root      168:     uint32_t dmalen;
1.1       root      169:     int target;
                    170: 
1.1.1.7   root      171:     target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2   root      172:     if (s->dma) {
1.1.1.7   root      173:         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
                    174:         s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2   root      175:     } else {
1.1.1.7   root      176:         dmalen = s->ti_size;
                    177:         memcpy(buf, s->ti_buf, dmalen);
1.1.1.6   root      178:         buf[0] = 0;
1.1.1.2   root      179:     }
1.1.1.7   root      180:     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.4   root      181: 
1.1       root      182:     s->ti_size = 0;
1.1.1.2   root      183:     s->ti_rptr = 0;
                    184:     s->ti_wptr = 0;
1.1       root      185: 
1.1.1.5   root      186:     if (s->current_dev) {
                    187:         /* Started a new command before the old one finished.  Cancel it.  */
1.1.1.6   root      188:         s->current_dev->cancel_io(s->current_dev, 0);
1.1.1.5   root      189:         s->async_len = 0;
                    190:     }
                    191: 
1.1.1.6   root      192:     if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) {
1.1.1.4   root      193:         // No such drive
1.1.1.7   root      194:         s->rregs[ESP_RSTAT] = 0;
1.1.1.6   root      195:         s->rregs[ESP_RINTR] = INTR_DC;
                    196:         s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7   root      197:         esp_raise_irq(s);
1.1.1.6   root      198:         return 0;
1.1       root      199:     }
1.1.1.4   root      200:     s->current_dev = s->scsi_dev[target];
                    201:     return dmalen;
                    202: }
                    203: 
                    204: static void do_cmd(ESPState *s, uint8_t *buf)
                    205: {
                    206:     int32_t datalen;
                    207:     int lun;
                    208: 
                    209:     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
                    210:     lun = buf[0] & 7;
1.1.1.6   root      211:     datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
1.1.1.5   root      212:     s->ti_size = datalen;
                    213:     if (datalen != 0) {
1.1.1.7   root      214:         s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5   root      215:         s->dma_left = 0;
                    216:         s->dma_counter = 0;
1.1.1.4   root      217:         if (datalen > 0) {
1.1.1.6   root      218:             s->rregs[ESP_RSTAT] |= STAT_DI;
                    219:             s->current_dev->read_data(s->current_dev, 0);
1.1.1.4   root      220:         } else {
1.1.1.6   root      221:             s->rregs[ESP_RSTAT] |= STAT_DO;
                    222:             s->current_dev->write_data(s->current_dev, 0);
1.1.1.2   root      223:         }
1.1       root      224:     }
1.1.1.6   root      225:     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    226:     s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      227:     esp_raise_irq(s);
1.1       root      228: }
                    229: 
1.1.1.4   root      230: static void handle_satn(ESPState *s)
                    231: {
                    232:     uint8_t buf[32];
                    233:     int len;
                    234: 
                    235:     len = get_cmd(s, buf);
                    236:     if (len)
                    237:         do_cmd(s, buf);
                    238: }
                    239: 
                    240: static void handle_satn_stop(ESPState *s)
1.1       root      241: {
1.1.1.4   root      242:     s->cmdlen = get_cmd(s, s->cmdbuf);
                    243:     if (s->cmdlen) {
                    244:         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
                    245:         s->do_cmd = 1;
1.1.1.7   root      246:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6   root      247:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    248:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      249:         esp_raise_irq(s);
1.1.1.4   root      250:     }
                    251: }
1.1       root      252: 
1.1.1.4   root      253: static void write_response(ESPState *s)
                    254: {
                    255:     DPRINTF("Transfer status (sense=%d)\n", s->sense);
                    256:     s->ti_buf[0] = s->sense;
                    257:     s->ti_buf[1] = 0;
1.1.1.2   root      258:     if (s->dma) {
1.1.1.7   root      259:         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
                    260:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6   root      261:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    262:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2   root      263:     } else {
1.1.1.6   root      264:         s->ti_size = 2;
                    265:         s->ti_rptr = 0;
                    266:         s->ti_wptr = 0;
                    267:         s->rregs[ESP_RFLAGS] = 2;
1.1.1.2   root      268:     }
1.1.1.7   root      269:     esp_raise_irq(s);
1.1.1.5   root      270: }
1.1       root      271: 
1.1.1.5   root      272: static void esp_dma_done(ESPState *s)
                    273: {
1.1.1.7   root      274:     s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6   root      275:     s->rregs[ESP_RINTR] = INTR_BS;
                    276:     s->rregs[ESP_RSEQ] = 0;
                    277:     s->rregs[ESP_RFLAGS] = 0;
                    278:     s->rregs[ESP_TCLO] = 0;
                    279:     s->rregs[ESP_TCMID] = 0;
1.1.1.7   root      280:     esp_raise_irq(s);
1.1       root      281: }
1.1.1.2   root      282: 
1.1.1.5   root      283: static void esp_do_dma(ESPState *s)
                    284: {
                    285:     uint32_t len;
                    286:     int to_device;
                    287: 
                    288:     to_device = (s->ti_size < 0);
                    289:     len = s->dma_left;
                    290:     if (s->do_cmd) {
                    291:         DPRINTF("command len %d + %d\n", s->cmdlen, len);
1.1.1.7   root      292:         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5   root      293:         s->ti_size = 0;
                    294:         s->cmdlen = 0;
                    295:         s->do_cmd = 0;
                    296:         do_cmd(s, s->cmdbuf);
                    297:         return;
                    298:     }
                    299:     if (s->async_len == 0) {
                    300:         /* Defer until data is available.  */
                    301:         return;
                    302:     }
                    303:     if (len > s->async_len) {
                    304:         len = s->async_len;
                    305:     }
                    306:     if (to_device) {
1.1.1.7   root      307:         s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      308:     } else {
1.1.1.7   root      309:         s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      310:     }
                    311:     s->dma_left -= len;
                    312:     s->async_buf += len;
                    313:     s->async_len -= len;
                    314:     if (to_device)
                    315:         s->ti_size += len;
                    316:     else
                    317:         s->ti_size -= len;
                    318:     if (s->async_len == 0) {
                    319:         if (to_device) {
                    320:             // ti_size is negative
1.1.1.6   root      321:             s->current_dev->write_data(s->current_dev, 0);
1.1.1.5   root      322:         } else {
1.1.1.6   root      323:             s->current_dev->read_data(s->current_dev, 0);
1.1.1.5   root      324:             /* If there is still data to be read from the device then
1.1.1.7   root      325:                complete the DMA operation immediately.  Otherwise defer
1.1.1.5   root      326:                until the scsi layer has completed.  */
                    327:             if (s->dma_left == 0 && s->ti_size > 0) {
                    328:                 esp_dma_done(s);
                    329:             }
                    330:         }
                    331:     } else {
                    332:         /* Partially filled a scsi buffer. Complete immediately.  */
                    333:         esp_dma_done(s);
                    334:     }
                    335: }
                    336: 
                    337: static void esp_command_complete(void *opaque, int reason, uint32_t tag,
                    338:                                  uint32_t arg)
1.1.1.4   root      339: {
                    340:     ESPState *s = (ESPState *)opaque;
                    341: 
1.1.1.5   root      342:     if (reason == SCSI_REASON_DONE) {
                    343:         DPRINTF("SCSI Command complete\n");
                    344:         if (s->ti_size != 0)
                    345:             DPRINTF("SCSI command completed unexpectedly\n");
                    346:         s->ti_size = 0;
                    347:         s->dma_left = 0;
                    348:         s->async_len = 0;
                    349:         if (arg)
                    350:             DPRINTF("Command failed\n");
                    351:         s->sense = arg;
1.1.1.6   root      352:         s->rregs[ESP_RSTAT] = STAT_ST;
1.1.1.5   root      353:         esp_dma_done(s);
                    354:         s->current_dev = NULL;
                    355:     } else {
                    356:         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
                    357:         s->async_len = arg;
1.1.1.6   root      358:         s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
1.1.1.5   root      359:         if (s->dma_left) {
                    360:             esp_do_dma(s);
                    361:         } else if (s->dma_counter != 0 && s->ti_size <= 0) {
                    362:             /* If this was the last part of a DMA transfer then the
                    363:                completion interrupt is deferred to here.  */
                    364:             esp_dma_done(s);
                    365:         }
                    366:     }
1.1.1.4   root      367: }
1.1       root      368: 
                    369: static void handle_ti(ESPState *s)
                    370: {
1.1.1.5   root      371:     uint32_t dmalen, minlen;
1.1       root      372: 
1.1.1.6   root      373:     dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4   root      374:     if (dmalen==0) {
                    375:       dmalen=0x10000;
                    376:     }
1.1.1.5   root      377:     s->dma_counter = dmalen;
1.1.1.4   root      378: 
                    379:     if (s->do_cmd)
                    380:         minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5   root      381:     else if (s->ti_size < 0)
                    382:         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4   root      383:     else
                    384:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
                    385:     DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2   root      386:     if (s->dma) {
1.1.1.5   root      387:         s->dma_left = minlen;
1.1.1.6   root      388:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5   root      389:         esp_do_dma(s);
1.1.1.4   root      390:     } else if (s->do_cmd) {
                    391:         DPRINTF("command len %d\n", s->cmdlen);
                    392:         s->ti_size = 0;
                    393:         s->cmdlen = 0;
                    394:         s->do_cmd = 0;
                    395:         do_cmd(s, s->cmdbuf);
                    396:         return;
                    397:     }
1.1       root      398: }
                    399: 
1.1.1.6   root      400: static void esp_reset(void *opaque)
1.1       root      401: {
                    402:     ESPState *s = opaque;
1.1.1.5   root      403: 
1.1.1.6   root      404:     memset(s->rregs, 0, ESP_REGS);
                    405:     memset(s->wregs, 0, ESP_REGS);
                    406:     s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3   root      407:     s->ti_size = 0;
                    408:     s->ti_rptr = 0;
                    409:     s->ti_wptr = 0;
                    410:     s->dma = 0;
1.1.1.4   root      411:     s->do_cmd = 0;
1.1.1.7   root      412: 
                    413:     s->rregs[ESP_CFG1] = 7;
1.1       root      414: }
                    415: 
1.1.1.6   root      416: static void parent_esp_reset(void *opaque, int irq, int level)
                    417: {
                    418:     if (level)
                    419:         esp_reset(opaque);
                    420: }
                    421: 
1.1       root      422: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    423: {
                    424:     ESPState *s = opaque;
1.1.1.8 ! root      425:     uint32_t saddr, old_val;
1.1       root      426: 
1.1.1.7   root      427:     saddr = addr >> s->it_shift;
1.1.1.2   root      428:     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1       root      429:     switch (saddr) {
1.1.1.6   root      430:     case ESP_FIFO:
                    431:         if (s->ti_size > 0) {
                    432:             s->ti_size--;
                    433:             if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7   root      434:                 /* Data out.  */
                    435:                 ESP_ERROR("PIO data read not implemented\n");
1.1.1.6   root      436:                 s->rregs[ESP_FIFO] = 0;
1.1.1.4   root      437:             } else {
1.1.1.6   root      438:                 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4   root      439:             }
1.1.1.7   root      440:             esp_raise_irq(s);
1.1.1.6   root      441:         }
                    442:         if (s->ti_size == 0) {
1.1.1.2   root      443:             s->ti_rptr = 0;
                    444:             s->ti_wptr = 0;
                    445:         }
1.1.1.6   root      446:         break;
                    447:     case ESP_RINTR:
1.1.1.8 ! root      448:         /* Clear sequence step, interrupt register and all status bits
        !           449:            except TC */
        !           450:         old_val = s->rregs[ESP_RINTR];
        !           451:         s->rregs[ESP_RINTR] = 0;
        !           452:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
        !           453:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      454:         esp_lower_irq(s);
1.1.1.8 ! root      455: 
        !           456:         return old_val;
1.1       root      457:     default:
1.1.1.6   root      458:         break;
1.1       root      459:     }
                    460:     return s->rregs[saddr];
                    461: }
                    462: 
                    463: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    464: {
                    465:     ESPState *s = opaque;
                    466:     uint32_t saddr;
                    467: 
1.1.1.7   root      468:     saddr = addr >> s->it_shift;
1.1.1.6   root      469:     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
                    470:             val);
1.1       root      471:     switch (saddr) {
1.1.1.6   root      472:     case ESP_TCLO:
                    473:     case ESP_TCMID:
                    474:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2   root      475:         break;
1.1.1.6   root      476:     case ESP_FIFO:
1.1.1.4   root      477:         if (s->do_cmd) {
                    478:             s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7   root      479:         } else if (s->ti_size == TI_BUFSZ - 1) {
                    480:             ESP_ERROR("fifo overrun\n");
1.1.1.4   root      481:         } else {
                    482:             s->ti_size++;
                    483:             s->ti_buf[s->ti_wptr++] = val & 0xff;
                    484:         }
1.1.1.6   root      485:         break;
                    486:     case ESP_CMD:
1.1.1.2   root      487:         s->rregs[saddr] = val;
1.1.1.6   root      488:         if (val & CMD_DMA) {
                    489:             s->dma = 1;
1.1.1.5   root      490:             /* Reload DMA counter.  */
1.1.1.6   root      491:             s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
                    492:             s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
                    493:         } else {
                    494:             s->dma = 0;
                    495:         }
                    496:         switch(val & CMD_CMD) {
                    497:         case CMD_NOP:
                    498:             DPRINTF("NOP (%2.2x)\n", val);
                    499:             break;
                    500:         case CMD_FLUSH:
                    501:             DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2   root      502:             //s->ti_size = 0;
1.1.1.6   root      503:             s->rregs[ESP_RINTR] = INTR_FC;
                    504:             s->rregs[ESP_RSEQ] = 0;
1.1.1.7   root      505:             s->rregs[ESP_RFLAGS] = 0;
1.1.1.6   root      506:             break;
                    507:         case CMD_RESET:
                    508:             DPRINTF("Chip reset (%2.2x)\n", val);
                    509:             esp_reset(s);
                    510:             break;
                    511:         case CMD_BUSRESET:
                    512:             DPRINTF("Bus reset (%2.2x)\n", val);
                    513:             s->rregs[ESP_RINTR] = INTR_RST;
                    514:             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7   root      515:                 esp_raise_irq(s);
1.1.1.2   root      516:             }
1.1.1.6   root      517:             break;
                    518:         case CMD_TI:
                    519:             handle_ti(s);
                    520:             break;
                    521:         case CMD_ICCS:
                    522:             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
                    523:             write_response(s);
1.1.1.7   root      524:             s->rregs[ESP_RINTR] = INTR_FC;
                    525:             s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6   root      526:             break;
                    527:         case CMD_MSGACC:
                    528:             DPRINTF("Message Accepted (%2.2x)\n", val);
                    529:             write_response(s);
                    530:             s->rregs[ESP_RINTR] = INTR_DC;
                    531:             s->rregs[ESP_RSEQ] = 0;
                    532:             break;
                    533:         case CMD_SATN:
                    534:             DPRINTF("Set ATN (%2.2x)\n", val);
                    535:             break;
                    536:         case CMD_SELATN:
                    537:             DPRINTF("Set ATN (%2.2x)\n", val);
                    538:             handle_satn(s);
                    539:             break;
                    540:         case CMD_SELATNS:
                    541:             DPRINTF("Set ATN & stop (%2.2x)\n", val);
                    542:             handle_satn_stop(s);
                    543:             break;
                    544:         case CMD_ENSEL:
                    545:             DPRINTF("Enable selection (%2.2x)\n", val);
1.1.1.7   root      546:             s->rregs[ESP_RINTR] = 0;
1.1.1.6   root      547:             break;
                    548:         default:
1.1.1.7   root      549:             ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6   root      550:             break;
                    551:         }
                    552:         break;
                    553:     case ESP_WBUSID ... ESP_WSYNO:
                    554:         break;
                    555:     case ESP_CFG1:
1.1.1.2   root      556:         s->rregs[saddr] = val;
                    557:         break;
1.1.1.6   root      558:     case ESP_WCCF ... ESP_WTEST:
1.1.1.2   root      559:         break;
1.1.1.7   root      560:     case ESP_CFG2 ... ESP_RES4:
1.1.1.2   root      561:         s->rregs[saddr] = val;
                    562:         break;
1.1       root      563:     default:
1.1.1.7   root      564:         ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
                    565:         return;
1.1       root      566:     }
                    567:     s->wregs[saddr] = val;
                    568: }
                    569: 
                    570: static CPUReadMemoryFunc *esp_mem_read[3] = {
                    571:     esp_mem_readb,
1.1.1.6   root      572:     NULL,
                    573:     NULL,
1.1       root      574: };
                    575: 
                    576: static CPUWriteMemoryFunc *esp_mem_write[3] = {
                    577:     esp_mem_writeb,
1.1.1.6   root      578:     NULL,
1.1.1.7   root      579:     esp_mem_writeb,
1.1       root      580: };
                    581: 
                    582: static void esp_save(QEMUFile *f, void *opaque)
                    583: {
                    584:     ESPState *s = opaque;
                    585: 
1.1.1.6   root      586:     qemu_put_buffer(f, s->rregs, ESP_REGS);
                    587:     qemu_put_buffer(f, s->wregs, ESP_REGS);
1.1.1.7   root      588:     qemu_put_sbe32s(f, &s->ti_size);
1.1.1.2   root      589:     qemu_put_be32s(f, &s->ti_rptr);
                    590:     qemu_put_be32s(f, &s->ti_wptr);
                    591:     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
1.1.1.6   root      592:     qemu_put_be32s(f, &s->sense);
1.1.1.2   root      593:     qemu_put_be32s(f, &s->dma);
1.1.1.6   root      594:     qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
                    595:     qemu_put_be32s(f, &s->cmdlen);
                    596:     qemu_put_be32s(f, &s->do_cmd);
                    597:     qemu_put_be32s(f, &s->dma_left);
                    598:     // There should be no transfers in progress, so dma_counter is not saved
1.1       root      599: }
                    600: 
                    601: static int esp_load(QEMUFile *f, void *opaque, int version_id)
                    602: {
                    603:     ESPState *s = opaque;
                    604: 
1.1.1.6   root      605:     if (version_id != 3)
                    606:         return -EINVAL; // Cannot emulate 2
                    607: 
                    608:     qemu_get_buffer(f, s->rregs, ESP_REGS);
                    609:     qemu_get_buffer(f, s->wregs, ESP_REGS);
1.1.1.7   root      610:     qemu_get_sbe32s(f, &s->ti_size);
1.1.1.2   root      611:     qemu_get_be32s(f, &s->ti_rptr);
                    612:     qemu_get_be32s(f, &s->ti_wptr);
                    613:     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
1.1.1.6   root      614:     qemu_get_be32s(f, &s->sense);
1.1.1.2   root      615:     qemu_get_be32s(f, &s->dma);
1.1.1.6   root      616:     qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
                    617:     qemu_get_be32s(f, &s->cmdlen);
                    618:     qemu_get_be32s(f, &s->do_cmd);
                    619:     qemu_get_be32s(f, &s->dma_left);
1.1       root      620: 
                    621:     return 0;
                    622: }
                    623: 
1.1.1.8 ! root      624: static void esp_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
1.1.1.5   root      625: {
1.1.1.8 ! root      626:     ESPState *s = FROM_SYSBUS(ESPState, sysbus_from_qdev(host));
1.1.1.5   root      627: 
                    628:     if (id < 0) {
                    629:         for (id = 0; id < ESP_MAX_DEVS; id++) {
1.1.1.7   root      630:             if (id == (s->rregs[ESP_CFG1] & 0x7))
                    631:                 continue;
1.1.1.5   root      632:             if (s->scsi_dev[id] == NULL)
                    633:                 break;
                    634:         }
                    635:     }
                    636:     if (id >= ESP_MAX_DEVS) {
                    637:         DPRINTF("Bad Device ID %d\n", id);
                    638:         return;
                    639:     }
                    640:     if (s->scsi_dev[id]) {
                    641:         DPRINTF("Destroying device %d\n", id);
1.1.1.6   root      642:         s->scsi_dev[id]->destroy(s->scsi_dev[id]);
1.1.1.5   root      643:     }
                    644:     DPRINTF("Attaching block device %d\n", id);
                    645:     /* Command queueing is not implemented.  */
1.1.1.6   root      646:     s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s);
                    647:     if (s->scsi_dev[id] == NULL)
                    648:         s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
1.1.1.5   root      649: }
                    650: 
1.1.1.8 ! root      651: void esp_init(target_phys_addr_t espaddr, int it_shift,
        !           652:               espdma_memory_read_write dma_memory_read,
        !           653:               espdma_memory_read_write dma_memory_write,
        !           654:               void *dma_opaque, qemu_irq irq, qemu_irq *reset)
        !           655: {
        !           656:     DeviceState *dev;
        !           657:     SysBusDevice *s;
        !           658:     ESPState *esp;
        !           659: 
        !           660:     dev = qdev_create(NULL, "esp");
        !           661:     esp = DO_UPCAST(ESPState, busdev.qdev, dev);
        !           662:     esp->dma_memory_read = dma_memory_read;
        !           663:     esp->dma_memory_write = dma_memory_write;
        !           664:     esp->dma_opaque = dma_opaque;
        !           665:     esp->it_shift = it_shift;
        !           666:     qdev_init(dev);
        !           667:     s = sysbus_from_qdev(dev);
        !           668:     sysbus_connect_irq(s, 0, irq);
        !           669:     sysbus_mmio_map(s, 0, espaddr);
        !           670: }
        !           671: 
        !           672: static void esp_init1(SysBusDevice *dev)
1.1       root      673: {
1.1.1.8 ! root      674:     ESPState *s = FROM_SYSBUS(ESPState, dev);
1.1.1.5   root      675:     int esp_io_memory;
1.1       root      676: 
1.1.1.8 ! root      677:     sysbus_init_irq(dev, &s->irq);
        !           678:     assert(s->it_shift != -1);
1.1       root      679: 
1.1.1.8 ! root      680:     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
        !           681:     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
1.1       root      682: 
                    683:     esp_reset(s);
                    684: 
1.1.1.8 ! root      685:     register_savevm("esp", -1, 3, esp_save, esp_load, s);
1.1       root      686:     qemu_register_reset(esp_reset, s);
                    687: 
1.1.1.8 ! root      688:     qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1);
1.1.1.6   root      689: 
1.1.1.8 ! root      690:     scsi_bus_new(&dev->qdev, esp_scsi_attach);
1.1.1.5   root      691: }
1.1.1.8 ! root      692: 
        !           693: static void esp_register_devices(void)
        !           694: {
        !           695:     sysbus_register_dev("esp", sizeof(ESPState), esp_init1);
        !           696: }
        !           697: 
        !           698: device_init(esp_register_devices)

unix.superglobalmegacorp.com