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

1.1       root        1: /*
                      2:  * QEMU ESP emulation
                      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: 
                     29: #ifdef DEBUG_ESP
                     30: #define DPRINTF(fmt, args...) \
                     31: do { printf("ESP: " fmt , ##args); } while (0)
1.1.1.2   root       32: #define pic_set_irq(irq, level) \
                     33: do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
1.1       root       34: #else
                     35: #define DPRINTF(fmt, args...)
                     36: #endif
                     37: 
                     38: #define ESPDMA_REGS 4
                     39: #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
                     40: #define ESP_MAXREG 0x3f
1.1.1.4 ! root       41: #define TI_BUFSZ 32
1.1.1.2   root       42: #define DMA_VER 0xa0000000
                     43: #define DMA_INTR 1
                     44: #define DMA_INTREN 0x10
1.1.1.4 ! root       45: #define DMA_WRITE_MEM 0x100
1.1.1.2   root       46: #define DMA_LOADED 0x04000000
1.1.1.3   root       47: typedef struct ESPState ESPState;
1.1       root       48: 
1.1.1.3   root       49: struct ESPState {
1.1       root       50:     BlockDriverState **bd;
                     51:     uint8_t rregs[ESP_MAXREG];
                     52:     uint8_t wregs[ESP_MAXREG];
                     53:     int irq;
                     54:     uint32_t espdmaregs[ESPDMA_REGS];
                     55:     uint32_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.3   root       65: };
1.1       root       66: 
                     67: #define STAT_DO 0x00
                     68: #define STAT_DI 0x01
                     69: #define STAT_CD 0x02
                     70: #define STAT_ST 0x03
                     71: #define STAT_MI 0x06
                     72: #define STAT_MO 0x07
                     73: 
                     74: #define STAT_TC 0x10
                     75: #define STAT_IN 0x80
                     76: 
                     77: #define INTR_FC 0x08
                     78: #define INTR_BS 0x10
                     79: #define INTR_DC 0x20
1.1.1.2   root       80: #define INTR_RST 0x80
1.1       root       81: 
                     82: #define SEQ_0 0x0
                     83: #define SEQ_CD 0x4
                     84: 
1.1.1.4 ! root       85: static int get_cmd(ESPState *s, uint8_t *buf)
1.1       root       86: {
                     87:     uint32_t dmaptr, dmalen;
                     88:     int target;
                     89: 
                     90:     dmalen = s->wregs[0] | (s->wregs[1] << 8);
1.1.1.2   root       91:     target = s->wregs[4] & 7;
1.1.1.4 ! root       92:     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.2   root       93:     if (s->dma) {
                     94:        dmaptr = iommu_translate(s->espdmaregs[1]);
1.1.1.4 ! root       95:        DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
        !            96:                 s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
1.1.1.2   root       97:        cpu_physical_memory_read(dmaptr, buf, dmalen);
                     98:     } else {
                     99:        buf[0] = 0;
                    100:        memcpy(&buf[1], s->ti_buf, dmalen);
                    101:        dmalen++;
                    102:     }
1.1.1.4 ! root      103: 
1.1       root      104:     s->ti_size = 0;
1.1.1.2   root      105:     s->ti_rptr = 0;
                    106:     s->ti_wptr = 0;
1.1       root      107: 
1.1.1.4 ! root      108:     if (target >= 4 || !s->scsi_dev[target]) {
        !           109:         // No such drive
1.1       root      110:        s->rregs[4] = STAT_IN;
                    111:        s->rregs[5] = INTR_DC;
                    112:        s->rregs[6] = SEQ_0;
1.1.1.2   root      113:        s->espdmaregs[0] |= DMA_INTR;
1.1       root      114:        pic_set_irq(s->irq, 1);
1.1.1.4 ! root      115:        return 0;
1.1       root      116:     }
1.1.1.4 ! root      117:     s->current_dev = s->scsi_dev[target];
        !           118:     return dmalen;
        !           119: }
        !           120: 
        !           121: static void do_cmd(ESPState *s, uint8_t *buf)
        !           122: {
        !           123:     int32_t datalen;
        !           124:     int lun;
        !           125: 
        !           126:     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
        !           127:     lun = buf[0] & 7;
        !           128:     datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
        !           129:     if (datalen == 0) {
        !           130:         s->ti_size = 0;
        !           131:     } else {
        !           132:         s->rregs[4] = STAT_IN | STAT_TC;
        !           133:         if (datalen > 0) {
        !           134:             s->rregs[4] |= STAT_DI;
        !           135:             s->ti_size = datalen;
        !           136:         } else {
        !           137:             s->rregs[4] |= STAT_DO;
        !           138:             s->ti_size = -datalen;
1.1.1.2   root      139:         }
1.1       root      140:     }
                    141:     s->rregs[5] = INTR_BS | INTR_FC;
                    142:     s->rregs[6] = SEQ_CD;
1.1.1.2   root      143:     s->espdmaregs[0] |= DMA_INTR;
1.1       root      144:     pic_set_irq(s->irq, 1);
                    145: }
                    146: 
1.1.1.4 ! root      147: static void handle_satn(ESPState *s)
        !           148: {
        !           149:     uint8_t buf[32];
        !           150:     int len;
        !           151: 
        !           152:     len = get_cmd(s, buf);
        !           153:     if (len)
        !           154:         do_cmd(s, buf);
        !           155: }
        !           156: 
        !           157: static void handle_satn_stop(ESPState *s)
1.1       root      158: {
1.1.1.4 ! root      159:     s->cmdlen = get_cmd(s, s->cmdbuf);
        !           160:     if (s->cmdlen) {
        !           161:         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
        !           162:         s->do_cmd = 1;
        !           163:         s->espdmaregs[1] += s->cmdlen;
        !           164:         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
        !           165:         s->rregs[5] = INTR_BS | INTR_FC;
        !           166:         s->rregs[6] = SEQ_CD;
        !           167:         s->espdmaregs[0] |= DMA_INTR;
        !           168:         pic_set_irq(s->irq, 1);
        !           169:     }
        !           170: }
1.1       root      171: 
1.1.1.4 ! root      172: static void write_response(ESPState *s)
        !           173: {
        !           174:     uint32_t dmaptr;
        !           175: 
        !           176:     DPRINTF("Transfer status (sense=%d)\n", s->sense);
        !           177:     s->ti_buf[0] = s->sense;
        !           178:     s->ti_buf[1] = 0;
1.1.1.2   root      179:     if (s->dma) {
                    180:        dmaptr = iommu_translate(s->espdmaregs[1]);
1.1.1.4 ! root      181:        DPRINTF("DMA Direction: %c\n",
        !           182:                 s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
        !           183:        cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
1.1.1.2   root      184:        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
                    185:        s->rregs[5] = INTR_BS | INTR_FC;
                    186:        s->rregs[6] = SEQ_CD;
                    187:     } else {
1.1.1.4 ! root      188:        s->ti_size = 2;
1.1.1.2   root      189:        s->ti_rptr = 0;
                    190:        s->ti_wptr = 0;
1.1.1.4 ! root      191:        s->rregs[7] = 2;
1.1.1.2   root      192:     }
                    193:     s->espdmaregs[0] |= DMA_INTR;
1.1       root      194:     pic_set_irq(s->irq, 1);
                    195: 
                    196: }
1.1.1.2   root      197: 
1.1.1.4 ! root      198: static void esp_command_complete(void *opaque, uint32_t tag, int sense)
        !           199: {
        !           200:     ESPState *s = (ESPState *)opaque;
        !           201: 
        !           202:     DPRINTF("SCSI Command complete\n");
        !           203:     if (s->ti_size != 0)
        !           204:         DPRINTF("SCSI command completed unexpectedly\n");
        !           205:     s->ti_size = 0;
        !           206:     if (sense)
        !           207:         DPRINTF("Command failed\n");
        !           208:     s->sense = sense;
        !           209:     s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
        !           210: }
1.1       root      211: 
                    212: static void handle_ti(ESPState *s)
                    213: {
1.1.1.4 ! root      214:     uint32_t dmaptr, dmalen, minlen, len, from, to;
1.1       root      215:     unsigned int i;
1.1.1.4 ! root      216:     int to_device;
        !           217:     uint8_t buf[TARGET_PAGE_SIZE];
1.1       root      218: 
                    219:     dmalen = s->wregs[0] | (s->wregs[1] << 8);
1.1.1.4 ! root      220:     if (dmalen==0) {
        !           221:       dmalen=0x10000;
        !           222:     }
        !           223: 
        !           224:     if (s->do_cmd)
        !           225:         minlen = (dmalen < 32) ? dmalen : 32;
        !           226:     else
        !           227:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
        !           228:     DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2   root      229:     if (s->dma) {
                    230:        dmaptr = iommu_translate(s->espdmaregs[1]);
1.1.1.4 ! root      231:         /* Check if the transfer writes to to reads from the device.  */
        !           232:         to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
        !           233:        DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
        !           234:                 to_device ? 'r': 'w', dmaptr, s->ti_size);
        !           235:        from = s->espdmaregs[1];
        !           236:        to = from + minlen;
        !           237:        for (i = 0; i < minlen; i += len, from += len) {
1.1.1.2   root      238:            dmaptr = iommu_translate(s->espdmaregs[1] + i);
1.1.1.4 ! root      239:            if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
        !           240:                len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
        !           241:             } else {
        !           242:               len = to - from;
        !           243:             }
        !           244:             DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
        !           245:             s->ti_size -= len;
        !           246:             if (s->do_cmd) {
        !           247:                 DPRINTF("command len %d + %d\n", s->cmdlen, len);
        !           248:                 cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
        !           249:                 s->ti_size = 0;
        !           250:                 s->cmdlen = 0;
        !           251:                 s->do_cmd = 0;
        !           252:                 do_cmd(s, s->cmdbuf);
        !           253:                 return;
        !           254:             } else {
        !           255:                 if (to_device) {
        !           256:                     cpu_physical_memory_read(dmaptr, buf, len);
        !           257:                     scsi_write_data(s->current_dev, buf, len);
        !           258:                 } else {
        !           259:                     scsi_read_data(s->current_dev, buf, len);
        !           260:                     cpu_physical_memory_write(dmaptr, buf, len);
        !           261:                 }
        !           262:             }
1.1.1.3   root      263:         }
1.1.1.4 ! root      264:         if (s->ti_size) {
        !           265:            s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
        !           266:         }
        !           267:         s->rregs[5] = INTR_BS;
1.1.1.2   root      268:        s->rregs[6] = 0;
1.1.1.4 ! root      269:        s->rregs[7] = 0;
1.1.1.2   root      270:        s->espdmaregs[0] |= DMA_INTR;
1.1.1.4 ! root      271:     } else if (s->do_cmd) {
        !           272:         DPRINTF("command len %d\n", s->cmdlen);
        !           273:         s->ti_size = 0;
        !           274:         s->cmdlen = 0;
        !           275:         s->do_cmd = 0;
        !           276:         do_cmd(s, s->cmdbuf);
        !           277:         return;
        !           278:     }
1.1       root      279:     pic_set_irq(s->irq, 1);
                    280: }
                    281: 
                    282: static void esp_reset(void *opaque)
                    283: {
                    284:     ESPState *s = opaque;
                    285:     memset(s->rregs, 0, ESP_MAXREG);
1.1.1.3   root      286:     memset(s->wregs, 0, ESP_MAXREG);
1.1       root      287:     s->rregs[0x0e] = 0x4; // Indicate fas100a
                    288:     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
1.1.1.3   root      289:     s->ti_size = 0;
                    290:     s->ti_rptr = 0;
                    291:     s->ti_wptr = 0;
                    292:     s->dma = 0;
1.1.1.4 ! root      293:     s->do_cmd = 0;
1.1       root      294: }
                    295: 
                    296: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    297: {
                    298:     ESPState *s = opaque;
                    299:     uint32_t saddr;
                    300: 
                    301:     saddr = (addr & ESP_MAXREG) >> 2;
1.1.1.2   root      302:     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1       root      303:     switch (saddr) {
1.1.1.2   root      304:     case 2:
                    305:        // FIFO
                    306:        if (s->ti_size > 0) {
                    307:            s->ti_size--;
1.1.1.4 ! root      308:             if ((s->rregs[4] & 6) == 0) {
        !           309:                 /* Data in/out.  */
        !           310:                 scsi_read_data(s->current_dev, &s->rregs[2], 0);
        !           311:             } else {
        !           312:                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
        !           313:             }
1.1.1.2   root      314:            pic_set_irq(s->irq, 1);
                    315:        }
                    316:        if (s->ti_size == 0) {
                    317:             s->ti_rptr = 0;
                    318:             s->ti_wptr = 0;
                    319:         }
                    320:        break;
                    321:     case 5:
                    322:         // interrupt
                    323:         // Clear status bits except TC
                    324:         s->rregs[4] &= STAT_TC;
                    325:         pic_set_irq(s->irq, 0);
                    326:        s->espdmaregs[0] &= ~DMA_INTR;
                    327:         break;
1.1       root      328:     default:
                    329:        break;
                    330:     }
                    331:     return s->rregs[saddr];
                    332: }
                    333: 
                    334: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    335: {
                    336:     ESPState *s = opaque;
                    337:     uint32_t saddr;
                    338: 
                    339:     saddr = (addr & ESP_MAXREG) >> 2;
                    340:     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
                    341:     switch (saddr) {
1.1.1.2   root      342:     case 0:
                    343:     case 1:
                    344:         s->rregs[saddr] = val;
                    345:         break;
                    346:     case 2:
                    347:        // FIFO
1.1.1.4 ! root      348:         if (s->do_cmd) {
        !           349:             s->cmdbuf[s->cmdlen++] = val & 0xff;
        !           350:         } else if ((s->rregs[4] & 6) == 0) {
        !           351:             uint8_t buf;
        !           352:             buf = val & 0xff;
        !           353:             s->ti_size--;
        !           354:             scsi_write_data(s->current_dev, &buf, 0);
        !           355:         } else {
        !           356:             s->ti_size++;
        !           357:             s->ti_buf[s->ti_wptr++] = val & 0xff;
        !           358:         }
1.1.1.2   root      359:        break;
1.1       root      360:     case 3:
1.1.1.2   root      361:         s->rregs[saddr] = val;
1.1       root      362:        // Command
1.1.1.2   root      363:        if (val & 0x80) {
                    364:            s->dma = 1;
                    365:        } else {
                    366:            s->dma = 0;
                    367:        }
1.1       root      368:        switch(val & 0x7f) {
                    369:        case 0:
                    370:            DPRINTF("NOP (%2.2x)\n", val);
                    371:            break;
                    372:        case 1:
                    373:            DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2   root      374:             //s->ti_size = 0;
1.1       root      375:            s->rregs[5] = INTR_FC;
1.1.1.2   root      376:            s->rregs[6] = 0;
1.1       root      377:            break;
                    378:        case 2:
                    379:            DPRINTF("Chip reset (%2.2x)\n", val);
                    380:            esp_reset(s);
                    381:            break;
                    382:        case 3:
                    383:            DPRINTF("Bus reset (%2.2x)\n", val);
1.1.1.2   root      384:            s->rregs[5] = INTR_RST;
                    385:             if (!(s->wregs[8] & 0x40)) {
                    386:                 s->espdmaregs[0] |= DMA_INTR;
                    387:                 pic_set_irq(s->irq, 1);
                    388:             }
1.1       root      389:            break;
                    390:        case 0x10:
                    391:            handle_ti(s);
                    392:            break;
                    393:        case 0x11:
                    394:            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
1.1.1.4 ! root      395:            write_response(s);
1.1       root      396:            break;
                    397:        case 0x12:
                    398:            DPRINTF("Message Accepted (%2.2x)\n", val);
1.1.1.4 ! root      399:            write_response(s);
1.1       root      400:            s->rregs[5] = INTR_DC;
                    401:            s->rregs[6] = 0;
                    402:            break;
                    403:        case 0x1a:
                    404:            DPRINTF("Set ATN (%2.2x)\n", val);
                    405:            break;
                    406:        case 0x42:
1.1.1.4 ! root      407:            DPRINTF("Set ATN (%2.2x)\n", val);
1.1       root      408:            handle_satn(s);
                    409:            break;
                    410:        case 0x43:
                    411:            DPRINTF("Set ATN & stop (%2.2x)\n", val);
1.1.1.4 ! root      412:            handle_satn_stop(s);
1.1       root      413:            break;
                    414:        default:
1.1.1.2   root      415:            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
1.1       root      416:            break;
                    417:        }
                    418:        break;
                    419:     case 4 ... 7:
                    420:        break;
1.1.1.2   root      421:     case 8:
                    422:         s->rregs[saddr] = val;
                    423:         break;
                    424:     case 9 ... 10:
                    425:         break;
                    426:     case 11:
                    427:         s->rregs[saddr] = val & 0x15;
                    428:         break;
                    429:     case 12 ... 15:
                    430:         s->rregs[saddr] = val;
                    431:         break;
1.1       root      432:     default:
                    433:        break;
                    434:     }
                    435:     s->wregs[saddr] = val;
                    436: }
                    437: 
                    438: static CPUReadMemoryFunc *esp_mem_read[3] = {
                    439:     esp_mem_readb,
                    440:     esp_mem_readb,
                    441:     esp_mem_readb,
                    442: };
                    443: 
                    444: static CPUWriteMemoryFunc *esp_mem_write[3] = {
                    445:     esp_mem_writeb,
                    446:     esp_mem_writeb,
                    447:     esp_mem_writeb,
                    448: };
                    449: 
                    450: static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
                    451: {
                    452:     ESPState *s = opaque;
                    453:     uint32_t saddr;
                    454: 
                    455:     saddr = (addr & ESPDMA_MAXADDR) >> 2;
1.1.1.2   root      456:     DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
                    457: 
1.1       root      458:     return s->espdmaregs[saddr];
                    459: }
                    460: 
                    461: static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    462: {
                    463:     ESPState *s = opaque;
                    464:     uint32_t saddr;
                    465: 
                    466:     saddr = (addr & ESPDMA_MAXADDR) >> 2;
1.1.1.2   root      467:     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
1.1       root      468:     switch (saddr) {
                    469:     case 0:
1.1.1.2   root      470:        if (!(val & DMA_INTREN))
1.1       root      471:            pic_set_irq(s->irq, 0);
1.1.1.2   root      472:        if (val & 0x80) {
                    473:             esp_reset(s);
                    474:         } else if (val & 0x40) {
                    475:             val &= ~0x40;
                    476:         } else if (val == 0)
                    477:             val = 0x40;
                    478:         val &= 0x0fffffff;
                    479:         val |= DMA_VER;
                    480:        break;
                    481:     case 1:
1.1.1.4 ! root      482:         s->espdmaregs[0] |= DMA_LOADED;
1.1.1.2   root      483:         break;
1.1       root      484:     default:
                    485:        break;
                    486:     }
                    487:     s->espdmaregs[saddr] = val;
                    488: }
                    489: 
                    490: static CPUReadMemoryFunc *espdma_mem_read[3] = {
                    491:     espdma_mem_readl,
                    492:     espdma_mem_readl,
                    493:     espdma_mem_readl,
                    494: };
                    495: 
                    496: static CPUWriteMemoryFunc *espdma_mem_write[3] = {
                    497:     espdma_mem_writel,
                    498:     espdma_mem_writel,
                    499:     espdma_mem_writel,
                    500: };
                    501: 
                    502: static void esp_save(QEMUFile *f, void *opaque)
                    503: {
                    504:     ESPState *s = opaque;
                    505:     unsigned int i;
                    506: 
                    507:     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
                    508:     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
                    509:     qemu_put_be32s(f, &s->irq);
                    510:     for (i = 0; i < ESPDMA_REGS; i++)
                    511:        qemu_put_be32s(f, &s->espdmaregs[i]);
1.1.1.2   root      512:     qemu_put_be32s(f, &s->ti_size);
                    513:     qemu_put_be32s(f, &s->ti_rptr);
                    514:     qemu_put_be32s(f, &s->ti_wptr);
                    515:     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
                    516:     qemu_put_be32s(f, &s->dma);
1.1       root      517: }
                    518: 
                    519: static int esp_load(QEMUFile *f, void *opaque, int version_id)
                    520: {
                    521:     ESPState *s = opaque;
                    522:     unsigned int i;
                    523:     
                    524:     if (version_id != 1)
                    525:         return -EINVAL;
                    526: 
                    527:     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
                    528:     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
                    529:     qemu_get_be32s(f, &s->irq);
                    530:     for (i = 0; i < ESPDMA_REGS; i++)
                    531:        qemu_get_be32s(f, &s->espdmaregs[i]);
1.1.1.2   root      532:     qemu_get_be32s(f, &s->ti_size);
                    533:     qemu_get_be32s(f, &s->ti_rptr);
                    534:     qemu_get_be32s(f, &s->ti_wptr);
                    535:     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
                    536:     qemu_get_be32s(f, &s->dma);
1.1       root      537: 
                    538:     return 0;
                    539: }
                    540: 
                    541: void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
                    542: {
                    543:     ESPState *s;
                    544:     int esp_io_memory, espdma_io_memory;
1.1.1.4 ! root      545:     int i;
1.1       root      546: 
                    547:     s = qemu_mallocz(sizeof(ESPState));
                    548:     if (!s)
                    549:         return;
                    550: 
                    551:     s->bd = bd;
                    552:     s->irq = irq;
                    553: 
                    554:     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
                    555:     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
                    556: 
                    557:     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
                    558:     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
                    559: 
                    560:     esp_reset(s);
                    561: 
                    562:     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
                    563:     qemu_register_reset(esp_reset, s);
1.1.1.4 ! root      564:     for (i = 0; i < MAX_DISKS; i++) {
        !           565:         if (bs_table[i]) {
        !           566:             s->scsi_dev[i] =
        !           567:                 scsi_disk_init(bs_table[i], esp_command_complete, s);
        !           568:         }
        !           569:     }
1.1       root      570: }
                    571: 

unix.superglobalmegacorp.com