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

📄 ide.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static inline void cpu_to_ube16(uint8_t *buf, int val){    buf[0] = val >> 8;    buf[1] = val;}static inline void cpu_to_ube32(uint8_t *buf, unsigned int val){    buf[0] = val >> 24;    buf[1] = val >> 16;    buf[2] = val >> 8;    buf[3] = val;}static inline int ube16_to_cpu(const uint8_t *buf){    return (buf[0] << 8) | buf[1];}static inline int ube32_to_cpu(const uint8_t *buf){    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];}static void lba_to_msf(uint8_t *buf, int lba){    lba += 150;    buf[0] = (lba / 75) / 60;    buf[1] = (lba / 75) % 60;    buf[2] = lba % 75;}static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,                            int sector_size){    switch(sector_size) {    case 2048:        bdrv_read(bs, (int64_t)lba << 2, buf, 4);        break;    case 2352:        /* sync bytes */        buf[0] = 0x00;        memset(buf + 1, 0xff, 10);        buf[11] = 0x00;        buf += 12;        /* MSF */        lba_to_msf(buf, lba);        buf[3] = 0x01; /* mode 1 data */        buf += 4;        /* data */        bdrv_read(bs, (int64_t)lba << 2, buf, 4);        buf += 2048;        /* ECC */        memset(buf, 0, 288);        break;    default:        break;    }}/* The whole ATAPI transfer logic is handled in this function */static void ide_atapi_cmd_reply_end(IDEState *s){    int byte_count_limit, size;#ifdef DEBUG_IDE_ATAPI    printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",            s->packet_transfer_size,           s->elementary_transfer_size,           s->io_buffer_index);#endif    if (s->packet_transfer_size <= 0) {        /* end of transfer */        ide_transfer_stop(s);        s->status = READY_STAT;        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;        ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI        printf("status=0x%x\n", s->status);#endif    } else {        /* see if a new sector must be read */        if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {            cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);            s->lba++;            s->io_buffer_index = 0;        }        if (s->elementary_transfer_size > 0) {            /* there are some data left to transmit in this elementary               transfer */            size = s->cd_sector_size - s->io_buffer_index;            if (size > s->elementary_transfer_size)                size = s->elementary_transfer_size;            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,                                size, ide_atapi_cmd_reply_end);            s->packet_transfer_size -= size;            s->elementary_transfer_size -= size;            s->io_buffer_index += size;        } else {            /* a new transfer is needed */            s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;            byte_count_limit = s->lcyl | (s->hcyl << 8);#ifdef DEBUG_IDE_ATAPI            printf("byte_count_limit=%d\n", byte_count_limit);#endif            if (byte_count_limit == 0xffff)                byte_count_limit--;            size = s->packet_transfer_size;            if (size > byte_count_limit) {                /* byte count limit must be even if this case */                if (byte_count_limit & 1)                    byte_count_limit--;                size = byte_count_limit;            }            s->lcyl = size;            s->hcyl = size >> 8;            s->elementary_transfer_size = size;            /* we cannot transmit more than one sector at a time */            if (s->lba != -1) {                if (size > (s->cd_sector_size - s->io_buffer_index))                    size = (s->cd_sector_size - s->io_buffer_index);            }            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,                                size, ide_atapi_cmd_reply_end);            s->packet_transfer_size -= size;            s->elementary_transfer_size -= size;            s->io_buffer_index += size;            ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI            printf("status=0x%x\n", s->status);#endif        }    }}/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size){    if (size > max_size)        size = max_size;    s->lba = -1; /* no sector read */    s->packet_transfer_size = size;    s->elementary_transfer_size = 0;    s->io_buffer_index = 0;    s->status = READY_STAT;    ide_atapi_cmd_reply_end(s);}/* start a CD-CDROM read command */static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,                                   int sector_size){    s->lba = lba;    s->packet_transfer_size = nb_sectors * sector_size;    s->elementary_transfer_size = 0;    s->io_buffer_index = sector_size;    s->cd_sector_size = sector_size;    s->status = READY_STAT;    ide_atapi_cmd_reply_end(s);}/* ATAPI DMA support */static int ide_atapi_cmd_read_dma_cb(IDEState *s,                                      target_phys_addr_t phys_addr,                                      int transfer_size1){    int len, transfer_size;        transfer_size = transfer_size1;    while (transfer_size > 0) {#ifdef DEBUG_IDE_ATAPI        printf("transfer_size: %d phys_addr=%08x\n", transfer_size, phys_addr);#endif        if (s->packet_transfer_size <= 0)            break;        len = s->cd_sector_size - s->io_buffer_index;        if (len <= 0) {            /* transfert next data */            cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);            s->lba++;            s->io_buffer_index = 0;            len = s->cd_sector_size;        }        if (len > transfer_size)            len = transfer_size;        cpu_physical_memory_write(phys_addr,                                   s->io_buffer + s->io_buffer_index, len);        s->packet_transfer_size -= len;        s->io_buffer_index += len;        transfer_size -= len;        phys_addr += len;    }    if (s->packet_transfer_size <= 0) {        s->status = READY_STAT;        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;        ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI        printf("dma status=0x%x\n", s->status);#endif        return 0;    }    return transfer_size1 - transfer_size;}/* start a CD-CDROM read command with DMA *//* XXX: test if DMA is available */static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,                                   int sector_size){    s->lba = lba;    s->packet_transfer_size = nb_sectors * sector_size;    s->io_buffer_index = sector_size;    s->cd_sector_size = sector_size;    s->status = READY_STAT | DRQ_STAT;    ide_dma_start(s, ide_atapi_cmd_read_dma_cb);}static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,                                int sector_size){#ifdef DEBUG_IDE_ATAPI    printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);#endif    if (s->atapi_dma) {        ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);    } else {        ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);    }}/* same toc as bochs. Return -1 if error or the toc length *//* XXX: check this */static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track){    uint8_t *q;    int nb_sectors, len;        if (start_track > 1 && start_track != 0xaa)        return -1;    q = buf + 2;    *q++ = 1; /* first session */    *q++ = 1; /* last session */    if (start_track <= 1) {        *q++ = 0; /* reserved */        *q++ = 0x14; /* ADR, control */        *q++ = 1;    /* track number */        *q++ = 0; /* reserved */        if (msf) {            *q++ = 0; /* reserved */            lba_to_msf(q, 0);            q += 3;        } else {            /* sector 0 */            cpu_to_ube32(q, 0);            q += 4;        }    }    /* lead out track */    *q++ = 0; /* reserved */    *q++ = 0x16; /* ADR, control */    *q++ = 0xaa; /* track number */    *q++ = 0; /* reserved */    nb_sectors = s->nb_sectors >> 2;    if (msf) {        *q++ = 0; /* reserved */        lba_to_msf(q, nb_sectors);        q += 3;    } else {        cpu_to_ube32(q, nb_sectors);        q += 4;    }    len = q - buf;    cpu_to_ube16(buf, len - 2);    return len;}/* mostly same info as PearPc */static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf,                               int session_num){    uint8_t *q;    int nb_sectors, len;        q = buf + 2;    *q++ = 1; /* first session */    *q++ = 1; /* last session */    *q++ = 1; /* session number */    *q++ = 0x14; /* data track */    *q++ = 0; /* track number */    *q++ = 0xa0; /* lead-in */    *q++ = 0; /* min */    *q++ = 0; /* sec */    *q++ = 0; /* frame */    *q++ = 0;    *q++ = 1; /* first track */    *q++ = 0x00; /* disk type */    *q++ = 0x00;        *q++ = 1; /* session number */    *q++ = 0x14; /* data track */    *q++ = 0; /* track number */    *q++ = 0xa1;    *q++ = 0; /* min */    *q++ = 0; /* sec */    *q++ = 0; /* frame */    *q++ = 0;    *q++ = 1; /* last track */    *q++ = 0x00;    *q++ = 0x00;        *q++ = 1; /* session number */    *q++ = 0x14; /* data track */    *q++ = 0; /* track number */    *q++ = 0xa2; /* lead-out */    *q++ = 0; /* min */    *q++ = 0; /* sec */    *q++ = 0; /* frame */    nb_sectors = s->nb_sectors >> 2;    if (msf) {        *q++ = 0; /* reserved */        lba_to_msf(q, nb_sectors);        q += 3;    } else {        cpu_to_ube32(q, nb_sectors);        q += 4;    }    *q++ = 1; /* session number */    *q++ = 0x14; /* ADR, control */    *q++ = 0;    /* track number */    *q++ = 1;    /* point */    *q++ = 0; /* min */    *q++ = 0; /* sec */    *q++ = 0; /* frame */    if (msf) {        *q++ = 0;         lba_to_msf(q, 0);        q += 3;    } else {        *q++ = 0;         *q++ = 0;         *q++ = 0;         *q++ = 0;     }    len = q - buf;    cpu_to_ube16(buf, len - 2);    return len;}static void ide_atapi_cmd(IDEState *s){    const uint8_t *packet;    uint8_t *buf;    int max_len;    packet = s->io_buffer;    buf = s->io_buffer;#ifdef DEBUG_IDE_ATAPI    {        int i;        printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));        for(i = 0; i < ATAPI_PACKET_SIZE; i++) {            printf(" %02x", packet[i]);        }        printf("\n");    }#endif    switch(s->io_buffer[0]) {    case GPCMD_TEST_UNIT_READY:        if (bdrv_is_inserted(s->bs)) {            ide_atapi_cmd_ok(s);        } else {            ide_atapi_cmd_error(s, SENSE_NOT_READY,                                 ASC_MEDIUM_NOT_PRESENT);        }        break;    case GPCMD_MODE_SENSE_10:        {            int action, code;            max_len = ube16_to_cpu(packet + 7);            action = packet[2] >> 6;            code = packet[2] & 0x3f;            switch(action) {            case 0: /* current values */                switch(code) {                case 0x01: /* error recovery */                    cpu_to_ube16(&buf[0], 16 + 6);                    buf[2] = 0x70;                    buf[3] = 0;                    buf[4] = 0;                    buf[5] = 0;                    buf[6] = 0;                    buf[7] = 0;                    buf[8] = 0x01;                    buf[9] = 0x06;                    buf[10] = 0x00;                    buf[11] = 0x05;                    buf[12] = 0x00;                    buf[13] = 0x00;                    buf[14] = 0x00;                    buf[15] = 0x00;                    ide_atapi_cmd_reply(s, 16, max_len);                    break;                case 0x2a:                    cpu_to_ube16(&buf[0], 28 + 6);                    buf[2] = 0x70;                    buf[3] = 0;                    buf[4] = 0;                    buf[5] = 0;                    buf[6] = 0;                    buf[7] = 0;                    buf[8] = 0x2a;                    buf[9] = 0x12;                    buf[10] = 0x00;                    buf[11] = 0x00;                                        buf[12] = 0x70;                    buf[13] = 3 << 5;                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);                    if (bdrv_is_locked(s->bs))

⌨️ 快捷键说明

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