⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdc.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value){    fdctrl_t *fdctrl = opaque;    FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);    switch (reg & 0x07) {    case 0x02:	fdctrl_write_dor(fdctrl, value);	break;    case 0x03:        fdctrl_write_tape(fdctrl, value);	break;    case 0x04:        fdctrl_write_rate(fdctrl, value);	break;    case 0x05:        fdctrl_write_data(fdctrl, value);	break;    default:	break;    }}static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg){    return fdctrl_read(opaque, reg);}static void fdctrl_write_mem (void *opaque,                               target_phys_addr_t reg, uint32_t value){    fdctrl_write(opaque, reg, value);}static CPUReadMemoryFunc *fdctrl_mem_read[3] = {    fdctrl_read_mem,    fdctrl_read_mem,    fdctrl_read_mem,};static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {    fdctrl_write_mem,    fdctrl_write_mem,    fdctrl_write_mem,};fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,                        uint32_t io_base,                       BlockDriverState **fds){    fdctrl_t *fdctrl;    int io_mem;    int i;    FLOPPY_DPRINTF("init controller\n");    fdctrl = qemu_mallocz(sizeof(fdctrl_t));    if (!fdctrl)        return NULL;    fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);    if (fdctrl->fifo == NULL) {        qemu_free(fdctrl);        return NULL;    }    fdctrl->result_timer = qemu_new_timer(vm_clock,                                           fdctrl_result_timer, fdctrl);    fdctrl->version = 0x90; /* Intel 82078 controller */    fdctrl->irq_lvl = irq_lvl;    fdctrl->dma_chann = dma_chann;    fdctrl->io_base = io_base;    fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */    if (fdctrl->dma_chann != -1) {        fdctrl->dma_en = 1;        DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);    } else {        fdctrl->dma_en = 0;    }    for (i = 0; i < 2; i++) {        fd_init(&fdctrl->drives[i], fds[i]);    }    fdctrl_reset(fdctrl, 0);    fdctrl->state = FD_CTRL_ACTIVE;    if (mem_mapped) {        io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);        cpu_register_physical_memory(io_base, 0x08, io_mem);    } else {        register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);        register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);        register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);        register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);    }    for (i = 0; i < 2; i++) {        fd_revalidate(&fdctrl->drives[i]);    }    return fdctrl;}/* XXX: may change if moved to bdrv */int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num){    return fdctrl->drives[drive_num].drive;}/* Change IRQ state */static void fdctrl_reset_irq (fdctrl_t *fdctrl){    FLOPPY_DPRINTF("Reset interrupt\n");    pic_set_irq(fdctrl->irq_lvl, 0);    fdctrl->state &= ~FD_CTRL_INTR;}static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status){#ifdef TARGET_SPARC    // Sparc mutation    if (!fdctrl->dma_en) {	fdctrl->state &= ~FD_CTRL_BUSY;	fdctrl->int_status = status;	return;    }#endif    if (~(fdctrl->state & FD_CTRL_INTR)) {        pic_set_irq(fdctrl->irq_lvl, 1);        fdctrl->state |= FD_CTRL_INTR;    }    FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);    fdctrl->int_status = status;}/* Reset controller */static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq){    int i;    FLOPPY_DPRINTF("reset controller\n");    fdctrl_reset_irq(fdctrl);    /* Initialise controller */    fdctrl->cur_drv = 0;    /* FIFO state */    fdctrl->data_pos = 0;    fdctrl->data_len = 0;    fdctrl->data_state = FD_STATE_CMD;    fdctrl->data_dir = FD_DIR_WRITE;    for (i = 0; i < MAX_FD; i++)        fd_reset(&fdctrl->drives[i]);    fdctrl_reset_fifo(fdctrl);    if (do_irq)        fdctrl_raise_irq(fdctrl, 0xc0);}static inline fdrive_t *drv0 (fdctrl_t *fdctrl){    return &fdctrl->drives[fdctrl->bootsel];}static inline fdrive_t *drv1 (fdctrl_t *fdctrl){    return &fdctrl->drives[1 - fdctrl->bootsel];}static fdrive_t *get_cur_drv (fdctrl_t *fdctrl){    return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);}/* Status B register : 0x01 (read-only) */static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl){    FLOPPY_DPRINTF("status register: 0x00\n");    return 0;}/* Digital output register : 0x02 */static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl){    uint32_t retval = 0;    /* Drive motors state indicators */    if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)	retval |= 1 << 5;    if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)	retval |= 1 << 4;    /* DMA enable */    retval |= fdctrl->dma_en << 3;    /* Reset indicator */    retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0;    /* Selected drive */    retval |= fdctrl->cur_drv;    FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);    return retval;}static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value){    /* Reset mode */    if (fdctrl->state & FD_CTRL_RESET) {        if (!(value & 0x04)) {            FLOPPY_DPRINTF("Floppy controller in RESET state !\n");            return;        }    }    FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);    /* Drive motors state indicators */    if (value & 0x20)        fd_start(drv1(fdctrl));    else        fd_stop(drv1(fdctrl));    if (value & 0x10)        fd_start(drv0(fdctrl));    else        fd_stop(drv0(fdctrl));    /* DMA enable */#if 0    if (fdctrl->dma_chann != -1)        fdctrl->dma_en = 1 - ((value >> 3) & 1);#endif    /* Reset */    if (!(value & 0x04)) {        if (!(fdctrl->state & FD_CTRL_RESET)) {            FLOPPY_DPRINTF("controller enter RESET state\n");            fdctrl->state |= FD_CTRL_RESET;        }    } else {        if (fdctrl->state & FD_CTRL_RESET) {            FLOPPY_DPRINTF("controller out of RESET state\n");            fdctrl_reset(fdctrl, 1);            fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);        }    }    /* Selected drive */    fdctrl->cur_drv = value & 1;}/* Tape drive register : 0x03 */static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl){    uint32_t retval = 0;    /* Disk boot selection indicator */    retval |= fdctrl->bootsel << 2;    /* Tape indicators: never allowed */    FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);    return retval;}static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value){    /* Reset mode */    if (fdctrl->state & FD_CTRL_RESET) {        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");        return;    }    FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);    /* Disk boot selection indicator */    fdctrl->bootsel = (value >> 2) & 1;    /* Tape indicators: never allow */}/* Main status register : 0x04 (read) */static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl){    uint32_t retval = 0;    fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);    if (!(fdctrl->state & FD_CTRL_BUSY)) {        /* Data transfer allowed */        retval |= 0x80;        /* Data transfer direction indicator */        if (fdctrl->data_dir == FD_DIR_READ)            retval |= 0x40;    }    /* Should handle 0x20 for SPECIFY command */    /* Command busy indicator */    if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||        FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)        retval |= 0x10;    FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);    return retval;}/* Data select rate register : 0x04 (write) */static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value){    /* Reset mode */    if (fdctrl->state & FD_CTRL_RESET) {            FLOPPY_DPRINTF("Floppy controller in RESET state !\n");            return;        }    FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);    /* Reset: autoclear */    if (value & 0x80) {        fdctrl->state |= FD_CTRL_RESET;        fdctrl_reset(fdctrl, 1);        fdctrl->state &= ~FD_CTRL_RESET;    }    if (value & 0x40) {        fdctrl->state |= FD_CTRL_SLEEP;        fdctrl_reset(fdctrl, 1);    }//        fdctrl.precomp = (value >> 2) & 0x07;}static int fdctrl_media_changed(fdrive_t *drv){    int ret;    if (!drv->bs)         return 0;    ret = bdrv_media_changed(drv->bs);    if (ret) {        fd_revalidate(drv);    }    return ret;}/* Digital input register : 0x07 (read-only) */static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl){    uint32_t retval = 0;    if (fdctrl_media_changed(drv0(fdctrl)) ||	fdctrl_media_changed(drv1(fdctrl)))        retval |= 0x80;    if (retval != 0)        FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);    return retval;}/* FIFO state control */static void fdctrl_reset_fifo (fdctrl_t *fdctrl){    fdctrl->data_dir = FD_DIR_WRITE;    fdctrl->data_pos = 0;    FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);}/* Set FIFO status for the host to read */static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq){    fdctrl->data_dir = FD_DIR_READ;    fdctrl->data_len = fifo_len;    fdctrl->data_pos = 0;    FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);    if (do_irq)        fdctrl_raise_irq(fdctrl, 0x00);}/* Set an error: unimplemented/unknown command */static void fdctrl_unimplemented (fdctrl_t *fdctrl){#if 0    fdrive_t *cur_drv;    cur_drv = get_cur_drv(fdctrl);    fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;    fdctrl->fifo[1] = 0x00;    fdctrl->fifo[2] = 0x00;    fdctrl_set_fifo(fdctrl, 3, 1);#else    //    fdctrl_reset_fifo(fdctrl);    fdctrl->fifo[0] = 0x80;    fdctrl_set_fifo(fdctrl, 1, 0);#endif}/* Callback for transfer end (stop or abort) */static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,				  uint8_t status1, uint8_t status2){    fdrive_t *cur_drv;    cur_drv = get_cur_drv(fdctrl);    FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",                   status0, status1, status2,                   status0 | (cur_drv->head << 2) | fdctrl->cur_drv);    fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;    fdctrl->fifo[1] = status1;    fdctrl->fifo[2] = status2;    fdctrl->fifo[3] = cur_drv->track;    fdctrl->fifo[4] = cur_drv->head;    fdctrl->fifo[5] = cur_drv->sect;    fdctrl->fifo[6] = FD_SECTOR_SC;    fdctrl->data_dir = FD_DIR_READ;    if (fdctrl->state & FD_CTRL_BUSY) {        DMA_release_DREQ(fdctrl->dma_chann);        fdctrl->state &= ~FD_CTRL_BUSY;    }    fdctrl_set_fifo(fdctrl, 7, 1);}/* Prepare a data transfer (either DMA or FIFO) */static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction){    fdrive_t *cur_drv;    uint8_t kh, kt, ks;    int did_seek;    fdctrl->cur_drv = fdctrl->fifo[1] & 1;    cur_drv = get_cur_drv(fdctrl);    kt = fdctrl->fifo[2];    kh = fdctrl->fifo[3];    ks = fdctrl->fifo[4];    FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",                   fdctrl->cur_drv, kh, kt, ks,                   _fd_sector(kh, kt, ks, cur_drv->last_sect));    did_seek = 0;    switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {    case 2:        /* sect too big */        fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);        fdctrl->fifo[3] = kt;        fdctrl->fifo[4] = kh;        fdctrl->fifo[5] = ks;        return;    case 3:        /* track too big */        fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);        fdctrl->fifo[3] = kt;        fdctrl->fifo[4] = kh;        fdctrl->fifo[5] = ks;        return;    case 4:        /* No seek enabled */        fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);        fdctrl->fifo[3] = kt;        fdctrl->fifo[4] = kh;        fdctrl->fifo[5] = ks;        return;    case 1:        did_seek = 1;        break;    default:        break;    }    /* Set the FIFO state */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -