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

📄 ide_drv.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
                return(FALSE);
        }
        pc->drive[phys_drive].atapi_packet.generic.lun=0;
        pc->drive[phys_drive].atapi_packet.generic.reserved1=
        pc->drive[phys_drive].atapi_packet.generic.reserved2=
        pc->drive[phys_drive].atapi_packet.generic.reserved3=
        pc->drive[phys_drive].atapi_packet.generic.reserved4=0;
    /* Now load the rest of the register file. (send command last) */
        if(pc->drive[phys_drive].media_descriptor==0xef)
            ide_wr_drive_head(pc, (pc->vo_drive_head|0xa0)&0xb0);               /* ALAN CDROM */
        else
            ide_wr_drive_head(pc, pc->vo_drive_head|0xa0);                          /* 176 Atapi Drive Select */ 
        while((pc->vi_status = ide_rd_status(pc))&(IDE_STB_BUSY|IDE_STB_DRQ))   /* wait till busy off and drq off*/
        {
            pc->vi_sector_number = ide_rd_sector_number(pc);
            if(pc->vi_sector_number&IDE_IRR_CoD)
            {
                if(pc->vi_sector_number&IDE_IRR_IO)
                    INWORD(pc->register_file_address + IDE_OFF_DATA);               /* read a word  */
                 else
                    OUTWORD(pc->register_file_address + IDE_OFF_DATA, 0x0000);      /* write a word */
            }
            else
            {
                if(loop_count)
                    loop_count--;
                else
                {
                    ide_wr_command(pc, IDE_CMD_SOFT_RESET);
                    loop_count=8;
                }
            }
        }
        utemp=pc->drive[phys_drive].atapi_packet.generic.transfer_length.lsb;
        utemp += (word)(pc->drive[phys_drive].atapi_packet.generic.transfer_length.msb<<8);
        utemp<<=9;
        ide_wr_cyl_low(pc,  utemp);        /* 174 Atapi Byte Count Register (bits 0-7) */
        ide_wr_cyl_high(pc, utemp>>8);     /* 175 Atapi Byte Count Register (bits 8-15) */
        ide_wr_feature(pc, pc->vo_feature);/* 171 Atapi Features */
        
    /* Write the digital output register (interrupts on/off) */
        ide_wr_dig_out(pc, pc->vo_dig_out | 0x08);                      
        
    /* The register file is loaded.Now load the command into the command register. */
        ide_wr_command(pc, ATAPI_CMD_PKT);
        if(pc->drive[phys_drive].CMD_DRQ_type == 0x01)                              /* CDROM Alan*/
        {
            // DRQ type is == 1. drive interrupts when ready for packet
            if (!(pc->vo_dig_out & IDE_OUT_IEN))    /* Interupt mode */
            {
                if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
                    return(ide_error(pc,IDE_ERC_BUS));
            }
            else
            {
               // DRQ type is == 1. but we aren't using interrupt
               // This is not guaranteed to always work
                if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
                    return(ide_error(pc,IDE_ERC_BUS));
            }
        }
        else
        {   
            /* CDROM Alan*/
            // DRQ type is != 1. drive drops busy and asserts drq   
            if (!(ide_wait_not_busy(pc, TIMEOUT_TYPICAL) && ide_wait_drq(pc, TIMEOUT_TYPICAL)))
            {
                pc->vo_command=save_vo_command;
                return(ide_error(pc,IDE_ERC_BUS));
            }                                                                        /* CDROM Alan*/
        }                                                                            /* CDROM Alan*/

        // DRQ should be set error should be clear
        if(!(ide_rd_status(pc)&IDE_STB_DRQ)||(ide_rd_status(pc)&IDE_STB_ERROR))
        {                                                                                   
            return(ide_error(pc,IDE_ERC_BUS));
        }

        save_useraddress=pc->user_address;
        pc->user_address=(PFBYTE)&pc->drive[phys_drive].atapi_packet;

//      if((ide_rd_sector_count(pc)&0x03)!=0x01)
//          _asm int 3
        if(!ide_out_words(pc, sizeof(ATAPI_PACKET_DESC)>>1))            /* Packet size /2 */
            return(ide_error(pc,IDE_ERC_BUS));

        pc->user_address=save_useraddress;
        if(pc->drive[phys_drive].atapi_packet.generic.op_code==ATAPI_PKT_CMD_FORMAT_UNIT)
        {
            if(!ide_out_words(pc, sizeof(HIMAWARI_FORMAT_DESCRIPTOR)>>1))           /* Packet size /2 */
            {
                return(ide_error(pc,IDE_ERC_BUS));
            }
        }
        if (!(pc->vo_dig_out & IDE_OUT_IEN))    /* Interupt mode */
        {
            if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
                return(ide_error(pc,IDE_ERC_BUS));
        }
        else
        {
            if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
                return(ide_error(pc,IDE_ERC_BUS));
        }
        if (ide_rd_status(pc)&IDE_STB_ERROR)    /* if error */
        {
            if (save_vo_command != ATAPI_PKT_CMD_TEST_UNIT_READY)
                return(ide_error(pc,IDE_ERC_STATUS));
        }                                                                
        words_remaining = ((dword)pc->sectors_remaining)<<10;           /* Calculate the number of words (blocks * 1024) CDROM Jerry; I think this is in error in the Himawari Code */
        while(ide_rd_status(pc)&IDE_STB_DRQ)                        /* if DRQ then data to transfer */
        {
            words_to_transfer =(dword)(((ide_rd_cyl_low(pc))+(ide_rd_cyl_high(pc)<<8))>>1); /* number of words to transfer */
            if(words_remaining)
            {
                if(words_remaining<words_to_transfer)
                    words_to_transfer=words_remaining;
                switch(ide_rd_sector_count(pc)&0x03)
                {
                    case    0x00:                                           /* write to device */
                        ide_out_words(pc, (word)words_to_transfer);
                        break;
                    case    0x02:                                           /* read from device */
                        ide_in_words(pc, (word)words_to_transfer);
                        break;
                    case    0x01:
                    case    0x03:
                        return(ide_error(pc,IDE_ERC_BUS));
                }
            }
            else
            {
                switch(ide_rd_sector_count(pc)&0x03)
                {
                    case    0x00:                                           /* write to device */
                        dummyWord = 0;
                        for (i=0; i < words_to_transfer; i++)
                            OUTWORD(pc->register_file_address + IDE_OFF_DATA,dummyWord);
                        break;
                    case    0x02:                                           /* read from device */
                        for (i=0; i < words_to_transfer; i++)
                            dummyWord = INWORD(pc->register_file_address + IDE_OFF_DATA);
                        break;
                    case    0x01:
                    case    0x03:
                        return(ide_error(pc,IDE_ERC_BUS));
                }
            }
                
            words_remaining -= words_to_transfer;
            if(words_remaining)
            {
                if (!(pc->vo_dig_out & IDE_OUT_IEN))    /* Interupt mode */
                {
                     if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
                            return(ide_error(pc,IDE_ERC_BUS));
                }
                else
                {
                    if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
                            return(ide_error(pc,IDE_ERC_BUS));
                }
            }
        }
        pc->vo_command=save_vo_command;

        if (ide_rd_status(pc)&IDE_STB_ERROR)    /* if error */
                return(ide_error(pc,IDE_ERC_STATUS));

        if (ide_rd_status(pc)&IDE_STB_DRQ)     /* if drq */
            return(ide_error(pc,IDE_ERC_BUS));
    }
    else
#endif /* (IDE_USE_ATAPI) */

    {
     /* Now load the rest of the register file. (send command last) */
        ide_wr_sector_count(pc, pc->vo_sector_count);
        ide_wr_sector_number(pc, pc->vo_sector_number);
        ide_wr_cyl_low(pc,  pc->vo_cyl_low);
        ide_wr_cyl_high(pc, pc->vo_cyl_high);
        ide_wr_drive_head(pc, pc->vo_drive_head);
        ide_wr_feature(pc, pc->vo_feature);
     /* Write the digital output register (interrupts on/off) */
        ide_wr_dig_out(pc, pc->vo_dig_out);
     /* The register file is loaded.Now load the command into the command register. */
        
        ide_wr_command(pc, pc->vo_command);
    
        if ((pc->vo_command == IDE_CMD_WRITES) ||
            (pc->vo_command == IDE_CMD_WRITES_NE) ||
            (pc->vo_command == IDE_CMD_WRITEM) ||
            (pc->vo_command == IDE_CMD_WRITEM_NE) )
        {
            /* Busy should deassert. DRQ should assert */
            if (!(ide_wait_not_busy(pc, pc->timer) && ide_wait_drq(pc, pc->timer)))
            {
                pc->error_code = IDE_ERC_BUS;
                pc->command_complete = TRUE;            /* Shesssaaa hung */
                return(FALSE);
            }
            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;
        }

    /* The NEW SMART WAY OF DOING IT. DOING THE DATA TRANSFER AT THE APP LAYER */
        while (!pc->command_complete)
        {
            if (!(pc->vo_dig_out & IDE_OUT_IEN))    /* Interupt mode */
            {
                /* Wait for a signal of completion from ide_interrupt. Pass in 
                   pc->timer (# ticks to wait before detecting a timeout */
                if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
                    goto bail;
            }
            else
            {
                io_delay(); /* Give time for BUSY to assert */
                io_delay();
                if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
                {
    bail:
                    pc->error_code      = IDE_ERC_TIMEOUT;
                    pc->command_complete = TRUE;            /* Shesssaaa hung */
                }
            }
            if (!pc->command_complete)
                ide_interrupt(pc->controller_number);
        }
    }
    if (pc->error_code) 
        return(FALSE);
    else
        return(TRUE);
}

/*  ide_interrupt - Respond to the ide_disk interupt.
* Inputs:
*   uses values in cs (the control structure)
* Outputs:
*   pc->command_complete and pc->error_code are set. If error_code is non zero
*   the command failed.
* Returns:
*   Nothing
*   
*   This routine is called by ide_isr or do_command if it is polling. Its job
*   is to
*   determine the cause of the IDE disk interrupt and process it correctly.
*   On multi block reads and writes it performs the data transfer and returns if
*   the multiblock transfer is incomplete. In other cases it checks the status 
*   bits for errors. If no errors were found pc->error_code is zero other wise
*   pc->error_code is set to an appropriate value. If the driver is in interrupt
*   mode the task is woken up when command_complete is set.
*
*/

void ide_interrupt(int controller_number)                       /* __fn__ */
{
word utemp;
PIDE_CONTROLLER pc;

    pc = &controller_s[controller_number];

 /* Read the status register. This also clears the interrupt status if pending */
    pc->vi_status = ide_rd_status(pc);

 /* Read the sector count register. We'll need it in reads and writes */
    pc->vi_sector_count = ide_rd_sector_count(pc);

  /* Check if the drive reported an error */
    if (pc->vi_status & IDE_STB_ERROR)
    {
// BUGBUGBUG - For READS and READM commands we need to read the data 
// to put the controller in command mode

        ide_read_register_file(pc);
        /* Report the error on all but diagnostipc-> The error bits
            are treated differently on this command. */ 
        if (pc->vo_command != IDE_CMD_DIAG)
        {
            pc->error_code = IDE_ERC_STATUS;
            goto io_done_label;
        }
    }
    /* =================================================================== */
    /* ================= Now process command completes==================== */
    /* =================================================================== */

    /* Reads and Write are treated differently from the rest of the commands.
        They may recieve multiple interrupts and the performance of this 
        routine is very important. To pick up some performance we only read
        the register file entries that we need. 
    */
/* Command::::: IDE_CMD_READM - read multiple, IDE_CMD_READS - read sector(s) */
    if((pc->vo_command == IDE_CMD_READM)||(pc->vo_command == IDE_CMD_READS))
    {
        if (pc->sectors_remaining >= (word) pc->block_size)
            utemp = (word) pc->block_size;
        else
            utemp = pc->sectors_remaining;
//BUGBUGBUG - We should compare the sector count register.

        if (!ide_in_words(pc, (word) (utemp << 8)))/* 256 times xfr size */
        {
            /* Serious problem. Bus state incorrect */
            pc->error_code = IDE_ERC_BUS;
            goto io_done_label;
        }
        pc->sectors_remaining -= utemp;

        /* see if we've completed transferring all of our blocks */
        if (pc->sectors_remaining)
            return;             /* NOPE - More to come */
        else
        {
            ide_read_register_file(pc);
            if (pc->vi_status & IDE_STB_ERROR)
                pc->error_code = IDE_ERC_STATUS;
            goto io_done_label; 
        }
    }

/* Command::::: IDE_CMD_WRITEM IDE_CMS_WRITES - write multiple, write sectors */
    if ((pc->vo_command == IDE_CMD_WRITES) ||
        (pc->vo_command == IDE_CMD_WRITES_NE) ||
        (pc->vo_command == IDE_CMD_WRITEM) ||
        (pc->vo_command == IDE_CMD_WRITEM_NE))
    {
        if (!pc->sectors_remaining)
        {
            /* Sector count reg is 0. we're done. We'll read the register
                File in case we want to look at the values */
            ide_read_register_file(pc);
            goto io_done_label; 
        }

⌨️ 快捷键说明

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