Commit c9159e5321628a29bcc26216f0166e9cdd7e4b26
1 parent
8c9b861e
added IDE mult support - reduced irq latency (IDE should have good performances now)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@295 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
77 additions
and
31 deletions
vl.c
... | ... | @@ -54,6 +54,7 @@ |
54 | 54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
55 | 55 | |
56 | 56 | //#define DEBUG_UNUSED_IOPORT |
57 | +//#define DEBUG_IRQ_LATENCY | |
57 | 58 | |
58 | 59 | #define PHYS_RAM_BASE 0xa8000000 |
59 | 60 | #define KERNEL_LOAD_ADDR 0x00100000 |
... | ... | @@ -598,14 +599,9 @@ static int pic_get_irq(PicState *s) |
598 | 599 | } |
599 | 600 | } |
600 | 601 | |
601 | -void pic_set_irq(int irq, int level) | |
602 | -{ | |
603 | - pic_set_irq1(&pics[irq >> 3], irq & 7, level); | |
604 | -} | |
605 | - | |
606 | -/* can be called at any time outside cpu_exec() to raise irqs if | |
607 | - necessary */ | |
608 | -void pic_handle_irq(void) | |
602 | +/* raise irq to CPU if necessary. must be called every time the active | |
603 | + irq may change */ | |
604 | +static void pic_update_irq(void) | |
609 | 605 | { |
610 | 606 | int irq2, irq; |
611 | 607 | |
... | ... | @@ -626,16 +622,36 @@ void pic_handle_irq(void) |
626 | 622 | /* from master pic */ |
627 | 623 | pic_irq_requested = irq; |
628 | 624 | } |
629 | - global_env->hard_interrupt_request = 1; | |
625 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_HARD); | |
630 | 626 | } |
631 | 627 | } |
632 | 628 | |
629 | +#ifdef DEBUG_IRQ_LATENCY | |
630 | +int64_t irq_time[16]; | |
631 | +int64_t cpu_get_ticks(void); | |
632 | +#endif | |
633 | + | |
634 | +void pic_set_irq(int irq, int level) | |
635 | +{ | |
636 | +#ifdef DEBUG_IRQ_LATENCY | |
637 | + if (level) { | |
638 | + irq_time[irq] = cpu_get_ticks(); | |
639 | + } | |
640 | +#endif | |
641 | + pic_set_irq1(&pics[irq >> 3], irq & 7, level); | |
642 | + pic_update_irq(); | |
643 | +} | |
644 | + | |
633 | 645 | int cpu_x86_get_pic_interrupt(CPUX86State *env) |
634 | 646 | { |
635 | 647 | int irq, irq2, intno; |
636 | 648 | |
637 | 649 | /* signal the pic that the irq was acked by the CPU */ |
638 | 650 | irq = pic_irq_requested; |
651 | +#ifdef DEBUG_IRQ_LATENCY | |
652 | + printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]); | |
653 | +#endif | |
654 | + | |
639 | 655 | if (irq >= 8) { |
640 | 656 | irq2 = irq & 7; |
641 | 657 | pics[1].isr |= (1 << irq2); |
... | ... | @@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
706 | 722 | case 0: |
707 | 723 | /* normal mode */ |
708 | 724 | s->imr = val; |
725 | + pic_update_irq(); | |
709 | 726 | break; |
710 | 727 | case 1: |
711 | 728 | s->irq_base = val & 0xf8; |
... | ... | @@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
1570 | 1587 | s->rcnt == 0) { |
1571 | 1588 | s->isr |= ENISR_RDC; |
1572 | 1589 | ne2000_update_irq(s); |
1573 | - /* XXX: find a better solution for irqs */ | |
1574 | - cpu_x86_interrupt(global_env); | |
1575 | 1590 | } |
1576 | 1591 | if (val & E8390_TRANS) { |
1577 | 1592 | net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt); |
... | ... | @@ -1931,7 +1946,8 @@ void ne2000_init(void) |
1931 | 1946 | #define WIN_SET_MAX 0xF9 |
1932 | 1947 | #define DISABLE_SEAGATE 0xFB |
1933 | 1948 | |
1934 | -#define MAX_MULT_SECTORS 16 | |
1949 | +/* set to 1 set disable mult support */ | |
1950 | +#define MAX_MULT_SECTORS 8 | |
1935 | 1951 | |
1936 | 1952 | #define MAX_DISKS 2 |
1937 | 1953 | |
... | ... | @@ -1948,7 +1964,7 @@ typedef struct IDEState { |
1948 | 1964 | /* ide regs */ |
1949 | 1965 | uint8_t feature; |
1950 | 1966 | uint8_t error; |
1951 | - uint8_t nsector; | |
1967 | + uint16_t nsector; /* 0 is 256 to ease computations */ | |
1952 | 1968 | uint8_t sector; |
1953 | 1969 | uint8_t lcyl; |
1954 | 1970 | uint8_t hcyl; |
... | ... | @@ -1959,6 +1975,7 @@ typedef struct IDEState { |
1959 | 1975 | /* depends on bit 4 in select, only meaningful for drive 0 */ |
1960 | 1976 | struct IDEState *cur_drive; |
1961 | 1977 | BlockDriverState *bs; |
1978 | + int req_nb_sectors; /* number of sectors per interrupt */ | |
1962 | 1979 | EndTransferFunc *end_transfer_func; |
1963 | 1980 | uint8_t *data_ptr; |
1964 | 1981 | uint8_t *data_end; |
... | ... | @@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s) |
1998 | 2015 | stw(p + 21, 512); /* cache size in sectors */ |
1999 | 2016 | stw(p + 22, 4); /* ecc bytes */ |
2000 | 2017 | padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); |
2001 | - // stw(p + 47, MAX_MULT_SECTORS); | |
2018 | +#if MAX_MULT_SECTORS > 1 | |
2019 | + stw(p + 47, MAX_MULT_SECTORS); | |
2020 | +#endif | |
2002 | 2021 | stw(p + 48, 1); /* dword I/O */ |
2003 | 2022 | stw(p + 49, 1 << 9); /* LBA supported, no DMA */ |
2004 | 2023 | stw(p + 51, 0x200); /* PIO transfer cycle */ |
... | ... | @@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s) |
2032 | 2051 | { |
2033 | 2052 | if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) { |
2034 | 2053 | pic_set_irq(s->irq, 1); |
2035 | - cpu_x86_interrupt(global_env); | |
2036 | 2054 | } |
2037 | 2055 | } |
2038 | 2056 | |
... | ... | @@ -2090,51 +2108,60 @@ static void ide_set_sector(IDEState *s, int64_t sector_num) |
2090 | 2108 | static void ide_sector_read(IDEState *s) |
2091 | 2109 | { |
2092 | 2110 | int64_t sector_num; |
2093 | - int ret; | |
2111 | + int ret, n; | |
2094 | 2112 | |
2095 | 2113 | s->status = READY_STAT | SEEK_STAT; |
2096 | 2114 | sector_num = ide_get_sector(s); |
2097 | - s->nsector--; | |
2098 | - if (s->nsector == 0xff) { | |
2115 | + n = s->nsector; | |
2116 | + if (n == 0) { | |
2099 | 2117 | /* no more sector to read from disk */ |
2100 | 2118 | ide_transfer_stop(s); |
2101 | 2119 | } else { |
2102 | 2120 | #if defined(DEBUG_IDE) |
2103 | 2121 | printf("read sector=%Ld\n", sector_num); |
2104 | 2122 | #endif |
2105 | - ret = bdrv_read(s->bs, sector_num, s->io_buffer, 1); | |
2106 | - ide_transfer_start(s, 512, ide_sector_read); | |
2123 | + if (n > s->req_nb_sectors) | |
2124 | + n = s->req_nb_sectors; | |
2125 | + ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); | |
2126 | + ide_transfer_start(s, 512 * n, ide_sector_read); | |
2107 | 2127 | ide_set_irq(s); |
2128 | + ide_set_sector(s, sector_num + n); | |
2129 | + s->nsector -= n; | |
2108 | 2130 | } |
2109 | - ide_set_sector(s, sector_num + 1); | |
2110 | 2131 | } |
2111 | 2132 | |
2112 | 2133 | static void ide_sector_write(IDEState *s) |
2113 | 2134 | { |
2114 | 2135 | int64_t sector_num; |
2115 | - int ret; | |
2136 | + int ret, n, n1; | |
2116 | 2137 | |
2117 | 2138 | s->status = READY_STAT | SEEK_STAT; |
2118 | 2139 | sector_num = ide_get_sector(s); |
2119 | 2140 | #if defined(DEBUG_IDE) |
2120 | 2141 | printf("write sector=%Ld\n", sector_num); |
2121 | 2142 | #endif |
2122 | - ret = bdrv_write(s->bs, sector_num, s->io_buffer, 1); | |
2123 | - s->nsector--; | |
2143 | + n = s->nsector; | |
2144 | + if (n > s->req_nb_sectors) | |
2145 | + n = s->req_nb_sectors; | |
2146 | + ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); | |
2147 | + s->nsector -= n; | |
2124 | 2148 | if (s->nsector == 0) { |
2125 | 2149 | /* no more sector to write */ |
2126 | 2150 | ide_transfer_stop(s); |
2127 | 2151 | } else { |
2128 | - ide_transfer_start(s, 512, ide_sector_write); | |
2152 | + n1 = s->nsector; | |
2153 | + if (n1 > s->req_nb_sectors) | |
2154 | + n1 = s->req_nb_sectors; | |
2155 | + ide_transfer_start(s, 512 * n1, ide_sector_write); | |
2129 | 2156 | } |
2130 | - ide_set_sector(s, sector_num + 1); | |
2157 | + ide_set_sector(s, sector_num + n); | |
2131 | 2158 | ide_set_irq(s); |
2132 | 2159 | } |
2133 | 2160 | |
2134 | 2161 | void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2135 | 2162 | { |
2136 | 2163 | IDEState *s = ide_state[0].cur_drive; |
2137 | - int unit; | |
2164 | + int unit, n; | |
2138 | 2165 | |
2139 | 2166 | addr &= 7; |
2140 | 2167 | #ifdef DEBUG_IDE |
... | ... | @@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2147 | 2174 | s->feature = val; |
2148 | 2175 | break; |
2149 | 2176 | case 2: |
2177 | + if (val == 0) | |
2178 | + val = 256; | |
2150 | 2179 | s->nsector = val; |
2151 | 2180 | break; |
2152 | 2181 | case 3: |
... | ... | @@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2201 | 2230 | break; |
2202 | 2231 | case WIN_READ: |
2203 | 2232 | case WIN_READ_ONCE: |
2233 | + s->req_nb_sectors = 1; | |
2204 | 2234 | ide_sector_read(s); |
2205 | 2235 | break; |
2206 | 2236 | case WIN_WRITE: |
2207 | 2237 | case WIN_WRITE_ONCE: |
2208 | 2238 | s->status = SEEK_STAT; |
2239 | + s->req_nb_sectors = 1; | |
2209 | 2240 | ide_transfer_start(s, 512, ide_sector_write); |
2210 | 2241 | break; |
2242 | + case WIN_MULTREAD: | |
2243 | + if (!s->mult_sectors) | |
2244 | + goto abort_cmd; | |
2245 | + s->req_nb_sectors = s->mult_sectors; | |
2246 | + ide_sector_read(s); | |
2247 | + break; | |
2248 | + case WIN_MULTWRITE: | |
2249 | + if (!s->mult_sectors) | |
2250 | + goto abort_cmd; | |
2251 | + s->status = SEEK_STAT; | |
2252 | + s->req_nb_sectors = s->mult_sectors; | |
2253 | + n = s->nsector; | |
2254 | + if (n > s->req_nb_sectors) | |
2255 | + n = s->req_nb_sectors; | |
2256 | + ide_transfer_start(s, 512 * n, ide_sector_write); | |
2257 | + break; | |
2211 | 2258 | default: |
2259 | + abort_cmd: | |
2212 | 2260 | ide_abort_command(s); |
2213 | 2261 | ide_set_irq(s); |
2214 | 2262 | break; |
... | ... | @@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) |
2230 | 2278 | ret = s->error; |
2231 | 2279 | break; |
2232 | 2280 | case 2: |
2233 | - ret = s->nsector; | |
2281 | + ret = s->nsector & 0xff; | |
2234 | 2282 | break; |
2235 | 2283 | case 3: |
2236 | 2284 | ret = s->sector; |
... | ... | @@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, |
2400 | 2448 | timer_irq_count = 2; |
2401 | 2449 | timer_irq_count--; |
2402 | 2450 | /* just exit from the cpu to have a chance to handle timers */ |
2403 | - cpu_x86_interrupt(global_env); | |
2451 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
2404 | 2452 | timer_irq_pending = 1; |
2405 | 2453 | } |
2406 | 2454 | } |
... | ... | @@ -2487,8 +2535,6 @@ void main_loop(void *opaque) |
2487 | 2535 | pic_set_irq(0, 0); |
2488 | 2536 | timer_irq_pending = 0; |
2489 | 2537 | } |
2490 | - | |
2491 | - pic_handle_irq(); | |
2492 | 2538 | } |
2493 | 2539 | } |
2494 | 2540 | ... | ... |