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

📄 ide_drv.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Not Done. We have to send more data */
        /* Note: blocks size is 1 for write sectors */
        if (pc->sectors_remaining >= (word) pc->block_size)
            utemp = (word) pc->block_size;
        else
            utemp = pc->sectors_remaining;
        ide_out_words(pc, (word) (utemp << 8));/* 256 times xfer size */
        pc->sectors_remaining -= utemp;
        return;     /* Return from the int with the command still valid. */
    }
    
    /* all other interrupts are not as performance sensitive so load the
        register file up */
    ide_read_register_file(pc);

    if(pc->vo_command == IDE_CMD_DIAG)
    {
#if (ZERO)
        /* Diagnostics return 01 on no error */
        if (pc->vi_error != 0x01)
                pc->error_code = IDE_ERC_DIAG;
        goto io_done_label;
#else
        /* Diagnostics return 01 on no error */
/*      if (pc->vi_error != 0x01)*/                                                     /* this fails if either drive fails*/
/*              pc->error_code = IDE_ERC_DIAG;*/
/* the following tests to see if the relavent drive failed */
        if(pc->vo_drive_head&0x10)
            {
            if ((pc->vi_error == 0x00)||(pc->vi_error == 0x81))                         /* drive 1 failure */
                pc->error_code = IDE_ERC_DIAG;
            }
        else
            if ((pc->vi_error != 0x01)&&(pc->vi_error != 0x81))                         /* drive 0 failure */
                pc->error_code = IDE_ERC_DIAG;
        goto io_done_label;
#endif
    }
    else
    {
        if ((pc->vo_command == IDE_CMD_IDENT) || (pc->vo_command == ATAPI_CMD_IDENT))   /* :::::- Identify drive completed */
        {
            if (!(pc->vi_status & IDE_STB_DRQ))     /* Drive should be requesting */
            {
                /* Serious problem. Bus state incorrect */
                pc->error_code = IDE_ERC_BUS;
                goto io_done_label;
            }
            ide_in_words(pc, 256); /* 256 times xfr size 1 block */
            ide_read_register_file(pc);
            if (pc->vi_status & IDE_STB_ERROR)
                pc->error_code = IDE_ERC_STATUS;
        }       
    }

io_done_label:
 /* If it gets here the current command is complete. If pc->error_code is
    zero we had success */
    pc->command_complete = TRUE;
    return;
}


/* void ide_clear_voregs()
*
*  This routine clears the virtual output register file to a known state.
*  All commands first call this routine. This is done because they all
*  eventually send the vo_regs to the ide drive. We want them to be in a
*  known state when sent.
*
*  Note: We don't clear the digital output register. This is used to enable
*       interrupts on the drive. We don't want to effect this each time.
*
*  This routine is portable
*/

static void ide_clear_voregs(PIDE_CONTROLLER pc) /* __fn__ */
{
    pc->vo_write_precomp =  
    pc->vo_sector_count  =  
    pc->vo_sector_number =  
    pc->vo_cyl_low      =  
    pc->vo_cyl_high     =  
    pc->vo_drive_head   =  
    pc->vo_feature      =  
    pc->vo_command      =  0;
}

/* ide_wait_not_busy - Wait for the busy bit to deassert
*
*
*  This routine polls the busy bit in the alternate status register
*  until is clears. It uses a watchdog timer to guard against
*  latchup
*
*   Returns:
*       TRUE if the bit cleared
*       FALSE  if it timed out.
*
*/

BOOLEAN ide_wait_not_busy(PIDE_CONTROLLER pc,int ticks) /* __fn__ */
{
byte alt_status;
dword  l;
dword  lticks;

    alt_status = ide_rd_alt_status(pc);
    if (!(alt_status & IDE_STB_BUSY))
        return(TRUE);

    /* Set a watchdog to time out in ticks seconds */
    lticks = l = ks_get_ticks();
    lticks += ticks;
    if (l > lticks)
        lticks = ticks;

    while(alt_status & IDE_STB_BUSY)
    {
        if (ks_get_ticks() > lticks)
            break;                      /* timer expired. hung, */
        alt_status = ide_rd_alt_status(pc);
    }
    if(alt_status & IDE_STB_BUSY)
    {
        pc->error_code      = IDE_ERC_TIMEOUT;
        return(FALSE);
    }
    else
        return(TRUE);
}


/* ide_wait_ready - Wait for the ready bit to assert
*
*
*  This routine polls the ready bit in the alternate status register
*  until is asserts. It uses a watchdog timer to guard against
*  latchup
*
*   Returns:
*       TRUE if the bit set
*       FALSE  if it timed out.
*
*/

BOOLEAN ide_wait_ready(PIDE_CONTROLLER pc,int ticks) /* __fn__ */
{
byte alt_status;
dword  l;
dword  lticks;

    alt_status = ide_rd_alt_status(pc);
    if (alt_status & IDE_STB_READY)
        return(TRUE);

    /* Set a watchdog to time out in ticks seconds   */
    lticks = l = ks_get_ticks();
    lticks += ticks;
    if (l > lticks)
        lticks = ticks;

    while(!(alt_status & IDE_STB_READY))
    {
        if (ks_get_ticks() > lticks)
            break;                      /* timer expired. hung, */
        alt_status = ide_rd_alt_status(pc);
    }
    if(!(alt_status & IDE_STB_READY))
    {
        pc->error_code      = IDE_ERC_TIMEOUT;
        return(FALSE);
    }
    else
        return(TRUE);
}




/* ide_wait_drq - Wait for the data request bit to assert
*
*
*  This routine polls the drq bit in the alternate status register
*  until it asserts. It uses a watchdog timer to guard against
*  latchup.
*
*   If the bit never sets ERC_BUS is set
*
*   Returns:
*       TRUE if the bit set
*       FALSE  if it timed out.
*
*/

BOOLEAN ide_wait_drq(PIDE_CONTROLLER pc, int ticks) /* __fn__ */
{
byte alt_status;
dword lticks, l;
int i;


    /* At first stay in a tight loop without a watch dog. This
        is because DRQ should come up fast. We don't want the overhead of
        setting a watchdog */
    for (i =0; i < 10000; i++) 
    {
        alt_status = ide_rd_alt_status(pc);
        if (alt_status & IDE_STB_DRQ)
            return(TRUE);
    }

    /* Set a watchdog to time out in ticks seconds */
        /* Set a watchdog to time out in ticks seconds */
    lticks = l = ks_get_ticks();
    lticks += ticks;
    if (l > lticks)
        lticks = ticks;

    while(!(alt_status & IDE_STB_DRQ))
    {
        if (ks_get_ticks() > lticks)
            break;                      /* timer expired. hung, */
        alt_status = ide_rd_alt_status(pc);
    }

    if(!(alt_status & IDE_STB_DRQ))
    {
        pc->error_code      = IDE_ERC_BUS;
        return(FALSE);
    }
    else
        return(TRUE);
}

/* void ide_read_register_file(pc)
*
*  This routine reads the register file into the vi_xxxx fields
*  in ide control structure. It is called after a drive interrupt
*  has occured and register file data is needed.
*
*/

static void ide_read_register_file(PIDE_CONTROLLER pc) /* __fn__ */
{
    pc->vi_error        = ide_rd_error(pc);
    pc->vi_sector_count  = ide_rd_sector_count(pc);
    pc->vi_sector_number = ide_rd_sector_number(pc);
    pc->vi_cyl_low      = ide_rd_cyl_low(pc);
    pc->vi_cyl_high     = ide_rd_cyl_high(pc);
    pc->vi_drive_head   = ide_rd_drive_head(pc);
    pc->vi_status       = ide_rd_status(pc);
    pc->vi_drive_addr   = ide_rd_drive_address(pc);
}


#if (IDE_USE_ATAPI)
BOOLEAN ls120_format(DDRIVE *pdr);
#endif

int ide_perform_device_ioctl(int driveno, int opcode, PFVOID pargs)
{
DDRIVE *pdr;
DEV_GEOMETRY gc;        // used by DEVCTL_GET_GEOMETRY
PIDE_CONTROLLER pc;
 

    pdr = pc_drno_to_drive_struct(driveno);
    if (!pdr)
        return(-1);
    pc = &controller_s[pdr->controller_number];

    switch (opcode)
    {
        case DEVCTL_GET_GEOMETRY:

        pc_memfill(&gc, sizeof(gc), '\0');
        gc.dev_geometry_heads       =       pc->drive[pdr->logical_unit_number].num_heads;
        gc.dev_geometry_cylinders   =       pc->drive[pdr->logical_unit_number].num_cylinders;
        gc.dev_geometry_secptrack   =       pc->drive[pdr->logical_unit_number].sec_p_track;
        gc.dev_geometry_lbas        =       pc->drive[pdr->logical_unit_number].total_lba;
        copybuff(pargs, &gc, sizeof(gc));
        return (0);

        case DEVCTL_FORMAT:
#if (IDE_USE_ATAPI)
        if(pc->drive[pdr->logical_unit_number].protocol==2)
        {
            if (!ls120_format(pdr))
                return(-1);
        }
#endif
        return (0);

        case DEVCTL_REPORT_REMOVE:

        pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
        /* Close out the drive so we re-open */
        pc->drive[pdr->logical_unit_number].open_count = 0;
        return(0);

        case DEVCTL_CHECKSTATUS:
            if (!(pdr->drive_flags & DRIVE_FLAGS_REMOVABLE))
                return(DEVTEST_NOCHANGE);

            if (pdr->drive_flags & DRIVE_FLAGS_INSERTED)
                return(DEVTEST_NOCHANGE);
            /* If the drive is open but the inserted is clear
               that means another partition accessed the drive
               and succeed so return CHANGED to force a remount
               with no low level drive initialization */
            if (pc->drive[pdr->logical_unit_number].open_count)
            {
                pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
                return(DEVTEST_CHANGED);
            }

#if (IDE_USE_ATAPI)
            /* If its an atapi drive do a get media status and check the media changed
            bit in bit 5 */
            if(pc->drive[pdr->logical_unit_number].protocol==2)
            {
                /* Do a media status call - if it fails try it again. 
                needed by some LS-120 drives */
                if (ide_command(IDE_CMD_GET_MEDIA_STATUS, pc, pdr->logical_unit_number, 0, 0))
                    if (ide_command(IDE_CMD_GET_MEDIA_STATUS, pc, pdr->logical_unit_number, 0, 0))
                        return(DEVTEST_NOMEDIA);

                /* If the user accepted a media change.. do an eject */
                if (pc->vi_error & 0x08)
                    ide_eject_media(pdr);

                /* This isn't right. needs minor fixes */
                if (pc->vi_error & 0x20)
                {
                    pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
                    return(DEVTEST_CHANGED);
                }
                else
              

⌨️ 快捷键说明

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