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

📄 old-fdc.c

📁 用于汇编领域的,运用于OS的MAIN函数.基于硬件基础的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    #if 0    {        unsigned i;        LOG_PRINTF(("Result bytes: "));        for (i = 0; i < fdd->fdc->result_size; i++)            LOG_PRINTF(("%u(%02xh) ", fdd->fdc->result[i], fdd->fdc->result[i]));        LOG_PRINTF(("\n"));    }    #endif    return FDC_OK;}/* Returns nonzero if the motor of the specified drive is on */static inline int is_motor_on(Fdc *fdc, unsigned drive){    return fdc->dor & (1 << (drive + 4));}/* Turns the motor off after the spindown time */static void motor_off_cb(void *params){    Fdd *fdd = (Fdd *) params;    if (is_motor_on(fdd->fdc, fdd->number))    {        fdd->fdc->dor &= ~(1 << (fdd->number + 4));        fd32_outb(fdd->fdc->base_port + FDC_DOR, fdd->fdc->dor);        fdd->flags &= ~(DF_SPINUP | DF_SPINDN);    }}/* Signals that motor spinup time elapsed */static void motor_spin_cb(void *fdd){    ((Fdd *) fdd)->flags |= DF_SPINUP;}/* Turns the motor on and selects the drive */static void motor_on(Fdd *fdd){    if (fdd->flags & DF_SPINDN) fd32_event_delete(fdd->spin_down);    fdd->flags   &= ~DF_SPINDN;    if (!is_motor_on(fdd->fdc, fdd->number))    {        if (!(fdd->flags & DF_SPINUP))            /* TODO: Check for FD32_EVENT_NULL */            if (fd32_event_post(fdd->dp->spin_up, motor_spin_cb, fdd) < 0)                LOG_PRINTF(("Motor on: Out of events!\n"));        fdd->fdc->dor |= (1 << (fdd->number + 4));        /* Select drive */        fdd->fdc->dor = (fdd->fdc->dor & 0xFC) | fdd->number;        fd32_outb(fdd->fdc->base_port + FDC_DOR, fdd->fdc->dor);    }}/* Schedule motor off setting up the spindown timer */static void motor_down(Fdd *fdd){    if (is_motor_on(fdd->fdc, fdd->number))    {        if (fdd->flags & DF_SPINDN) return;        fdd->spin_down = fd32_event_post(fdd->dp->spin_down, motor_off_cb, fdd);        if (fdd->spin_down == -1) LOG_PRINTF(("[FDC] motor_down: out of events!\n"));        fdd->flags |= DF_SPINDN;    }}/* This is the IRQ6 handler. irq_signaled is global! */static void irq6(int n){    irq_signaled = 1;  /* Signal operation finished */    fd32_master_eoi(); /* Send EOI the PIC          */}/* Returns nonzero if there was a disk change */int fdc_disk_changed(Fdd *fdd){    unsigned changeline;    motor_on(fdd);    changeline = fd32_inb(fdd->fdc->base_port + FDC_DIR) & 0x80;    motor_down(fdd);    return changeline || (fdd->flags & DF_CHANGED);}/* Recalibrates a drive (seek head to track 0).                     *//* Since the RECALIBRATE command sends up to 79 pulses to the head, *//* this function issues as many RECALIBRATE as needed.              *//* The drive is supposed to be selected (motor on).                 */static void recalibrate(Fdd *fdd){    unsigned k;    LOG_PRINTF(("Recalibrate\n"));    for (k = 0; k < 13; k++)    {        sendbyte(fdd->fdc->base_port, CMD_RECAL);        sendbyte(fdd->fdc->base_port, fdd->number);        wait_fdc(fdd);        /* Send a "sense interrupt status" command */        sendbyte(fdd->fdc->base_port, CMD_SENSEI);        fdd->fdc->sr0 = getbyte(fdd->fdc->base_port);        fdd->track    = getbyte(fdd->fdc->base_port);        if (!(fdd->fdc->sr0 & 0x10)) break; /* Exit if Unit Check is not set */    }    LOG_PRINTF(("Calibration result on drive %u: SR0=%02xh, Track=%u\n",                fdd->number, fdd->fdc->sr0, fdd->track));}/* Seeks a drive to the specified track.            *//* The drive is supposed to be selected (motor on). */int fdc_seek(Fdd *fdd, unsigned track){    if (fdd->track == track) return FDC_OK; /* Already there */    if (track >= fdd->fmt->tracks) return FDC_ERROR; /* Invalid track */    sendbyte(fdd->fdc->base_port, CMD_SEEK);    sendbyte(fdd->fdc->base_port, fdd->number);    sendbyte(fdd->fdc->base_port, track);    if (wait_fdc(fdd)) return FDC_TIMEOUT; /* Timeout */    /* Send a "sense interrupt status" command */    sendbyte(fdd->fdc->base_port, CMD_SENSEI);    fdd->fdc->sr0 = getbyte(fdd->fdc->base_port);    fdd->track    = getbyte(fdd->fdc->base_port);    /* Check that seek worked */    if ((fdd->fdc->sr0 != 0x20 + fdd->number) || (fdd->track != track))    {        LOG_PRINTF(("Seek error on drive %u: SR0=%02xh, Track=%u Expected=%u\n",                    fdd->number, fdd->fdc->sr0, fdd->track, track));        return FDC_ERROR;    }    LOG_PRINTF(("Seek result on drive %u: SR0=%02xh, Track=%u\n", fdd->number,                fdd->fdc->sr0, fdd->track));    return FDC_OK;}/* Gets the position of the heads by reading the next sector identifier. *//* Fills chs with the current head position.                             *//* The drive is supposed to be selected (motor on).                      */static int readid(Fdd *fdd, Chs *chs){    int res = 0;    sendbyte(fdd->fdc->base_port, CMD_READID);    sendbyte(fdd->fdc->base_port, fdd->number);    if (wait_fdc(fdd)) res = FDC_TIMEOUT;    if (res < 0) return res;    if ((fdd->fdc->result[0] & 0xC0) != 0) return FDC_ERROR;    chs->c = fdd->fdc->result[3];    chs->h = fdd->fdc->result[4];    chs->s = fdd->fdc->result[5];    return FDC_OK;}/* Program data rate and specify drive timings using the SPECIFY command */static void specify(const Fdd *fdd){    fd32_outb(fdd->fdc->base_port + FDC_CCR, fdd->fmt->rate);    sendbyte(fdd->fdc->base_port, CMD_SPECIFY);    sendbyte(fdd->fdc->base_port, fdd->fmt->sr_hut);    sendbyte(fdd->fdc->base_port, fdd->dp->hlt << 1); /* Always DMA */}#endif/* Resets the FDC to a known state */static void reset_fdc(Fdc *fdc){    unsigned      k;    volatile int  irq_timeout = 0;    int irq_timeout_event;    fd32_outb(fdc->base_port + FDC_DOR, 0);    /* Stop the motor and disable IRQ/DMA  */    /* TODO: Add a small delay (20 us) to make older controllers more happy */    //fd32_outb(fdc->base_port + FDC_DOR, 0x1C); /* Re-enable IRQ/DMA and release reset */    fd32_outb(fdc->base_port + FDC_MSR, 0x80); /* reset */    fd32_outb(fdc->base_port + FDC_DOR, 0x0C); /* Re-enable IRQ/DMA and release reset */    fdc->dor = 0x0C;    /* Resetting triggered 4 interrupts - handle them */    //irq_timeout_event = fd32_event_post(default_drive_params[0].int_tmout, irq_timeout_cb, (void *) &irq_timeout);    /* TODO: Check for FD32_EVENT_NULL */    //WFC(!irq_signaled && !irq_timeout);    //fd32_event_delete(irq_timeout_event);	irq_signaled=0;	printk("now waiting for irq6\n");	k = inp(0x3f4); // read status of fdc	printk("status of fdc: %x\n",k);	while (!irq_signaled);	printk("pased irq6\n");    //if (irq_timeout)    //    LOG_PRINTF(("Timed out while waiting for FDC after reset\n"));    /* FDC specs say to sense interrupt status four times */    for (k = 0; k < 4; k++)    {        /* Send a "sense interrupt status" command */        sendbyte(fdc->base_port, CMD_SENSEI);        fdc->sr0            = getbyte(fdc->base_port);		printk("sr0:%x\n",fdc->sr0);        fdc->drive[k].track = getbyte(fdc->base_port);    }    irq_signaled = 0;}#ifdef MYFDC     /* Get a drive to a known state */static void reset_drive(Fdd *fdd){    if (fdd->dp->cmos_type == 0) return;    if (fdd->flags & DF_SPINDN) fd32_event_delete(fdd->spin_down);    fdd->flags   = 0;    fdd->track   = 0;    specify(fdd);    motor_on(fdd);    fdc_seek(fdd, SAFESEEK);    recalibrate(fdd);    motor_down(fdd);    fdd->flags |= DF_CHANGED; /* So that fdc_log_disk can be issued */}/* Transfer sectors between the disk and the DMA buffer. *//* The drive is supposed to be selected (motor on).      */static int fdc_xfer(Fdd *fdd, const Chs *chs, DWORD dma_addr, unsigned num_sectors, FdcTransfer op){    LOG_PRINTF(("[FDC] fdc_xfer: C=%u, H=%u, S=%u, n=%u, op=%u\n", chs->c, chs->h, chs->s, num_sectors, op));    /* Wait for motor spin quickly enough */    WFC(!(fdd->flags & DF_SPINUP));    /* Send read/write command */    if (op == FDC_READ)    {        dma_xfer(dma_addr, 512 * num_sectors, 0); /* Read */        sendbyte(fdd->fdc->base_port, CMD_READ);    }    else    {        dma_xfer(dma_addr, 512 * num_sectors, 1); /* Write */        sendbyte(fdd->fdc->base_port, CMD_WRITE);    }    sendbyte(fdd->fdc->base_port, (chs->h << 2) | fdd->number);    sendbyte(fdd->fdc->base_port, chs->c);    sendbyte(fdd->fdc->base_port, chs->h);    sendbyte(fdd->fdc->base_port, chs->s);    sendbyte(fdd->fdc->base_port, 2); /* 512 bytes per sector */    sendbyte(fdd->fdc->base_port, fdd->fmt->sec_per_trk);    sendbyte(fdd->fdc->base_port, fdd->fmt->gap3);    sendbyte(fdd->fdc->base_port, 0xFF); /* DTL (bytes to transfer) = unused */    /* Wait for completion and produce exit code */    if (wait_fdc(fdd))    {        reset_fdc(fdd->fdc);        reset_drive(fdd);        return FDC_TIMEOUT;    }    if ((fdd->fdc->result[0] & 0xC0) == 0) return FDC_OK;    return FDC_ERROR;}/* Reads sectors from the floppy, up to the end of the cylinder.         *//* If buffer is NULL, the read data is discarded (may be used to probe). */int fdc_read(Fdd *fdd, const Chs *chs, BYTE *buffer, unsigned num_sectors){    unsigned tries;    int      res = FDC_ERROR;    if (fdd->dp->cmos_type == 0) return FDC_ERROR; /* Drive not available */    /* TODO: Place a timeout for Busy check */    while (busy); /* Wait while the floppy driver is already busy: BUSY WAIT! */    busy = 1;    motor_on(fdd);    specify(fdd);    for (tries = 0; tries < 3; tries++)    {        /* Move head to right track */        if (fdc_seek(fdd, chs->c) == FDC_OK)        {            /* If changeline is active, no disk is in drive */            if (fd32_inb(fdd->fdc->base_port + FDC_DIR) & 0x80)            {                LOG_PRINTF(("[FDC] fdc_read: no disk in drive\n"));                res = FDC_NODISK;                break;            }            res = fdc_xfer(fdd, chs, dma_addr, num_sectors, FDC_READ);            if (res == FDC_OK) break;

⌨️ 快捷键说明

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