📄 ide.c
字号:
padstr8(buf + 32, 4, QEMU_VERSION); ide_atapi_cmd_reply(s, 36, max_len); break; default: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE); break; }}/* called when the inserted state of the media has changed */static void cdrom_change_cb(void *opaque){ IDEState *s = opaque; int64_t nb_sectors; if (!s->bs) return; /* yikes */ /* XXX: send interrupt too */ bdrv_get_geometry(s->bs, &nb_sectors); s->nb_sectors = nb_sectors;}static void ide_cmd_lba48_transform(IDEState *s, int lba48){ s->lba48 = lba48; /* handle the 'magic' 0 nsector count conversion here. to avoid * fiddling with the rest of the read logic, we just store the * full sector count in ->nsector and ignore ->hob_nsector from now */ if (!s->lba48) { if (!s->nsector) s->nsector = 256; } else { if (!s->nsector && !s->hob_nsector) s->nsector = 65536; else { int lo = s->nsector; int hi = s->hob_nsector; s->nsector = (hi << 8) | lo; } }}static void ide_clear_hob(IDEState *ide_if){ /* any write clears HOB high bit of device control register */ ide_if[0].select &= ~(1 << 7); ide_if[1].select &= ~(1 << 7);}static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val){ IDEState *ide_if = opaque; IDEState *s; int unit, n; int lba48 = 0; int ret;#ifdef DEBUG_IDE printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);#endif addr &= 7; switch(addr) { case 0: break; case 1: ide_clear_hob(ide_if); /* NOTE: data is written to the two drives */ ide_if[0].hob_feature = ide_if[0].feature; ide_if[1].hob_feature = ide_if[1].feature; ide_if[0].feature = val; ide_if[1].feature = val; break; case 2: ide_clear_hob(ide_if); ide_if[0].hob_nsector = ide_if[0].nsector; ide_if[1].hob_nsector = ide_if[1].nsector; ide_if[0].nsector = val; ide_if[1].nsector = val; break; case 3: ide_clear_hob(ide_if); ide_if[0].hob_sector = ide_if[0].sector; ide_if[1].hob_sector = ide_if[1].sector; ide_if[0].sector = val; ide_if[1].sector = val; break; case 4: ide_clear_hob(ide_if); ide_if[0].hob_lcyl = ide_if[0].lcyl; ide_if[1].hob_lcyl = ide_if[1].lcyl; ide_if[0].lcyl = val; ide_if[1].lcyl = val; break; case 5: ide_clear_hob(ide_if); ide_if[0].hob_hcyl = ide_if[0].hcyl; ide_if[1].hob_hcyl = ide_if[1].hcyl; ide_if[0].hcyl = val; ide_if[1].hcyl = val; break; case 6: /* FIXME: HOB readback uses bit 7 */ ide_if[0].select = (val & ~0x10) | 0xa0; ide_if[1].select = (val | 0x10) | 0xa0; /* select drive */ buffered_pio_reset(ide_if->cur_drive); unit = (val >> 4) & 1; s = ide_if + unit; ide_if->cur_drive = s; break; default: case 7: /* command */#if defined(DEBUG_IDE) printf("ide: CMD=%02x\n", val);#endif s = ide_if->cur_drive; /* ignore commands to non existant device */ if (!s->bs) break; switch(val) { case WIN_IDENTIFY: if (s->bs && !s->is_cdrom) { ide_identify(s); s->status = READY_STAT | SEEK_STAT; ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); } else { if (s->is_cdrom) { ide_set_signature(s); } ide_abort_command(s); } ide_set_irq(s); break; case WIN_SPECIFY: case WIN_RECAL: s->error = 0; s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); break; case WIN_SETMULT: if (s->nsector > MAX_MULT_SECTORS || (s->nsector & (s->nsector - 1)) != 0) { ide_abort_command(s); } else { s->mult_sectors = s->nsector; s->status = READY_STAT; } ide_set_irq(s); break; case WIN_VERIFY_EXT: lba48 = 1; case WIN_VERIFY: case WIN_VERIFY_ONCE: /* do sector number check ? */ ide_cmd_lba48_transform(s, lba48); s->status = READY_STAT; ide_set_irq(s); break; case WIN_READ_EXT: lba48 = 1; case WIN_READ: case WIN_READ_ONCE: if (!s->bs) goto abort_cmd; ide_cmd_lba48_transform(s, lba48); s->req_nb_sectors = 1; ide_sector_read(s); break; case WIN_WRITE_EXT: lba48 = 1; case WIN_WRITE: case WIN_WRITE_ONCE: ide_cmd_lba48_transform(s, lba48); s->error = 0; s->status = SEEK_STAT | READY_STAT; s->req_nb_sectors = 1; ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); break; case WIN_MULTREAD_EXT: lba48 = 1; case WIN_MULTREAD: if (!s->mult_sectors) goto abort_cmd; ide_cmd_lba48_transform(s, lba48); s->req_nb_sectors = s->mult_sectors; ide_sector_read(s); break; case WIN_MULTWRITE_EXT: lba48 = 1; case WIN_MULTWRITE: if (!s->mult_sectors) goto abort_cmd; ide_cmd_lba48_transform(s, lba48); s->error = 0; s->status = SEEK_STAT | READY_STAT; s->req_nb_sectors = s->mult_sectors; n = s->nsector; if (n > s->req_nb_sectors) n = s->req_nb_sectors; 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 */ s->write_cache = 1; s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); break; case 0x82: /* write cache disable */ s->write_cache = 0; s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); break; case 0xaa: /* read look-ahead enable */ case 0x55: /* read look-ahead disable */ case 0x42: /* EN_AAM: enable Automatic Acoustic Mode */ case 0xc2: /* DIS_AAM: disable Automatic Acoustic Mode */ case 0x85: /* DIS_APM: disable APM */ 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: s->status = BUSY_STAT; bdrv_aio_flush(s->bs, ide_flush_cb, s); break; case WIN_IDLEIMMEDIATE: case WIN_STANDBY: case WIN_SETIDLE1: case WIN_STANDBYNOW1: case WIN_SLEEPNOW1: case WIN_STANDBY2: case WIN_SETIDLE2: case WIN_STANDBYNOW2: case WIN_SLEEPNOW2: 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->status = READY_STAT; 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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -