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

📄 ide.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);            break;	case WIN_READDMA_EXT:	    lba48 = 1;        case WIN_READDMA:        case WIN_READDMA_ONCE:            if (!s->bs)                 goto abort_cmd;	    ide_cmd_lba48_transform(s, lba48);            ide_sector_read_dma(s);            break;	case WIN_WRITEDMA_EXT:	    lba48 = 1;        case WIN_WRITEDMA:        case WIN_WRITEDMA_ONCE:            if (!s->bs)                 goto abort_cmd;	    ide_cmd_lba48_transform(s, lba48);            ide_sector_write_dma(s);            break;        case WIN_READ_NATIVE_MAX_EXT:	    lba48 = 1;        case WIN_READ_NATIVE_MAX:	    ide_cmd_lba48_transform(s, lba48);            ide_set_sector(s, s->nb_sectors - 1);            s->status = READY_STAT;            ide_set_irq(s);            break;        case WIN_CHECKPOWERMODE1:            s->nsector = 0xff; /* device active or idle */            s->status = READY_STAT;            ide_set_irq(s);            break;        case WIN_SETFEATURES:            if (!s->bs)                goto abort_cmd;            /* XXX: valid for CDROM ? */            switch(s->feature) {            case 0x02: /* write cache enable */            case 0x82: /* write cache disable */            case 0xaa: /* read look-ahead enable */            case 0x55: /* read look-ahead disable */                s->status = READY_STAT | SEEK_STAT;                ide_set_irq(s);                break;            case 0x03: { /* set transfer mode */		uint8_t val = s->nsector & 0x07;		switch (s->nsector >> 3) {		    case 0x00: /* pio default */		    case 0x01: /* pio mode */			put_le16(s->identify_data + 63,0x07);			put_le16(s->identify_data + 88,0x3f);			break;		    case 0x04: /* mdma mode */			put_le16(s->identify_data + 63,0x07 | (1 << (val + 8)));			put_le16(s->identify_data + 88,0x3f);			break;		    case 0x08: /* udma mode */			put_le16(s->identify_data + 63,0x07);			put_le16(s->identify_data + 88,0x3f | (1 << (val + 8)));			break;		    default:			goto abort_cmd;		}                s->status = READY_STAT | SEEK_STAT;                ide_set_irq(s);                break;	    }            default:                goto abort_cmd;            }            break;        case WIN_FLUSH_CACHE:        case WIN_FLUSH_CACHE_EXT:	case WIN_STANDBYNOW1:        case WIN_IDLEIMMEDIATE:	    s->status = READY_STAT;            ide_set_irq(s);            break;            /* ATAPI commands */        case WIN_PIDENTIFY:            if (s->is_cdrom) {                ide_atapi_identify(s);                s->status = READY_STAT | SEEK_STAT;                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);            } else {                ide_abort_command(s);            }            ide_set_irq(s);            break;        case WIN_DIAGNOSE:            ide_set_signature(s);            s->status = 0x00; /* NOTE: READY is _not_ set */            s->error = 0x01;            break;        case WIN_SRST:            if (!s->is_cdrom)                goto abort_cmd;            ide_set_signature(s);            s->status = 0x00; /* NOTE: READY is _not_ set */            s->error = 0x01;            break;        case WIN_PACKETCMD:            if (!s->is_cdrom)                goto abort_cmd;            /* overlapping commands not supported */            if (s->feature & 0x02)                goto abort_cmd;            s->atapi_dma = s->feature & 1;            s->nsector = 1;            ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,                                ide_atapi_cmd);            break;        default:        abort_cmd:            ide_abort_command(s);            ide_set_irq(s);            break;        }    }}static uint32_t ide_ioport_read(void *opaque, uint32_t addr1){    IDEState *ide_if = opaque;    IDEState *s = ide_if->cur_drive;    uint32_t addr;    int ret, hob;    addr = addr1 & 7;    /* FIXME: HOB readback uses bit 7, but it's always set right now */    //hob = s->select & (1 << 7);    hob = 0;    switch(addr) {    case 0:        ret = 0xff;        break;    case 1:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else if (!hob)            ret = s->error;	else	    ret = s->hob_feature;        break;    case 2:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else if (!hob)            ret = s->nsector & 0xff;	else	    ret = s->hob_nsector;        break;    case 3:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else if (!hob)            ret = s->sector;	else	    ret = s->hob_sector;        break;    case 4:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else if (!hob)            ret = s->lcyl;	else	    ret = s->hob_lcyl;        break;    case 5:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else if (!hob)            ret = s->hcyl;	else	    ret = s->hob_hcyl;        break;    case 6:        if (!ide_if[0].bs && !ide_if[1].bs)            ret = 0;        else            ret = s->select;        break;    default:    case 7:        if ((!ide_if[0].bs && !ide_if[1].bs) ||            (s != ide_if && !s->bs))            ret = 0;        else            ret = s->status;        s->set_irq(s->irq_opaque, s->irq, 0);        break;    }#ifdef DEBUG_IDE    printf("ide: read addr=0x%x val=%02x\n", addr1, ret);#endif    return ret;}static uint32_t ide_status_read(void *opaque, uint32_t addr){    IDEState *ide_if = opaque;    IDEState *s = ide_if->cur_drive;    int ret;    if ((!ide_if[0].bs && !ide_if[1].bs) ||        (s != ide_if && !s->bs))        ret = 0;    else        ret = s->status;#ifdef DEBUG_IDE    printf("ide: read status addr=0x%x val=%02x\n", addr, ret);#endif    return ret;}static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val){    IDEState *ide_if = opaque;    IDEState *s;    int i;#ifdef DEBUG_IDE    printf("ide: write control addr=0x%x val=%02x\n", addr, val);#endif    /* common for both drives */    if (!(ide_if[0].cmd & IDE_CMD_RESET) &&        (val & IDE_CMD_RESET)) {        /* reset low to high */        for(i = 0;i < 2; i++) {            s = &ide_if[i];            s->status = BUSY_STAT | SEEK_STAT;            s->error = 0x01;        }    } else if ((ide_if[0].cmd & IDE_CMD_RESET) &&               !(val & IDE_CMD_RESET)) {        /* high to low */        for(i = 0;i < 2; i++) {            s = &ide_if[i];            if (s->is_cdrom)                s->status = 0x00; /* NOTE: READY is _not_ set */            else                s->status = READY_STAT | SEEK_STAT;            ide_set_signature(s);        }    }    ide_if[0].cmd = val;    ide_if[1].cmd = val;}static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val){    IDEState *s = ((IDEState *)opaque)->cur_drive;    uint8_t *p;    p = s->data_ptr;    *(uint16_t *)p = le16_to_cpu(val);    p += 2;    s->data_ptr = p;    if (p >= s->data_end)        s->end_transfer_func(s);}static uint32_t ide_data_readw(void *opaque, uint32_t addr){    IDEState *s = ((IDEState *)opaque)->cur_drive;    uint8_t *p;    int ret;    p = s->data_ptr;    ret = cpu_to_le16(*(uint16_t *)p);    p += 2;    s->data_ptr = p;    if (p >= s->data_end)        s->end_transfer_func(s);    return ret;}static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val){    IDEState *s = ((IDEState *)opaque)->cur_drive;    uint8_t *p;    p = s->data_ptr;    *(uint32_t *)p = le32_to_cpu(val);    p += 4;    s->data_ptr = p;    if (p >= s->data_end)        s->end_transfer_func(s);}static uint32_t ide_data_readl(void *opaque, uint32_t addr){    IDEState *s = ((IDEState *)opaque)->cur_drive;    uint8_t *p;    int ret;        p = s->data_ptr;    ret = cpu_to_le32(*(uint32_t *)p);    p += 4;    s->data_ptr = p;    if (p >= s->data_end)        s->end_transfer_func(s);    return ret;}static void ide_dummy_transfer_stop(IDEState *s){    s->data_ptr = s->io_buffer;    s->data_end = s->io_buffer;    s->io_buffer[0] = 0xff;    s->io_buffer[1] = 0xff;    s->io_buffer[2] = 0xff;    s->io_buffer[3] = 0xff;}static void ide_reset(IDEState *s){    s->mult_sectors = MAX_MULT_SECTORS;    s->cur_drive = s;    s->select = 0xa0;    s->status = READY_STAT;    ide_set_signature(s);    /* init the transfer handler so that 0xffff is returned on data       accesses */    s->end_transfer_func = ide_dummy_transfer_stop;    ide_dummy_transfer_stop(s);}struct partition {	uint8_t boot_ind;		/* 0x80 - active */	uint8_t head;		/* starting head */	uint8_t sector;		/* starting sector */	uint8_t cyl;		/* starting cylinder */	uint8_t sys_ind;		/* What partition type */	uint8_t end_head;		/* end head */	uint8_t end_sector;	/* end sector */	uint8_t end_cyl;		/* end cylinder */	uint32_t start_sect;	/* starting sector counting from 0 */	uint32_t nr_sects;		/* nr of sectors in partition */} __attribute__((packed));/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */static int guess_disk_lchs(IDEState *s,                            int *pcylinders, int *pheads, int *psectors){    uint8_t buf[512];    int ret, i, heads, sectors, cylinders;    struct partition *p;    uint32_t nr_sects;    ret = bdrv_read(s->bs, 0, buf, 1);    if (ret < 0)        return -1;    /* test msdos magic */    if (buf[510] != 0x55 || buf[511] != 0xaa)        return -1;    for(i = 0; i < 4; i++) {        p = ((struct partition *)(buf + 0x1be)) + i;        nr_sects = le32_to_cpu(p->nr_sects);        if (nr_sects && p->end_head) {            /* We make the assumption that the partition terminates on               a cylinder boundary */            heads = p->end_head + 1;            sectors = p->end_sector & 63;            if (sectors == 0)                continue;            cylinders = s->nb_sectors / (heads * sectors);            if (cylinders < 1 || cylinders > 16383)                continue;            *pheads = heads;            *psectors = sectors;            *pcylinders = cylinders;#if 0            printf("guessed geometry: LCHS=%d %d %d\n",                    cylinders, heads, sectors);#endif            return 0;        }    }    return -1;}static void ide_init2(IDEState *ide_state,                      BlockDriverState *hd0, BlockDriverState *hd1,                      SetIRQFunc *set_irq, void *irq_opaque, int irq){    IDEState *s;    static int drive_serial = 1;    int i, cylinders, heads, secs, translation;    int64_t nb_sectors;    for(i = 0; i < 2; i++) {        s = ide_state + i;        if (i == 0)            s->bs = hd0;        else            s->bs = hd1;        if (s->bs) {            bdrv_get_geometry(s->bs, &nb_sectors);            s->nb_sectors = nb_sectors;            /* if a geometry hint is available, use it */            bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);            if (cylinders != 0) {                s->cylinders = cylinders;                s->heads = heads;                s->sectors = secs;            } else {                if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) {                    if (heads > 16) {                        /* if heads > 16, it means that a BIOS LBA                           translation was active, so the default                           hardware geometry is OK */                        goto default_geometry;                    } else {                        s->cylinders = cylinders;                        s->heads = heads;                        s->sectors = secs;                        /* disable any translation to be in sync with                           the logical geometry */                        translation = bdrv_get_translation_hint(s->bs);                        if (translation == BIOS_ATA_TRANSLATION_AUTO) {                            bdrv_set_translation_hint(s->bs,                                            

⌨️ 快捷键说明

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