/*
* @(#) pci.h $Date: 2000/03/09 15:31:26 $Revision: r11ros/3 PATCH_11.00 (PHKL_21270)
*/
/*-------------------------------------------------------------------------
 *
 * PCI Bus Dependent Services 
 *
 *-------------------------------------------------------------------------
 */

#ifndef PCI_H
#define PCI_H

#ifdef _KERNEL_BUILD
#include "../h/_inttypes.h"
#else	/* ! _KERNEL_BUILD */
#include <sys/_inttypes.h>
#endif /* _KERNEL_BUILD */

/*-------------------------------------------------------------------------
 *
 * System Private Structures (exposed for macros and strong type checking)
 * No assumptions on size or names should be made!  Driver useable 
 * definitions follow.
 *
 *                       All fields are reserved!
 *
 *-------------------------------------------------------------------------
 */
typedef void *PHOST_ADAPTER;
typedef uint32_t PCI_CFG_TOKEN;

typedef union {
	char *addr;
	uint32_t hndl;
} PCI_PORT_HNDL;

typedef struct _bus_trans_desc {
    uint32_t read_width;      /* performance access DMA typical width    *
			       * (in 32bit words) for reads              */
    uint32_t write_width;     /* performance access DMA typical width    *
			       * (in 32bit words) for writes             */
    uint8_t reserved[20];     /* reserved */
} BUS_TRANS_DESC;


#if defined(__STDC__) || defined(__cplusplus)
/*
 * ANSI C Function Prototypes
 */
typedef void (*RD_CFG_B)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint8_t *);
typedef void (*RD_CFG_W)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint16_t *);
typedef void (*RD_CFG_D)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint32_t *);

typedef void (*WR_CFG_B)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint8_t);
typedef void (*WR_CFG_W)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint16_t);
typedef void (*WR_CFG_D)(PHOST_ADAPTER, PCI_CFG_TOKEN, int, uint32_t);

typedef void (*RD_IO_B)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint8_t *);
typedef void (*RD_IO_W)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint16_t *);
typedef void (*RD_IO_D)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint32_t *);

typedef void (*WR_IO_B)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint8_t);
typedef void (*WR_IO_W)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint16_t);
typedef void (*WR_IO_D)(PHOST_ADAPTER, PCI_PORT_HNDL, unsigned int, uint32_t);

typedef void (*RD_B)(PHOST_ADAPTER,  uint8_t *, uint8_t *);
typedef void (*RD_W)(PHOST_ADAPTER, uint16_t *, uint16_t *);
typedef void (*RD_D)(PHOST_ADAPTER, uint32_t *, uint32_t *);
#if defined(__LP64__) || defined(__LL_MODE__)
typedef void (*RD_DD)(PHOST_ADAPTER, uint64_t *, uint64_t *);
#else
typedef void *RD_DD;   /* Function not available to non-64-bit drivers */
#endif

typedef void (*WR_B)(PHOST_ADAPTER, uint8_t *, uint8_t);
typedef void (*WR_W)(PHOST_ADAPTER, uint16_t *, uint16_t);
typedef void (*WR_D)(PHOST_ADAPTER, uint32_t *, uint32_t);
#if defined(__LP64__) || defined(__LL_MODE__)
typedef void (*WR_DD)(PHOST_ADAPTER, uint64_t *, uint64_t);
#else
typedef void *WR_DD;   /* Function not available to non-64-bit drivers */
#endif

typedef int (*GET_PORT)(PHOST_ADAPTER, uint32_t, unsigned int, PCI_PORT_HNDL*);
typedef int (*UNMAP_PORT)(PHOST_ADAPTER, uint32_t, unsigned int, PCI_PORT_HNDL);

typedef int (*BUS_TRANS)(PHOST_ADAPTER, PCI_CFG_TOKEN, BUS_TRANS_DESC *);
typedef int (*GET_FRU_INFO)(PHOST_ADAPTER, PCI_CFG_TOKEN, int *);
typedef int (*GET_MEM_MODE)(PHOST_ADAPTER, PCI_CFG_TOKEN);
typedef void (*DRIVER_SCAN)(void *);
typedef int (*SET_SCAN_BOOKMARKS)(PHOST_ADAPTER, PCI_CFG_TOKEN,
                DRIVER_SCAN, DRIVER_SCAN, void * );

typedef int (*PCI_ATTACH)(uint32_t, struct isc_table_type*);

#else
/*
 * K & R forward declarations
 */
typedef void (*RD_CFG_B)();
typedef void (*RD_CFG_W)();
typedef void (*RD_CFG_D)();

typedef void (*WR_CFG_B)();
typedef void (*WR_CFG_W)();
typedef void (*WR_CFG_D)();

typedef void (*RD_IO_B)();
typedef void (*RD_IO_W)();
typedef void (*RD_IO_D)();

typedef void (*WR_IO_B)();
typedef void (*WR_IO_W)();
typedef void (*WR_IO_D)();

typedef void (*RD_B)();
typedef void (*RD_W)();
typedef void (*RD_D)();
typedef void (*RD_DD)();

typedef void (*WR_B)();
typedef void (*WR_W)();
typedef void (*WR_D)();
typedef void (*WR_DD)();

typedef int (*GET_PORT)();
typedef int (*UNMAP_PORT)();

typedef int (*BUS_TRANS)();
typedef int (*GET_FRU_INFO)();
typedef int (*GET_MEM_MODE)();
typedef void (*DRIVER_SCAN)();
typedef int (*SET_SCAN_BOOKMARKS)();

typedef int (*PCI_ATTACH)();

#endif


extern PCI_ATTACH pci_attach;


/*
 * These tables should NEVER be accessed by drivers directly!
 */
typedef struct _pci_bus_dep_func_tbl { 
    RD_CFG_B rd_cfg_b; 
    RD_CFG_W rd_cfg_w; 
    RD_CFG_D rd_cfg_d; 
    WR_CFG_B wr_cfg_b; 
    WR_CFG_W wr_cfg_w;
    WR_CFG_D wr_cfg_d; 
    
    RD_IO_B rd_io_b; 
    RD_IO_W rd_io_w; 
    RD_IO_D rd_io_d;
    WR_IO_B wr_io_b; 
    WR_IO_W wr_io_w; 
    WR_IO_D wr_io_d; 

    RD_B rd_uint8;
    RD_W rd_uint16;
    RD_D rd_uint32;
    RD_DD rd_uint64;
    WR_B wr_uint8;
    WR_W wr_uint16;
    WR_D wr_uint32;
    WR_DD wr_uint64;
    
    GET_PORT get_port;
    UNMAP_PORT unmap_port; 

    GET_FRU_INFO get_fru_info; 
    BUS_TRANS bus_trans;

    /*
     * All functions above this point in the table were available in
     * revision 0 of PCI services.  The functionality added below is
     * usable only in revision 1 and above.  Drivers trying to use new
     * functionality on an old rev of services will get an
     * "unavailable" error code returned to them.
     */
    uintptr_t rev_field;          /* rev field - revision 1 */

    uintptr_t reserved_future;    /* reserved for future use */
    uintptr_t reserved_busdep;    /* reserved for PCI-adapter-specific use */

    GET_MEM_MODE get_mem_mode;    /* rev 1 function */

    uintptr_t reserved1;
    uintptr_t reserved2;
    uintptr_t reserved3;
    uintptr_t reserved4;
} PCI_BUS_DEP_FUNC_TBL, *PPCI_BUS_DEP_FUNC_TBL; 

/*
** "host_adapter" property is created for each PCI device.
** "bridge data" property is only created for each bus converter.
**     host adapter field is derived from "bridge_data.ha".
**
** WARNING: PCI bus info is "public". PCI macros (defined below) derefence
** fields from this structure. The host adapter field is passed to
** functions defined  in func tbl. cfg_tok is only passed to configuration
** space accessor functions/macros.
*/
typedef struct _pci_bus_info { 
    PHOST_ADAPTER host_adapter; 	/* pointer to H2P object */
    PCI_CFG_TOKEN cfg_tok;              /* token to access pci device */
    PPCI_BUS_DEP_FUNC_TBL func_tbl; 
} PCI_BUS_INFO, *PPCI_BUS_INFO;



/*----------------------------------------------------------------------------
 *
 * Driver Useable Definitions
 *
 *----------------------------------------------------------------------------
 */

/*
 * Configuration space offsets.
 */
#define PCI_CS_VENDOR_ID       0x00
#define PCI_CS_DEVICE_ID       0x02
#define PCI_CS_COMMAND         0x04
#define PCI_CS_STATUS          0x06
#define PCI_CS_REV_ID          0x08
#define PCI_CS_REV_CLASS       0x08
#define PCI_CS_CLASS_BASE      0x0b
#define PCI_CS_CLASS_SUB_CLASS 0x0a
#define PCI_CS_CLASS_PROG_IF   0x09
#define PCI_CS_CACHE_LINE_SIZE 0x0c
#define PCI_CS_LATENCY_TIMER   0x0d
#define PCI_CS_HEADER_TYPE     0x0e
#define PCI_CS_BIST            0x0f
#define PCI_CS_BAR0            0x10
#define PCI_CS_BAR1            0x14
#define PCI_CS_BAR2            0x18
#define PCI_CS_BAR3            0x1c
#define PCI_CS_BAR4            0x20
#define PCI_CS_BAR5            0x24
#define PCI_CS_SUBVENDOR_ID    0x28
#define PCI_CS_SUBDEVICE_ID    0x2c
#define PCI_CS_EXP_ROM_BAR     0x30
/* reserved                    0x34 */
/* reserved                    0x38 */
#define PCI_CS_INTERRUPT_LINE  0x3c
#define PCI_CS_INTERRUPT_PIN   0x3d
#define PCI_CS_MIN_GNT         0x3e
#define PCI_CS_MAX_LAT         0x3f

/*
 * Masks for configuration data
 */
#define PCI_TYPE_MASK	0x7f
#define PCI_TYPE_MF	0x80
#define MULTI_FUNCTION(header_type) (((header_type) & PCI_TYPE_MF) == PCI_TYPE_MF)
#define P2P_BRIDGE(header_type) (((header_type) & PCI_TYPE_MASK) == 0x01)
#define PCI_TYPE_0(header_type) (((header_type) & PCI_TYPE_MASK) == 0x00)

/*
 * Bit definitions for configuration space command register
 */
#define PCI_CMD_IO_SPACE          0x001
#define PCI_CMD_MEM_SPACE         0x002
#define PCI_CMD_BUS_MASTER        0x004
#define PCI_CMD_SPEC_CYCLES       0x008
#define PCI_CMD_MEM_WR_INVAL_EN   0x010
#define PCI_CMD_VGA_PAL_SNOOP     0x020
#define PCI_CMD_PARITY_ERR_RESP   0x040
#define PCI_CMD_WAIT_CYCLE_CNTL   0x080
#define PCI_CMD_SERR_ENABLE       0x100
#define PCI_CMD_FBB_ENB           0x200

/*
** Bit definitions for configuration space status register
** Secondary Status register on PPB uses mostly same defs.
** Comments refer to status reg on primary bus.
*/
/*  bits 0:3 (aka 16:19) are reserved */
#define PCI_STAT_ECP              0x0010   /* capability */
#define PCI_STAT_66MHZ            0x0020   /* capability */
/*  bit  6   (aka 22)     is reserved */
#define PCI_STAT_FBB              0x0080   /* capability */
#define PCI_STAT_PERR_L           0x0100   /* (as mstr) perr_l asserted */
#define PCI_STAT_DEVSEL_MASK      0x0600   /* 9:10 (aka 25:26) */
#define PCI_STAT_ABORT_TGT        0x0800   /* (as mstr) we aborted target */
#define PCI_STAT_TGT_ABORTED      0x1000   /* (as mstr) target aborted us */
#define PCI_STAT_MASTER_ABORT     0x2000   /* (as tgt)  master aborted us */
#define PCI_STAT_SIG_SERR         0x4000
#define PCI_STAT_PERR_DETECT      0x8000   /* (as tgt) saw Data/Address perr */

/*
** Moved from dino3.h - it's generic
*/
#define MEM_BASE_MASK         0xfffffff0
#define IO_BASE_MASK          0xfffffffc
#define ROM_BASE_MASK         0xfffffffe

#define BAR_SPACE_INDICATOR   0x00000001
#define BAR_MEM_SPACE         0x00000000
#define BAR_IO_SPACE          0x00000001

#define MEM_BAR_TYPE(bar)            ((bar) & MEM_BAR_TYPE_RESERVED)
#define MEM_BAR_TYPE_32_BIT          0
#define MEM_BAR_TYPE_32_BELOW_1MEG   2
#define MEM_BAR_TYPE_64_BIT          4
#define MEM_BAR_TYPE_RESERVED        6

#define MEM_BAR_PREFETCHABLE         8
/* end of defines moved from dino3.h */

/*
 * Bit definitions for class code values
 */
#define PCI_CC_LEGACY        0x0
#define PCI_CC_MASSSTORE     0x1
#define PCI_CC_NETWORK       0x2
#define PCI_CC_DISPLAY       0x3
#define PCI_CC_MULTIMEDIA    0x4
#define PCI_CC_MEMORY        0x5
#define PCI_CC_BRIDGE        0x6
#define PCI_CC_SIMPLECOMM    0x7
#define PCI_CC_BASESYSTEM    0x8
#define PCI_CC_INPUTDEV      0x9
#define PCI_CC_DOCKINGSTN    0xa
#define PCI_CC_PROCESSOR     0xb
#define PCI_CC_SERIALBUS     0xc
#define PCI_CC_WIRELESS      0xd
#define PCI_CC_I2O           0xe
#define PCI_CC_SATCOMM       0xf
#define PCI_CC_CRYPTCNTRL    0x10
#define PCI_CC_DSP           0x11

/*
** PCI ID - gets passed to claim functions
** vendor_id  is "lower" part of PCI configuration space word but
** must be upper part of ID property.
*/
typedef struct _PCI_ID {
    uint32_t vendor_id:16;
    uint32_t device_id:16;
#ifdef __LP64__
    uint32_t reserved;	/* pad to shift above bits into right place */
#endif

} PCI_ID;

/*-------------------------------------------------------------------------
 *
 *
 * PCI Services API
 *
 *
 *-------------------------------------------------------------------------
 */

/*-------------------------------------------------------------------------
 *
 * PCI Configuration Space Access API
 *
 *-------------------------------------------------------------------------
 */

/*
 * pci_read_cfg_uint8_isc(
 *     IN struct isc_table_type isc, 
 *     IN int reg_num, 
 *     OUT uint8_t *byte_read
 *     );
 */
#define pci_read_cfg_uint8_isc(isc, reg_num, byte_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_cfg_b( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	byte_read) 

/*
 * pci_read_cfg_uint16_isc(
 *     IN struct isc_table_type isc, 
 *     IN int reg_num, 
 *     OUT uint16_t *word_read
 *     );
 */
#define pci_read_cfg_uint16_isc(isc, reg_num, word_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_cfg_w( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	word_read) 

/*
 * pci_read_cfg_uint32_isc(
 *     IN struct isc_table_type isc, 
 *     IN int reg_num, 
 *     OUT uint32_t *dword_read
 *     );
 */
#define pci_read_cfg_uint32_isc(isc, reg_num, dword_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_cfg_d( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	dword_read) 


/*
 * pci_write_cfg_uint8_isc(
 *     IN struct isc_table_type isc, 
 *     IN int reg_num, 
 *     IN uint8_t byte_write
 *     );
 */
#define pci_write_cfg_uint8_isc(isc, reg_num, byte_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_cfg_b( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	byte_write) 

/*
 * pci_write_cfg_uint16_isc(
 *     IN struct isc_table_type isc, 
 *     IN int re_tg_num, 
 *     IN uint16 word_write
 *     );
 */
#define pci_write_cfg_uint16_isc(isc, reg_num, word_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_cfg_w( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	word_write) 

/*
 * pci_write_cfg_uint32_isc(
 *     IN struct isc_table_type isc, 
 *     IN int reg_num, 
 *     IN uint32_t dword_write
 *     );
 */
#define pci_write_cfg_uint32_isc(isc, reg_num, dword_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_cfg_d( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	reg_num, \
	dword_write) 


/*-------------------------------------------------------------------------
 *
 * PCI I/O Port Access API
 *
 *-------------------------------------------------------------------------
 */

/* 
 * Described Above
 *
 * typedef union {
 *   char *addr;
 *   uint32_t hndl;
 * } PCI_PORT_HNDL;
 */

/*
 * pci_read_port_uint8_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     OUT uint8_t *byte_read
 *     );
 */
#define pci_read_port_uint8_isc(isc, phndl, offset, byte_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_io_b( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	byte_read) 

/*
 * pci_read_port_uint16_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     OUT uint16_t *word_read
 *     );
 */
#define pci_read_port_uint16_isc(isc, phndl, offset, word_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_io_w( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	word_read) 

/*
 * pci_read_port_uint32_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     OUT uint32_t *dword_read
 *     );
 */
#define pci_read_port_uint32_isc(isc, phndl, offset, dword_read) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_io_d( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	dword_read) 

/*
 * pci_write_port_uint8_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     IN uint8_t byte_write
 *     );
 */
#define pci_write_port_uint8_isc(isc, phndl, offset, byte_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_io_b( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	byte_write) 

/*
 * pci_write_port_uint16_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     IN uint16_t word_write
 *     );
 */
#define pci_write_port_uint16_isc(isc, phndl, offset, word_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_io_w( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	word_write) 

/*
 * pci_write_port_uint32_isc(
 *     IN struct isc_table_type isc, 
 *     IN PCI_PORT_HNDL phndl, 
 *     IN unsigned int offset, 
 *     IN uint32_t dword_write
 *     );
 */
#define pci_write_port_uint32_isc(isc, phndl, offset, dword_write) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_io_d( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	phndl, \
	offset, \
	dword_write) 

/*
 * pci_get_port_hndl_isc(
 *     IN struct isc_table_type *isc, 
 *     IN uint32_t port_bus_addr, 
 *     IN unsigned int size, 
 *     OUT PCI_PORT_HNDL *phndl
 *     );
 */
#define pci_get_port_hndl_isc(isc, port_bus_addr, size, phndl) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->get_port( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	port_bus_addr, \
	size, \
	phndl)

/*
 * pci_unget_port_hndl_isc(
 *     IN struct isc_table_type *isc, 
 *     IN uint32_t port_bus_addr, 
 *     IN unsigned int size, 
 *     IN PCI_PORT_HNDL phndl
 *     );
 */
#define pci_unget_port_hndl_isc(isc, port_bus_addr, size, phndl) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->unmap_port( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	port_bus_addr, \
	size, \
	phndl)

/*
 * DMA Optimizations
 *
 * A performance driver may want to tune DMA performance by describing the
 * "performance" path DMA transactions to the system.
 *
 */

/*
 * typedef struct _bus_trans_desc {
    uint32_t read_width;     
			     
    uint32_t write_width;    
			     
    uint8_t reserved[20];    
 * } BUS_TRANS_DESC;
 *
 * A width of 0 indicates to use the default.
 */

#define PCI_OKAY 0
#define PCI_BUS_HINTS_NOT_USED 1
#define PCI_BUS_HINTS_BAD_DATA 2

/*
 * int pci_desc_bus_transactions_isc(
 *     IN struct isc_table_type *isc,
 *     IN BUS_TRANS_DESC *desc
 *     );
 */
#define pci_desc_bus_transactions_isc(isc, desc) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->bus_trans( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	desc)
	
/*
 * Get "field replacable unit" info on a device
 */

/* Possible return codes for the question "What slot is device X in?" */
#define PCI_GET_FRU_INFO_NOT_IMPLEMENTED  0  /* get_fru call unavailable */
#define PCI_GET_FRU_INFO_DEV_NOT_FOUND    1  /* not directly in any slot */
#define PCI_GET_FRU_INFO_BUILT_IN_FRU     2  /* built-in dev with a number */
#define PCI_GET_FRU_INFO_BUILT_IN_NO_FRU  3  /* built-in dev with no number */
#define PCI_GET_FRU_INFO_EXPANSION_DEVICE 4  /* expansion dev w/ a slot # */

/*
 * int pci_get_fru_info_isc(
 *     IN struct isc_table_type *isc,
 *     OUT INT *fru_info
 *     );
 */
#define pci_get_fru_info_isc(isc, fru_info) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->get_fru_info( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok, \
	fru_info)


/*
 * A macro that tells the driver what revision of PCI services it's
 * running under.  Drivers should not need to know this, but the
 * information is available if they want it.
 */
#define PCI_SERVICES_REVISION_ISC(isc) \
    (((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rev_field)


/*
 * Driver "initialization" routines.
 *
 * A driver which desires an init routine should use the following macro or code
 * sequence to associate the function "init_routine" with a particular driver
 * instance. Init routines are special in that they execute after all PCI
 * device/functions are found and all PCI attach routines have had an 
 * opportunity to claim them.
 */
#if defined(__STDC__) || defined(__cplusplus)
    typedef int (*INIT_ROUTINE)(struct isc_table_type *);
#else
    typedef int (*INIT_ROUTINE)();
#endif
#define CONNECT_INIT_ROUTINE(isc, init_routine) \
                            ((isc)->gfsw->init = (INIT_ROUTINE)(init_routine))

/*
 * Error macro to be used if an error occurs in attach or init:
 */
#define PCI_ATTACH_DEV_INIT_ERROR(isc) \
    (((struct wsio_if_info *)((isc)->if_info))->flags |= INIT_ERROR)


/*
 * DIRECT-MAPPED MEMORY SPACE ACCESSORS:
 *     Macros for direct-mapped memory access:
 */
#define PCI_WRITE_MEM8_DIRECT_MAPPED(addr, value) \
    (*((volatile uint8_t *)(addr)) = (uint8_t)(value))

#define PCI_WRITE_MEM16_DIRECT_MAPPED(addr, value) \
    (*((volatile uint16_t *)(addr)) =              \
          (uint16_t) (((uint16_t)(value) >> 8) |   \
                     (((uint16_t)(value) & 0xff) << 8)))

#define PCI_WRITE_MEM32_DIRECT_MAPPED(addr, value)            \
    (*((volatile uint32_t *)(addr)) =                         \
          (uint32_t) (((uint32_t)(value) >> 24) |             \
                     (((uint32_t)(value) & 0xff0000) >> 8) |  \
                     (((uint32_t)(value) & 0xff00) << 8) |    \
                     (((uint32_t)(value) & 0xff) << 24)))

#define PCI_READ_MEM8_DIRECT_MAPPED(addr, value) \
    (*((uint8_t *)(value)) = *((volatile uint8_t *)(addr)))

#define PCI_READ_MEM16_DIRECT_MAPPED(addr, value) \
{ \
    uint16_t _rru16_val = *((volatile uint16_t *)(addr)); \
        *((uint16_t*)(value)) = ((_rru16_val >> 8) | ((_rru16_val & 0xff) << 8)); \
}

#define PCI_READ_MEM32_DIRECT_MAPPED(addr, value) \
{ \
    uint32_t _rru32_val = *((volatile uint32_t *)(addr)); \
        *((uint32_t*)(value)) = (uint32_t)((_rru32_val >> 24) \
        | ((_rru32_val & 0x00ff0000) >> 8) \
        | ((_rru32_val & 0x0000ff00)<< 8) \
        | ((_rru32_val & 0x000000ff) << 24)); \
}


/*
 * FUNCTION CALL MEMORY SPACE ACCESSORS:
 *     PCI-adapter-dependent function call memory accessors:
 */
#define PCI_WRITE_MEM8_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_uint8( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint8_t *)(addr), \
	value)

#define PCI_WRITE_MEM16_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_uint16( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint16_t *)(addr), \
	value)

