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

📄 ide_drv.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
*
* Inputs:
*   drive       - Drive number (0 or 1)
*   heads      - 
*   sectors
*
* Returns:
*   TRUE on success else FALSE. If FALSE pc->error_no will contain the error.
*   
*   This routine tells the drive how many heads and sectors per track
*   we will be basing our block to sector:trak:head calculations. The
*   drive will map sector:trak:head to its internal geometry. 
*
* This routine is portable
*/

#if (USE_SETPARMS)

static BOOLEAN ide_command_setparms(PIDE_CONTROLLER pc, int logical_unit_number, byte heads, byte sectors) /* __fn__ */
{
byte max_head;

    ide_clear_voregs(pc);                 /* Clear virtual output registers */
  /* Sectors per track go in sector count register */
    pc->vo_sector_count  = sectors;
  /* number of heads - 1 goes in the drive head register */
    max_head = (byte) (heads - 1);
    pc->vo_drive_head    = (byte) (max_head & 0x0f);   /* bit 0-3 is head */
    pc->vo_drive_head    |= 0x20;                   /* Bit five is always one */
    if (logical_unit_number)                                     /* Bit four is drive (1 or 0) */
        pc->vo_drive_head |= 0x10;
    pc->vo_command = IDE_CMD_INITP;
    pc->timer = (word)TIMEOUT_TYPICAL;
 /* Call the processing routine */
    return(ide_do_command(pc));
}

#endif


/*  ide_command_read_multiple - Execute read multiple commands
*
* Inputs:
*   address - Destination address for the data
*   drive       - Drive number (0 or 1)
*   blockno - Block number to read
*   nblocks - Number of blocks (legal range: 1-256)
*
* Returns:
*   TRUE on success else FALSE. If FALSE pc->error_no will contain the error.
*   
*   This is the read worker function for the device driver. It performs a one
*   or many block read operation. It calls ide_rdwr_setup() and ide_do_command
*   to do most of the work.
*
*   Called by ide_io
*
* This routine is portable
*/

static BOOLEAN ide_command_read_multiple(PIDE_CONTROLLER pc, int logical_unit_number, dword blockno, word nblocks) /* __fn__ */
{
    /* Call set multiple */
/* 11-10=2000 - Don't call this, we did it in the open
    if (!ide_command(IDE_CMD_SETM, pc, logical_unit_number, 0, 0))
        return(FALSE);
*/
 
    return(ide_command(IDE_CMD_READM, pc, logical_unit_number, blockno, nblocks));
}

/*  ide_command_write_multiple - Execute write_multiple(s) command
*
* Inputs:
*   address - Source address for the data
*   drive       - Drive number (0 or 1)
*   blockno - Block number to read
*   nblocks - Number of blocks (legal range: 1-256)
*
* Returns:
*   TRUE on success else FALSE. If FALSE pc->error_no will contain the error.
*   
*   This routine performs a one or many block write operation. It calls
*   ide_rdwr_setup() and ide_do_command() to do most of the work.
*   
*   This is the write worker function for the device driver. It performs a one
*   or many block write operation. It calls ide_rdwr_setup() and ide_do_command
*   to do most of the work.
*
*   Called by ide_do_block
*
* This routine is portable
*/

static BOOLEAN ide_command_write_multiple(PIDE_CONTROLLER pc, int logical_unit_number, dword blockno, word nblocks) /* __fn__ */
{
    /* Call set multiple */
/* 11-10=2000 - Don't call this, we did it in the open
    if (!ide_command(IDE_CMD_SETM, pc, logical_unit_number, 0, 0))
        return(FALSE);
*/
    return(ide_command(IDE_CMD_WRITEM, pc, logical_unit_number, blockno, nblocks));
}

