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

📄 ide.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    unsigned int oldsize;    char buf[20];    if (s->identify_set) {	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));	return;    }    memset(s->io_buffer, 0, 512);    p = (uint16_t *)s->io_buffer;    put_le16(p + 0, 0x0040);    put_le16(p + 1, s->cylinders);     put_le16(p + 3, s->heads);    put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */    put_le16(p + 5, 512); /* XXX: retired, remove ? */    put_le16(p + 6, s->sectors);     snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);    padstr((uint8_t *)(p + 10), buf, 20); /* serial number */    put_le16(p + 20, 3); /* XXX: retired, remove ? */    put_le16(p + 21, 512); /* cache size in sectors */    put_le16(p + 22, 4); /* ecc bytes */    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */    padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */#if MAX_MULT_SECTORS > 1        put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);#endif    put_le16(p + 48, 1); /* dword I/O */    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */    put_le16(p + 51, 0x200); /* PIO transfer cycle */    put_le16(p + 52, 0x200); /* DMA transfer cycle */    put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */    put_le16(p + 54, s->cylinders);    put_le16(p + 55, s->heads);    put_le16(p + 56, s->sectors);    oldsize = s->cylinders * s->heads * s->sectors;    put_le16(p + 57, oldsize);    put_le16(p + 58, oldsize >> 16);    if (s->mult_sectors)        put_le16(p + 59, 0x100 | s->mult_sectors);    put_le16(p + 60, s->nb_sectors);    put_le16(p + 61, s->nb_sectors >> 16);    put_le16(p + 63, 0x07); /* mdma0-2 supported */    put_le16(p + 65, 120);    put_le16(p + 66, 120);    put_le16(p + 67, 120);    put_le16(p + 68, 120);    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */    put_le16(p + 81, 0x16); /* conforms to ata5 */    put_le16(p + 82, (1 << 14));    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));    put_le16(p + 84, (1 << 14));    put_le16(p + 85, (1 << 14));    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));    put_le16(p + 87, (1 << 14));    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */    put_le16(p + 93, 1 | (1 << 14) | 0x2000);    put_le16(p + 100, s->nb_sectors);    put_le16(p + 101, s->nb_sectors >> 16);    put_le16(p + 102, s->nb_sectors >> 32);    put_le16(p + 103, s->nb_sectors >> 48);    memcpy(s->identify_data, p, sizeof(s->identify_data));    s->identify_set = 1;}static void ide_atapi_identify(IDEState *s){    uint16_t *p;    char buf[20];    if (s->identify_set) {	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));	return;    }    memset(s->io_buffer, 0, 512);    p = (uint16_t *)s->io_buffer;    /* Removable CDROM, 50us response, 12 byte packets */    put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);    padstr((uint8_t *)(p + 10), buf, 20); /* serial number */    put_le16(p + 20, 3); /* buffer type */    put_le16(p + 21, 512); /* cache size in sectors */    put_le16(p + 22, 4); /* ecc bytes */    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */    padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */    put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */    put_le16(p + 53, 3); /* words 64-70, 54-58 valid */    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */    put_le16(p + 64, 1); /* PIO modes */    put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */    put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */    put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */    put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */    put_le16(p + 71, 30); /* in ns */    put_le16(p + 72, 30); /* in ns */    put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */    memcpy(s->identify_data, p, sizeof(s->identify_data));    s->identify_set = 1;}static void ide_set_signature(IDEState *s){    s->select &= 0xf0; /* clear head */    /* put signature */    s->nsector = 1;    s->sector = 1;    if (s->is_cdrom) {        s->lcyl = 0x14;        s->hcyl = 0xeb;    } else if (s->bs) {        s->lcyl = 0;        s->hcyl = 0;    } else {        s->lcyl = 0xff;        s->hcyl = 0xff;    }}static inline void ide_abort_command(IDEState *s){    s->status = READY_STAT | ERR_STAT;    s->error = ABRT_ERR;}static inline void ide_set_irq(IDEState *s){    BMDMAState *bm = s->bmdma;    if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {        if (bm) {            bm->status |= BM_STATUS_INT;        }        s->set_irq(s->irq_opaque, s->irq, 1);    }}/* prepare data transfer and tell what to do after */static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,                                EndTransferFunc *end_transfer_func){    s->end_transfer_func = end_transfer_func;    s->data_ptr = buf;    s->data_end = buf + size;    s->status |= DRQ_STAT;}static void ide_transfer_stop(IDEState *s){    s->end_transfer_func = ide_transfer_stop;    s->data_ptr = s->io_buffer;    s->data_end = s->io_buffer;    s->status &= ~DRQ_STAT;}static int64_t ide_get_sector(IDEState *s){    int64_t sector_num;    if (s->select & 0x40) {        /* lba */	if (!s->lba48) {	    sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |		(s->lcyl << 8) | s->sector;	} else {	    sector_num = ((int64_t)s->hob_hcyl << 40) |		((int64_t) s->hob_lcyl << 32) |		((int64_t) s->hob_sector << 24) |		((int64_t) s->hcyl << 16) |		((int64_t) s->lcyl << 8) | s->sector;	}    } else {        sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +            (s->select & 0x0f) * s->sectors + (s->sector - 1);    }    return sector_num;}static void ide_set_sector(IDEState *s, int64_t sector_num){    unsigned int cyl, r;    if (s->select & 0x40) {	if (!s->lba48) {            s->select = (s->select & 0xf0) | (sector_num >> 24);            s->hcyl = (sector_num >> 16);            s->lcyl = (sector_num >> 8);            s->sector = (sector_num);	} else {	    s->sector = sector_num;	    s->lcyl = sector_num >> 8;	    s->hcyl = sector_num >> 16;	    s->hob_sector = sector_num >> 24;	    s->hob_lcyl = sector_num >> 32;	    s->hob_hcyl = sector_num >> 40;	}    } else {        cyl = sector_num / (s->heads * s->sectors);        r = sector_num % (s->heads * s->sectors);        s->hcyl = cyl >> 8;        s->lcyl = cyl;        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);        s->sector = (r % s->sectors) + 1;    }}static void ide_sector_read(IDEState *s){    int64_t sector_num;    int ret, n;    s->status = READY_STAT | SEEK_STAT;    s->error = 0; /* not needed by IDE spec, but needed by Windows */    sector_num = ide_get_sector(s);    n = s->nsector;    if (n == 0) {        /* no more sector to read from disk */        ide_transfer_stop(s);    } else {#if defined(DEBUG_IDE)        printf("read sector=%Ld\n", sector_num);#endif        if (n > s->req_nb_sectors)            n = s->req_nb_sectors;        ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);        ide_set_irq(s);        ide_set_sector(s, sector_num + n);        s->nsector -= n;    }}static int ide_read_dma_cb(IDEState *s,                            target_phys_addr_t phys_addr,                            int transfer_size1){    int len, transfer_size, n;    int64_t sector_num;    transfer_size = transfer_size1;    while (transfer_size > 0) {        len = s->io_buffer_size - s->io_buffer_index;        if (len <= 0) {            /* transfert next data */            n = s->nsector;            if (n == 0)                break;            if (n > MAX_MULT_SECTORS)                n = MAX_MULT_SECTORS;            sector_num = ide_get_sector(s);            bdrv_read(s->bs, sector_num, s->io_buffer, n);            s->io_buffer_index = 0;            s->io_buffer_size = n * 512;            len = s->io_buffer_size;            sector_num += n;            ide_set_sector(s, sector_num);            s->nsector -= n;        }        if (len > transfer_size)            len = transfer_size;        cpu_physical_memory_write(phys_addr,                                   s->io_buffer + s->io_buffer_index, len);        s->io_buffer_index += len;        transfer_size -= len;        phys_addr += len;    }    if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) {        s->status = READY_STAT | SEEK_STAT;        ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI        printf("dma status=0x%x\n", s->status);#endif        return 0;    }    return transfer_size1 - transfer_size;}static void ide_sector_read_dma(IDEState *s){    s->status = READY_STAT | SEEK_STAT | DRQ_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 ret, 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;    ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);    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);    #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);    }}static int ide_write_dma_cb(IDEState *s,                             target_phys_addr_t phys_addr,                             int transfer_size1){    int len, transfer_size, n;    int64_t sector_num;    transfer_size = transfer_size1;    for(;;) {        len = s->io_buffer_size - s->io_buffer_index;        if (len == 0) {            n = s->io_buffer_size >> 9;            sector_num = ide_get_sector(s);            bdrv_write(s->bs, sector_num, s->io_buffer,                        s->io_buffer_size >> 9);            sector_num += n;            ide_set_sector(s, sector_num);            s->nsector -= n;            n = s->nsector;            if (n == 0) {                /* end of transfer */                s->status = READY_STAT | SEEK_STAT;#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);                return 0;            }            if (n > MAX_MULT_SECTORS)                n = MAX_MULT_SECTORS;            s->io_buffer_index = 0;            s->io_buffer_size = n * 512;            len = s->io_buffer_size;        }        if (transfer_size <= 0)            break;        if (len > transfer_size)            len = transfer_size;        cpu_physical_memory_read(phys_addr,                                  s->io_buffer + s->io_buffer_index, len);        s->io_buffer_index += len;        transfer_size -= len;        phys_addr += len;    }    return transfer_size1 - transfer_size;}static void ide_sector_write_dma(IDEState *s){    int n;    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;    n = s->nsector;    if (n > MAX_MULT_SECTORS)        n = MAX_MULT_SECTORS;    s->io_buffer_index = 0;    s->io_buffer_size = n * 512;    ide_dma_start(s, ide_write_dma_cb);}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);}

⌨️ 快捷键说明

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