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

📄 ide.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
    int packet_transfer_size;    int elementary_transfer_size;    int io_buffer_index;    int lba;    int cd_sector_size;    int atapi_dma; /* true if dma is requested for the packet cmd */    /* ATA DMA state */    int io_buffer_size;    /* PIO transfer handling */    int req_nb_sectors; /* number of sectors per interrupt */    EndTransferFunc *end_transfer_func;    uint8_t *data_ptr;    uint8_t *data_end;    uint8_t *io_buffer;    QEMUTimer *sector_write_timer; /* only used for win2k install hack */    uint32_t irq_count; /* counts IRQs when using win2k install hack */    /* CF-ATA extended error */    uint8_t ext_error;    /* CF-ATA metadata storage */    uint32_t mdata_size;    uint8_t *mdata_storage;    int media_changed;} IDEState;#define BM_STATUS_DMAING 0x01#define BM_STATUS_ERROR  0x02#define BM_STATUS_INT    0x04#define BM_CMD_START     0x01#define BM_CMD_READ      0x08#define IDE_TYPE_PIIX3   0#define IDE_TYPE_CMD646  1#define IDE_TYPE_PIIX4   2/* CMD646 specific */#define MRDMODE		0x71#define   MRDMODE_INTR_CH0	0x04#define   MRDMODE_INTR_CH1	0x08#define   MRDMODE_BLK_CH0	0x10#define   MRDMODE_BLK_CH1	0x20#define UDIDETCR0	0x73#define UDIDETCR1	0x7Btypedef struct BMDMAState {    uint8_t cmd;    uint8_t status;    uint32_t addr;    struct PCIIDEState *pci_dev;    /* current transfer state */    uint32_t cur_addr;    uint32_t cur_prd_last;    uint32_t cur_prd_addr;    uint32_t cur_prd_len;    IDEState *ide_if;    BlockDriverCompletionFunc *dma_cb;    BlockDriverAIOCB *aiocb;} BMDMAState;typedef struct PCIIDEState {    PCIDevice dev;    IDEState ide_if[4];    BMDMAState bmdma[2];    int type; /* see IDE_TYPE_xxx */} PCIIDEState;#if defined(__ia64__)#include <xen/hvm/ioreq.h>struct buffered_piopage *buffered_pio_page;static inline struct pio_buffer *piobuf_by_addr(uint32_t addr){    if (addr == 0x1F0)        return &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];    if (addr == 0x170)        return &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];    return NULL;}static voidbuffered_pio_init(void){    struct pio_buffer *p1, *p2;    uint32_t off1, off2;    if (!buffered_pio_page)        return;    p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];    p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];    off1 = offsetof(struct buffered_piopage, buffer);    off2 = (off1 + TARGET_PAGE_SIZE)/2;    p1->buf_size = off2 - off1;    p1->page_offset = off1;    p2->buf_size = TARGET_PAGE_SIZE - off2;    p2->page_offset = off2;}static inline void__buffered_pio_flush(struct pio_buffer *piobuf, IDEState *s, uint32_t pointer){    uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;    memcpy(s->data_ptr, buf, pointer);    s->data_ptr += pointer;}static inline voidbuffered_pio_flush(struct pio_buffer *piobuf){    IDEState *s = piobuf->opaque;    uint32_t pointer = piobuf->pointer;    if (s != NULL && pointer > 0)        __buffered_pio_flush(piobuf, s, pointer);}static inline voidbuffered_pio_reset(IDEState *s){    struct pio_buffer *piobuf;    if ((unsigned)s->drive_serial - 1 < 2)      /* 1,2 */        piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];    else if ((unsigned)s->drive_serial - 3 < 2) /* 3,4 */        piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];    else        return;    buffered_pio_flush(piobuf);    piobuf->pointer = 0;    piobuf->data_end = 0;    piobuf->opaque = NULL;}static inline voidbuffered_pio_write(IDEState *s, uint32_t addr, int size){    struct pio_buffer *piobuf = piobuf_by_addr(addr);    int data_end;    if (!piobuf)        return;    buffered_pio_flush(piobuf);    data_end = s->data_end - s->data_ptr - size;    if (data_end <= 0)        data_end = 0;    else if (data_end > piobuf->buf_size)        data_end = piobuf->buf_size;    piobuf->pointer = 0;    piobuf->data_end = data_end;    piobuf->opaque = s;}static inline voidbuffered_pio_read(IDEState *s, uint32_t addr, int size){    struct pio_buffer *piobuf = piobuf_by_addr(addr);    int data_end;    if (!piobuf)        return;    s->data_ptr += piobuf->pointer;    data_end = s->data_end - s->data_ptr - size;    if (data_end <= 0) {        data_end = 0;    } else {	uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;        if (data_end > piobuf->buf_size)            data_end = piobuf->buf_size;        memcpy(buf, s->data_ptr + size, data_end);    }    piobuf->pointer = 0;    piobuf->data_end = data_end;    piobuf->opaque = NULL;}/* * buffered pio reads are undone. It results in normal pio when the domain * is restored. * buffered pio writes are handled before saving domain. * However currently pci_ide_save/load() just discards a pending transfer. XXX */static void__handle_buffered_pio(struct pio_buffer *piobuf){    IDEState *s = piobuf->opaque;    uint32_t pointer = piobuf->pointer;        if (pointer == 0)        return;/* no buffered pio */    if (s != NULL) {        /* written data are pending in pio_buffer. process it */        __buffered_pio_flush(piobuf, s, pointer);    } else {        /* data are buffered for pio read in pio_buffer.         * undone buffering by buffered_pio_read()         */        if (pointer > s->data_ptr - s->io_buffer)            pointer = s->data_ptr - s->io_buffer;        s->data_ptr -= pointer;    }	    piobuf->pointer = 0;    piobuf->data_end = 0;    piobuf->opaque = NULL;}voidhandle_buffered_pio(void){    struct pio_buffer *p1, *p2;    if (!buffered_pio_page)        return;    p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];    p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];    __handle_buffered_pio(p1);    __handle_buffered_pio(p2);}#else /* !__ia64__ */#define buffered_pio_init()         do {} while (0)#define buffered_pio_reset(I)       do {} while (0)#define buffered_pio_write(I,A,S)   do {} while (0)#define buffered_pio_read(I,A,S)    do {} while (0)#endifstatic void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);static void padstr(char *str, const char *src, int len){    int i, v;    for(i = 0; i < len; i++) {        if (*src)            v = *src++;        else            v = ' ';        str[i^1] = v;    }}static void padstr8(uint8_t *buf, int buf_size, const char *src){    int i;    for(i = 0; i < buf_size; i++) {        if (*src)            buf[i] = *src++;        else            buf[i] = ' ';    }}static void put_le16(uint16_t *p, unsigned int v){    *p = cpu_to_le16(v);}static void ide_identify(IDEState *s){    uint16_t *p;    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((char *)(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((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */    padstr((char *)(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 + 62, 0x07); /* single word dma0-2 supported */    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 */    /* 14=nop 5=write_cache */    put_le16(p + 82, (1 << 14) | (1 << 5));    /* 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) | (s->write_cache << 5));    /* 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((char *)(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((char *)(p + 23), QEMU_VERSION, 8); /* firmware version */    padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */    put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */#ifdef USE_DMA_CDROM    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */    put_le16(p + 62, 7);  /* single word dma0-2 supported */    put_le16(p + 63, 7);  /* mdma0-2 supported */    put_le16(p + 64, 0x3f); /* PIO modes supported */#else    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 */#endif    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 */#ifdef USE_DMA_CDROM    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */#endif    memcpy(s->identify_data, p, sizeof(s->identify_data));    s->identify_set = 1;}static void ide_cfata_identify(IDEState *s){    uint16_t *p;    uint32_t cur_sec;    char buf[20];    p = (uint16_t *) s->identify_data;    if (s->identify_set)        goto fill_buffer;    memset(p, 0, sizeof(s->identify_data));    cur_sec = s->cylinders * s->heads * s->sectors;    put_le16(p + 0, 0x848a);			/* CF Storage Card signature */    put_le16(p + 1, s->cylinders);		/* Default cylinders */    put_le16(p + 3, s->heads);			/* Default heads */    put_le16(p + 6, s->sectors);		/* Default sectors per track */    put_le16(p + 7, s->nb_sectors >> 16);	/* Sectors per card */    put_le16(p + 8, s->nb_sectors);		/* Sectors per card */    snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);    padstr((char *)(p + 10), buf, 20);	/* Serial number in ASCII */    put_le16(p + 22, 0x0004);			/* ECC bytes */    padstr((char *) (p + 23), QEMU_VERSION, 8);	/* Firmware Revision */    padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */#if MAX_MULT_SECTORS > 1    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);#else    put_le16(p + 47, 0x0000);

⌨️ 快捷键说明

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