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

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

unix.superglobalmegacorp.com