/* ide_rdwr_setup - Setup routine for read  for read and write operations
* Inputs:
*   address - Destination address for the data
*   drive       - Drive number (0 or 1)
*   blockno - Block number to read/write
*   nblocks - Number of blocks (legal range: 1-256)
*
* Outputs:
*   
*   Sets the following register file registers:
*   vo_sector_count,vo_sector_number,vo_cyl_low,vo_cyl_high,vo_drive_head
*
*   
* Returns:
*   TRUE if inputs are valid else FALSE
*   
*   This routine performs setup operations common to read and write. The
*   registers listed above are set up and the user transfer address is
*   set up.
*
* This routine is portable
*
*/

static  byte l_to_byte(dword l, int bit)
{
    if (bit)
        l >>= bit;
    l &= 0xff;
    return( (byte) l);
}


    
#if (IDE_USE_ATAPI)
static void reverse(byte *sink, byte *source, word bytes)
{
    source+=bytes;
    while(bytes--)
        *(sink++)=*(--source);
}
#endif



static BOOLEAN ide_rdwr_setup(PIDE_CONTROLLER pc, int logical_unit_number, dword blockno, word nblocks) /* __fn__ */
{
word cylinder;
word head;
word sector;
word blk_offs_in_cyl;

    /* Check against max_blocks. this is 256 for IDE. In real mode 80xx we limit
        it to 128 to eliminate segment wrap. */
    if ( (nblocks > MAX_BLOCKS) || 
        (logical_unit_number && logical_unit_number != 1)  ||               /* Can only be 0 or 1 */
        (!pc->drive[logical_unit_number].sec_p_cyl&&(pc->drive[logical_unit_number].media_descriptor!=0xef)) )  /* Will be non zeroe if the */ /* CDROM Jerry*/
    {                                               /* Drive is initted */
        pc->error_code      = IDE_ERC_ARGS;
        return(FALSE);                          /* Drive is initted */
    }

#if (IDE_USE_ATAPI)
    /* In lba mode sector no = block (0.7), cyl_low = (8.15), cyl_high = (16,23)
        drive_head = (24, 27) */
    if(pc->drive[logical_unit_number].protocol==2)
    {
        reverse((byte *)&pc->drive[logical_unit_number].atapi_packet.generic.lba,(byte *)&blockno,4);
        pc->drive[logical_unit_number].atapi_packet.generic.transfer_length.lsb=(byte)nblocks;
        pc->drive[logical_unit_number].atapi_packet.generic.transfer_length.msb=(byte)(nblocks>>8);
    }
#endif
        
    if (pc->drive[logical_unit_number].supports_lba)
    {
        pc->vo_sector_number = (byte) l_to_byte(blockno, 0);
        pc->vo_cyl_low      = (byte) l_to_byte(blockno, 8);
        pc->vo_cyl_high     = (byte) l_to_byte(blockno, 16);
        pc->vo_drive_head   = (byte) (l_to_byte(blockno, 24) & 0x0f);  
        pc->vo_drive_head   |= 0x40;  /* Select lba mode */
    }
    else
    {
    /* Calculate block address */
        cylinder = (word) (blockno/pc->drive[logical_unit_number].sec_p_cyl);
        blk_offs_in_cyl = (word) (blockno%pc->drive[logical_unit_number].sec_p_cyl);
        head = (word) (blk_offs_in_cyl/pc->drive[logical_unit_number].sec_p_track);
        sector = (word) (blk_offs_in_cyl%pc->drive[logical_unit_number].sec_p_track);
/* Load registers */
        pc->vo_sector_number = (byte) (sector + 1); /* Note in 1-N order at the controller */
        pc->vo_cyl_low      = (byte) (cylinder & 0xff);
        pc->vo_cyl_high     = (byte) (cylinder >> 8);
        pc->vo_drive_head   = (byte) (head & 0x0f); /* bit 0-3 is head */
    }
    pc->vo_sector_count  = (byte) nblocks; /* 1-255. 256 becomes 0 */
    return(TRUE);
}


