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

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

unix.superglobalmegacorp.com