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

📄 ide_drv.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* Portable IDE Device driver.
*
*
*/

// 10-24-2000 added LBA formatting. Submit to main tree
 
  
#include "pcdisk.h"


#if (INCLUDE_PCMCIA)
#include "pcmcia.h"
#endif

#define IDE_USE_SET_FEATURES    0 
/* if one use the following set features call when the drive is opened: 
        IDE_FEATURE_SETPERF     Set Perfomance Option 
        IDE_FEATURE_WCACHE_ON   Enable the write cache
        IDE_FEATURE_DEFECT_ON   Enable the defect re-assignment
        IDE_FEATURE_RLOOK_ON	   Enable read look-ahead
*/

#define IDE_USE_ATAPI           1  /* if one enable ATAPI support (for CD, LS-120, etc) */


#if (defined(ERTFS_SA))
#define OS_IDE_SIGNAL_TEST(X,Y) ks_test_ide_signal(X, Y)
#define  OS_IDE_SIGNAL_CLEAR(X) ks_clear_ide_signal(X)
#define  OS_IDE_SIGNAL_BIND(X)
#endif

#if (defined(ERTFS_SA))
void ks_invoke_ide_interrupt(int controller_number);
void hook_ide_interrupt(int irq, int controller_number);
void ks_clear_ide_signal(int controller);
BOOLEAN ks_test_ide_signal(int controller, word timeout);
#endif

#define ZERO 0
/* Set USE_SETPARMS to 1 to force this driver to set the drive to use its
   true geometry (cyls, hds, sec/track) when this driver initializes.
   This is only necessary if the IDE drive had already been set to use
   a translated geometry during BIOS initialization at boot. It may also
   be needed for ancient IDE drives. It should not cause any harm on 
   newer devices -- it just adds a little unnecessary code. */

#define USE_SETPARMS 0

#if (USE_ATA)

#if (IDE_USE_SET_FEATURES || IDE_USE_ATAPI)
static BOOLEAN ide_set_features(PIDE_CONTROLLER pc, int phys_drive, byte feature, byte config);
#endif
static BOOLEAN ide_command(byte command, PIDE_CONTROLLER pc, int phys_drive, dword blockno, word nblocks);
BOOLEAN atapi_command(byte command, PIDE_CONTROLLER pc, int phys_drive);
/*static BOOLEAN ide_reset(PIDE_CONTROLLER pc);*/
static BOOLEAN ide_command_diags(PIDE_CONTROLLER pc);
static BOOLEAN ide_command_read_multiple(PIDE_CONTROLLER pc, int phys_drive, dword blockno, word nblocks);
static BOOLEAN ide_command_write_multiple(PIDE_CONTROLLER pc, int phys_drive, dword blockno, word nblocks);
static BOOLEAN ide_rdwr_setup(PIDE_CONTROLLER pc, int phys_drive, dword blockno, word nblocks);
static BOOLEAN ide_do_command(PIDE_CONTROLLER pc);
#if (USE_SETPARMS)
static BOOLEAN ide_command_setparms(PIDE_CONTROLLER pc, int phys_drive, byte heads, byte sectors);
#endif
static void ide_clear_voregs(PIDE_CONTROLLER pc);
static void ide_read_register_file(PIDE_CONTROLLER pc);

BOOLEAN ide_in_words(PIDE_CONTROLLER pc, word nwords);
BOOLEAN ide_out_words(PIDE_CONTROLLER pc, word nwords);


extern IDE_CONTROLLER controller_s[N_ATA_CONTROLLERS];

#ifndef ide_rd_status

/* If ide_rd_status is defined it is a macro in ide_drv.h   */
#define ide_inbyte(X) ((byte) INBYTE((X)))
#define ide_outbyte(X,Y) OUTBYTE((X), (byte)(Y))

byte ide_rd_status(PIDE_CONTROLLER pc)      /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_STATUS));
}
byte ide_rd_sector_count(PIDE_CONTROLLER pc)        /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_SECTOR_int));
}
byte ide_rd_alt_status(PIDE_CONTROLLER pc)      /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_ALT_STATUS));
}
byte ide_rd_error(PIDE_CONTROLLER pc)       /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_ERROR));
}
byte ide_rd_sector_number(PIDE_CONTROLLER pc)       /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_SECTOR_NUMBER));
}
byte ide_rd_cyl_low(PIDE_CONTROLLER pc)     /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_CYL_LOW));
}
byte ide_rd_cyl_high(PIDE_CONTROLLER pc)        /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_CYL_HIGH));
}
byte ide_rd_drive_head(PIDE_CONTROLLER pc)      /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_DRIVE_HEAD));
}
byte ide_rd_drive_address(PIDE_CONTROLLER pc)       /* __fn__ */
{
    return(ide_inbyte(pc->register_file_address + IDE_OFF_DRIVE_ADDRESS));
}
void ide_wr_dig_out(PIDE_CONTROLLER pc, byte v)     /* __fn__ */
{
    ide_outbyte(pc->register_file_address + IDE_OFF_DIG_OUTPUT, v);
}
void ide_wr_sector_count(PIDE_CONTROLLER pc, byte v)        /* __fn__ */
{
    ide_outbyte(pc->register_file_address + IDE_OFF_SECTOR_int, v);
}
void ide_wr_sector_number(PIDE_CONTROLLER pc, byte v)       /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_SECTOR_NUMBER, v);
}
void ide_wr_cyl_low(PIDE_CONTROLLER pc, byte v)     /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_CYL_LOW, v);
}
void ide_wr_cyl_high(PIDE_CONTROLLER pc, byte v)        /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_CYL_HIGH, v);
}
void ide_wr_drive_head(PIDE_CONTROLLER pc, byte v)      /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_DRIVE_HEAD, v);
} 
void ide_wr_command(PIDE_CONTROLLER pc, byte v)     /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_COMMAND, v);
}
void ide_wr_feature(PIDE_CONTROLLER pc, byte v)     /* __fn__ */
{ 
    ide_outbyte(pc->register_file_address + IDE_OFF_FEATURE, v);
}

#endif   /* #ifndef ide_rd_status */


/* void ide_in_words(word nwords)
*   
*   This routine reads nwords 16 bit words from the IDE data register
*   and places it in the buffer at user_address. It must increment the
*   user_address pointer so future calls will work correctly. In the IBM
*   PC port we do an equivalent operation in assembler and update 
*   user_offset and user_segment. 
*
*   This has to be FAST !!!!
*
*/

BOOLEAN ide_in_words(PIDE_CONTROLLER pc, word nwords)       /* __fn__ */
{
unsigned short KS_FAR *p;
    pc->vi_status = ide_rd_status(pc);
    if (!(pc->vi_status & IDE_STB_DRQ))     /* Drive should have data ready */
    {
        /* Serious problem. Bus state incorrect   */
        pc->error_code = IDE_ERC_BUS;
        return(FALSE);
    }
    /* Note: the word wide data port is at offset 0 in the register file   */
    p = (unsigned short KS_FAR *) pc->user_address;
    insw(pc->register_file_address + IDE_OFF_DATA, p, nwords);
    pc->user_address += (nwords*2);
    return(TRUE);
}

/* extern void ide_out_words(word nwords)
*   
*   This routine writes nwords 16 bit words from the buffer at 
*   user_address to the IDE data register.
*   It must increment the user_address pointer so future calls will work
*   correctly. In the IBM PC port we do an equivalent operation in assembler 
*   and update user_offset and user_segment. 
*
*   This is just a sample. This has to be FAST !!!!
*
*/


BOOLEAN ide_out_words(PIDE_CONTROLLER pc, word nwords)      /* __fn__ */
{
unsigned short KS_FAR *p;

    pc->vi_status = ide_rd_status(pc);

    if (!(pc->vi_status & IDE_STB_DRQ))     /* Drive should be requesting */
    {
        pc->error_code = IDE_ERC_BUS;
        return(FALSE);
    }

    p = (unsigned short KS_FAR *) pc->user_address;
    outsw((IOADDRESS)(pc->register_file_address + IDE_OFF_DATA), p, nwords);
    pc->user_address += (nwords*2);
    return(TRUE);
}

/* ide_isr() - IDE ISR routine.
*
*   This routine is a portable interrupt service routine.
*
*/

