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

📄 esp.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * QEMU ESP emulation *  * Copyright (c) 2005-2006 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"/* debug ESP card *///#define DEBUG_ESP#ifdef DEBUG_ESP#define DPRINTF(fmt, args...) \do { printf("ESP: " fmt , ##args); } while (0)#define pic_set_irq(irq, level) \do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)#else#define DPRINTF(fmt, args...)#endif#define ESPDMA_REGS 4#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)#define ESP_MAXREG 0x3f#define TI_BUFSZ 1024*1024 // XXX#define DMA_VER 0xa0000000#define DMA_INTR 1#define DMA_INTREN 0x10#define DMA_LOADED 0x04000000typedef struct ESPState ESPState;typedef int ESPDMAFunc(ESPState *s,                        target_phys_addr_t phys_addr,                        int transfer_size1);struct ESPState {    BlockDriverState **bd;    uint8_t rregs[ESP_MAXREG];    uint8_t wregs[ESP_MAXREG];    int irq;    uint32_t espdmaregs[ESPDMA_REGS];    uint32_t ti_size;    uint32_t ti_rptr, ti_wptr;    int ti_dir;    uint8_t ti_buf[TI_BUFSZ];    int dma;    ESPDMAFunc *dma_cb;    int64_t offset, len;    int target;};#define STAT_DO 0x00#define STAT_DI 0x01#define STAT_CD 0x02#define STAT_ST 0x03#define STAT_MI 0x06#define STAT_MO 0x07#define STAT_TC 0x10#define STAT_IN 0x80#define INTR_FC 0x08#define INTR_BS 0x10#define INTR_DC 0x20#define INTR_RST 0x80#define SEQ_0 0x0#define SEQ_CD 0x4/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */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 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;}/* same toc as bochs. Return -1 if error or the toc length *//* XXX: check this */static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track){    uint8_t *q;    int 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 */    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(int nb_sectors, uint8_t *buf, int msf,                               int session_num){    uint8_t *q;    int 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 */    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 int esp_write_dma_cb(ESPState *s,                             target_phys_addr_t phys_addr,                             int transfer_size1){    DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",            s->offset, s->len, s->ti_size, transfer_size1);    bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);    s->offset = 0;    s->len = 0;    s->target = 0;    return 0;}static void handle_satn(ESPState *s){    uint8_t buf[32];    uint32_t dmaptr, dmalen;    unsigned int i;    int64_t nb_sectors;    int target;    dmalen = s->wregs[0] | (s->wregs[1] << 8);    target = s->wregs[4] & 7;    DPRINTF("Select with ATN len %d target %d\n", dmalen, target);    if (s->dma) {	dmaptr = iommu_translate(s->espdmaregs[1]);	DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);	cpu_physical_memory_read(dmaptr, buf, dmalen);    } else {	buf[0] = 0;	memcpy(&buf[1], s->ti_buf, dmalen);	dmalen++;    }    for (i = 0; i < dmalen; i++) {	DPRINTF("Command %2.2x\n", buf[i]);    }    s->ti_dir = 0;    s->ti_size = 0;    s->ti_rptr = 0;    s->ti_wptr = 0;    if (target >= 4 || !s->bd[target]) { // No such drive	s->rregs[4] = STAT_IN;	s->rregs[5] = INTR_DC;	s->rregs[6] = SEQ_0;	s->espdmaregs[0] |= DMA_INTR;	pic_set_irq(s->irq, 1);	return;    }    switch (buf[1]) {    case 0x0:	DPRINTF("Test Unit Ready (len %d)\n", buf[5]);	break;    case 0x12:	DPRINTF("Inquiry (len %d)\n", buf[5]);	memset(s->ti_buf, 0, 36);	if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {	    s->ti_buf[0] = 5;	    memcpy(&s->ti_buf[16], "QEMU CDROM     ", 16);	} else {	    s->ti_buf[0] = 0;	    memcpy(&s->ti_buf[16], "QEMU HARDDISK  ", 16);	}	memcpy(&s->ti_buf[8], "QEMU   ", 8);	s->ti_buf[2] = 1;	s->ti_buf[3] = 2;	s->ti_buf[4] = 32;	s->ti_dir = 1;	s->ti_size = 36;	break;    case 0x1a:	DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);	break;    case 0x25:	DPRINTF("Read Capacity (len %d)\n", buf[5]);	memset(s->ti_buf, 0, 8);	bdrv_get_geometry(s->bd[target], &nb_sectors);	s->ti_buf[0] = (nb_sectors >> 24) & 0xff;	s->ti_buf[1] = (nb_sectors >> 16) & 0xff;	s->ti_buf[2] = (nb_sectors >> 8) & 0xff;	s->ti_buf[3] = nb_sectors & 0xff;	s->ti_buf[4] = 0;	s->ti_buf[5] = 0;	if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)	    s->ti_buf[6] = 8; // sector size 2048	else	    s->ti_buf[6] = 2; // sector size 512	s->ti_buf[7] = 0;	s->ti_dir = 1;	s->ti_size = 8;	break;    case 0x28:	{	    int64_t offset, len;	    if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {		offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;		len = ((buf[8] << 8) | buf[9]) * 4;		s->ti_size = len * 2048;	    } else {		offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];		len = (buf[8] << 8) | buf[9];		s->ti_size = len * 512;	    }	    DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);            if (s->ti_size > TI_BUFSZ) {                DPRINTF("size too large %d\n", s->ti_size);            }	    bdrv_read(s->bd[target], offset, s->ti_buf, len);	    // XXX error handling	    s->ti_dir = 1;	    break;	}    case 0x2a:	{	    int64_t offset, len;	    if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {		offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;		len = ((buf[8] << 8) | buf[9]) * 4;		s->ti_size = len * 2048;	    } else {		offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];		len = (buf[8] << 8) | buf[9];		s->ti_size = len * 512;	    }	    DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);            if (s->ti_size > TI_BUFSZ) {                DPRINTF("size too large %d\n", s->ti_size);            }            s->dma_cb = esp_write_dma_cb;            s->offset = offset;            s->len = len;            s->target = target;	    // XXX error handling	    s->ti_dir = 0;	    break;	}    case 0x43:        {            int start_track, format, msf, len;            msf = buf[2] & 2;            format = buf[3] & 0xf;            start_track = buf[7];            bdrv_get_geometry(s->bd[target], &nb_sectors);            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);

⌨️ 快捷键说明

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