#define PCI_WRITE_MEM32_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->wr_uint32( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint32_t *)(addr), \
	value)

#define PCI_READ_MEM8_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_uint8( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint8_t *)(addr), \
	value)

#define PCI_READ_MEM16_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_uint16( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint16_t *)(addr), \
	value)

#define PCI_READ_MEM32_FUNC_CALL_ISC(isc, addr, value) \
    ((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rd_uint32( \
	((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	(uint32_t *)(addr), \
	value)

/*-------------------------------------------------------------------------
 *
 * PCI Memory Space Access API
 *
 *-------------------------------------------------------------------------
 *
 *    PCI MEMORY ACCESSORS:
 *
 *    Drivers in general should use the following macros to perform
 *    their accesses to PCI memory space:
 *
 *        WRITE_REG_UINT8_ISC(isc, addr, value)
 *        WRITE_REG_UINT16_ISC(isc, addr, value)
 *        WRITE_REG_UINT32_ISC(isc, addr, value)
 *
 *        READ_REG_UINT8_ISC(isc, addr, value)
 *        READ_REG_UINT16_ISC(isc, addr, value)
 *        READ_REG_UINT32_ISC(isc, addr, value)
 */

/* #define PCI_LITTLE_ENDIAN_ONLY */
/*
 * Use of PCI_LITTLE_ENDIAN_ONLY flag:
 *
 * When the driver sets this compile flag, the macros
 *  READ_REG_UINTxx_ISC() and WRITE_REG_UINTxx_ISC() are #defined to a
 *  direct dereference of the address given to them.  This will have
 *  the correct behavior as long as the PCI adapter directly maps PCI
 *  memory space into host space.
 *
 * When the flag is not set (the default behavior), the
 *  READ_REG_UINTxx_ISC() and WRITE_REG_UINTxx_ISC() macros are
 *  #defined to make function calls into the PCI adapter's table of
 *  memory accessor functions.
 *
 * Not setting the flag is the safe default for all systems.  Accesses
 *  are a little faster if the flag is defined.  Drivers who want the
 *  best of both worlds are free to use these lower-level macros:
 *      PCI_READ/WRITE_MEMxx_DIRECT_MAPPED(addr, value)
 *      PCI_READ/WRITE_MEMxx_FUNC_CALL_ISC(isc, addr, value) 
 *
 *  A driver can find out at run-time which to use by calling
 *  pci_get_mem_mode_isc()
 */

#ifdef PCI_LITTLE_ENDIAN_ONLY
/*
 * --------- PCI_LITTLE_ENDIAN_ONLY memory accessors ---------------
 */
#define WRITE_REG_UINT8_ISC(isc, addr, value) \
    PCI_WRITE_MEM8_DIRECT_MAPPED(addr, value)

#define WRITE_REG_UINT16_ISC(isc, addr, value) \
    PCI_WRITE_MEM16_DIRECT_MAPPED(addr, value)

#define WRITE_REG_UINT32_ISC(isc, addr, value) \
    PCI_WRITE_MEM32_DIRECT_MAPPED(addr, value)

#define READ_REG_UINT8_ISC(isc, addr, value) \
    PCI_READ_MEM8_DIRECT_MAPPED(addr, value)

#define READ_REG_UINT16_ISC(isc, addr, value) \
    PCI_READ_MEM16_DIRECT_MAPPED(addr, value)

#define READ_REG_UINT32_ISC(isc, addr, value) \
    PCI_READ_MEM32_DIRECT_MAPPED(addr, value)

#else
/*
 * --------- non-PCI_LITTLE_ENDIAN_ONLY memory accessors -----------
 */
#define WRITE_REG_UINT8_ISC(isc, addr, value) \
    PCI_WRITE_MEM8_FUNC_CALL_ISC(isc, addr, value)

#define WRITE_REG_UINT16_ISC(isc, addr, value) \
    PCI_WRITE_MEM16_FUNC_CALL_ISC(isc, addr, value)

#define WRITE_REG_UINT32_ISC(isc, addr, value) \
    PCI_WRITE_MEM32_FUNC_CALL_ISC(isc, addr, value)

#define READ_REG_UINT8_ISC(isc, addr, value) \
    PCI_READ_MEM8_FUNC_CALL_ISC(isc, addr, value)

#define READ_REG_UINT16_ISC(isc, addr, value) \
    PCI_READ_MEM16_FUNC_CALL_ISC(isc, addr, value)

#define READ_REG_UINT32_ISC(isc, addr, value) \
    PCI_READ_MEM32_FUNC_CALL_ISC(isc, addr, value)

#endif   /* ifdef PCI_LITTLE_ENDIAN_ONLY */

/*
 * pci_get_mem_mode_isc():
 *
 *      A call to allow the driver to find out if their memory space
 *      is directly mapped into host I/O space (so that they can
 *      dereference pointers into their memory space directly) or
 *      mapped in a special way that requires them to perform their
 *      memory accesses through function calls in PCI services.
 */

/* RETURN VALUES for the pci_get_mem_mode_isc() call: */
#define PCI_MEM_DIRECT_MAPPED_MODE  0  /* mapped directly to host I/O space */
#define PCI_MEM_SPECIAL_MODE        1  /* mem accesses must go thru services */
#define PCI_FUNCTION_UNAVAILABLE   -1  /* get_mem_mode call not available */

/*
 * int pci_get_mem_mode_isc(
 *     struct isc_table_type *isc
 *     );
 */
#define pci_get_mem_mode_isc(isc) \
    (((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->rev_field < 1) ? \
        PCI_FUNCTION_UNAVAILABLE : \
        (((PPCI_BUS_INFO)((isc)->bus_info))->func_tbl->get_mem_mode( \
	    ((PPCI_BUS_INFO)((isc)->bus_info))->host_adapter, \
	    ((PPCI_BUS_INFO)((isc)->bus_info))->cfg_tok))

/*
 * DDG1 WSIO Functions and types
 */
#if defined(__STDC__) || defined(__cplusplus)
typedef int (*WSIO_ISR_OLD)(void *, void *);
#endif



/*-------------------------------------------------------------------------
 *
 *                   PCI Bus-dependent Services API 
 *              (for post-WSIO1 environments - UDI?, WSIO2?)
 *
 *-------------------------------------------------------------------------
 */

/*
 * Function Prototypes for bus-dependent functions (non-wsio1 stuff)
 */
#if defined(__STDC__) || defined(__cplusplus)
    /* ANSI C Function Prototypes */
typedef int (*PCI_DESC_TRANS)(void *, PCI_CFG_TOKEN, BUS_TRANS_DESC *);
typedef int (*PCI_GET_FRU)(void *, PCI_CFG_TOKEN, int *);
#else
    /* K & R style */
typedef int (*PCI_DESC_TRANS)();
typedef int (*PCI_GET_FRU)();
#endif


/*
 * Driver Debugging Assistance
 */
#ifdef OSDEBUG
#define DBG_PCI
#endif

#ifdef DBG_PCI 
#define DbgPrint(str) DbgPrintf str
#define DLOG DbgPrintf("PCI DEBUG: FILE = \"%s\"  LINE = %d\n", __FILE__, __LINE__)
#else
#define DbgPrint(str) 
#define DLOG
#endif

#endif
