//==========================================================================
//
//      i386_pc_disk_ide_drivers.inl
//
//      PC target IDE disk driver configuration
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
// -------------------------------------------                              
// This file is part of eCos, the Embedded Configurable Operating System.   
// Copyright (C) 2004, 2006 Free Software Foundation, Inc.                  
// Copyright (C) 2004, 2006 eCosCentric Limited                             
//
// 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.,    
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 v2.                                               
//
// This exception does not invalidate any other reasons why a work based    
// on this file might be covered by the GNU General Public License.         
// -------------------------------------------                              
// ####ECOSGPLCOPYRIGHTEND####                                              
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    nickg
// Contributors: 
// Date:         2004-01-19
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/devs_disk_i386_pc.h>


#ifdef CYGPKG_DEVS_DISK_I386_PC_IDE

// ----------------------------------------------------------------------------
// IDE Register Indices

#define IDE_REG_DATA      0
#define IDE_REG_ERROR     1
#define IDE_REG_FEATURES  1
#define IDE_REG_COUNT     2
#define IDE_REG_REASON    2  // ATAPI
#define IDE_REG_LBALOW    3
#define IDE_REG_LBAMID    4
#define IDE_REG_LBAHI     5
#define IDE_REG_DEVICE    6
#define IDE_REG_STATUS    7
#define IDE_REG_COMMAND   7

#define SECTOR_SIZE      512

#define CDROM_SECTOR_SIZE 2048
#define SECTORS_PER_CDROM_SECTOR (CDROM_SECTOR_SIZE/SECTOR_SIZE)

// ----------------------------------------------------------------------------

#ifdef CYGPKG_HAL_I386_PCMB

// These definition should be exported back to pcmb_io.h

#define HAL_IDE_NUM_CONTROLLERS 2

// Initialize the IDE controller(s).
#define HAL_IDE_INIT() (HAL_IDE_NUM_CONTROLLERS)

#define __PCMB_IDE_PRI_CMD   0x1f0
#define __PCMB_IDE_PRI_CTL   0x3f4
#define __PCMB_IDE_SEC_CMD   0x170
#define __PCMB_IDE_SEC_CTL   0x374

#define __CMD_ADDR(__n) ((__n) ? __PCMB_IDE_SEC_CMD : __PCMB_IDE_PRI_CMD)
#define __CTL_ADDR(__n) ((__n) ? __PCMB_IDE_SEC_CTL : __PCMB_IDE_PRI_CTL)

#define HAL_IDE_READ_UINT8( __ctlr, __regno, __val )  \
    HAL_READ_UINT8(__CMD_ADDR(__ctlr) + (__regno), (__val))
#define HAL_IDE_READ_UINT16( __ctlr, __regno, __val )  \
    HAL_READ_UINT16(__CMD_ADDR(__ctlr) + (__regno), (__val))
#undef HAL_IDE_READ_ALTSTATUS
#define HAL_IDE_READ_ALTSTATUS( __ctlr, __val )  \
    HAL_READ_UINT8(__CTL_ADDR(__ctlr) + 2, (__val))

#define HAL_IDE_WRITE_UINT8( __ctlr, __regno, __val )  \
    HAL_WRITE_UINT8(__CMD_ADDR(__ctlr) + (__regno), (__val))
#define HAL_IDE_WRITE_UINT16( __ctlr, __regno, __val )  \
    HAL_WRITE_UINT16(__CMD_ADDR(__ctlr) + (__regno), (__val))
#undef HAL_IDE_WRITE_CONTROL
#define HAL_IDE_WRITE_CONTROL( __ctlr, __val )  \
    HAL_WRITE_UINT8(__CTL_ADDR(__ctlr) + 2, (__val))

#define HAL_IDE_INTERRUPT_PRI   CYGNUM_HAL_INTERRUPT_HDD
#define HAL_IDE_INTERRUPT_SEC   CYGNUM_HAL_INTERRUPT_HDD2

#endif


//==========================================================================
// IDE disks

// ----------------------------------------------------------------------------

#if defined(CYGVAR_DEVS_DISK_IDE_DISK0) || defined(CYGVAR_DEVS_DISK_IDE_DISK1)

static ide_controller_info_t ide_controller_info_0 = {
    ctlr:       0,
#ifndef CYGVAR_DEVS_DISK_IDE_POLLED    
    vector:     HAL_IDE_INTERRUPT_PRI
#endif
};

DISK_CONTROLLER( ide_disk_controller_0, ide_controller_info_0 );

#endif

#if defined(CYGVAR_DEVS_DISK_IDE_DISK2) || defined(CYGVAR_DEVS_DISK_IDE_DISK3)

static ide_controller_info_t ide_controller_info_1 = {
    ctlr:       1,
#ifndef CYGVAR_DEVS_DISK_IDE_POLLED    
    vector:     HAL_IDE_INTERRUPT_SEC
#endif
};

DISK_CONTROLLER( ide_disk_controller_1, ide_controller_info_1 );

#endif

// ----------------------------------------------------------------------------

#define IDE_DISK_INSTANCE(_number_,_ctlr_,_dev_,_mbr_supp_)     \
static ide_disk_info_t ide_disk_info##_number_ = {              \
    num:           _number_,                                    \
    ctlr:          &ide_controller_info_##_ctlr_,               \
    dev:           _dev_,                                       \
};                                                              \
DISK_CHANNEL(ide_disk_channel##_number_,                        \
             ide_disk_funs,                                     \
             ide_disk_info##_number_,                           \
             ide_disk_controller_##_ctlr_,                      \
             _mbr_supp_,                                        \
             4                                                  \
);                                                              \
BLOCK_DEVTAB_ENTRY(ide_disk_io##_number_,                       \
             CYGDAT_IO_DISK_IDE_DISK##_number_##_NAME,          \
             0,                                                 \
             &cyg_io_disk_devio,                                \
             ide_disk_init,                                     \
             ide_disk_lookup,                                   \
             &ide_disk_channel##_number_                        \
);

// ----------------------------------------------------------------------------

#ifdef CYGVAR_DEVS_DISK_IDE_DISK0
IDE_DISK_INSTANCE(0, 0, 0, true);
#endif
#ifdef CYGVAR_DEVS_DISK_IDE_DISK1
IDE_DISK_INSTANCE(1, 0, 1, true);
#endif
#ifdef CYGVAR_DEVS_DISK_IDE_DISK2
IDE_DISK_INSTANCE(2, 1, 0, true);
#endif
#ifdef CYGVAR_DEVS_DISK_IDE_DISK3
IDE_DISK_INSTANCE(3, 1, 1, true);
#endif

#endif

// ----------------------------------------------------------------------------
// EOF i386_pc_disk_ide_drivers.inl