void  KS_FAR ide_isr(int controller_number)                           /*__fn__*/
{
PIDE_CONTROLLER pc;

    pc = &controller_s[controller_number];
    /* Read the status register. to clear the interrupt status   */
    pc->vi_status = ide_rd_status(pc);
    /* Signal that we got an interrupt   */
    ks_invoke_ide_interrupt(controller_number);
}

/* Open function. This is pointed to by the bdevsw[] table */
/* 
* Note: This routine is called with the drive already locked so
*       in several cases there is no need for critical section code handling
*/

#if (!CDFS_ONLY)
void ide_eject_media(DDRIVE *pdr)
{
PIDE_CONTROLLER pc;
 
    pc = &controller_s[pdr->controller_number];

#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)
    {
        atapi_command(ATAPI_PKT_CMD_START_STOP_UNIT, pc, pdr->logical_unit_number);
    }
#endif
}
#endif



BOOLEAN ide_drive_open(DDRIVE *pdr)                         /*__fn__*/
{
#if (IDE_USE_ATAPI)
    int i;
#endif
    byte heads;
    byte sectors;
    dword ltemp;
    dword ltemp2;
    word buf[256];                     
    PIDE_CONTROLLER pc;

    pc = &controller_s[pdr->controller_number];

    if (pc->drive[pdr->logical_unit_number].open_count)
        return(TRUE);

    /*ide_controller_reset(pc) */
    ide_clear_voregs(pc);               /* Clear virtual output registers */


    if (!ide_wait_ready(pc, (int)TIMEOUT_RESET))
        return(FALSE);
    /* First issue a reset to the controller */
    ide_wr_dig_out(pc, IDE_OUT_RESET);
    /* sleep 2 ticks can be as little as 12 microseconds) */
    ks_sleep(2);
    ide_wr_dig_out(pc, 0);
    /* Wait for busy to drop */
    if (!ide_wait_not_busy(pc, (int)TIMEOUT_RESET))
        return(FALSE);

      /*DM: This check fails on CDROM. If it can't be made to work, how can we
      do it only for hard disks? -- we haven't yet determined whether it's
      a hard disk or ATAPI device. That's done below. That's why this is
      done as a conditional, which is not great, since it means that this
      call is not done for IDE drives either, if CDFS linked. */
#if (!defined(USE_CDFS))
    /* Now perform drive diagnostics   */
    if (!ide_command_diags(pc))
        return(FALSE);
#endif

   /* Set the power value in case we are on a lowl power system */
   /* Note: change the default value */
#if (IDE_USE_SET_FEATURES)
    ide_set_features(pc, pdr->logical_unit_number, IDE_FEATURE_SETPERF, IDE_FEATURE_SETPERF_VALUE);
    ide_set_features(pc, pdr->logical_unit_number, IDE_FEATURE_WCACHE_ON, 0x00);
    ide_set_features(pc, pdr->logical_unit_number, IDE_FEATURE_DEFECT_ON, 0x00);
    ide_set_features(pc, pdr->logical_unit_number, IDE_FEATURE_RLOOK_ON, 0x00);
#endif
    /* Clear the atapi flag to start */
    pc->drive[pdr->logical_unit_number].protocol = 0;
    /*  Use the ATA identify command. word 3 == # heads */
    /*  word 6 == sectors per track */
    /*  word 47 bits 0-7 ==s max sectors per read/write multiple */
    /*  word 49 bit  9  == if 1 supports logocal block addressing */
    /*  word 60-61      == number of user addressable LBA's in LBA mode */
    pc->user_address = (PFBYTE) &buf[0];
    if (!ide_command(IDE_CMD_IDENT, pc, pdr->logical_unit_number, 0, 0))
    {
#if (IDE_USE_ATAPI)
        pc->user_address = (PFBYTE) &buf[0];
        if (ide_command(ATAPI_CMD_IDENT, pc, pdr->logical_unit_number, 0, 0))
        {

{
/* CDROM JERRY  START */
                
                if((to_WORD((byte *) &buf[0])&0xdf03)==0x8500)                                      
                {                                                           
                    pc->drive[pdr->logical_unit_number].media_descriptor=0xef;                
                    pc->drive[pdr->logical_unit_number].CMD_DRQ_type=(byte)(to_WORD((byte *) &buf[0])&0x60);
                }
/* CDROM JERRY  STOP */
}

⌨️ 快捷键说明

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