Commit c9159e5321628a29bcc26216f0166e9cdd7e4b26

Authored by bellard
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
@@ -54,6 +54,7 @@ @@ -54,6 +54,7 @@
54 #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" 54 #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup"
55 55
56 //#define DEBUG_UNUSED_IOPORT 56 //#define DEBUG_UNUSED_IOPORT
  57 +//#define DEBUG_IRQ_LATENCY
57 58
58 #define PHYS_RAM_BASE 0xa8000000 59 #define PHYS_RAM_BASE 0xa8000000
59 #define KERNEL_LOAD_ADDR 0x00100000 60 #define KERNEL_LOAD_ADDR 0x00100000
@@ -598,14 +599,9 @@ static int pic_get_irq(PicState *s) @@ -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 int irq2, irq; 606 int irq2, irq;
611 607
@@ -626,16 +622,36 @@ void pic_handle_irq(void) @@ -626,16 +622,36 @@ void pic_handle_irq(void)
626 /* from master pic */ 622 /* from master pic */
627 pic_irq_requested = irq; 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 int cpu_x86_get_pic_interrupt(CPUX86State *env) 645 int cpu_x86_get_pic_interrupt(CPUX86State *env)
634 { 646 {
635 int irq, irq2, intno; 647 int irq, irq2, intno;
636 648
637 /* signal the pic that the irq was acked by the CPU */ 649 /* signal the pic that the irq was acked by the CPU */
638 irq = pic_irq_requested; 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 if (irq >= 8) { 655 if (irq >= 8) {
640 irq2 = irq & 7; 656 irq2 = irq & 7;
641 pics[1].isr |= (1 << irq2); 657 pics[1].isr |= (1 << irq2);
@@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
706 case 0: 722 case 0:
707 /* normal mode */ 723 /* normal mode */
708 s->imr = val; 724 s->imr = val;
  725 + pic_update_irq();
709 break; 726 break;
710 case 1: 727 case 1:
711 s->irq_base = val & 0xf8; 728 s->irq_base = val & 0xf8;
@@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
1570 s->rcnt == 0) { 1587 s->rcnt == 0) {
1571 s->isr |= ENISR_RDC; 1588 s->isr |= ENISR_RDC;
1572 ne2000_update_irq(s); 1589 ne2000_update_irq(s);
1573 - /* XXX: find a better solution for irqs */  
1574 - cpu_x86_interrupt(global_env);  
1575 } 1590 }
1576 if (val & E8390_TRANS) { 1591 if (val & E8390_TRANS) {
1577 net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt); 1592 net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
@@ -1931,7 +1946,8 @@ void ne2000_init(void) @@ -1931,7 +1946,8 @@ void ne2000_init(void)
1931 #define WIN_SET_MAX 0xF9 1946 #define WIN_SET_MAX 0xF9
1932 #define DISABLE_SEAGATE 0xFB 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 #define MAX_DISKS 2 1952 #define MAX_DISKS 2
1937 1953
@@ -1948,7 +1964,7 @@ typedef struct IDEState { @@ -1948,7 +1964,7 @@ typedef struct IDEState {
1948 /* ide regs */ 1964 /* ide regs */
1949 uint8_t feature; 1965 uint8_t feature;
1950 uint8_t error; 1966 uint8_t error;
1951 - uint8_t nsector; 1967 + uint16_t nsector; /* 0 is 256 to ease computations */
1952 uint8_t sector; 1968 uint8_t sector;
1953 uint8_t lcyl; 1969 uint8_t lcyl;
1954 uint8_t hcyl; 1970 uint8_t hcyl;
@@ -1959,6 +1975,7 @@ typedef struct IDEState { @@ -1959,6 +1975,7 @@ typedef struct IDEState {
1959 /* depends on bit 4 in select, only meaningful for drive 0 */ 1975 /* depends on bit 4 in select, only meaningful for drive 0 */
1960 struct IDEState *cur_drive; 1976 struct IDEState *cur_drive;
1961 BlockDriverState *bs; 1977 BlockDriverState *bs;
  1978 + int req_nb_sectors; /* number of sectors per interrupt */
1962 EndTransferFunc *end_transfer_func; 1979 EndTransferFunc *end_transfer_func;
1963 uint8_t *data_ptr; 1980 uint8_t *data_ptr;
1964 uint8_t *data_end; 1981 uint8_t *data_end;
@@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s) @@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s)
1998 stw(p + 21, 512); /* cache size in sectors */ 2015 stw(p + 21, 512); /* cache size in sectors */
1999 stw(p + 22, 4); /* ecc bytes */ 2016 stw(p + 22, 4); /* ecc bytes */
2000 padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); 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 stw(p + 48, 1); /* dword I/O */ 2021 stw(p + 48, 1); /* dword I/O */
2003 stw(p + 49, 1 << 9); /* LBA supported, no DMA */ 2022 stw(p + 49, 1 << 9); /* LBA supported, no DMA */
2004 stw(p + 51, 0x200); /* PIO transfer cycle */ 2023 stw(p + 51, 0x200); /* PIO transfer cycle */
@@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s) @@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s)
2032 { 2051 {
2033 if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) { 2052 if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) {
2034 pic_set_irq(s->irq, 1); 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,51 +2108,60 @@ static void ide_set_sector(IDEState *s, int64_t sector_num)
2090 static void ide_sector_read(IDEState *s) 2108 static void ide_sector_read(IDEState *s)
2091 { 2109 {
2092 int64_t sector_num; 2110 int64_t sector_num;
2093 - int ret; 2111 + int ret, n;
2094 2112
2095 s->status = READY_STAT | SEEK_STAT; 2113 s->status = READY_STAT | SEEK_STAT;
2096 sector_num = ide_get_sector(s); 2114 sector_num = ide_get_sector(s);
2097 - s->nsector--;  
2098 - if (s->nsector == 0xff) { 2115 + n = s->nsector;
  2116 + if (n == 0) {
2099 /* no more sector to read from disk */ 2117 /* no more sector to read from disk */
2100 ide_transfer_stop(s); 2118 ide_transfer_stop(s);
2101 } else { 2119 } else {
2102 #if defined(DEBUG_IDE) 2120 #if defined(DEBUG_IDE)
2103 printf("read sector=%Ld\n", sector_num); 2121 printf("read sector=%Ld\n", sector_num);
2104 #endif 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 ide_set_irq(s); 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 static void ide_sector_write(IDEState *s) 2133 static void ide_sector_write(IDEState *s)
2113 { 2134 {
2114 int64_t sector_num; 2135 int64_t sector_num;
2115 - int ret; 2136 + int ret, n, n1;
2116 2137
2117 s->status = READY_STAT | SEEK_STAT; 2138 s->status = READY_STAT | SEEK_STAT;
2118 sector_num = ide_get_sector(s); 2139 sector_num = ide_get_sector(s);
2119 #if defined(DEBUG_IDE) 2140 #if defined(DEBUG_IDE)
2120 printf("write sector=%Ld\n", sector_num); 2141 printf("write sector=%Ld\n", sector_num);
2121 #endif 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 if (s->nsector == 0) { 2148 if (s->nsector == 0) {
2125 /* no more sector to write */ 2149 /* no more sector to write */
2126 ide_transfer_stop(s); 2150 ide_transfer_stop(s);
2127 } else { 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 ide_set_irq(s); 2158 ide_set_irq(s);
2132 } 2159 }
2133 2160
2134 void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) 2161 void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
2135 { 2162 {
2136 IDEState *s = ide_state[0].cur_drive; 2163 IDEState *s = ide_state[0].cur_drive;
2137 - int unit; 2164 + int unit, n;
2138 2165
2139 addr &= 7; 2166 addr &= 7;
2140 #ifdef DEBUG_IDE 2167 #ifdef DEBUG_IDE
@@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
2147 s->feature = val; 2174 s->feature = val;
2148 break; 2175 break;
2149 case 2: 2176 case 2:
  2177 + if (val == 0)
  2178 + val = 256;
2150 s->nsector = val; 2179 s->nsector = val;
2151 break; 2180 break;
2152 case 3: 2181 case 3:
@@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
2201 break; 2230 break;
2202 case WIN_READ: 2231 case WIN_READ:
2203 case WIN_READ_ONCE: 2232 case WIN_READ_ONCE:
  2233 + s->req_nb_sectors = 1;
2204 ide_sector_read(s); 2234 ide_sector_read(s);
2205 break; 2235 break;
2206 case WIN_WRITE: 2236 case WIN_WRITE:
2207 case WIN_WRITE_ONCE: 2237 case WIN_WRITE_ONCE:
2208 s->status = SEEK_STAT; 2238 s->status = SEEK_STAT;
  2239 + s->req_nb_sectors = 1;
2209 ide_transfer_start(s, 512, ide_sector_write); 2240 ide_transfer_start(s, 512, ide_sector_write);
2210 break; 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 default: 2258 default:
  2259 + abort_cmd:
2212 ide_abort_command(s); 2260 ide_abort_command(s);
2213 ide_set_irq(s); 2261 ide_set_irq(s);
2214 break; 2262 break;
@@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) @@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr)
2230 ret = s->error; 2278 ret = s->error;
2231 break; 2279 break;
2232 case 2: 2280 case 2:
2233 - ret = s->nsector; 2281 + ret = s->nsector & 0xff;
2234 break; 2282 break;
2235 case 3: 2283 case 3:
2236 ret = s->sector; 2284 ret = s->sector;
@@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, @@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info,
2400 timer_irq_count = 2; 2448 timer_irq_count = 2;
2401 timer_irq_count--; 2449 timer_irq_count--;
2402 /* just exit from the cpu to have a chance to handle timers */ 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 timer_irq_pending = 1; 2452 timer_irq_pending = 1;
2405 } 2453 }
2406 } 2454 }
@@ -2487,8 +2535,6 @@ void main_loop(void *opaque) @@ -2487,8 +2535,6 @@ void main_loop(void *opaque)
2487 pic_set_irq(0, 0); 2535 pic_set_irq(0, 0);
2488 timer_irq_pending = 0; 2536 timer_irq_pending = 0;
2489 } 2537 }
2490 -  
2491 - pic_handle_irq();  
2492 } 2538 }
2493 } 2539 }
2494 2540