FDC fix 9/10 (Hervé Poussineau):
- Supports up to 4 floppy drives if MAX_FD is set to 4. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4289 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									46d3233ba0
								
							
						
					
					
						commit
						78ae820cfe
					
				
							
								
								
									
										85
									
								
								hw/fdc.c
								
								
								
								
							
							
						
						
									
										85
									
								
								hw/fdc.c
								
								
								
								
							| 
						 | 
				
			
			@ -417,7 +417,11 @@ enum {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
    FD_DOR_SELMASK  = 0x03,
 | 
			
		||||
#else
 | 
			
		||||
    FD_DOR_SELMASK  = 0x01,
 | 
			
		||||
#endif
 | 
			
		||||
    FD_DOR_nRESET   = 0x04,
 | 
			
		||||
    FD_DOR_DMAEN    = 0x08,
 | 
			
		||||
    FD_DOR_MOTEN0   = 0x10,
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +431,11 @@ enum {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
    FD_TDR_BOOTSEL  = 0x0c,
 | 
			
		||||
#else
 | 
			
		||||
    FD_TDR_BOOTSEL  = 0x04,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
| 
						 | 
				
			
			@ -494,7 +502,7 @@ struct fdctrl_t {
 | 
			
		|||
    /* Sun4m quirks? */
 | 
			
		||||
    int sun4m;
 | 
			
		||||
    /* Floppy drives */
 | 
			
		||||
    fdrive_t drives[2];
 | 
			
		||||
    fdrive_t drives[MAX_FD];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint32_t fdctrl_read (void *opaque, uint32_t reg)
 | 
			
		||||
| 
						 | 
				
			
			@ -602,6 +610,8 @@ static void fd_save (QEMUFile *f, fdrive_t *fd)
 | 
			
		|||
static void fdc_save (QEMUFile *f, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    fdctrl_t *s = opaque;
 | 
			
		||||
    uint8_t tmp;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    /* Controller state */
 | 
			
		||||
    qemu_put_8s(f, &s->sra);
 | 
			
		||||
| 
						 | 
				
			
			@ -627,8 +637,11 @@ static void fdc_save (QEMUFile *f, void *opaque)
 | 
			
		|||
    qemu_put_8s(f, &s->config);
 | 
			
		||||
    qemu_put_8s(f, &s->lock);
 | 
			
		||||
    qemu_put_8s(f, &s->pwrd);
 | 
			
		||||
    fd_save(f, &s->drives[0]);
 | 
			
		||||
    fd_save(f, &s->drives[1]);
 | 
			
		||||
 | 
			
		||||
    tmp = MAX_FD;
 | 
			
		||||
    qemu_put_8s(f, &tmp);
 | 
			
		||||
    for (i = 0; i < MAX_FD; i++)
 | 
			
		||||
        fd_save(f, &s->drives[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fd_load (QEMUFile *f, fdrive_t *fd)
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +656,8 @@ static int fd_load (QEMUFile *f, fdrive_t *fd)
 | 
			
		|||
static int fdc_load (QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    fdctrl_t *s = opaque;
 | 
			
		||||
    int ret;
 | 
			
		||||
    int i, ret = 0;
 | 
			
		||||
    uint8_t n;
 | 
			
		||||
 | 
			
		||||
    if (version_id != 2)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -672,10 +686,16 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id)
 | 
			
		|||
    qemu_get_8s(f, &s->config);
 | 
			
		||||
    qemu_get_8s(f, &s->lock);
 | 
			
		||||
    qemu_get_8s(f, &s->pwrd);
 | 
			
		||||
    qemu_get_8s(f, &n);
 | 
			
		||||
 | 
			
		||||
    ret = fd_load(f, &s->drives[0]);
 | 
			
		||||
    if (ret == 0)
 | 
			
		||||
        ret = fd_load(f, &s->drives[1]);
 | 
			
		||||
    if (n > MAX_FD)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < n; i++) {
 | 
			
		||||
        ret = fd_load(f, &s->drives[i]);
 | 
			
		||||
        if (ret != 0)
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -773,9 +793,35 @@ static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
 | 
			
		|||
        return &fdctrl->drives[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
static inline fdrive_t *drv2 (fdctrl_t *fdctrl)
 | 
			
		||||
{
 | 
			
		||||
    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
 | 
			
		||||
        return &fdctrl->drives[2];
 | 
			
		||||
    else
 | 
			
		||||
        return &fdctrl->drives[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline fdrive_t *drv3 (fdctrl_t *fdctrl)
 | 
			
		||||
{
 | 
			
		||||
    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
 | 
			
		||||
        return &fdctrl->drives[3];
 | 
			
		||||
    else
 | 
			
		||||
        return &fdctrl->drives[2];
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
 | 
			
		||||
{
 | 
			
		||||
    return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
 | 
			
		||||
    switch (fdctrl->cur_drv) {
 | 
			
		||||
        case 0: return drv0(fdctrl);
 | 
			
		||||
        case 1: return drv1(fdctrl);
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
        case 2: return drv2(fdctrl);
 | 
			
		||||
        case 3: return drv3(fdctrl);
 | 
			
		||||
#endif
 | 
			
		||||
        default: return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Status A register : 0x00 (read-only) */
 | 
			
		||||
| 
						 | 
				
			
			@ -923,8 +969,13 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
 | 
			
		|||
{
 | 
			
		||||
    uint32_t retval = 0;
 | 
			
		||||
 | 
			
		||||
    if (fdctrl_media_changed(drv0(fdctrl)) ||
 | 
			
		||||
        fdctrl_media_changed(drv1(fdctrl)))
 | 
			
		||||
    if (fdctrl_media_changed(drv0(fdctrl))
 | 
			
		||||
     || fdctrl_media_changed(drv1(fdctrl))
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
     || fdctrl_media_changed(drv2(fdctrl))
 | 
			
		||||
     || fdctrl_media_changed(drv3(fdctrl))
 | 
			
		||||
#endif
 | 
			
		||||
        )
 | 
			
		||||
        retval |= FD_DIR_DSKCHG;
 | 
			
		||||
    if (retval != 0)
 | 
			
		||||
        FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
 | 
			
		||||
| 
						 | 
				
			
			@ -1367,8 +1418,13 @@ static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction)
 | 
			
		|||
    /* Drives position */
 | 
			
		||||
    fdctrl->fifo[0] = drv0(fdctrl)->track;
 | 
			
		||||
    fdctrl->fifo[1] = drv1(fdctrl)->track;
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
    fdctrl->fifo[2] = drv2(fdctrl)->track;
 | 
			
		||||
    fdctrl->fifo[3] = drv3(fdctrl)->track;
 | 
			
		||||
#else
 | 
			
		||||
    fdctrl->fifo[2] = 0;
 | 
			
		||||
    fdctrl->fifo[3] = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    /* timers */
 | 
			
		||||
    fdctrl->fifo[4] = fdctrl->timer0;
 | 
			
		||||
    fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1400,6 +1456,10 @@ static void fdctrl_handle_restore (fdctrl_t *fdctrl, int direction)
 | 
			
		|||
    /* Drives position */
 | 
			
		||||
    drv0(fdctrl)->track = fdctrl->fifo[3];
 | 
			
		||||
    drv1(fdctrl)->track = fdctrl->fifo[4];
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
    drv2(fdctrl)->track = fdctrl->fifo[5];
 | 
			
		||||
    drv3(fdctrl)->track = fdctrl->fifo[6];
 | 
			
		||||
#endif
 | 
			
		||||
    /* timers */
 | 
			
		||||
    fdctrl->timer0 = fdctrl->fifo[7];
 | 
			
		||||
    fdctrl->timer1 = fdctrl->fifo[8];
 | 
			
		||||
| 
						 | 
				
			
			@ -1421,8 +1481,13 @@ static void fdctrl_handle_save (fdctrl_t *fdctrl, int direction)
 | 
			
		|||
    /* Drives position */
 | 
			
		||||
    fdctrl->fifo[2] = drv0(fdctrl)->track;
 | 
			
		||||
    fdctrl->fifo[3] = drv1(fdctrl)->track;
 | 
			
		||||
#if MAX_FD == 4
 | 
			
		||||
    fdctrl->fifo[4] = drv2(fdctrl)->track;
 | 
			
		||||
    fdctrl->fifo[5] = drv3(fdctrl)->track;
 | 
			
		||||
#else
 | 
			
		||||
    fdctrl->fifo[4] = 0;
 | 
			
		||||
    fdctrl->fifo[5] = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    /* timers */
 | 
			
		||||
    fdctrl->fifo[6] = fdctrl->timer0;
 | 
			
		||||
    fdctrl->fifo[7] = fdctrl->timer1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue