
typedef void *pointer;

typedef unsigned int memType;

typedef struct { float hi, lo; } range;


typedef enum
{
    CHIP_FAMILY_UNKNOW,
    CHIP_FAMILY_LEGACY,
    CHIP_FAMILY_RADEON,
    CHIP_FAMILY_RV100,
    CHIP_FAMILY_RS100,    /* U1 (IGP320M) or A3 (IGP320)*/
    CHIP_FAMILY_RV200,
    CHIP_FAMILY_RS200,    /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */
    CHIP_FAMILY_R200,
    CHIP_FAMILY_RV250,
    CHIP_FAMILY_RS300,    /* RS300/RS350 */
    CHIP_FAMILY_RV280,
    CHIP_FAMILY_R300,
    CHIP_FAMILY_R350,
    CHIP_FAMILY_RV350,
    CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
    CHIP_FAMILY_R420,     /* R420/R423/M18 */
    CHIP_FAMILY_RV410,    /* RV410, M26 */
    CHIP_FAMILY_RS400,    /* xpress 200, 200m (RS400) Intel */
    CHIP_FAMILY_RS480,    /* xpress 200, 200m (RS410/480/482/485) AMD */
    CHIP_FAMILY_RV515,    /* rv515 */
    CHIP_FAMILY_R520,     /* r520 */
    CHIP_FAMILY_RV530,    /* rv530 */
    CHIP_FAMILY_R580,     /* r580 */
    CHIP_FAMILY_RV560,    /* rv560 */
    CHIP_FAMILY_RV570,    /* rv570 */
    CHIP_FAMILY_RS600,
    CHIP_FAMILY_RS690,
    CHIP_FAMILY_RS740,
    CHIP_FAMILY_R600,     /* r600 */
    CHIP_FAMILY_R630,
    CHIP_FAMILY_RV610,
    CHIP_FAMILY_RV630,
    CHIP_FAMILY_RV670,
    CHIP_FAMILY_RV620,
    CHIP_FAMILY_RV635,
    CHIP_FAMILY_RS780,
    CHIP_FAMILY_RV770,
    CHIP_FAMILY_LAST
} RADEONChipFamily;

#define IS_RV100_VARIANT ((rhdPtr->ChipFamily == CHIP_FAMILY_RV100)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RV200)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RS100)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RS200)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RV250)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RV280)  ||  \
        (rhdPtr->ChipFamily == CHIP_FAMILY_RS300))


#define IS_R300_VARIANT ((info->ChipFamily == CHIP_FAMILY_R300)  ||  \
        (info->ChipFamily == CHIP_FAMILY_RV350) ||  \
        (info->ChipFamily == CHIP_FAMILY_R350)  ||  \
        (info->ChipFamily == CHIP_FAMILY_RV380) ||  \
        (info->ChipFamily == CHIP_FAMILY_R420)  ||  \
        (info->ChipFamily == CHIP_FAMILY_RV410) ||  \
        (info->ChipFamily == CHIP_FAMILY_RS400) ||  \
        (info->ChipFamily == CHIP_FAMILY_RS480))

#define IS_AVIVO_VARIANT ((info->ChipFamily >= CHIP_FAMILY_RV515))

#define IS_DCE3_VARIANT ((info->ChipFamily >= CHIP_FAMILY_RV620))

#define IS_R500_3D ((info->ChipFamily == CHIP_FAMILY_RV515)  ||  \
	(info->ChipFamily == CHIP_FAMILY_R520)   ||  \
	(info->ChipFamily == CHIP_FAMILY_RV530)  ||  \
	(info->ChipFamily == CHIP_FAMILY_R580)   ||  \
	(info->ChipFamily == CHIP_FAMILY_RV560)  ||  \
	(info->ChipFamily == CHIP_FAMILY_RV570))

#define IS_R300_3D ((info->ChipFamily == CHIP_FAMILY_R300)  ||  \
	(info->ChipFamily == CHIP_FAMILY_RV350) ||  \
	(info->ChipFamily == CHIP_FAMILY_R350)  ||  \
	(info->ChipFamily == CHIP_FAMILY_RV380) ||  \
	(info->ChipFamily == CHIP_FAMILY_R420)  ||  \
	(info->ChipFamily == CHIP_FAMILY_RV410) ||  \
	(info->ChipFamily == CHIP_FAMILY_RS690) ||  \
	(info->ChipFamily == CHIP_FAMILY_RS600) ||  \
	(info->ChipFamily == CHIP_FAMILY_RS740) ||  \
	(info->ChipFamily == CHIP_FAMILY_RS400) ||  \
    (info->ChipFamily == CHIP_FAMILY_RS480))


typedef enum {
	CARD_PCI,
	CARD_AGP,
	CARD_PCIE
} RADEONCardType;

enum radeon_chip_flags {
    RADEON_FAMILY_MASK  =  0x0000ffffUL,
    RADEON_FLAGS_MASK   =  0xffff0000UL,
    RADEON_IS_MOBILITY  =  0x00010000UL,
    RADEON_IS_IGP       =  0x00020000UL,
    RADEON_SINGLE_CRTC  =  0x00040000UL,
    RADEON_IS_AGP       =  0x00080000UL,
    RADEON_HAS_HIERZ    =  0x00100000UL,
    RADEON_IS_PCIE      =  0x00200000UL,
    RADEON_NEW_MEMMAP   =  0x00400000UL,
    RADEON_IS_PCI       =  0x00800000UL,
    RADEON_IS_IGPGART   =  0x01000000UL,
};


/*
 * Errata workarounds
 */
typedef enum {
       CHIP_ERRATA_R300_CG             = 0x00000001,
       CHIP_ERRATA_PLL_DUMMYREADS      = 0x00000002,
       CHIP_ERRATA_PLL_DELAY           = 0x00000004
} RADEONErrata;

typedef struct
{
    u32_t pci_device_id;
    RADEONChipFamily chip_family;
    int mobility;
    int igp;
    int nocrtc2;
    int nointtvout;
    int singledac;
} RADEONCardInfo;


#define RHD_FB_BAR         0
#define RHD_MMIO_BAR       2

#define RHD_MEM_GART       1
#define RHD_MEM_FB         2

#define RADEON_DEFAULT_GART_SIZE         8       /* MB (must be 2^n and > 4MB) */
#define R300_DEFAULT_GART_SIZE           32      /* MB (for R300 and above) */
#define RADEON_DEFAULT_RING_SIZE         1       /* MB (must be page aligned) */
#define RADEON_DEFAULT_BUFFER_SIZE       2       /* MB (must be page aligned) */
#define RADEON_DEFAULT_GART_TEX_SIZE     1       /* MB (must be page aligned) */

#define RADEON_DEFAULT_CP_TIMEOUT        100000  /* usecs */

#define RADEON_DEFAULT_PCI_APER_SIZE     32      /* in MB */

#define RADEON_PCIGART_TABLE_SIZE      (32*1024)

#define RADEON_IDLE_RETRY      16 /* Fall out of idle loops after this count */
#define RADEON_TIMEOUT    4000000 /* Fall out of wait loops after this count */


typedef struct RHDRec
{
  addr_t            MMIOBase;
  size_t            MMIOMapSize;

  u32_t             lock;

  addr_t            FbFreeStart;
  addr_t            FbFreeSize;

 /* visible part of the framebuffer */
//  unsigned int      FbScanoutStart;
//  unsigned int      FbScanoutSize;

//  u32_t            LinearAddr;           /* Frame buffer physical address     */

  addr_t            fbLocation;           /* Frame buffer physical address */
  u32_t             mc_fb_location;
  u32_t             mc_agp_location;
  u32_t             mc_agp_location_hi;

  size_t            videoRam;

  u32_t             MemCntl;
  u32_t             BusCntl;
  unsigned long     FbMapSize;            /* Size of frame buffer, in bytes    */
  unsigned long     FbSecureSize;         /* Size of secured fb area at end of
                                            framebuffer */

  RADEONChipFamily  ChipFamily;
  RADEONErrata      ChipErrata;

  char             *chipset;

  Bool              IsIGP;
  Bool              IsMobility;
  Bool              HasCRTC2;

  u32_t             bus;
  u32_t             devfn;

  PCITAG            PciTag;
  u16_t             PciDeviceID;

  u16_t             subvendor_id;
  u16_t             subdevice_id;

  RADEONCardType    cardType;            /* Current card is a PCI card */

  u32_t             memBase[6];
  u32_t             ioBase[6];
  u32_t             memtype[6];
  u32_t             memsize[6];

  struct mem_block  *fb_heap;
  struct mem_block  *gart_heap;

  u32_t             displayWidth;
  u32_t             displayHeight;

  u32_t             gart_type;
  u32_t            *gart_table;
  addr_t            gart_table_dma;
  addr_t            gart_vm_start;
  size_t            gart_size;

  u32_t*            ringBase;
  u32_t             ring_rp;
  u32_t             ring_wp;
  u32_t             ringSize;
  u32_t             ring_avail;

  u32_t             bufSize;
  u32_t             pciAperSize;
  u32_t             CPusecTimeout;

  int               __xmin;
  int               __ymin;
  int               __xmax;
  int               __ymax;

  u32_t             gui_control;
  u32_t             dst_pitch_offset;
  u32_t             surface_cntl;


  volatile u32_t    host_rp   __attribute__ ((aligned (128)));

  volatile u32_t    scratch0  __attribute__ ((aligned (128)));
  volatile u32_t    scratch1;
  volatile u32_t    scratch2;
  volatile u32_t    scratch3;
  volatile u32_t    scratch4;
  volatile u32_t    scratch5;
  volatile u32_t    scratch6;
  volatile u32_t    scratch7;

  int               RamWidth  __attribute__ ((aligned (128)));
  Bool              IsDDR;

  int               num_gb_pipes;
  int               has_tcl;

}RHD_t, *RHDPtr;

extern RHD_t rhd;

#define RADEON_CP_PACKET0              0x00000000
#define RADEON_CP_PACKET1              0x40000000
#define RADEON_CP_PACKET2              0x80000000
#define RADEON_CP_PACKET3              0xC0000000

# define RADEON_CNTL_PAINT             0x00009100
# define RADEON_CNTL_BITBLT            0x00009200
# define RADEON_CNTL_TRANBLT           0x00009C00

# define RADEON_CNTL_PAINT_POLYLINE    0x00009500
# define RADEON_CNTL_PAINT_MULTI       0x00009A00

#if R300_PIO

#define BEGIN_ACCEL(n)      FIFOWait(n)
#define FINISH_ACCEL()
#define COMMIT_RING()
#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val)

#else

#define CP_PACKET0(reg, n)            \
    (RADEON_CP_PACKET0 | ((n - 1 ) << 16) | ((reg) >> 2))

#define CP_PACKET1(reg0, reg1)            \
	(RADEON_CP_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))

#define CP_PACKET2()                     \
  (RADEON_CP_PACKET2)

#define CP_PACKET3( pkt, n )             \
	(RADEON_CP_PACKET3 | (pkt) | ((n) << 16))


#define BEGIN_RING( req ) do {                                     \
     int avail = rhd.ring_rp-rhd.ring_wp;                          \
     if (avail <=0 ) avail+= 0x4000;                               \
     if( (req)+128 > avail)                                        \
     {                                                             \
        rhd.ring_rp = INREG(RADEON_CP_RB_RPTR);                    \
        avail = rhd.ring_rp-rhd.ring_wp;                           \
        if (avail <= 0) avail+= 0x4000;                            \
        if( (req)+128 > avail){                                    \
           unlock_device();                                        \
           return 0;                                               \
        };                                                         \
     }                                                             \
     ring = &rhd.ringBase[rhd.ring_wp];                            \
}while(0)

#define ADVANCE_RING()

#define OUT_RING( x )        *ring++ = (x)

#define CP_REG(reg, val)                 \
do {                                     \
    ring[0]  = CP_PACKET0((reg), 1);     \
    ring[1]  = (val);                    \
    ring+=  2;                           \
} while (0)

#define DRM_MEMORYBARRIER()  __asm__ volatile("lock; addl $0,0(%%esp)" : : : "memory");

#define COMMIT_RING() do {                             \
  rhd.ring_wp = (ring - rhd.ringBase) & 0x3FFF;        \
  /* Flush writes to ring */                           \
    DRM_MEMORYBARRIER();                               \
  /*GET_RING_HEAD( dev_priv );          */             \
  OUTREG( RADEON_CP_RB_WPTR, rhd.ring_wp);             \
    /* read from PCI bus to ensure correct posting */  \
/*  INREG( RADEON_CP_RB_RPTR );    */                  \
} while (0)

#define BEGIN_ACCEL(n)          BEGIN_RING(2*(n))
#define FINISH_ACCEL()          COMMIT_RING()

#define OUT_ACCEL_REG(reg, val) CP_REG((reg), (val))

#endif

typedef struct {
    int			token;		/* id of the token */
    const char *	name;		/* token name */
} SymTabRec, *SymTabPtr;


extern inline void lock_device()
{
     __asm__ __volatile__ (
     "call *__imp__WaitMutex"
     ::"b" (&rhd.lock));
};

extern inline void unlock_device()
{
    rhd.lock = 0;
}

extern inline void
OUTREG8(u16_t offset, u8_t value)
{
  *(volatile u8_t *)((u8_t *)(rhd.MMIOBase + offset)) = value;
}


extern inline u32_t INREG(u16_t offset)
{
  return *(volatile u32_t *)((u8_t*)(rhd.MMIOBase + offset));
}


extern inline void OUTREG(u16_t offset, u32_t value)
{
  *(volatile u32_t *)((u8_t *)(rhd.MMIOBase + offset)) = value;
}

//#define OUTREG( offset, value) \
//  *(volatile u32_t *)((u8_t *)(rhd.MMIOBase + (u32_t)(offset))) = (u32_t)value


extern inline u32_t _RHDRegRead(RHDPtr rhdPtr, u16_t offset)
{
  return *(volatile u32_t *)((u8_t*)(rhdPtr->MMIOBase + offset));
}

extern inline void
MASKREG(u16_t offset, u32_t value, u32_t mask)
{
  u32_t tmp;

  tmp = INREG(offset);
  tmp &= ~mask;
  tmp |= (value & mask);
  OUTREG(offset, tmp);
};


#define INPLL( addr) RADEONINPLL( addr)

#define OUTPLL( addr, val) RADEONOUTPLL( addr, val)


extern inline void
_RHDRegWrite(RHDPtr rhdPtr, u16_t offset, u32_t value)
{
  *(volatile u32_t *)((u8_t *)(rhdPtr->MMIOBase + offset)) = value;
}

extern inline void
_RHDRegMask(RHDPtr rhdPtr, u16_t offset, u32_t value, u32_t mask)
{
  u32_t tmp;

  tmp = _RHDRegRead(rhdPtr, offset);
  tmp &= ~mask;
  tmp |= (value & mask);
  _RHDRegWrite(rhdPtr, offset, tmp);
};

#define RHDRegRead(ptr, offset) _RHDRegRead((ptr)->rhdPtr, (offset))
#define RHDRegWrite(ptr, offset, value) _RHDRegWrite((ptr)->rhdPtr, (offset), (value))
#define RHDRegMask(ptr, offset, value, mask) _RHDRegMask((ptr)->rhdPtr, (offset), (value), (mask))


#define RHDFUNC(ptr)

#define DBG(x) x
//  #define DBG(x)

#pragma pack (push,1)
typedef struct s_cursor
{
   u32_t   magic;                           // 'CURS'
   void  (*destroy)(struct s_cursor*);    // destructor
   u32_t   fd;                              // next object in list
   u32_t   bk;                              // prev object in list
   u32_t   pid;                             // owner id

   void *base;                            // allocated memory
   u32_t   hot_x;                           // hotspot coords
   u32_t   hot_y;
}cursor_t;
#pragma pack (pop)

#define LOAD_FROM_FILE   0
#define LOAD_FROM_MEM    1
#define LOAD_INDIRECT    2

cursor_t *create_cursor(u32_t pid, void *src, u32_t flags);
void __stdcall copy_cursor(void *img, void *src);
void destroy_cursor(cursor_t *cursor);
void __destroy_cursor(cursor_t *cursor);                // wrap

void __stdcall r500_SelectCursor(cursor_t *cursor);
void __stdcall r500_SetCursor(cursor_t *cursor, int x, int y);
void __stdcall r500_CursorRestore(int x, int y);


typedef struct {
    u32_t x ;
    u32_t y ;
} xPointFixed;

typedef u32_t   xFixed_16_16;

typedef xFixed_16_16  xFixed;

#define XFIXED_BITS 16

#define xFixedToInt(f)  (int) ((f) >> XFIXED_BITS)
#define IntToxFixed(i)  ((xFixed) (i) << XFIXED_BITS)

#define xFixedToFloat(f) (((float) (f)) / 65536)

#define PICT_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) |  \
					 ((type) << 16) | \
					 ((a) << 12) | \
					 ((r) << 8) | \
					 ((g) << 4) | \
					 ((b)))

#define PICT_FORMAT_A(f)  (((f) >> 12) & 0x0f)
#define PICT_FORMAT_RGB(f)  (((f)      ) & 0xfff)

#define PICT_TYPE_OTHER 0
#define PICT_TYPE_A     1
#define PICT_TYPE_ARGB	2
#define PICT_TYPE_ABGR	3
#define PICT_TYPE_COLOR	4
#define PICT_TYPE_GRAY	5

typedef enum _PictFormatShort {
   PICT_a8r8g8b8 =	PICT_FORMAT(32,PICT_TYPE_ARGB,8,8,8,8),
   PICT_x8r8g8b8 =	PICT_FORMAT(32,PICT_TYPE_ARGB,0,8,8,8),
   PICT_a8b8g8r8 =	PICT_FORMAT(32,PICT_TYPE_ABGR,8,8,8,8),
   PICT_x8b8g8r8 =	PICT_FORMAT(32,PICT_TYPE_ABGR,0,8,8,8),

/* 24bpp formats */
   PICT_r8g8b8 =	PICT_FORMAT(24,PICT_TYPE_ARGB,0,8,8,8),
   PICT_b8g8r8 =	PICT_FORMAT(24,PICT_TYPE_ABGR,0,8,8,8),

/* 16bpp formats */
   PICT_r5g6b5 =	PICT_FORMAT(16,PICT_TYPE_ARGB,0,5,6,5),
   PICT_b5g6r5 =	PICT_FORMAT(16,PICT_TYPE_ABGR,0,5,6,5),

   PICT_a1r5g5b5 =	PICT_FORMAT(16,PICT_TYPE_ARGB,1,5,5,5),
   PICT_x1r5g5b5 =	PICT_FORMAT(16,PICT_TYPE_ARGB,0,5,5,5),
   PICT_a1b5g5r5 =	PICT_FORMAT(16,PICT_TYPE_ABGR,1,5,5,5),
   PICT_x1b5g5r5 =	PICT_FORMAT(16,PICT_TYPE_ABGR,0,5,5,5),
   PICT_a4r4g4b4 =	PICT_FORMAT(16,PICT_TYPE_ARGB,4,4,4,4),
   PICT_x4r4g4b4 =	PICT_FORMAT(16,PICT_TYPE_ARGB,0,4,4,4),
   PICT_a4b4g4r4 =	PICT_FORMAT(16,PICT_TYPE_ABGR,4,4,4,4),
   PICT_x4b4g4r4 =	PICT_FORMAT(16,PICT_TYPE_ABGR,0,4,4,4),

/* 8bpp formats */
   PICT_a8 =		PICT_FORMAT(8,PICT_TYPE_A,8,0,0,0),
   PICT_r3g3b2 =	PICT_FORMAT(8,PICT_TYPE_ARGB,0,3,3,2),
   PICT_b2g3r3 =	PICT_FORMAT(8,PICT_TYPE_ABGR,0,3,3,2),
   PICT_a2r2g2b2 =	PICT_FORMAT(8,PICT_TYPE_ARGB,2,2,2,2),
   PICT_a2b2g2r2 =	PICT_FORMAT(8,PICT_TYPE_ABGR,2,2,2,2),

   PICT_c8 =		PICT_FORMAT(8,PICT_TYPE_COLOR,0,0,0,0),
   PICT_g8 =		PICT_FORMAT(8,PICT_TYPE_GRAY,0,0,0,0),

   PICT_x4a4 =		PICT_FORMAT(8,PICT_TYPE_A,4,0,0,0),

   PICT_x4c4 =		PICT_FORMAT(8,PICT_TYPE_COLOR,0,0,0,0),
   PICT_x4g4 =		PICT_FORMAT(8,PICT_TYPE_GRAY,0,0,0,0),

/* 4bpp formats */
   PICT_a4 =		PICT_FORMAT(4,PICT_TYPE_A,4,0,0,0),
   PICT_r1g2b1 =	PICT_FORMAT(4,PICT_TYPE_ARGB,0,1,2,1),
   PICT_b1g2r1 =	PICT_FORMAT(4,PICT_TYPE_ABGR,0,1,2,1),
   PICT_a1r1g1b1 =	PICT_FORMAT(4,PICT_TYPE_ARGB,1,1,1,1),
   PICT_a1b1g1r1 =	PICT_FORMAT(4,PICT_TYPE_ABGR,1,1,1,1),

   PICT_c4 =		PICT_FORMAT(4,PICT_TYPE_COLOR,0,0,0,0),
   PICT_g4 =		PICT_FORMAT(4,PICT_TYPE_GRAY,0,0,0,0),

/* 1bpp formats */
   PICT_a1 =		PICT_FORMAT(1,PICT_TYPE_A,1,0,0,0),

   PICT_g1 =		PICT_FORMAT(1,PICT_TYPE_GRAY,0,0,0,0),
} PictFormatShort;

void dump_mem();



RHDPtr  FindPciDevice();

static __inline__ int drm_device_is_pcie(PCITAG pciTag);
static void init_pipes(RHDPtr info);
Bool   init_cp(RHDPtr info);

Bool    RHDPreInit();

void    R5xx2DInit();

int     Init3DEngine(RHDPtr info);

void    init_gart(RHDPtr info);

int     rhdInitHeap(RHDPtr rhdPtr);


