diff --git a/hw/ide/core.c b/hw/ide/core.c index a7f8445e9e..87897586b6 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1206,6 +1206,80 @@ static bool cmd_check_power_mode(IDEState *s, uint8_t cmd) return true; } +static bool cmd_set_features(IDEState *s, uint8_t cmd) +{ + uint16_t *identify_data; + + if (!s->bs) { + ide_abort_command(s); + return true; + } + + /* XXX: valid for CDROM ? */ + switch (s->feature) { + case 0x02: /* write cache enable */ + bdrv_set_enable_write_cache(s->bs, true); + identify_data = (uint16_t *)s->identify_data; + put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1); + return true; + case 0x82: /* write cache disable */ + bdrv_set_enable_write_cache(s->bs, false); + identify_data = (uint16_t *)s->identify_data; + put_le16(identify_data + 85, (1 << 14) | 1); + ide_flush_cache(s); + return false; + case 0xcc: /* reverting to power-on defaults enable */ + case 0x66: /* reverting to power-on defaults disable */ + case 0xaa: /* read look-ahead enable */ + case 0x55: /* read look-ahead disable */ + case 0x05: /* set advanced power management mode */ + case 0x85: /* disable advanced power management mode */ + case 0x69: /* NOP */ + case 0x67: /* NOP */ + case 0x96: /* NOP */ + case 0x9a: /* NOP */ + case 0x42: /* enable Automatic Acoustic Mode */ + case 0xc2: /* disable Automatic Acoustic Mode */ + return true; + case 0x03: /* set transfer mode */ + { + uint8_t val = s->nsector & 0x07; + identify_data = (uint16_t *)s->identify_data; + + switch (s->nsector >> 3) { + case 0x00: /* pio default */ + case 0x01: /* pio mode */ + put_le16(identify_data + 62, 0x07); + put_le16(identify_data + 63, 0x07); + put_le16(identify_data + 88, 0x3f); + break; + case 0x02: /* sigle word dma mode*/ + put_le16(identify_data + 62, 0x07 | (1 << (val + 8))); + put_le16(identify_data + 63, 0x07); + put_le16(identify_data + 88, 0x3f); + break; + case 0x04: /* mdma mode */ + put_le16(identify_data + 62, 0x07); + put_le16(identify_data + 63, 0x07 | (1 << (val + 8))); + put_le16(identify_data + 88, 0x3f); + break; + case 0x08: /* udma mode */ + put_le16(identify_data + 62, 0x07); + put_le16(identify_data + 63, 0x07); + put_le16(identify_data + 88, 0x3f | (1 << (val + 8))); + break; + default: + goto abort_cmd; + } + return true; + } + } + +abort_cmd: + ide_abort_command(s); + return true; +} + #define HD_OK (1u << IDE_HD) #define CD_OK (1u << IDE_CD) #define CFA_OK (1u << IDE_CFATA) @@ -1274,7 +1348,7 @@ static const struct { [WIN_FLUSH_CACHE] = { NULL, ALL_OK }, [WIN_FLUSH_CACHE_EXT] = { NULL, HD_CFA_OK }, [WIN_IDENTIFY] = { cmd_identify, ALL_OK }, - [WIN_SETFEATURES] = { NULL, ALL_OK }, + [WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC }, [IBM_SENSE_CONDITION] = { NULL, CFA_OK }, [CFA_WEAR_LEVEL] = { NULL, HD_CFA_OK }, [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, ALL_OK | SET_DSC }, @@ -1288,7 +1362,6 @@ static bool ide_cmd_permitted(IDEState *s, uint32_t cmd) void ide_exec_cmd(IDEBus *bus, uint32_t val) { - uint16_t *identify_data; IDEState *s; int n; @@ -1330,76 +1403,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) } switch(val) { - case WIN_SETFEATURES: - if (!s->bs) - goto abort_cmd; - /* XXX: valid for CDROM ? */ - switch(s->feature) { - case 0x02: /* write cache enable */ - bdrv_set_enable_write_cache(s->bs, true); - identify_data = (uint16_t *)s->identify_data; - put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1); - s->status = READY_STAT | SEEK_STAT; - ide_set_irq(s->bus); - break; - case 0x82: /* write cache disable */ - bdrv_set_enable_write_cache(s->bs, false); - identify_data = (uint16_t *)s->identify_data; - put_le16(identify_data + 85, (1 << 14) | 1); - ide_flush_cache(s); - break; - case 0xcc: /* reverting to power-on defaults enable */ - case 0x66: /* reverting to power-on defaults disable */ - case 0xaa: /* read look-ahead enable */ - case 0x55: /* read look-ahead disable */ - case 0x05: /* set advanced power management mode */ - case 0x85: /* disable advanced power management mode */ - case 0x69: /* NOP */ - case 0x67: /* NOP */ - case 0x96: /* NOP */ - case 0x9a: /* NOP */ - case 0x42: /* enable Automatic Acoustic Mode */ - case 0xc2: /* disable Automatic Acoustic Mode */ - s->status = READY_STAT | SEEK_STAT; - ide_set_irq(s->bus); - break; - case 0x03: { /* set transfer mode */ - uint8_t val = s->nsector & 0x07; - identify_data = (uint16_t *)s->identify_data; - - switch (s->nsector >> 3) { - case 0x00: /* pio default */ - case 0x01: /* pio mode */ - put_le16(identify_data + 62,0x07); - put_le16(identify_data + 63,0x07); - put_le16(identify_data + 88,0x3f); - break; - case 0x02: /* sigle word dma mode*/ - put_le16(identify_data + 62,0x07 | (1 << (val + 8))); - put_le16(identify_data + 63,0x07); - put_le16(identify_data + 88,0x3f); - break; - case 0x04: /* mdma mode */ - put_le16(identify_data + 62,0x07); - put_le16(identify_data + 63,0x07 | (1 << (val + 8))); - put_le16(identify_data + 88,0x3f); - break; - case 0x08: /* udma mode */ - put_le16(identify_data + 62,0x07); - put_le16(identify_data + 63,0x07); - put_le16(identify_data + 88,0x3f | (1 << (val + 8))); - break; - default: - goto abort_cmd; - } - s->status = READY_STAT | SEEK_STAT; - ide_set_irq(s->bus); - break; - } - default: - goto abort_cmd; - } - break; case WIN_FLUSH_CACHE: case WIN_FLUSH_CACHE_EXT: ide_flush_cache(s);