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

1.1       root        1: /*
1.1.1.5 ! root        2:  * QEMU ESP/NCR53C9x emulation
1.1       root        3:  * 
1.1.1.3   root        4:  * Copyright (c) 2005-2006 Fabrice Bellard
1.1       root        5:  * 
                      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:  */
                     24: #include "vl.h"
                     25: 
                     26: /* debug ESP card */
                     27: //#define DEBUG_ESP
                     28: 
1.1.1.5 ! root       29: /*
        !            30:  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
        !            31:  * produced as NCR89C100. See
        !            32:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
        !            33:  * and
        !            34:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
        !            35:  */
        !            36: 
1.1       root       37: #ifdef DEBUG_ESP
                     38: #define DPRINTF(fmt, args...) \
                     39: do { printf("ESP: " fmt , ##args); } while (0)
                     40: #else
                     41: #define DPRINTF(fmt, args...)
                     42: #endif
                     43: 
                     44: #define ESP_MAXREG 0x3f
1.1.1.4   root       45: #define TI_BUFSZ 32
1.1.1.5 ! root       46: /* The HBA is ID 7, so for simplicitly limit to 7 devices.  */
        !            47: #define ESP_MAX_DEVS      7
        !            48: 
1.1.1.3   root       49: typedef struct ESPState ESPState;
1.1       root       50: 
1.1.1.3   root       51: struct ESPState {
1.1       root       52:     BlockDriverState **bd;
                     53:     uint8_t rregs[ESP_MAXREG];
                     54:     uint8_t wregs[ESP_MAXREG];
1.1.1.5 ! root       55:     int32_t ti_size;
1.1.1.2   root       56:     uint32_t ti_rptr, ti_wptr;
                     57:     uint8_t ti_buf[TI_BUFSZ];
1.1.1.4   root       58:     int sense;
1.1.1.2   root       59:     int dma;
1.1.1.4   root       60:     SCSIDevice *scsi_dev[MAX_DISKS];
                     61:     SCSIDevice *current_dev;
                     62:     uint8_t cmdbuf[TI_BUFSZ];
                     63:     int cmdlen;
                     64:     int do_cmd;
1.1.1.5 ! root       65: 
        !            66:     /* The amount of data left in the current DMA transfer.  */
        !            67:     uint32_t dma_left;
        !            68:     /* The size of the current DMA transfer.  Zero if no transfer is in
        !            69:        progress.  */
        !            70:     uint32_t dma_counter;
        !            71:     uint8_t *async_buf;
        !            72:     uint32_t async_len;
        !            73:     void *dma_opaque;
1.1.1.3   root       74: };
1.1       root       75: 
                     76: #define STAT_DO 0x00
                     77: #define STAT_DI 0x01
                     78: #define STAT_CD 0x02
                     79: #define STAT_ST 0x03
                     80: #define STAT_MI 0x06
                     81: #define STAT_MO 0x07
                     82: 
                     83: #define STAT_TC 0x10
1.1.1.5 ! root       84: #define STAT_PE 0x20
        !            85: #define STAT_GE 0x40
1.1       root       86: #define STAT_IN 0x80
                     87: 
                     88: #define INTR_FC 0x08
                     89: #define INTR_BS 0x10
                     90: #define INTR_DC 0x20
1.1.1.2   root       91: #define INTR_RST 0x80
1.1       root       92: 
                     93: #define SEQ_0 0x0
                     94: #define SEQ_CD 0x4
                     95: 
1.1.1.4   root       96: static int get_cmd(ESPState *s, uint8_t *buf)
1.1       root       97: {
1.1.1.5 ! root       98:     uint32_t dmalen;
1.1       root       99:     int target;
                    100: 
1.1.1.5 ! root      101:     dmalen = s->rregs[0] | (s->rregs[1] << 8);
1.1.1.2   root      102:     target = s->wregs[4] & 7;
1.1.1.4   root      103:     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.2   root      104:     if (s->dma) {
1.1.1.5 ! root      105:         espdma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2   root      106:     } else {
                    107:        buf[0] = 0;
                    108:        memcpy(&buf[1], s->ti_buf, dmalen);
                    109:        dmalen++;
                    110:     }
1.1.1.4   root      111: 
1.1       root      112:     s->ti_size = 0;
1.1.1.2   root      113:     s->ti_rptr = 0;
                    114:     s->ti_wptr = 0;
1.1       root      115: 
1.1.1.5 ! root      116:     if (s->current_dev) {
        !           117:         /* Started a new command before the old one finished.  Cancel it.  */
        !           118:         scsi_cancel_io(s->current_dev, 0);
        !           119:         s->async_len = 0;
        !           120:     }
        !           121: 
        !           122:     if (target >= MAX_DISKS || !s->scsi_dev[target]) {
1.1.1.4   root      123:         // No such drive
1.1       root      124:        s->rregs[4] = STAT_IN;
                    125:        s->rregs[5] = INTR_DC;
                    126:        s->rregs[6] = SEQ_0;
1.1.1.5 ! root      127:        espdma_raise_irq(s->dma_opaque);
1.1.1.4   root      128:        return 0;
1.1       root      129:     }
1.1.1.4   root      130:     s->current_dev = s->scsi_dev[target];
                    131:     return dmalen;
                    132: }
                    133: 
                    134: static void do_cmd(ESPState *s, uint8_t *buf)
                    135: {
                    136:     int32_t datalen;
                    137:     int lun;
                    138: 
                    139:     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
                    140:     lun = buf[0] & 7;
                    141:     datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
1.1.1.5 ! root      142:     s->ti_size = datalen;
        !           143:     if (datalen != 0) {
1.1.1.4   root      144:         s->rregs[4] = STAT_IN | STAT_TC;
1.1.1.5 ! root      145:         s->dma_left = 0;
        !           146:         s->dma_counter = 0;
1.1.1.4   root      147:         if (datalen > 0) {
                    148:             s->rregs[4] |= STAT_DI;
1.1.1.5 ! root      149:             scsi_read_data(s->current_dev, 0);
1.1.1.4   root      150:         } else {
                    151:             s->rregs[4] |= STAT_DO;
1.1.1.5 ! root      152:             scsi_write_data(s->current_dev, 0);
1.1.1.2   root      153:         }
1.1       root      154:     }
                    155:     s->rregs[5] = INTR_BS | INTR_FC;
                    156:     s->rregs[6] = SEQ_CD;
1.1.1.5 ! root      157:     espdma_raise_irq(s->dma_opaque);
1.1       root      158: }
                    159: 
1.1.1.4   root      160: static void handle_satn(ESPState *s)
                    161: {
                    162:     uint8_t buf[32];
                    163:     int len;
                    164: 
                    165:     len = get_cmd(s, buf);
                    166:     if (len)
                    167:         do_cmd(s, buf);
                    168: }
                    169: 
                    170: static void handle_satn_stop(ESPState *s)
1.1       root      171: {
1.1.1.4   root      172:     s->cmdlen = get_cmd(s, s->cmdbuf);
                    173:     if (s->cmdlen) {
                    174:         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
                    175:         s->do_cmd = 1;
                    176:         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
                    177:         s->rregs[5] = INTR_BS | INTR_FC;
                    178:         s->rregs[6] = SEQ_CD;
1.1.1.5 ! root      179:         espdma_raise_irq(s->dma_opaque);
1.1.1.4   root      180:     }
                    181: }
1.1       root      182: 
1.1.1.4   root      183: static void write_response(ESPState *s)
                    184: {
                    185:     DPRINTF("Transfer status (sense=%d)\n", s->sense);
                    186:     s->ti_buf[0] = s->sense;
                    187:     s->ti_buf[1] = 0;
1.1.1.2   root      188:     if (s->dma) {
1.1.1.5 ! root      189:         espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
1.1.1.2   root      190:        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
                    191:        s->rregs[5] = INTR_BS | INTR_FC;
                    192:        s->rregs[6] = SEQ_CD;
                    193:     } else {
1.1.1.4   root      194:        s->ti_size = 2;
1.1.1.2   root      195:        s->ti_rptr = 0;
                    196:        s->ti_wptr = 0;
1.1.1.4   root      197:        s->rregs[7] = 2;
1.1.1.2   root      198:     }
1.1.1.5 ! root      199:     espdma_raise_irq(s->dma_opaque);
        !           200: }
1.1       root      201: 
1.1.1.5 ! root      202: static void esp_dma_done(ESPState *s)
        !           203: {
        !           204:     s->rregs[4] |= STAT_IN | STAT_TC;
        !           205:     s->rregs[5] = INTR_BS;
        !           206:     s->rregs[6] = 0;
        !           207:     s->rregs[7] = 0;
        !           208:     s->rregs[0] = 0;
        !           209:     s->rregs[1] = 0;
        !           210:     espdma_raise_irq(s->dma_opaque);
1.1       root      211: }
1.1.1.2   root      212: 
1.1.1.5 ! root      213: static void esp_do_dma(ESPState *s)
        !           214: {
        !           215:     uint32_t len;
        !           216:     int to_device;
        !           217: 
        !           218:     to_device = (s->ti_size < 0);
        !           219:     len = s->dma_left;
        !           220:     if (s->do_cmd) {
        !           221:         DPRINTF("command len %d + %d\n", s->cmdlen, len);
        !           222:         espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
        !           223:         s->ti_size = 0;
        !           224:         s->cmdlen = 0;
        !           225:         s->do_cmd = 0;
        !           226:         do_cmd(s, s->cmdbuf);
        !           227:         return;
        !           228:     }
        !           229:     if (s->async_len == 0) {
        !           230:         /* Defer until data is available.  */
        !           231:         return;
        !           232:     }
        !           233:     if (len > s->async_len) {
        !           234:         len = s->async_len;
        !           235:     }
        !           236:     if (to_device) {
        !           237:         espdma_memory_read(s->dma_opaque, s->async_buf, len);
        !           238:     } else {
        !           239:         espdma_memory_write(s->dma_opaque, s->async_buf, len);
        !           240:     }
        !           241:     s->dma_left -= len;
        !           242:     s->async_buf += len;
        !           243:     s->async_len -= len;
        !           244:     if (to_device)
        !           245:         s->ti_size += len;
        !           246:     else
        !           247:         s->ti_size -= len;
        !           248:     if (s->async_len == 0) {
        !           249:         if (to_device) {
        !           250:             // ti_size is negative
        !           251:             scsi_write_data(s->current_dev, 0);
        !           252:         } else {
        !           253:             scsi_read_data(s->current_dev, 0);
        !           254:             /* If there is still data to be read from the device then
        !           255:                complete the DMA operation immeriately.  Otherwise defer
        !           256:                until the scsi layer has completed.  */
        !           257:             if (s->dma_left == 0 && s->ti_size > 0) {
        !           258:                 esp_dma_done(s);
        !           259:             }
        !           260:         }
        !           261:     } else {
        !           262:         /* Partially filled a scsi buffer. Complete immediately.  */
        !           263:         esp_dma_done(s);
        !           264:     }
        !           265: }
        !           266: 
        !           267: static void esp_command_complete(void *opaque, int reason, uint32_t tag,
        !           268:                                  uint32_t arg)
1.1.1.4   root      269: {
                    270:     ESPState *s = (ESPState *)opaque;
                    271: 
1.1.1.5 ! root      272:     if (reason == SCSI_REASON_DONE) {
        !           273:         DPRINTF("SCSI Command complete\n");
        !           274:         if (s->ti_size != 0)
        !           275:             DPRINTF("SCSI command completed unexpectedly\n");
        !           276:         s->ti_size = 0;
        !           277:         s->dma_left = 0;
        !           278:         s->async_len = 0;
        !           279:         if (arg)
        !           280:             DPRINTF("Command failed\n");
        !           281:         s->sense = arg;
        !           282:         s->rregs[4] = STAT_ST;
        !           283:         esp_dma_done(s);
        !           284:         s->current_dev = NULL;
        !           285:     } else {
        !           286:         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
        !           287:         s->async_len = arg;
        !           288:         s->async_buf = scsi_get_buf(s->current_dev, 0);
        !           289:         if (s->dma_left) {
        !           290:             esp_do_dma(s);
        !           291:         } else if (s->dma_counter != 0 && s->ti_size <= 0) {
        !           292:             /* If this was the last part of a DMA transfer then the
        !           293:                completion interrupt is deferred to here.  */
        !           294:             esp_dma_done(s);
        !           295:         }
        !           296:     }
1.1.1.4   root      297: }
1.1       root      298: 
                    299: static void handle_ti(ESPState *s)
                    300: {
1.1.1.5 ! root      301:     uint32_t dmalen, minlen;
1.1       root      302: 
1.1.1.5 ! root      303:     dmalen = s->rregs[0] | (s->rregs[1] << 8);
1.1.1.4   root      304:     if (dmalen==0) {
                    305:       dmalen=0x10000;
                    306:     }
1.1.1.5 ! root      307:     s->dma_counter = dmalen;
1.1.1.4   root      308: 
                    309:     if (s->do_cmd)
                    310:         minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5 ! root      311:     else if (s->ti_size < 0)
        !           312:         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4   root      313:     else
                    314:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
                    315:     DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2   root      316:     if (s->dma) {
1.1.1.5 ! root      317:         s->dma_left = minlen;
        !           318:         s->rregs[4] &= ~STAT_TC;
        !           319:         esp_do_dma(s);
1.1.1.4   root      320:     } else if (s->do_cmd) {
                    321:         DPRINTF("command len %d\n", s->cmdlen);
                    322:         s->ti_size = 0;
                    323:         s->cmdlen = 0;
                    324:         s->do_cmd = 0;
                    325:         do_cmd(s, s->cmdbuf);
                    326:         return;
                    327:     }
1.1       root      328: }
                    329: 
1.1.1.5 ! root      330: void esp_reset(void *opaque)
1.1       root      331: {
                    332:     ESPState *s = opaque;
1.1.1.5 ! root      333: 
1.1       root      334:     memset(s->rregs, 0, ESP_MAXREG);
1.1.1.3   root      335:     memset(s->wregs, 0, ESP_MAXREG);
1.1       root      336:     s->rregs[0x0e] = 0x4; // Indicate fas100a
1.1.1.3   root      337:     s->ti_size = 0;
                    338:     s->ti_rptr = 0;
                    339:     s->ti_wptr = 0;
                    340:     s->dma = 0;
1.1.1.4   root      341:     s->do_cmd = 0;
1.1       root      342: }
                    343: 
                    344: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    345: {
                    346:     ESPState *s = opaque;
                    347:     uint32_t saddr;
                    348: 
                    349:     saddr = (addr & ESP_MAXREG) >> 2;
1.1.1.2   root      350:     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1       root      351:     switch (saddr) {
1.1.1.2   root      352:     case 2:
                    353:        // FIFO
                    354:        if (s->ti_size > 0) {
                    355:            s->ti_size--;
1.1.1.4   root      356:             if ((s->rregs[4] & 6) == 0) {
                    357:                 /* Data in/out.  */
1.1.1.5 ! root      358:                 fprintf(stderr, "esp: PIO data read not implemented\n");
        !           359:                 s->rregs[2] = 0;
1.1.1.4   root      360:             } else {
                    361:                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
                    362:             }
1.1.1.5 ! root      363:             espdma_raise_irq(s->dma_opaque);
1.1.1.2   root      364:        }
                    365:        if (s->ti_size == 0) {
                    366:             s->ti_rptr = 0;
                    367:             s->ti_wptr = 0;
                    368:         }
                    369:        break;
                    370:     case 5:
                    371:         // interrupt
1.1.1.5 ! root      372:         // Clear interrupt/error status bits
        !           373:         s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
        !           374:        espdma_clear_irq(s->dma_opaque);
1.1.1.2   root      375:         break;
1.1       root      376:     default:
                    377:        break;
                    378:     }
                    379:     return s->rregs[saddr];
                    380: }
                    381: 
                    382: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    383: {
                    384:     ESPState *s = opaque;
                    385:     uint32_t saddr;
                    386: 
                    387:     saddr = (addr & ESP_MAXREG) >> 2;
                    388:     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
                    389:     switch (saddr) {
1.1.1.2   root      390:     case 0:
                    391:     case 1:
1.1.1.5 ! root      392:         s->rregs[4] &= ~STAT_TC;
1.1.1.2   root      393:         break;
                    394:     case 2:
                    395:        // FIFO
1.1.1.4   root      396:         if (s->do_cmd) {
                    397:             s->cmdbuf[s->cmdlen++] = val & 0xff;
                    398:         } else if ((s->rregs[4] & 6) == 0) {
                    399:             uint8_t buf;
                    400:             buf = val & 0xff;
                    401:             s->ti_size--;
1.1.1.5 ! root      402:             fprintf(stderr, "esp: PIO data write not implemented\n");
1.1.1.4   root      403:         } else {
                    404:             s->ti_size++;
                    405:             s->ti_buf[s->ti_wptr++] = val & 0xff;
                    406:         }
1.1.1.2   root      407:        break;
1.1       root      408:     case 3:
1.1.1.2   root      409:         s->rregs[saddr] = val;
1.1       root      410:        // Command
1.1.1.2   root      411:        if (val & 0x80) {
                    412:            s->dma = 1;
1.1.1.5 ! root      413:             /* Reload DMA counter.  */
        !           414:             s->rregs[0] = s->wregs[0];
        !           415:             s->rregs[1] = s->wregs[1];
1.1.1.2   root      416:        } else {
                    417:            s->dma = 0;
                    418:        }
1.1       root      419:        switch(val & 0x7f) {
                    420:        case 0:
                    421:            DPRINTF("NOP (%2.2x)\n", val);
                    422:            break;
                    423:        case 1:
                    424:            DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2   root      425:             //s->ti_size = 0;
1.1       root      426:            s->rregs[5] = INTR_FC;
1.1.1.2   root      427:            s->rregs[6] = 0;
1.1       root      428:            break;
                    429:        case 2:
                    430:            DPRINTF("Chip reset (%2.2x)\n", val);
                    431:            esp_reset(s);
                    432:            break;
                    433:        case 3:
                    434:            DPRINTF("Bus reset (%2.2x)\n", val);
1.1.1.2   root      435:            s->rregs[5] = INTR_RST;
                    436:             if (!(s->wregs[8] & 0x40)) {
1.1.1.5 ! root      437:                 espdma_raise_irq(s->dma_opaque);
1.1.1.2   root      438:             }
1.1       root      439:            break;
                    440:        case 0x10:
                    441:            handle_ti(s);
                    442:            break;
                    443:        case 0x11:
                    444:            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
1.1.1.4   root      445:            write_response(s);
1.1       root      446:            break;
                    447:        case 0x12:
                    448:            DPRINTF("Message Accepted (%2.2x)\n", val);
1.1.1.4   root      449:            write_response(s);
1.1       root      450:            s->rregs[5] = INTR_DC;
                    451:            s->rregs[6] = 0;
                    452:            break;
                    453:        case 0x1a:
                    454:            DPRINTF("Set ATN (%2.2x)\n", val);
                    455:            break;
                    456:        case 0x42:
1.1.1.4   root      457:            DPRINTF("Set ATN (%2.2x)\n", val);
1.1       root      458:            handle_satn(s);
                    459:            break;
                    460:        case 0x43:
                    461:            DPRINTF("Set ATN & stop (%2.2x)\n", val);
1.1.1.4   root      462:            handle_satn_stop(s);
1.1       root      463:            break;
                    464:        default:
1.1.1.2   root      465:            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
1.1       root      466:            break;
                    467:        }
                    468:        break;
                    469:     case 4 ... 7:
                    470:        break;
1.1.1.2   root      471:     case 8:
                    472:         s->rregs[saddr] = val;
                    473:         break;
                    474:     case 9 ... 10:
                    475:         break;
                    476:     case 11:
                    477:         s->rregs[saddr] = val & 0x15;
                    478:         break;
                    479:     case 12 ... 15:
                    480:         s->rregs[saddr] = val;
                    481:         break;
1.1       root      482:     default:
                    483:        break;
                    484:     }
                    485:     s->wregs[saddr] = val;
                    486: }
                    487: 
                    488: static CPUReadMemoryFunc *esp_mem_read[3] = {
                    489:     esp_mem_readb,
                    490:     esp_mem_readb,
                    491:     esp_mem_readb,
                    492: };
                    493: 
                    494: static CPUWriteMemoryFunc *esp_mem_write[3] = {
                    495:     esp_mem_writeb,
                    496:     esp_mem_writeb,
                    497:     esp_mem_writeb,
                    498: };
                    499: 
                    500: static void esp_save(QEMUFile *f, void *opaque)
                    501: {
                    502:     ESPState *s = opaque;
                    503: 
                    504:     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
                    505:     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
1.1.1.2   root      506:     qemu_put_be32s(f, &s->ti_size);
                    507:     qemu_put_be32s(f, &s->ti_rptr);
                    508:     qemu_put_be32s(f, &s->ti_wptr);
                    509:     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
                    510:     qemu_put_be32s(f, &s->dma);
1.1       root      511: }
                    512: 
                    513: static int esp_load(QEMUFile *f, void *opaque, int version_id)
                    514: {
                    515:     ESPState *s = opaque;
                    516:     
1.1.1.5 ! root      517:     if (version_id != 2)
        !           518:         return -EINVAL; // Cannot emulate 1
1.1       root      519: 
                    520:     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
                    521:     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
1.1.1.2   root      522:     qemu_get_be32s(f, &s->ti_size);
                    523:     qemu_get_be32s(f, &s->ti_rptr);
                    524:     qemu_get_be32s(f, &s->ti_wptr);
                    525:     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
                    526:     qemu_get_be32s(f, &s->dma);
1.1       root      527: 
                    528:     return 0;
                    529: }
                    530: 
1.1.1.5 ! root      531: void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
        !           532: {
        !           533:     ESPState *s = (ESPState *)opaque;
        !           534: 
        !           535:     if (id < 0) {
        !           536:         for (id = 0; id < ESP_MAX_DEVS; id++) {
        !           537:             if (s->scsi_dev[id] == NULL)
        !           538:                 break;
        !           539:         }
        !           540:     }
        !           541:     if (id >= ESP_MAX_DEVS) {
        !           542:         DPRINTF("Bad Device ID %d\n", id);
        !           543:         return;
        !           544:     }
        !           545:     if (s->scsi_dev[id]) {
        !           546:         DPRINTF("Destroying device %d\n", id);
        !           547:         scsi_disk_destroy(s->scsi_dev[id]);
        !           548:     }
        !           549:     DPRINTF("Attaching block device %d\n", id);
        !           550:     /* Command queueing is not implemented.  */
        !           551:     s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
        !           552: }
        !           553: 
        !           554: void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
1.1       root      555: {
                    556:     ESPState *s;
1.1.1.5 ! root      557:     int esp_io_memory;
1.1       root      558: 
                    559:     s = qemu_mallocz(sizeof(ESPState));
                    560:     if (!s)
1.1.1.5 ! root      561:         return NULL;
1.1       root      562: 
                    563:     s->bd = bd;
1.1.1.5 ! root      564:     s->dma_opaque = dma_opaque;
1.1       root      565: 
                    566:     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
                    567:     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
                    568: 
                    569:     esp_reset(s);
                    570: 
1.1.1.5 ! root      571:     register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
1.1       root      572:     qemu_register_reset(esp_reset, s);
                    573: 
1.1.1.5 ! root      574:     return s;
        !           575: }

unix.superglobalmegacorp.com