static  BOOLEAN ide_error(PIDE_CONTROLLER pc, word error_code) 
{
    pc->error_code = error_code;
    pc->command_complete = TRUE;            /* Shesssaaa hung */
    return(FALSE);
}

/*  ide_do_command- Execute an ide cmd and poll or block until complete
* Inputs:
*   uses values in cs (the control structure)
* Outputs:
*   pc->command_complete and pc->error_code are updated. As well as all the 
*   vi_xxx (virtual register file in) are read in.
* Returns:
*   TRUE if command succeeded else look in error_code.
*   
*   This routine is called by all ide_command_xxx routines to begin 
*   command executiion. It copies the vo_xxxxx register file from the control
*   structure to the drive and then polls or blocks until completion. If 
*   pc->vo_dig_out & IDE_OUT_IEN is true it polls waiting for completion,
*   otherwise it blocks waiting for the ISR to wake it. Each command has
*   a time out value in pc->timer.
*
*/

static BOOLEAN ide_do_command(PIDE_CONTROLLER pc) /* __fn__ */
{
    word        utemp;
#if (IDE_USE_ATAPI)
    dword       words_remaining;
    dword       words_to_transfer;
    int         phys_drive;
    PFBYTE      save_useraddress;
    byte        save_vo_command;        /* command register see command patterns above (W) */
    dword    i;
    word     dummyWord;
#endif
    int         loop_count=8;

    pc->error_code = 0; 
    pc->command_complete = FALSE;
    
 /* The drive may be busy. If so, wait for it to complete */

    if (!ide_wait_not_busy(pc, pc->timer))
        return(ide_error(pc,IDE_ERC_BUS));                  /* bus is hung */
 
    /* There should be no pending interrupt complete signals
        so call os_ide_clear_signal(); to be sure we aren't 
        signalled until after an int occurs. */
        
    if (!(pc->vo_dig_out & IDE_OUT_IEN))
    {
        OS_IDE_SIGNAL_BIND(pc->controller_number);
        OS_IDE_SIGNAL_CLEAR(pc->controller_number);
    }
#if (IDE_USE_ATAPI)
    phys_drive=(pc->vo_drive_head & 0x10)>>4;               /* GET PHYSICAL DRIVE */
    if( ((pc->drive[phys_drive].protocol==2)            && 
        (pc->vo_command!=IDE_CMD_DIAG)              &&
        (pc->vo_command!=IDE_CMD_IDENT)             &&
        (pc->vo_command!=ATAPI_CMD_IDENT)           &&
        (pc->vo_command!=IDE_CMD_GET_MEDIA_STATUS)  &&
        (pc->vo_command!=IDE_CMD_SOFT_RESET)    &&
        (pc->vo_command!=IDE_CMD_SETF)) ||
        (pc->vo_command==ATAPI_PKT_CMD_TEST_UNIT_READY) ||
        (pc->vo_command==ATAPI_PKT_CMD_REQUEST_SENSE)   ||
        (pc->vo_command==ATAPI_PKT_CMD_MODE_SENSE)      ||
        (pc->vo_command==ATAPI_PKT_CMD_START_STOP_UNIT) ||
        (pc->vo_command==ATAPI_PKT_CMD_FORMAT_UNIT))
    {
        save_vo_command=pc->vo_command;
        pc->vo_command=ATAPI_CMD_PKT;
        switch(save_vo_command)
        {
            case    IDE_CMD_READS:      /* Read sector(s) */ 
                pc->timer<<=1;                  /* increase the timer to allow for spin up */
                pc->drive[phys_drive].atapi_packet.generic.op_code=ATAPI_PKT_CMD_READ;
                break;
            case    IDE_CMD_WRITES:     /* Write sector(s) */
                pc->timer<<=1;                  /* increase the timer to allow for spin up */
                pc->drive[phys_drive].atapi_packet.generic.op_code=ATAPI_PKT_CMD_WRITE;
                break;
            case    ATAPI_PKT_CMD_TEST_UNIT_READY:
                pc_memfill(&pc->drive[phys_drive].atapi_packet, sizeof(ATAPI_PACKET), (byte) 0);
                /* fall thru */
            case    ATAPI_PKT_CMD_MODE_SENSE:
            case    ATAPI_PKT_CMD_REQUEST_SENSE:
                pc->timer<<=1;                  /* increase the timer to allow for spin up */
                pc->drive[phys_drive].atapi_packet.generic.op_code=save_vo_command;
                break;
            case ATAPI_PKT_CMD_START_STOP_UNIT:
                /* timer should be already set for a few minutes */
                pc_memfill(&pc->drive[phys_drive].atapi_packet, sizeof(ATAPI_PACKET), (byte) 0);
                /* Eject the packet if possible */
                pc->drive[phys_drive].atapi_packet.start_stop.op_code=ATAPI_PKT_CMD_START_STOP_UNIT;
                pc->drive[phys_drive].atapi_packet.start_stop.eject = 0x02;
                break;
            case    ATAPI_PKT_CMD_FORMAT_UNIT:
                /* timer should be already set for a few minutes */
                pc_memfill(&pc->drive[phys_drive].atapi_packet, sizeof(ATAPI_PACKET), (byte) 0);
                switch(pc->drive[phys_drive].medium_type_code)                  /*                         Bytes/  Sectors/             */
                {                                                           /*                  Cyl H  Sector   Track   Capacity    */
                    case    0x22:                                               /* Formatted NEC     77 2   1024       8    1.20Mb*/
                    case    0x23:                                               /* Formatted Toshiba 80 2    512      15    1.20Mb*/
                    case    0x26:                                               /* DMF               80 2    512      21    1.7Mb*/
                    case    0x27:                                               /* NEC-DMF           77 2    512       9    720Kb*/
                    case    0x30:                                               /* Formatted UHD    963 8    512      32    120Mb */
                    case    0x31:                                               /* Unformatted UHD  963 8    512      32    120Mb */
                        pc->drive[phys_drive].atapi_packet.format.op_code=save_vo_command;
                        pc->drive[phys_drive].atapi_packet.format.defect_list_format=0x17;
                        pc->drive[phys_drive].atapi_packet.format.track_number=0x01;
                        break;
                    case    0x11:                                               /* Formatted DD      80 2    512       9    720Kb*/
                    case    0x10:                                               /* Unformatted DD    80 2    512       9    720Kb*/
                        pc->drive[phys_drive].atapi_packet.old_format.medium=0x11;
                        pc->drive[phys_drive].atapi_packet.old_format.op_code=ATAPI_PKT_CMD_OLD_FORMAT_UNIT;
                        pc->drive[phys_drive].atapi_packet.old_format.control_byte=0x21;
                        break;
                    case    0x20:                                               /* Unformatted HD    80 2    512      18    1.44Mb*/
                    case    0x24:                                               /* Formatted HD      80 2    512      18    1.44Mb*/
                        pc->drive[phys_drive].atapi_packet.old_format.medium=0x24;
                        pc->drive[phys_drive].atapi_packet.old_format.op_code=ATAPI_PKT_CMD_OLD_FORMAT_UNIT;
                        pc->drive[phys_drive].atapi_packet.old_format.control_byte=0x21;
                        break;
                    default:
                        return(FALSE);
                }
                break;
            case    IDE_CMD_ERASES:     /* Erase sector(s) */
            case    IDE_CMD_WRITES_NE:  /* Write sector(s) No pre-erase */
            case    IDE_CMD_WRITEM:     /* Write multiple sectors/interrupt */
            case    IDE_CMD_WRITEM_NE:  /* Write multiple No pre-erase */
            case    IDE_CMD_READM:      /* Read multiple sectors/interrupt */
            case    IDE_CMD_SETM:       /* Set multiple mode */
            default:
                pc->error_code=IDE_ERC_BAD_CMD;

⌨️ 快捷键说明

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