FDC fix 4/10 (Hervé Poussineau):
- Handles correctly FD_MSR_NONDMA/FD_DOR_NONDMA flags, and uses them when possible. Fixes a problem with SPECIFY command. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4284 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									8c6a4d7742
								
							
						
					
					
						commit
						368df94d16
					
				
							
								
								
									
										33
									
								
								hw/fdc.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								hw/fdc.c
									
									
									
									
									
								
							@ -494,6 +494,8 @@ struct fdctrl_t {
 | 
				
			|||||||
    QEMUTimer *result_timer;
 | 
					    QEMUTimer *result_timer;
 | 
				
			||||||
    uint8_t sra;
 | 
					    uint8_t sra;
 | 
				
			||||||
    uint8_t srb;
 | 
					    uint8_t srb;
 | 
				
			||||||
 | 
					    uint8_t dor;
 | 
				
			||||||
 | 
					    uint8_t msr;
 | 
				
			||||||
    uint8_t state;
 | 
					    uint8_t state;
 | 
				
			||||||
    uint8_t dma_en;
 | 
					    uint8_t dma_en;
 | 
				
			||||||
    uint8_t cur_drv;
 | 
					    uint8_t cur_drv;
 | 
				
			||||||
@ -771,6 +773,9 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
 | 
				
			|||||||
    if (!fdctrl->drives[1].bs)
 | 
					    if (!fdctrl->drives[1].bs)
 | 
				
			||||||
        fdctrl->sra |= FD_SRA_nDRV2;
 | 
					        fdctrl->sra |= FD_SRA_nDRV2;
 | 
				
			||||||
    fdctrl->cur_drv = 0;
 | 
					    fdctrl->cur_drv = 0;
 | 
				
			||||||
 | 
					    fdctrl->dor = 0;
 | 
				
			||||||
 | 
					    fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
 | 
				
			||||||
 | 
					    fdctrl->msr = 0;
 | 
				
			||||||
    /* FIFO state */
 | 
					    /* FIFO state */
 | 
				
			||||||
    fdctrl->data_pos = 0;
 | 
					    fdctrl->data_pos = 0;
 | 
				
			||||||
    fdctrl->data_len = 0;
 | 
					    fdctrl->data_len = 0;
 | 
				
			||||||
@ -829,7 +834,7 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
 | 
				
			|||||||
    if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
 | 
					    if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
 | 
				
			||||||
        retval |= FD_DOR_MOTEN1;
 | 
					        retval |= FD_DOR_MOTEN1;
 | 
				
			||||||
    /* DMA enable */
 | 
					    /* DMA enable */
 | 
				
			||||||
    if (fdctrl->dma_en)
 | 
					    if (fdctrl->dor & FD_DOR_DMAEN)
 | 
				
			||||||
        retval |= FD_DOR_DMAEN;
 | 
					        retval |= FD_DOR_DMAEN;
 | 
				
			||||||
    /* Reset indicator */
 | 
					    /* Reset indicator */
 | 
				
			||||||
    if (!(fdctrl->state & FD_CTRL_RESET))
 | 
					    if (!(fdctrl->state & FD_CTRL_RESET))
 | 
				
			||||||
@ -897,6 +902,8 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Selected drive */
 | 
					    /* Selected drive */
 | 
				
			||||||
    fdctrl->cur_drv = value & FD_DOR_SELMASK;
 | 
					    fdctrl->cur_drv = value & FD_DOR_SELMASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fdctrl->dor = value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Tape drive register : 0x03 */
 | 
					/* Tape drive register : 0x03 */
 | 
				
			||||||
@ -1085,10 +1092,11 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
 | 
				
			|||||||
    fdctrl->fifo[5] = cur_drv->sect;
 | 
					    fdctrl->fifo[5] = cur_drv->sect;
 | 
				
			||||||
    fdctrl->fifo[6] = FD_SECTOR_SC;
 | 
					    fdctrl->fifo[6] = FD_SECTOR_SC;
 | 
				
			||||||
    fdctrl->data_dir = FD_DIR_READ;
 | 
					    fdctrl->data_dir = FD_DIR_READ;
 | 
				
			||||||
    if (fdctrl->state & FD_CTRL_BUSY) {
 | 
					    if (!(fdctrl->msr & FD_MSR_NONDMA)) {
 | 
				
			||||||
        DMA_release_DREQ(fdctrl->dma_chann);
 | 
					        DMA_release_DREQ(fdctrl->dma_chann);
 | 
				
			||||||
        fdctrl->state &= ~FD_CTRL_BUSY;
 | 
					        fdctrl->state &= ~FD_CTRL_BUSY;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    fdctrl->msr &= ~FD_MSR_NONDMA;
 | 
				
			||||||
    fdctrl_set_fifo(fdctrl, 7, 1);
 | 
					    fdctrl_set_fifo(fdctrl, 7, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1159,7 +1167,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
 | 
				
			|||||||
        fdctrl->data_len *= tmp;
 | 
					        fdctrl->data_len *= tmp;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fdctrl->eot = fdctrl->fifo[6];
 | 
					    fdctrl->eot = fdctrl->fifo[6];
 | 
				
			||||||
    if (fdctrl->dma_en) {
 | 
					    if (fdctrl->dor & FD_DOR_DMAEN) {
 | 
				
			||||||
        int dma_mode;
 | 
					        int dma_mode;
 | 
				
			||||||
        /* DMA transfer are enabled. Check if DMA channel is well programmed */
 | 
					        /* DMA transfer are enabled. Check if DMA channel is well programmed */
 | 
				
			||||||
        dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
 | 
					        dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
 | 
				
			||||||
@ -1185,6 +1193,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    FLOPPY_DPRINTF("start non-DMA transfer\n");
 | 
					    FLOPPY_DPRINTF("start non-DMA transfer\n");
 | 
				
			||||||
 | 
					    fdctrl->msr |= FD_MSR_NONDMA;
 | 
				
			||||||
    /* IO based transfer: calculate len */
 | 
					    /* IO based transfer: calculate len */
 | 
				
			||||||
    fdctrl_raise_irq(fdctrl, 0x00);
 | 
					    fdctrl_raise_irq(fdctrl, 0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1325,7 +1334,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pos = fdctrl->data_pos;
 | 
					    pos = fdctrl->data_pos;
 | 
				
			||||||
    if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
 | 
					    if (fdctrl->msr & FD_MSR_NONDMA) {
 | 
				
			||||||
        pos %= FD_SECTOR_LEN;
 | 
					        pos %= FD_SECTOR_LEN;
 | 
				
			||||||
        if (pos == 0) {
 | 
					        if (pos == 0) {
 | 
				
			||||||
            if (fdctrl->data_pos != 0)
 | 
					            if (fdctrl->data_pos != 0)
 | 
				
			||||||
@ -1343,7 +1352,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
 | 
				
			|||||||
        /* Switch from transfer mode to status mode
 | 
					        /* Switch from transfer mode to status mode
 | 
				
			||||||
         * then from status mode to command mode
 | 
					         * then from status mode to command mode
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
 | 
					        if (fdctrl->msr & FD_MSR_NONDMA) {
 | 
				
			||||||
            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
 | 
					            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            fdctrl_reset_fifo(fdctrl);
 | 
					            fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
@ -1438,7 +1447,7 @@ static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction)
 | 
				
			|||||||
    fdctrl->fifo[3] = 0;
 | 
					    fdctrl->fifo[3] = 0;
 | 
				
			||||||
    /* timers */
 | 
					    /* timers */
 | 
				
			||||||
    fdctrl->fifo[4] = fdctrl->timer0;
 | 
					    fdctrl->fifo[4] = fdctrl->timer0;
 | 
				
			||||||
    fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
 | 
					    fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
 | 
				
			||||||
    fdctrl->fifo[6] = cur_drv->last_sect;
 | 
					    fdctrl->fifo[6] = cur_drv->last_sect;
 | 
				
			||||||
    fdctrl->fifo[7] = (fdctrl->lock << 7) |
 | 
					    fdctrl->fifo[7] = (fdctrl->lock << 7) |
 | 
				
			||||||
        (cur_drv->perpendicular << 2);
 | 
					        (cur_drv->perpendicular << 2);
 | 
				
			||||||
@ -1547,7 +1556,10 @@ static void fdctrl_handle_specify (fdctrl_t *fdctrl, int direction)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
 | 
					    fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
 | 
				
			||||||
    fdctrl->timer1 = fdctrl->fifo[2] >> 1;
 | 
					    fdctrl->timer1 = fdctrl->fifo[2] >> 1;
 | 
				
			||||||
    fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
 | 
					    if (fdctrl->fifo[2] & 1)
 | 
				
			||||||
 | 
					        fdctrl->dor &= ~FD_DOR_DMAEN;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        fdctrl->dor |= FD_DOR_DMAEN;
 | 
				
			||||||
    /* No result back */
 | 
					    /* No result back */
 | 
				
			||||||
    fdctrl_reset_fifo(fdctrl);
 | 
					    fdctrl_reset_fifo(fdctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1770,7 +1782,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Is it write command time ? */
 | 
					    /* Is it write command time ? */
 | 
				
			||||||
    if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
 | 
					    if (fdctrl->msr & FD_MSR_NONDMA) {
 | 
				
			||||||
        /* FIFO data write */
 | 
					        /* FIFO data write */
 | 
				
			||||||
        fdctrl->fifo[fdctrl->data_pos++] = value;
 | 
					        fdctrl->fifo[fdctrl->data_pos++] = value;
 | 
				
			||||||
        if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
 | 
					        if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
 | 
				
			||||||
@ -1862,10 +1874,7 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann,
 | 
				
			|||||||
    fdctrl->io_base = io_base;
 | 
					    fdctrl->io_base = io_base;
 | 
				
			||||||
    fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
 | 
					    fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
 | 
				
			||||||
    if (fdctrl->dma_chann != -1) {
 | 
					    if (fdctrl->dma_chann != -1) {
 | 
				
			||||||
        fdctrl->dma_en = 1;
 | 
					 | 
				
			||||||
        DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
 | 
					        DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        fdctrl->dma_en = 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    for (i = 0; i < MAX_FD; i++) {
 | 
					    for (i = 0; i < MAX_FD; i++) {
 | 
				
			||||||
        fd_init(&fdctrl->drives[i], fds[i]);
 | 
					        fd_init(&fdctrl->drives[i], fds[i]);
 | 
				
			||||||
@ -1915,7 +1924,7 @@ fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
 | 
				
			|||||||
    fdctrl_t *fdctrl;
 | 
					    fdctrl_t *fdctrl;
 | 
				
			||||||
    int io_mem;
 | 
					    int io_mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fdctrl = fdctrl_init_common(irq, 0, io_base, fds);
 | 
					    fdctrl = fdctrl_init_common(irq, -1, io_base, fds);
 | 
				
			||||||
    fdctrl->sun4m = 1;
 | 
					    fdctrl->sun4m = 1;
 | 
				
			||||||
    io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict,
 | 
					    io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict,
 | 
				
			||||||
                                    fdctrl_mem_write_strict,
 | 
					                                    fdctrl_mem_write_strict,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user