/*---------------------------------------------------------------------------*\
 *   
 *   Copyright (C) 2006 AVM GmbH <fritzbox_info@avm.de>
 *
 *   This program 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 version 2 of the License.
 *
 *   This program 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 this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
\*---------------------------------------------------------------------------*/

#if !defined (_ahcireg_h_)
#define _ahcireg_h_

#include "ahcidef.h"

/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/

typedef volatile AHCI_DWORD AHCI_REGISTER;

typedef AHCI_REGISTER *PAHCI_REGISTER;

/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/

struct AHCI_hw {
	AHCI_REGISTER	ListControlReg;
	AHCI_REGISTER	GlobalControlReg;
	
	AHCI_REGISTER	SofConfigReg;
	AHCI_REGISTER	MemoryConfigReg;
	AHCI_REGISTER	ResetConfigReg;
	AHCI_REGISTER	ResumeConfigReg;
	
	AHCI_REGISTER	InterruptStatusReg;
	AHCI_REGISTER	InterruptEnableReg;
	AHCI_REGISTER	InterruptConfigReg;

	AHCI_REGISTER	FrameNumberReg;
	AHCI_REGISTER	CurRxAddrReg;

	AHCI_REGISTER	RevisionIDReg;

	AHCI_REGISTER	HPStartPointerReg;
	AHCI_REGISTER	LPStartPointerReg;
	
	AHCI_REGISTER 	reserved[2];
	
	AHCI_REGISTER	PortControlRegs[CONFIG_AHCI_NUMPORTS];
};

/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
extern PAHCI_REGISTER AHCI_BaseAddress;

extern PAHCI_REGISTER pAHCI_ListControlReg;
extern PAHCI_REGISTER pAHCI_GlobalControlReg;

extern PAHCI_REGISTER pAHCI_SofConfigReg;
extern PAHCI_REGISTER pAHCI_MemoryConfigReg;
extern PAHCI_REGISTER pAHCI_ResetConfigReg;
extern PAHCI_REGISTER pAHCI_ResumeConfigReg;

extern PAHCI_REGISTER pAHCI_InterruptStatusReg;
extern PAHCI_REGISTER pAHCI_InterruptEnableReg;
extern PAHCI_REGISTER pAHCI_InterruptConfigReg;

extern PAHCI_REGISTER pAHCI_FrameNumberReg;
extern PAHCI_REGISTER pAHCI_CurRxAddrReg;

extern PAHCI_REGISTER pAHCI_RevisionIDReg;

extern PAHCI_REGISTER pAHCI_HPStartPointerReg;
extern PAHCI_REGISTER pAHCI_LPStartPointerReg;

extern PAHCI_REGISTER pAHCI_PortControlRegs;

/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
void AHCI_InitRegisterMapping (unsigned RegOffset);

/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
#define AHCI_PTR(offset) ((PAHCI_REGISTER)(((char*)AHCI_BaseAddress) + offset))

#define AHCI_READ_REGISTER(pr) ((AHCI_DWORD)*((PAHCI_REGISTER)pr))
#define AHCI_WRITE_REGISTER(pr, v) ((void) ((*(PAHCI_REGISTER)(pr)) = (AHCI_DWORD)v) )


/*---------------------------------------------------------------------------*\
	List Control Register
\*---------------------------------------------------------------------------*/
typedef enum {
	AHCI_LIST_nop = 0,
	AHCI_LIST_remove,
	AHCI_LIST_append,
	AHCI_LIST_insert
} AHCI_LIST_Command;

typedef enum {
	AHCI_LIST_lowPrio = 0,
	AHCI_LIST_highPrio
} AHCI_LIST_Type;

#define AHCI_LISTCR_workingTD_SHIFT	0
#define AHCI_LISTCR_command_SHIFT		14
#define AHCI_LISTCR_existingTD_SHIFT	16
#define AHCI_LISTCR_list_SHIFT			30

#define AHCI_LISTCR_workingTD_MASK		0x00003FFF //14 Bits
#define AHCI_LISTCR_command_MASK		0x0000C000 // 2 Bits
#define AHCI_LISTCR_existingTD_MASK		0x3FFF0000 //14 Bits
#define AHCI_LISTCR_list_MASK			0x40000000 // 1 Bit

#define AHCI_LISTCR_workingTD(v)	(((v) & AHCI_LISTCR_workingTD_MASK) >>	AHCI_LISTCR_workingTD_SHIFT)
#define AHCI_LISTCR_command(v)		(((v) & AHCI_LISTCR_COMMAND_MASK) >> AHCI_LISTCR_command_SHIFT)
#define AHCI_LISTCR_existingTD(v)	(((v) & AHCI_LISTCR_EXISTING_TD_MASK) >> AHCI_LISTCR_existingTD_SHIFT)
#define AHCI_LISTCR_list(v)			(((v) & AHCI_LISTCR_LIST_SHIFT) >> AHCI_LISTCR_list_SHIFT)

/*---------------------------------------------------------------------------*\
	Global Control Register
\*---------------------------------------------------------------------------*/
#define AHCI_GCR_globalReset_FLAG	0x1
#define AHCI_GCR_haltHost_FLAG		0x2
#define AHCI_GCR_restartHost_FLAG	0x4

/*---------------------------------------------------------------------------*\
	SOF Config Register
\*---------------------------------------------------------------------------*/
#define AHCI_SOFCR_sofReloadValue_MASK	0x3FFF //14 Bit
#define AHCI_SOFCR_sofReloadValue(v)	((v) & AHCI_SOFCR_sofReloadValue_MASK) 

/*---------------------------------------------------------------------------*\
	Memory Config Register
\*---------------------------------------------------------------------------*/
#define AHCI_MEMCR_lastRxAddress_MASK	0x0003FFFF //18 Bit
#define AHCI_MEMCR_lastRxAddress(v)	((v) & AHCI_MEMCR_lastRxAddress_MASK) 

/*---------------------------------------------------------------------------*\
	Reset Config Register
\*---------------------------------------------------------------------------*/
#define AHCI_RESETCR_resetDuration_MASK	0x000FFFFF //20 Bit
#define AHCI_RESETCR_resetDuration(v)	((v) & AHCI_RESETCR_resetDuration_MASK)

/*---------------------------------------------------------------------------*\
	Resume Config Register
\*---------------------------------------------------------------------------*/
#define AHCI_RESUMECR_resumeDuration_MASK	0x000FFFFF //20 Bit
#define AHCI_RESUMECR_resumeDuration(v)	((v) & AHCI_RESUMECR_resumeDuration_MASK)

/*---------------------------------------------------------------------------*\
	Port Control Register READ
\*---------------------------------------------------------------------------*/
#define AHCI_PCRR_portEnabled_FLAG		0x01
#define AHCI_PCRR_portReset_FLAG		0x02
#define AHCI_PCRR_portSuspended_FLAG	0x04
#define AHCI_PCRR_portResume_FLAG		0x08
#define AHCI_PCRR_deviceConnected_FLAG	0x10
#define AHCI_PCRR_remoteWakeup_FLAG		0x20

/*---------------------------------------------------------------------------*\
	Port Control Register WRITE
\*---------------------------------------------------------------------------*/
#define AHCI_PCRW_disablePort_FLAG			0x01
#define AHCI_PCRW_resetPort_FLAG			0x02
#define AHCI_PCRW_suspendPort_FLAG			0x04
#define AHCI_PCRW_resumePort_FLAG			0x08
#define AHCI_PCRW_clearRemoteWakeup_FLAG	0x20

/*---------------------------------------------------------------------------*\
	Interrupt Status Register
\*---------------------------------------------------------------------------*/
#define AHCI_ISR_sof_FLAG				0x01	//W1C
#define AHCI_ISR_newStatusWord_FLAG		0x02	//W1C
#define AHCI_ISR_portStatusChange_FLAG	0x04	//W1C
#define AHCI_ISR_hostHalted_FLAG		0x08	//W1C

/*---------------------------------------------------------------------------*\
	Interrupt Enable Register
\*---------------------------------------------------------------------------*/
#define AHCI_IER_sof_FLAG				0x01
#define AHCI_IER_newStatusWord_FLAG		0x02
#define AHCI_IER_portStatusChange_FLAG	0x04
#define AHCI_IER_hostHalted_FLAG		0x08

/*---------------------------------------------------------------------------*\
	Interrupt Config Register
\*---------------------------------------------------------------------------*/
#define AHCI_INTCR_intPeriod_MASK	0xFF //8 Bit
#define AHCI_INTCR_intPeriod(v)		((v) & AHCI_INTCR_intPeriod_MASK)

/*---------------------------------------------------------------------------*\
	Current Rx Address Register
\*---------------------------------------------------------------------------*/
#define AHCI_CRXAR_curRxAddress_MASK 0x0003FFFF //18 Bit
#define AHCI_CRXAR_curRxAddress(v) ((v) & AHCI_CRXAR_curRxAddress_MASK)

/*---------------------------------------------------------------------------*\
	Frame Number Register
\*---------------------------------------------------------------------------*/
#define AHCI_FNR_curFrameNumber_MASK 0xFFFF //16 Bit
#define AHCI_FNR_curFrameNumber(v) ((v) & AHCI_FNR_curFrameNumber_MASK)

/*---------------------------------------------------------------------------*\
	Revision ID Register
\*---------------------------------------------------------------------------*/
#define AHCI_RIDR_numPorts_SHIFT		0
#define AHCI_RIDR_revisionID_SHIFT		4
#define AHCI_RIDR_maxRamAddress_SHIFT	12

#define AHCI_RIDR_numPorts_MASK			0x0000000F
#define AHCI_RIDR_revisionID_MASK		0x00000FF0
#define AHCI_RIDR_maxRamAddress_MASK	0xFFFFF000

#define AHCI_RIDR_numPorts(v)		((v) & AHCI_RIDR_numPorts_MASK)
#define AHCI_RIDR_revisionID(v)		(((v) & AHCI_RIDR_revisionID_MASK) >> AHCI_RIDR_revisionID_SHIFT)
#define AHCI_RIDR_maxRamAddress(v)		(((v) & AHCI_RIDR_maxRamAddress_MASK) >> AHCI_RIDR_maxRamAddress_SHIFT)

#endif //_ahcireg_h_
