📄 ide.c
字号:
IDEState *s; int unit, n; int lba48 = 0;#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 slave */ if (s != ide_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: if (s->bs) bdrv_flush(s->bs); s->status = READY_STAT; ide_set_irq(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){ 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; buffered_pio_write(s, addr, 2); p = s->data_ptr; *(uint16_t *)p = le16_to_cpu(val); p += 2; s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -