⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lsi53c895a.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 4 页
字号:
                DPRINTF("Selected target %d%s\n",                        id, insn & (1 << 3) ? " ATN" : "");                /* ??? Linux drivers compain when this is set.  Maybe                   it only applies in low-level mode (unimplemented).                lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */                s->current_dev = s->scsi_dev[id];                s->current_tag = id << 8;                s->scntl1 |= LSI_SCNTL1_CON;                if (insn & (1 << 3)) {                    s->socl |= LSI_SOCL_ATN;                }                lsi_set_phase(s, PHASE_MO);                break;            case 1: /* Disconnect */                DPRINTF("Wait Disconect\n");                s->scntl1 &= ~LSI_SCNTL1_CON;                break;            case 2: /* Wait Reselect */                lsi_wait_reselect(s);                break;            case 3: /* Set */                DPRINTF("Set%s%s%s%s\n",                        insn & (1 << 3) ? " ATN" : "",                        insn & (1 << 6) ? " ACK" : "",                        insn & (1 << 9) ? " TM" : "",                        insn & (1 << 10) ? " CC" : "");                if (insn & (1 << 3)) {                    s->socl |= LSI_SOCL_ATN;                    lsi_set_phase(s, PHASE_MO);                }                if (insn & (1 << 9)) {                    BADF("Target mode not implemented\n");                    exit(1);                }                if (insn & (1 << 10))                    s->carry = 1;                break;            case 4: /* Clear */                DPRINTF("Clear%s%s%s%s\n",                        insn & (1 << 3) ? " ATN" : "",                        insn & (1 << 6) ? " ACK" : "",                        insn & (1 << 9) ? " TM" : "",                        insn & (1 << 10) ? " CC" : "");                if (insn & (1 << 3)) {                    s->socl &= ~LSI_SOCL_ATN;                }                if (insn & (1 << 10))                    s->carry = 0;                break;            }        } else {            uint8_t op0;            uint8_t op1;            uint8_t data8;            int reg;            int operator;#ifdef DEBUG_LSI            static const char *opcode_names[3] =                {"Write", "Read", "Read-Modify-Write"};            static const char *operator_names[8] =                {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"};#endif            reg = ((insn >> 16) & 0x7f) | (insn & 0x80);            data8 = (insn >> 8) & 0xff;            opcode = (insn >> 27) & 7;            operator = (insn >> 24) & 7;            DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n",                    opcode_names[opcode - 5], reg,                    operator_names[operator], data8, s->sfbr,                    (insn & (1 << 23)) ? " SFBR" : "");            op0 = op1 = 0;            switch (opcode) {            case 5: /* From SFBR */                op0 = s->sfbr;                op1 = data8;                break;            case 6: /* To SFBR */                if (operator)                    op0 = lsi_reg_readb(s, reg);                op1 = data8;                break;            case 7: /* Read-modify-write */                if (operator)                    op0 = lsi_reg_readb(s, reg);                if (insn & (1 << 23)) {                    op1 = s->sfbr;                } else {                    op1 = data8;                }                break;            }            switch (operator) {            case 0: /* move */                op0 = op1;                break;            case 1: /* Shift left */                op1 = op0 >> 7;                op0 = (op0 << 1) | s->carry;                s->carry = op1;                break;            case 2: /* OR */                op0 |= op1;                break;            case 3: /* XOR */                op0 |= op1;                break;            case 4: /* AND */                op0 &= op1;                break;            case 5: /* SHR */                op1 = op0 & 1;                op0 = (op0 >> 1) | (s->carry << 7);                break;            case 6: /* ADD */                op0 += op1;                s->carry = op0 < op1;                break;            case 7: /* ADC */                op0 += op1 + s->carry;                if (s->carry)                    s->carry = op0 <= op1;                else                    s->carry = op0 < op1;                break;            }            switch (opcode) {            case 5: /* From SFBR */            case 7: /* Read-modify-write */                lsi_reg_writeb(s, reg, op0);                break;            case 6: /* To SFBR */                s->sfbr = op0;                break;            }        }        break;    case 2: /* Transfer Control.  */        {            int cond;            int jmp;            if ((insn & 0x002e0000) == 0) {                DPRINTF("NOP\n");                break;            }            if (s->sist1 & LSI_SIST1_STO) {                DPRINTF("Delayed select timeout\n");                lsi_stop_script(s);                break;            }            cond = jmp = (insn & (1 << 19)) != 0;            if (cond == jmp && (insn & (1 << 21))) {                DPRINTF("Compare carry %d\n", s->carry == jmp);                cond = s->carry != 0;            }            if (cond == jmp && (insn & (1 << 17))) {                DPRINTF("Compare phase %d %c= %d\n",                        (s->sstat1 & PHASE_MASK),                        jmp ? '=' : '!',                        ((insn >> 24) & 7));                cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7);            }            if (cond == jmp && (insn & (1 << 18))) {                uint8_t mask;                mask = (~insn >> 8) & 0xff;                DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n",                        s->sfbr, mask, jmp ? '=' : '!', insn & mask);                cond = (s->sfbr & mask) == (insn & mask);            }            if (cond == jmp) {                if (insn & (1 << 23)) {                    /* Relative address.  */                    addr = s->dsp + sxt24(addr);                }                switch ((insn >> 27) & 7) {                case 0: /* Jump */                    DPRINTF("Jump to 0x%08x\n", addr);                    s->dsp = addr;                    break;                case 1: /* Call */                    DPRINTF("Call 0x%08x\n", addr);                    s->temp = s->dsp;                    s->dsp = addr;                    break;                case 2: /* Return */                    DPRINTF("Return to 0x%08x\n", s->temp);                    s->dsp = s->temp;                    break;                case 3: /* Interrupt */                    DPRINTF("Interrupt 0x%08x\n", s->dsps);                    if ((insn & (1 << 20)) != 0) {                        s->istat0 |= LSI_ISTAT0_INTF;                        lsi_update_irq(s);                    } else {                        lsi_script_dma_interrupt(s, LSI_DSTAT_SIR);                    }                    break;                default:                    DPRINTF("Illegal transfer control\n");                    lsi_script_dma_interrupt(s, LSI_DSTAT_IID);                    break;                }            } else {                DPRINTF("Control condition failed\n");            }        }        break;    case 3:        if ((insn & (1 << 29)) == 0) {            /* Memory move.  */            uint32_t dest;            /* ??? The docs imply the destination address is loaded into               the TEMP register.  However the Linux drivers rely on               the value being presrved.  */            dest = read_dword(s, s->dsp);            s->dsp += 4;            lsi_memcpy(s, dest, addr, insn & 0xffffff);        } else {            uint8_t data[7];            int reg;            int n;            int i;            if (insn & (1 << 28)) {                addr = s->dsa + sxt24(addr);            }            n = (insn & 7);            reg = (insn >> 16) & 0xff;            if (insn & (1 << 24)) {                cpu_physical_memory_read(addr, data, n);                DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n,                        addr, *(int *)data);                for (i = 0; i < n; i++) {                    lsi_reg_writeb(s, reg + i, data[i]);                }            } else {                DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr);                for (i = 0; i < n; i++) {                    data[i] = lsi_reg_readb(s, reg + i);                }                cpu_physical_memory_write(addr, data, n);            }        }    }    /* ??? Need to avoid infinite loops.  */    if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {        if (s->dcntl & LSI_DCNTL_SSM) {            lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);        } else {            goto again;        }    }    DPRINTF("SCRIPTS execution stopped\n");}static uint8_t lsi_reg_readb(LSIState *s, int offset){    uint8_t tmp;#define CASE_GET_REG32(name, addr) \    case addr: return s->name & 0xff; \    case addr + 1: return (s->name >> 8) & 0xff; \    case addr + 2: return (s->name >> 16) & 0xff; \    case addr + 3: return (s->name >> 24) & 0xff;#ifdef DEBUG_LSI_REG    DPRINTF("Read reg %x\n", offset);#endif    switch (offset) {    case 0x00: /* SCNTL0 */        return s->scntl0;    case 0x01: /* SCNTL1 */        return s->scntl1;    case 0x02: /* SCNTL2 */        return s->scntl2;    case 0x03: /* SCNTL3 */        return s->scntl3;    case 0x04: /* SCID */        return s->scid;    case 0x05: /* SXFER */        return s->sxfer;    case 0x06: /* SDID */        return s->sdid;    case 0x07: /* GPREG0 */        return 0x7f;    case 0xa: /* SSID */        return s->ssid;    case 0xb: /* SBCL */        /* ??? This is not correct. However it's (hopefully) only           used for diagnostics, so should be ok.  */        return 0;    case 0xc: /* DSTAT */        tmp = s->dstat | 0x80;        if ((s->istat0 & LSI_ISTAT0_INTF) == 0)            s->dstat = 0;        lsi_update_irq(s);        return tmp;    case 0x0d: /* SSTAT0 */        return s->sstat0;    case 0x0e: /* SSTAT1 */        return s->sstat1;    case 0x0f: /* SSTAT2 */        return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;    CASE_GET_REG32(dsa, 0x10)    case 0x14: /* ISTAT0 */        return s->istat0;    case 0x16: /* MBOX0 */        return s->mbox0;    case 0x17: /* MBOX1 */        return s->mbox1;    case 0x18: /* CTEST0 */        return 0xff;    case 0x19: /* CTEST1 */        return 0;    case 0x1a: /* CTEST2 */        tmp = LSI_CTEST2_DACK | LSI_CTEST2_CM;        if (s->istat0 & LSI_ISTAT0_SIGP) {            s->istat0 &= ~LSI_ISTAT0_SIGP;            tmp |= LSI_CTEST2_SIGP;        }        return tmp;    case 0x1b: /* CTEST3 */        return s->ctest3;    CASE_GET_REG32(temp, 0x1c)    case 0x20: /* DFIFO */        return 0;    case 0x21: /* CTEST4 */        return s->ctest4;    case 0x22: /* CTEST5 */        return s->ctest5;    case 0x24: /* DBC[0:7] */        return s->dbc & 0xff;    case 0x25: /* DBC[8:15] */        return (s->dbc >> 8) & 0xff;    case 0x26: /* DBC[16->23] */        return (s->dbc >> 16) & 0xff;    case 0x27: /* DCMD */        return s->dcmd;    CASE_GET_REG32(dsp, 0x2c)    CASE_GET_REG32(dsps, 0x30)    CASE_GET_REG32(scratch[0], 0x34)    case 0x38: /* DMODE */        return s->dmode;    case 0x39: /* DIEN */        return s->dien;    case 0x3b: /* DCNTL */        return s->dcntl;    case 0x40: /* SIEN0 */        return s->sien0;    case 0x41: /* SIEN1 */        return s->sien1;    case 0x42: /* SIST0 */        tmp = s->sist0;        s->sist0 = 0;        lsi_update_irq(s);        return tmp;    case 0x43: /* SIST1 */        tmp = s->sist1;        s->sist1 = 0;        lsi_update_irq(s);        return tmp;    case 0x47: /* GPCNTL0 */        return 0x0f;    case 0x48: /* STIME0 */        return s->stime0;    case 0x4a: /* RESPID0 */        return s->respid0;    case 0x4b: /* RESPID1 */        return s->respid1;    case 0x4d: /* STEST1 */        return s->stest1;    case 0x4e: /* STEST2 */        return s->stest2;    case 0x4f: /* STEST3 */        return s->stest3;    case 0x50: /* SIDL */        /* This is needed by the linux drivers.  We currently only update it           during the MSG IN phase.  */        return s->sidl;    case 0x52: /* STEST4 */        return 0xe0;    case 0x56: /* CCNTL0 */        return s->ccntl0;    case 0x57: /* CCNTL1 */        return s->ccntl1;    case 0x58: /* SBDL */        /* Some drivers peek at the data bus during the MSG IN phase.  */        if ((s->sstat1 & PHASE_MASK) == PHASE_MI)            return s->msg[0];        return 0;    case 0x59: /* SBDL high */        return 0;    CASE_GET_REG32(mmrs, 0xa0)    CASE_GET_REG32(mmws, 0xa4)    CASE_GET_REG32(sfs, 0xa8)    CASE_GET_REG32(drs, 0xac)    CASE_GET_REG32(sbms, 0xb0)    CASE_GET_REG32(dmbs, 0xb4)    CASE_GET_REG32(dnad64, 0xb8)    CASE_GET_REG32(pmjad1, 0xc0)    CASE_GET_REG32(pmjad2, 0xc4)    CASE_GET_REG32(rbc, 0xc8)    CASE_GET_REG32(ua, 0xcc)    CASE_GET_REG32(ia, 0xd4)    CASE_GET_REG32(sbc, 0xd8)    CASE_GET_REG32(csbc, 0xdc)    }    if (offset >= 0x5c && offset < 0xa0) {        int n;        int shift;        n = (offset - 0x58) >> 2;        shift = (offset & 3) * 8;        return (s->scratch[n] >> shift) & 0xff;    }    BADF("readb 0x%x\n", offset);    exit(1);#undef CASE_GET_REG32}static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val){#define CASE_SET_REG32(name, addr) \    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \    case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;#ifdef DEBUG_LSI_REG    DPRINTF("Write reg %x = %02x\n", offset, val);#endif    switch (offset) {    case 0x00: /* SCNTL0 */        s->scntl0 = val;        if (val & LSI_SCNTL0_START) {            BADF("Start sequence not implemented\n");        }        break;    case 0x01: /* SCNTL1 */        s->scntl1 = val & ~LSI_SCNTL1_SST;        if (val & LSI_SCNTL1_IARB) {            BADF("Immediate Arbritration not implemented\n");        }        if (val & LSI_SCNTL1_RST) {            s->sstat0 |= LSI_SSTAT0_RST;            lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);        } else {            s->sstat0 &= ~LSI_SSTAT0_RST;        }        break;    case 0x02: /* SCNTL2 */        val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);        s->scntl3 = val;        break;    case 0x03: /* SCNTL3 */        s->scntl3 = val;        break;    case 0x04: /* SCID */        s->scid = val;        break;    case 0x05: /* SXFER */        s->sxfer = val;        break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -