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

📄 ide.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif    put_le16(p + 49, 0x0f00);			/* Capabilities */    put_le16(p + 51, 0x0002);			/* PIO cycle timing mode */    put_le16(p + 52, 0x0001);			/* DMA cycle timing mode */    put_le16(p + 53, 0x0003);			/* Translation params valid */    put_le16(p + 54, s->cylinders);		/* Current cylinders */    put_le16(p + 55, s->heads);			/* Current heads */    put_le16(p + 56, s->sectors);		/* Current sectors */    put_le16(p + 57, cur_sec);			/* Current capacity */    put_le16(p + 58, cur_sec >> 16);		/* Current capacity */    if (s->mult_sectors)			/* Multiple sector setting */        put_le16(p + 59, 0x100 | s->mult_sectors);    put_le16(p + 60, s->nb_sectors);		/* Total LBA sectors */    put_le16(p + 61, s->nb_sectors >> 16);	/* Total LBA sectors */    put_le16(p + 63, 0x0203);			/* Multiword DMA capability */    put_le16(p + 64, 0x0001);			/* Flow Control PIO support */    put_le16(p + 65, 0x0096);			/* Min. Multiword DMA cycle */    put_le16(p + 66, 0x0096);			/* Rec. Multiword DMA cycle */    put_le16(p + 68, 0x00b4);			/* Min. PIO cycle time */    put_le16(p + 82, 0x400c);			/* Command Set supported */    put_le16(p + 83, 0x7068);			/* Command Set supported */    put_le16(p + 84, 0x4000);			/* Features supported */    put_le16(p + 85, 0x000c);			/* Command Set enabled */    put_le16(p + 86, 0x7044);			/* Command Set enabled */    put_le16(p + 87, 0x4000);			/* Features enabled */    put_le16(p + 91, 0x4060);			/* Current APM level */    put_le16(p + 129, 0x0002);			/* Current features option */    put_le16(p + 130, 0x0005);			/* Reassigned sectors */    put_le16(p + 131, 0x0001);			/* Initial power mode */    put_le16(p + 132, 0x0000);			/* User signature */    put_le16(p + 160, 0x8100);			/* Power requirement */    put_le16(p + 161, 0x8001);			/* CF command set */    s->identify_set = 1;fill_buffer:    memcpy(s->io_buffer, p, sizeof(s->identify_data));}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_dma_submit_check(IDEState *s,          BlockDriverCompletionFunc *dma_cb, BMDMAState *bm){    if (bm->aiocb)	return;    dma_cb(bm, -1);}static inline void ide_set_irq(IDEState *s){    BMDMAState *bm = s->bmdma;    if (!s->bs) return; /* yikes */    if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {        if (bm) {            bm->status |= BM_STATUS_INT;        }        qemu_irq_raise(s->irq);    }}/* 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;    if (!(s->status & ERR_STAT))        s->status |= DRQ_STAT;    buffered_pio_reset(s);}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;    buffered_pio_reset(s);}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_rw_error(IDEState *s) {    ide_abort_command(s);    ide_set_irq(s);}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);        if (ret != 0) {            ide_rw_error(s);            return;        }        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 void ide_dma_error(IDEState *s){    ide_transfer_stop(s);    s->error = ABRT_ERR;    s->status = READY_STAT | ERR_STAT;    ide_set_irq(s);}/* return 0 if buffer completed */static int dma_buf_rw(BMDMAState *bm, int is_write){    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;}static void ide_dma_eot(BMDMAState *bm) {    bm->status &= ~BM_STATUS_DMAING;    bm->status |= BM_STATUS_INT;    bm->dma_cb = NULL;    bm->ide_if = NULL;    bm->aiocb = NULL;}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 (ret < 0) {	ide_dma_error(s);	return;    }    if (!s->bs) return; /* yikes */    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:	ide_dma_eot(bm);        return;    }    /* launch next transfer */    n = s->nsector;    if (n > IDE_DMA_BUF_SECTORS)        n = IDE_DMA_BUF_SECTORS;    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);    ide_dma_submit_check(s, 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 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);    if (ret == 0 && !s->write_cache) {	ret = bdrv_flush(s->bs);    }    if (ret != 0) {	ide_rw_error(s);	return;    }    s->nsector -= n;    if (s->nsector == 0) {        /* no more sectors 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 void ide_write_flush_cb(void *opaque, int ret) {    BMDMAState *bm = opaque;    IDEState *s = bm->ide_if;    if (ret != 0) {	ide_dma_error(s);	return;    }    s->status = READY_STAT | SEEK_STAT;    ide_set_irq(s);    ide_dma_eot(bm);    return;}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 (ret < 0) {	ide_dma_error(s);	return;    }    if (!s->bs) return; /* yikes */    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) {	if (!s->write_cache) {	    bdrv_aio_flush(s->bs, ide_write_flush_cb, bm);	    return;	}        s->status = READY_STAT | SEEK_STAT;        ide_set_irq(s);    eot:	ide_dma_eot(bm);        return;    }    /* launch next transfer */    n = s->nsector;    if (n > IDE_DMA_BUF_SECTORS)

⌨️ 快捷键说明

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