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

📄 ide.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
    IDEState *s = bm->ide_if;    struct {        uint32_t addr;        uint32_t size;    } prd;    int l, len;    for(;;) {        l = s->io_buffer_size - s->io_buffer_index;        if (l <= 0)             break;        if (bm->cur_prd_len == 0) {            /* end of table (with a fail safe of one page) */            if (bm->cur_prd_last ||                (bm->cur_addr - bm->addr) >= 4096)                return 0;            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);            bm->cur_addr += 8;            prd.addr = le32_to_cpu(prd.addr);            prd.size = le32_to_cpu(prd.size);            len = prd.size & 0xfffe;            if (len == 0)                len = 0x10000;            bm->cur_prd_len = len;            bm->cur_prd_addr = prd.addr;            bm->cur_prd_last = (prd.size & 0x80000000);        }        if (l > bm->cur_prd_len)            l = bm->cur_prd_len;        if (l > 0) {            if (is_write) {                cpu_physical_memory_write(bm->cur_prd_addr,                                           s->io_buffer + s->io_buffer_index, l);            } else {                cpu_physical_memory_read(bm->cur_prd_addr,                                           s->io_buffer + s->io_buffer_index, l);            }            bm->cur_prd_addr += l;            bm->cur_prd_len -= l;            s->io_buffer_index += l;        }    }    return 1;}/* XXX: handle errors */static void ide_read_dma_cb(void *opaque, int ret){    BMDMAState *bm = opaque;    IDEState *s = bm->ide_if;    int n;    int64_t sector_num;    if (!s->bs) return; /* yikes */    n = s->io_buffer_size >> 9;    sector_num = ide_get_sector(s);    if (n > 0) {        sector_num += n;        ide_set_sector(s, sector_num);        s->nsector -= n;        if (dma_buf_rw(bm, 1) == 0)            goto eot;    }    /* end of transfer ? */    if (s->nsector == 0) {        s->status = READY_STAT | SEEK_STAT;        ide_set_irq(s);    eot:        bm->status &= ~BM_STATUS_DMAING;        bm->status |= BM_STATUS_INT;        bm->dma_cb = NULL;        bm->ide_if = NULL;        bm->aiocb = NULL;        return;    }    /* launch next transfer */    n = s->nsector;    if (n > IDE_DMA_BUF_SIZE / 512)        n = IDE_DMA_BUF_SIZE / 512;    s->io_buffer_index = 0;    s->io_buffer_size = n * 512;#ifdef DEBUG_AIO    printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);#endif    bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,                               ide_read_dma_cb, bm);}static void ide_sector_read_dma(IDEState *s){    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;    s->io_buffer_index = 0;    s->io_buffer_size = 0;    ide_dma_start(s, ide_read_dma_cb);}static void ide_sector_write_timer_cb(void *opaque){    IDEState *s = opaque;    ide_set_irq(s);}static void ide_sector_write(IDEState *s){    int64_t sector_num;    int n, n1;    s->status = READY_STAT | SEEK_STAT;    sector_num = ide_get_sector(s);#if defined(DEBUG_IDE)    printf("write sector=%Ld\n", sector_num);#endif    n = s->nsector;    if (n > s->req_nb_sectors)        n = s->req_nb_sectors;    if (bdrv_write(s->bs, sector_num, s->io_buffer, n) != 0) {        ide_abort_command(s);        ide_set_irq(s);        return;    }    s->nsector -= n;    if (s->nsector == 0) {        /* no more sector to write */        ide_transfer_stop(s);    } else {        n1 = s->nsector;        if (n1 > s->req_nb_sectors)            n1 = s->req_nb_sectors;        ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);    }    ide_set_sector(s, sector_num + n);        if (!s->write_cache)        bdrv_flush(s->bs);    #ifdef TARGET_I386    if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {        /* It seems there is a bug in the Windows 2000 installer HDD           IDE driver which fills the disk with empty logs when the           IDE write IRQ comes too early. This hack tries to correct           that at the expense of slower write performances. Use this           option _only_ to install Windows 2000. You must disable it           for normal use. */        qemu_mod_timer(s->sector_write_timer,                        qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));    } else #endif    {        ide_set_irq(s);    }}/* XXX: handle errors */static void ide_write_dma_cb(void *opaque, int ret){    BMDMAState *bm = opaque;    IDEState *s = bm->ide_if;    int n;    int64_t sector_num;    if (!s->bs) return; /* yikes */    n = s->io_buffer_size >> 9;    sector_num = ide_get_sector(s);    if (n > 0) {        sector_num += n;        ide_set_sector(s, sector_num);        s->nsector -= n;    }    /* end of transfer ? */    if (s->nsector == 0) {        /* Ensure the data hit disk before telling the guest OS so. */        if (!s->write_cache)            bdrv_flush(s->bs);        s->status = READY_STAT | SEEK_STAT;        ide_set_irq(s);    eot:        bm->status &= ~BM_STATUS_DMAING;        bm->status |= BM_STATUS_INT;        bm->dma_cb = NULL;        bm->ide_if = NULL;        bm->aiocb = NULL;        return;    }    /* launch next transfer */    n = s->nsector;    if (n > IDE_DMA_BUF_SIZE / 512)        n = IDE_DMA_BUF_SIZE / 512;    s->io_buffer_index = 0;    s->io_buffer_size = n * 512;    if (dma_buf_rw(bm, 0) == 0)        goto eot;#ifdef DEBUG_AIO    printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);#endif    bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,                                ide_write_dma_cb, bm);}static void ide_sector_write_dma(IDEState *s){    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;    s->io_buffer_index = 0;    s->io_buffer_size = 0;    ide_dma_start(s, ide_write_dma_cb);}static void ide_device_utterly_broken(IDEState *s) {    s->status |= BUSY_STAT;    s->bs = NULL;    /* This prevents all future commands from working.  All of the     * asynchronous callbacks (and ide_set_irq, as a safety measure)     * check to see whether this has happened and bail if so.     */}static void ide_flush_cb(void *opaque, int ret){    IDEState *s = opaque;    if (!s->bs) return; /* yikes */    if (ret) {        /* We are completely doomed.  The IDE spec does not permit us	 * to return an error from a flush except via a protocol which	 * requires us to say where the error is and which	 * contemplates the guest repeating the flush attempt to	 * attempt flush the remaining data.  We can't support that	 * because f(data)sync (which is what the block drivers use	 * eventually) doesn't report the necessary information or	 * give us the necessary control.  So we make the disk vanish.	 */	ide_device_utterly_broken(s);	return;    }    else        s->status = READY_STAT;    ide_set_irq(s);}static void ide_atapi_cmd_ok(IDEState *s){    s->error = 0;    s->status = READY_STAT;    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;    ide_set_irq(s);}static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc){#ifdef DEBUG_IDE_ATAPI    printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);#endif    s->error = sense_key << 4;    s->status = READY_STAT | ERR_STAT;    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;    s->sense_key = sense_key;    s->asc = asc;    ide_set_irq(s);}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_data_to_raw(uint8_t *buf, int lba){    /* 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 */    buf += 2048;    /* XXX: ECC not computed */    memset(buf, 0, 288);}static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,                            int sector_size){    int ret;    switch(sector_size) {    case 2048:        ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);        break;    case 2352:        ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);        if (ret < 0)            return ret;        cd_data_to_raw(buf, lba);        break;    default:        ret = -EIO;        break;    }    return ret;}static void ide_atapi_io_error(IDEState *s, int ret){    /* XXX: handle more errors */    if (ret == -ENOMEDIUM) {        ide_atapi_cmd_error(s, SENSE_NOT_READY,                             ASC_MEDIUM_NOT_PRESENT);    } else {        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,                             ASC_LOGICAL_BLOCK_OOR);    }}/* The whole ATAPI transfer logic is handled in this function */static void ide_atapi_cmd_reply_end(IDEState *s){    int byte_count_limit, size, ret;#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) {            ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);            if (ret < 0) {                ide_transfer_stop(s);                ide_atapi_io_error(s, ret);                return;            }            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;

⌨️ 快捷键说明

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