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
This commit is contained in:
		
							parent
							
								
									8c9b861e74
								
							
						
					
					
						commit
						c9159e5321
					
				
							
								
								
									
										108
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								vl.c
									
									
									
									
									
								
							@ -54,6 +54,7 @@
 | 
				
			|||||||
#define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup"
 | 
					#define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define DEBUG_UNUSED_IOPORT
 | 
					//#define DEBUG_UNUSED_IOPORT
 | 
				
			||||||
 | 
					//#define DEBUG_IRQ_LATENCY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PHYS_RAM_BASE 0xa8000000
 | 
					#define PHYS_RAM_BASE 0xa8000000
 | 
				
			||||||
#define KERNEL_LOAD_ADDR   0x00100000
 | 
					#define KERNEL_LOAD_ADDR   0x00100000
 | 
				
			||||||
@ -598,14 +599,9 @@ static int pic_get_irq(PicState *s)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pic_set_irq(int irq, int level)
 | 
					/* raise irq to CPU if necessary. must be called every time the active
 | 
				
			||||||
{
 | 
					   irq may change */
 | 
				
			||||||
    pic_set_irq1(&pics[irq >> 3], irq & 7, level);
 | 
					static void pic_update_irq(void)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* can be called at any time outside cpu_exec() to raise irqs if
 | 
					 | 
				
			||||||
   necessary */
 | 
					 | 
				
			||||||
void pic_handle_irq(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int irq2, irq;
 | 
					    int irq2, irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -626,16 +622,36 @@ void pic_handle_irq(void)
 | 
				
			|||||||
            /* from master pic */
 | 
					            /* from master pic */
 | 
				
			||||||
            pic_irq_requested = irq;
 | 
					            pic_irq_requested = irq;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        global_env->hard_interrupt_request = 1;
 | 
					        cpu_x86_interrupt(global_env, CPU_INTERRUPT_HARD);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG_IRQ_LATENCY
 | 
				
			||||||
 | 
					int64_t irq_time[16];
 | 
				
			||||||
 | 
					int64_t cpu_get_ticks(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pic_set_irq(int irq, int level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef DEBUG_IRQ_LATENCY
 | 
				
			||||||
 | 
					    if (level) {
 | 
				
			||||||
 | 
					        irq_time[irq] = cpu_get_ticks();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    pic_set_irq1(&pics[irq >> 3], irq & 7, level);
 | 
				
			||||||
 | 
					    pic_update_irq();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cpu_x86_get_pic_interrupt(CPUX86State *env)
 | 
					int cpu_x86_get_pic_interrupt(CPUX86State *env)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int irq, irq2, intno;
 | 
					    int irq, irq2, intno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* signal the pic that the irq was acked by the CPU */
 | 
					    /* signal the pic that the irq was acked by the CPU */
 | 
				
			||||||
    irq = pic_irq_requested;
 | 
					    irq = pic_irq_requested;
 | 
				
			||||||
 | 
					#ifdef DEBUG_IRQ_LATENCY
 | 
				
			||||||
 | 
					    printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (irq >= 8) {
 | 
					    if (irq >= 8) {
 | 
				
			||||||
        irq2 = irq & 7;
 | 
					        irq2 = irq & 7;
 | 
				
			||||||
        pics[1].isr |= (1 << irq2);
 | 
					        pics[1].isr |= (1 << irq2);
 | 
				
			||||||
@ -706,6 +722,7 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
				
			|||||||
        case 0:
 | 
					        case 0:
 | 
				
			||||||
            /* normal mode */
 | 
					            /* normal mode */
 | 
				
			||||||
            s->imr = val;
 | 
					            s->imr = val;
 | 
				
			||||||
 | 
					            pic_update_irq();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 1:
 | 
					        case 1:
 | 
				
			||||||
            s->irq_base = val & 0xf8;
 | 
					            s->irq_base = val & 0xf8;
 | 
				
			||||||
@ -1570,8 +1587,6 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
				
			|||||||
                s->rcnt == 0) {
 | 
					                s->rcnt == 0) {
 | 
				
			||||||
                s->isr |= ENISR_RDC;
 | 
					                s->isr |= ENISR_RDC;
 | 
				
			||||||
                ne2000_update_irq(s);
 | 
					                ne2000_update_irq(s);
 | 
				
			||||||
                /* XXX: find a better solution for irqs */
 | 
					 | 
				
			||||||
                cpu_x86_interrupt(global_env);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (val & E8390_TRANS) {
 | 
					            if (val & E8390_TRANS) {
 | 
				
			||||||
                net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
 | 
					                net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
 | 
				
			||||||
@ -1931,7 +1946,8 @@ void ne2000_init(void)
 | 
				
			|||||||
#define WIN_SET_MAX			0xF9
 | 
					#define WIN_SET_MAX			0xF9
 | 
				
			||||||
#define DISABLE_SEAGATE			0xFB
 | 
					#define DISABLE_SEAGATE			0xFB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_MULT_SECTORS 16
 | 
					/* set to 1 set disable mult support */
 | 
				
			||||||
 | 
					#define MAX_MULT_SECTORS 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_DISKS 2
 | 
					#define MAX_DISKS 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1948,7 +1964,7 @@ typedef struct IDEState {
 | 
				
			|||||||
    /* ide regs */
 | 
					    /* ide regs */
 | 
				
			||||||
    uint8_t feature;
 | 
					    uint8_t feature;
 | 
				
			||||||
    uint8_t error;
 | 
					    uint8_t error;
 | 
				
			||||||
    uint8_t nsector;
 | 
					    uint16_t nsector; /* 0 is 256 to ease computations */
 | 
				
			||||||
    uint8_t sector;
 | 
					    uint8_t sector;
 | 
				
			||||||
    uint8_t lcyl;
 | 
					    uint8_t lcyl;
 | 
				
			||||||
    uint8_t hcyl;
 | 
					    uint8_t hcyl;
 | 
				
			||||||
@ -1959,6 +1975,7 @@ typedef struct IDEState {
 | 
				
			|||||||
    /* depends on bit 4 in select, only meaningful for drive 0 */
 | 
					    /* depends on bit 4 in select, only meaningful for drive 0 */
 | 
				
			||||||
    struct IDEState *cur_drive; 
 | 
					    struct IDEState *cur_drive; 
 | 
				
			||||||
    BlockDriverState *bs;
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
 | 
					    int req_nb_sectors; /* number of sectors per interrupt */
 | 
				
			||||||
    EndTransferFunc *end_transfer_func;
 | 
					    EndTransferFunc *end_transfer_func;
 | 
				
			||||||
    uint8_t *data_ptr;
 | 
					    uint8_t *data_ptr;
 | 
				
			||||||
    uint8_t *data_end;
 | 
					    uint8_t *data_end;
 | 
				
			||||||
@ -1998,7 +2015,9 @@ static void ide_identify(IDEState *s)
 | 
				
			|||||||
    stw(p + 21, 512); /* cache size in sectors */
 | 
					    stw(p + 21, 512); /* cache size in sectors */
 | 
				
			||||||
    stw(p + 22, 4); /* ecc bytes */
 | 
					    stw(p + 22, 4); /* ecc bytes */
 | 
				
			||||||
    padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40);
 | 
					    padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40);
 | 
				
			||||||
    //    stw(p + 47, MAX_MULT_SECTORS);
 | 
					#if MAX_MULT_SECTORS > 1    
 | 
				
			||||||
 | 
					    stw(p + 47, MAX_MULT_SECTORS);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    stw(p + 48, 1); /* dword I/O */
 | 
					    stw(p + 48, 1); /* dword I/O */
 | 
				
			||||||
    stw(p + 49, 1 << 9); /* LBA supported, no DMA */
 | 
					    stw(p + 49, 1 << 9); /* LBA supported, no DMA */
 | 
				
			||||||
    stw(p + 51, 0x200); /* PIO transfer cycle */
 | 
					    stw(p + 51, 0x200); /* PIO transfer cycle */
 | 
				
			||||||
@ -2032,7 +2051,6 @@ static inline void ide_set_irq(IDEState *s)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) {
 | 
					    if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) {
 | 
				
			||||||
        pic_set_irq(s->irq, 1);
 | 
					        pic_set_irq(s->irq, 1);
 | 
				
			||||||
        cpu_x86_interrupt(global_env);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2090,51 +2108,60 @@ static void ide_set_sector(IDEState *s, int64_t sector_num)
 | 
				
			|||||||
static void ide_sector_read(IDEState *s)
 | 
					static void ide_sector_read(IDEState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int64_t sector_num;
 | 
					    int64_t sector_num;
 | 
				
			||||||
    int ret;
 | 
					    int ret, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->status = READY_STAT | SEEK_STAT;
 | 
					    s->status = READY_STAT | SEEK_STAT;
 | 
				
			||||||
    sector_num = ide_get_sector(s);
 | 
					    sector_num = ide_get_sector(s);
 | 
				
			||||||
    s->nsector--;
 | 
					    n = s->nsector;
 | 
				
			||||||
    if (s->nsector == 0xff) {
 | 
					    if (n == 0) {
 | 
				
			||||||
        /* no more sector to read from disk */
 | 
					        /* no more sector to read from disk */
 | 
				
			||||||
        ide_transfer_stop(s);
 | 
					        ide_transfer_stop(s);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
#if defined(DEBUG_IDE)
 | 
					#if defined(DEBUG_IDE)
 | 
				
			||||||
        printf("read sector=%Ld\n", sector_num);
 | 
					        printf("read sector=%Ld\n", sector_num);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        ret = bdrv_read(s->bs, sector_num, s->io_buffer, 1);
 | 
					        if (n > s->req_nb_sectors)
 | 
				
			||||||
        ide_transfer_start(s, 512, ide_sector_read);
 | 
					            n = s->req_nb_sectors;
 | 
				
			||||||
 | 
					        ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
 | 
				
			||||||
 | 
					        ide_transfer_start(s, 512 * n, ide_sector_read);
 | 
				
			||||||
        ide_set_irq(s);
 | 
					        ide_set_irq(s);
 | 
				
			||||||
 | 
					        ide_set_sector(s, sector_num + n);
 | 
				
			||||||
 | 
					        s->nsector -= n;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ide_set_sector(s, sector_num + 1);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ide_sector_write(IDEState *s)
 | 
					static void ide_sector_write(IDEState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int64_t sector_num;
 | 
					    int64_t sector_num;
 | 
				
			||||||
    int ret;
 | 
					    int ret, n, n1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->status = READY_STAT | SEEK_STAT;
 | 
					    s->status = READY_STAT | SEEK_STAT;
 | 
				
			||||||
    sector_num = ide_get_sector(s);
 | 
					    sector_num = ide_get_sector(s);
 | 
				
			||||||
#if defined(DEBUG_IDE)
 | 
					#if defined(DEBUG_IDE)
 | 
				
			||||||
    printf("write sector=%Ld\n", sector_num);
 | 
					    printf("write sector=%Ld\n", sector_num);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    ret = bdrv_write(s->bs, sector_num, s->io_buffer, 1);
 | 
					    n = s->nsector;
 | 
				
			||||||
    s->nsector--;
 | 
					    if (n > s->req_nb_sectors)
 | 
				
			||||||
 | 
					        n = s->req_nb_sectors;
 | 
				
			||||||
 | 
					    ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
 | 
				
			||||||
 | 
					    s->nsector -= n;
 | 
				
			||||||
    if (s->nsector == 0) {
 | 
					    if (s->nsector == 0) {
 | 
				
			||||||
        /* no more sector to write */
 | 
					        /* no more sector to write */
 | 
				
			||||||
        ide_transfer_stop(s);
 | 
					        ide_transfer_stop(s);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        ide_transfer_start(s, 512, ide_sector_write);
 | 
					        n1 = s->nsector;
 | 
				
			||||||
 | 
					        if (n1 > s->req_nb_sectors)
 | 
				
			||||||
 | 
					            n1 = s->req_nb_sectors;
 | 
				
			||||||
 | 
					        ide_transfer_start(s, 512 * n1, ide_sector_write);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ide_set_sector(s, sector_num + 1);
 | 
					    ide_set_sector(s, sector_num + n);
 | 
				
			||||||
    ide_set_irq(s);
 | 
					    ide_set_irq(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
					void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IDEState *s = ide_state[0].cur_drive;
 | 
					    IDEState *s = ide_state[0].cur_drive;
 | 
				
			||||||
    int unit;
 | 
					    int unit, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    addr &= 7;
 | 
					    addr &= 7;
 | 
				
			||||||
#ifdef DEBUG_IDE
 | 
					#ifdef DEBUG_IDE
 | 
				
			||||||
@ -2147,6 +2174,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
				
			|||||||
        s->feature = val;
 | 
					        s->feature = val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
 | 
					        if (val == 0)
 | 
				
			||||||
 | 
					            val = 256;
 | 
				
			||||||
        s->nsector = val;
 | 
					        s->nsector = val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
@ -2201,14 +2230,33 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case WIN_READ:
 | 
					        case WIN_READ:
 | 
				
			||||||
        case WIN_READ_ONCE:
 | 
					        case WIN_READ_ONCE:
 | 
				
			||||||
 | 
					            s->req_nb_sectors = 1;
 | 
				
			||||||
            ide_sector_read(s);
 | 
					            ide_sector_read(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case WIN_WRITE:
 | 
					        case WIN_WRITE:
 | 
				
			||||||
        case WIN_WRITE_ONCE:
 | 
					        case WIN_WRITE_ONCE:
 | 
				
			||||||
            s->status = SEEK_STAT;
 | 
					            s->status = SEEK_STAT;
 | 
				
			||||||
 | 
					            s->req_nb_sectors = 1;
 | 
				
			||||||
            ide_transfer_start(s, 512, ide_sector_write);
 | 
					            ide_transfer_start(s, 512, ide_sector_write);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case WIN_MULTREAD:
 | 
				
			||||||
 | 
					            if (!s->mult_sectors)
 | 
				
			||||||
 | 
					                goto abort_cmd;
 | 
				
			||||||
 | 
					            s->req_nb_sectors = s->mult_sectors;
 | 
				
			||||||
 | 
					            ide_sector_read(s);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case WIN_MULTWRITE:
 | 
				
			||||||
 | 
					            if (!s->mult_sectors)
 | 
				
			||||||
 | 
					                goto abort_cmd;
 | 
				
			||||||
 | 
					            s->status = SEEK_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, 512 * n, ide_sector_write);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
 | 
					        abort_cmd:
 | 
				
			||||||
            ide_abort_command(s);
 | 
					            ide_abort_command(s);
 | 
				
			||||||
            ide_set_irq(s);
 | 
					            ide_set_irq(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -2230,7 +2278,7 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr)
 | 
				
			|||||||
        ret = s->error;
 | 
					        ret = s->error;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
        ret = s->nsector;
 | 
					        ret = s->nsector & 0xff;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
        ret = s->sector;
 | 
					        ret = s->sector;
 | 
				
			||||||
@ -2400,7 +2448,7 @@ static void host_alarm_handler(int host_signum, siginfo_t *info,
 | 
				
			|||||||
            timer_irq_count = 2;
 | 
					            timer_irq_count = 2;
 | 
				
			||||||
        timer_irq_count--;
 | 
					        timer_irq_count--;
 | 
				
			||||||
        /* just exit from the cpu to have a chance to handle timers */
 | 
					        /* just exit from the cpu to have a chance to handle timers */
 | 
				
			||||||
        cpu_x86_interrupt(global_env);
 | 
					        cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT);
 | 
				
			||||||
        timer_irq_pending = 1;
 | 
					        timer_irq_pending = 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -2487,8 +2535,6 @@ void main_loop(void *opaque)
 | 
				
			|||||||
            pic_set_irq(0, 0);
 | 
					            pic_set_irq(0, 0);
 | 
				
			||||||
            timer_irq_pending = 0;
 | 
					            timer_irq_pending = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        pic_handle_irq();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user