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

📄 ide.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================
//
//      ide.c
//
//      RedBoot IDE support
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas <gary@mind.be>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    msalter
// Contributors: msalter
// Date:         2001-07-14
// Purpose:      
// Description:  
//              
// This code is part of RedBoot (tm).
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <redboot.h>
#include <cyg/hal/hal_io.h>
#include <fs/disk.h>
#include <fs/ide.h>

static int ide_read(struct disk *d,
		    cyg_uint32 start_sector,
		    cyg_uint32 *buf,
		    cyg_uint8  nr_sectors);

static disk_funs_t ide_funs = { ide_read };

static struct ide_priv ide_privs[HAL_IDE_NUM_CONTROLLERS * 2];

static inline void
__wait_for_ready(int ctlr)
{
    cyg_uint8 status;
    do {
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
    } while (status & (IDE_STAT_BSY | IDE_STAT_DRQ));
}

static inline int
__wait_for_drq(int ctlr)
{
    cyg_uint8 status;
    cyg_ucount32 tries;

    CYGACC_CALL_IF_DELAY_US(10);
    for (tries=0; tries<1000000; tries++) {
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
        if (!(status & IDE_STAT_BSY)) {
            if (status & IDE_STAT_DRQ)
                return 1;
            else
                return 0;
        }
    }
}

static int
ide_reset(int ctlr)
{
    cyg_uint8 status;
    int delay;
//
// VMware note:
// VMware virtual IDE device handler obviously expects that
// the reset and setup functions were already done
// by it's bios and complais if one uses reset here...
//
#ifndef CYGSEM_REDBOOT_DISK_IDE_VMWARE
    HAL_IDE_WRITE_CONTROL(ctlr, 6);	// polled mode, reset asserted
    CYGACC_CALL_IF_DELAY_US(5000);
    HAL_IDE_WRITE_CONTROL(ctlr, 2);	// polled mode, reset cleared
    CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
#endif

    // wait 30 seconds max for not busy and drive ready
    for (delay = 0; delay < 300; ++delay) {
	CYGACC_CALL_IF_DELAY_US((cyg_uint32)100000);
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
	  if (!(status & IDE_STAT_BSY)) {
		if (status & IDE_STAT_DRDY) {
	    return 1;
    }
	  }
    }
    return 0;
}

// Return true if any devices attached to controller
static int
ide_presence_detect(int ctlr)
{
    cyg_uint8 sel, val;
    int i;

    for (i = 0; i < 2; i++) {
	sel = (i << 4) | 0xA0;
	CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
	HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, sel);
	CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_DEVICE, val);
	if (val == sel) {
#ifndef CYGSEM_REDBOOT_DISK_IDE_VMWARE
	    if (i)
		HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 0);
#endif
	    return 1;
	}
    }
    return 0;
}

static int
ide_ident(int ctlr, int dev, int is_packet_dev, cyg_uint16 *buf)
{
    int i;

    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, is_packet_dev ? 0xA1 : 0xEC);
    CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000);

    if (!__wait_for_drq(ctlr))
	return 0;

    for (i = 0; i < (SECTOR_SIZE / sizeof(cyg_uint16)); i++, buf++)
	HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);

    return 1;
}

static int
ide_read_sectors(int ctlr, int dev, cyg_uint32 start, cyg_uint8 count, cyg_uint16 *buf)
{
    int  i, j;
    cyg_uint16 *p;

    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, count);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >>  8) & 0xff);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (start >> 16) & 0xff);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
			((start >> 24) & 0xf) | (dev << 4) | 0x40);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x20);

    for(p = buf, i = 0; i < count; i++) {

        if (!__wait_for_drq(ctlr)) {
            diag_printf("%s: NO DRQ for ide%d, device %d.\n",
                        __FUNCTION__, ctlr, dev);
            return 0;
        }

        for (j = 0; j < (SECTOR_SIZE / sizeof(cyg_uint16)); j++, p++)
            HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *p);
    }
    return 1;
}

// max number of sectors to xfer during a single packet command
#define MAX_CD_XFER 16

static inline int
send_packet_command(int ctlr, int dev, cyg_uint16 len, cyg_uint16 *pkt, int pktlen)
{
    int i;
    cyg_uint8 status, reason;

    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_FEATURES, 0);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, 0);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, 0);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, len & 0xff);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI,  (len >> 8) & 0xff);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
    HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xA0);

    if (!__wait_for_drq(ctlr)) {
	diag_printf("%s: NO DRQ for ide%d, device %d.\n",
		    __FUNCTION__, ctlr, dev);
	return 0;
    }

    // send packet
    for (i = 0; i < (pktlen/sizeof(cyg_uint16)); i++)
	HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, pkt[i]);

    // wait for not busy transferring packet
    do {
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
	HAL_IDE_READ_UINT8(ctlr, IDE_REG_REASON, reason);

	if ((status & (IDE_STAT_BSY | IDE_STAT_DRQ)) == IDE_STAT_DRQ)
	    if (reason & IDE_REASON_COD)
		continue;  // still wanting packet data (should timeout here)

    } while (status & IDE_STAT_BSY);

    return 1;
}

#define READ_COUNT(x)                                    \
        { unsigned char tmp;                             \
          HAL_IDE_READ_UINT8(ctlr, IDE_REG_LBAMID, tmp); \
          (x) = tmp;                                     \
          HAL_IDE_READ_UINT8(ctlr, IDE_REG_LBAHI, tmp);  \
          (x) = (x) | (tmp << 8);                        \
        }


// Read the sense data
static int
request_sense(int ctlr, int dev, cyg_uint16 count, cyg_uint16 *buf)
{
    int i;
    cyg_uint16 cdcount, pkt[6];
    unsigned char status, *cpkt = (unsigned char *)pkt;


    // Fill in REQUEST SENSE packet command block
    memset(cpkt, 0, sizeof(pkt));
    cpkt[0] = 0x03;
    cpkt[4] = 254;  // allocation length
	
    if (!send_packet_command(ctlr, dev, count, pkt, sizeof(pkt)))
	return 0;

    HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);

⌨️ 快捷键说明

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