/*
    Copyright 2000 (c) by Oliver Pfister,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/IO/ia32/Drivers/IOPci.h,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
*/
#ifndef _IOPCI_H
#define _IOPCI_H

#ifdef CONFIG_PCI // Defined in Makefiles/Makefile.ia32.i386

#include "List.h"
#include "Threads.h"
#include "IODevice.h"

#define IO_PCIDEVCOUNT 2
#define IO_AM79C970    1
#define IO_AM79C97X    0

#define PCI_MAX_NUM_IOPORT       6
#define PCI_MAX_NUM_MEMMAPPED32  6
#define PCI_MAX_NUM_MEMMAPPED64  3
#define IO_MAX_NAME_SIZE         256
#define IO_MAX_CLASSNAME_SIZE    64
#define MAXNBOFINTERRUPTSHARERS  8
#define PCI_MATCH_VENDORID       1
#define PCI_MATCH_DEVICEID       2
#define PCI_MATCH_CLASSID        4
#define PCI_MATCH_SUBCLASSID     8
#define PCI_MATCH_PROGRINTERFACE 16
#define PCI_MATCH_HEADERTYPE     32
#define PCI_MATCH_SUBSYSVENDORID 64
#define PCI_MATCH_SUBSYSDEVICEID 128
#define PCI_MATCH_REVISIONID     256
#define PCI_MATCH_BUS            512
#define PCI_MATCH_DEVFN          1024

typedef signed char        s8;
typedef unsigned char      u8;
typedef signed short       s16;
typedef unsigned short     u16;
typedef signed int         s32;
typedef unsigned int       u32;
typedef signed long long   s64;
typedef unsigned long long u64;

typedef struct IOPortDesc_t
{
  u32 address;      /* Start of Block Address */
  u32 blockSize;    /* Max Block size is 256 bytes */
  int baseAddrNum;  /* The number of the PCI Base Address Reg.: 0..5 */
}
IOPortDesc;

typedef struct IOMemMapped32Desc_t
{
  u32 address;      /* Start of Block Address */
  u32 blockSize;    /* Max Block size is 2GB */
  u16 selector;     /* Each Mem Mapped Region has its own memory segment */
  int prefetchable; /* 1=prefetchable, 0=not prefetchable */
  int baseAddrNum;  /* The number of the PCI Base Address Reg.: 0..5 */
}
IOMemMapped32Desc;

typedef struct IOMemMapped64Desc_t
{
  u64 address;      /* Start of Block Address */
  u32 blockSize;    /* Also with 64 bit Addresses the Max Block
                           size remains 2GB (PCI Specification 2.2) */
  u16 selector;
  int prefetchable;
  int baseAddrNum;  /* The start number of the Base Address Regs.: 0..5
                           Example : 2 means base Address 2 and 3 are used */
}
IOMemMapped64Desc;

typedef struct IOExpansionRomDesc_t
{
  u32 address;      /* Start of Block Address : 0-32MB */
  u32 blockSize;    /* Max Block size is 16MB */
}
IOExpansionRomDesc;


/************************************************************************************
 * Main PCI Device structure: R=Read Only PCI Register, R/W=Read Write PCI Register *
 ************************************************************************************/
typedef struct IOPciDeviceDesc_t
{
  u32 mask; /* mask is a bitwise OR combination of : PCI_MATCH_VENDORID, PCI_MATCH_DEVICEID,
                   PCI_MATCH_CLASSID, PCI_MATCH_SUBCLASSID, PCI_MATCH_PROGRINTERFACE,
                   PCI_MATCH_HEADERTYPE, PCI_MATCH_SUBSYSVENDORID, PCI_MATCH_SUBSYSDEVICEID,
                   PCI_MATCH_REVISIONID, PCI_MATCH_BUS, PCI_MATCH_DEVFN
                   Example: mask = PCI_MATCH_VENDORID | PCI_MATCH_DEVICEID */
  InterruptHandler interruptHandler; /* The PCI Interrupt Handler */
  char name[IO_MAX_NAME_SIZE]; /* the name of the device */
  char className[IO_MAX_CLASSNAME_SIZE]; /* the class name */
  u8 bus;   /* one of the possible 256 buses */
  u8 devfn; /* encoded device and function index :
                   devfn[0:2]=function0..7
                   devfn[3:7]=device0..31 */
  u8 headerType; /* R : headerType[7]=Multi-function Device bit : 1=Multi-function Device
                        headerType[6:0]=Header Type :
                        0=Normal Device, 1=PCI-to-PCI Bridge, 2=CardBus Bridge */
  u16 vendorID;  /* R : if a Device returns vendorID=0xFFFF -> Device not present */
  u16 deviceID;  /* R : device indentifier */
  u8 revisionID; /* R : Revision identifier */
  u8 classID;    /* R : Class Code identifier */
  u8 subClassID; /* R : Sub Class Code identifier */
  u8 progrInterfaceID; /* R : Programming Interface identifier of the Sub Class */
  u16 subsysVendorID;  /* R : subsystemVendorID=0 -> no subsytemVendorID specified */
  u16 subsysDeviceID;  /* R : subsystemDeviceID=0 -> no subsytemDeviceID specified */
  unsigned int irqPin; /* R : The Pci Interrupt Pin used :
                              0=no interrupts, 1=first pin, 2=second pin
                              3=third pin, 4=fourth pin */
  unsigned int irqLine; /* R/W : the Interrupt Number IRQ0..IRQ15 */
  unsigned int ioPortCount; /* can be 0..6, this number indicates the number
                                   of implemented IO Ports */
  unsigned int memMapped32Count;  /* can be 0..6, this number indicates the
                                        number of implemented IO Mem Regions */
  unsigned int memMapped64Count;  /* can be 0..3, this number indicates the number
                                        of implemented IO Mem64 Regions */
  unsigned int expansionRomCount; /* For type 0h and 1h devices this number can be 0 or 1,
                                         it indicates the number of
                                         Expansion Roms implemented */
  IOPortDesc ioPort[PCI_MAX_NUM_IOPORT]; /* R/W : the 6 possible I/O spaces */
  IOMemMapped32Desc memMapped32[PCI_MAX_NUM_MEMMAPPED32]; /* R/W : the 6 possible mem spaces */
  IOMemMapped64Desc memMapped64[PCI_MAX_NUM_MEMMAPPED64]; /* R/W : the 3 possible mem spaces */
  IOExpansionRomDesc expansionRom; /* R/W : the only possible ROM space */
  int masterCapable; /* 1=Device is Bus Master Capable */
  int fastBackToBackCapable; /* R : 1=Device supports Fast Back-To-Back */
  int devSelTiming;  /* R : the DEVSEL timing : 00=fast, 01=medium
                                                   10=slow, 11=reserved */
  u8 latencyTimer;   /* R/W : latency timer */
  u8 cacheLineSize;  /* R/W : cache line size */
  u8 bist;           /* R/W : Built-In Self Test */
  u8 minGnt;         /* R : min GNT */
  u8 maxLat;         /* R : max Latency */
  u8 capability;     /* R : Capability List offset */
  struct IOPciDeviceDesc_t* scanRootCopy; /* Pointer to the first created copy of this
                                                 structure, the first copy is the one created
                                                 while scanning the PCI Bus.
                                                 This first copy describes the Device, no driver
                                                 informations are present:
                                                 -> mask=0, interruptHandler=NULL, devPtr=NULL */
  IODevice devPtr; /* Pointer to the attached driver */
  void* extension; /* Extension pointer used for PCI device specific needs */
}
IOPciDeviceDesc;

extern IOPciDeviceDesc ioPciDeviceTable[];

#ifdef PCI_VERBOSE
void PCIprintf(char *fmt, ...);
#else
inline static void PCIprintf()
{}
;
#endif

/***************************************
 * Functions used by the Driver Writer *
 ***************************************/
Boolean ioPciEnableBusMaster(IOPciDeviceDesc* devPciPtr);
Boolean ioPciDisableBusMaster(IOPciDeviceDesc* devPciPtr);
Boolean ioPciEnableIODecoder(IOPciDeviceDesc* devPciPtr);
Boolean ioPciDisableIODecoder(IOPciDeviceDesc* devPciPtr);
Boolean ioPciEnableMemDecoder(IOPciDeviceDesc* devPciPtr);
Boolean ioPciDisableMemDecoder(IOPciDeviceDesc* devPciPtr);
Boolean ioPciEnableRomDecoder(IOPciDeviceDesc* devPciPtr);
Boolean ioPciDisableRomDecoder(IOPciDeviceDesc* devPciPtr);
u8 pci_read_config_byte(IOPciDeviceDesc *devPciPtr, int where);
u16 pci_read_config_word(IOPciDeviceDesc *devPciPtr, int where);
u32 pci_read_config_dword(IOPciDeviceDesc *devPciPtr, int where);
void pci_write_config_byte(IOPciDeviceDesc *devPciPtr, int where, u8 value);
void pci_write_config_word(IOPciDeviceDesc *devPciPtr, int where, u16 value);
void pci_write_config_dword(IOPciDeviceDesc *devPciPtr, int where, u32 value);
Boolean ioPciDeviceAttach(IODevice drvPtr);
Boolean ioPciDeviceDetach(IODevice drvPtr);

/**********************************************************
 * Functions used internally to initialize PCI operations *
 **********************************************************/
Error ioPci_init(IODevice devPtr);
Error ioPci_read(IODevice devPtr, ThreadId threadId, char* bufPtr, long int* sizePtr);
Error ioPci_write(IODevice devPtr, ThreadId threadId, char* bufPtr, long int* sizePtr);
void ioPciMainInterruptHandler(IODevice devPtr);
Boolean ioPciSetInterruptHandler(IODevice devPtr);
Boolean ioPciRemoveInterruptHandler(IODevice devPtr);
Boolean ioPciPresenceCheck(void);
void ioPciReadIrq(IOPciDeviceDesc * devPciPtr);
void ioPciReadRomBase(IOPciDeviceDesc * devPciPtr, u8 where);
void ioPciReadBases(IOPciDeviceDesc * devPciPtr, int num);
void ioPciMapMemoryIO(void);
void ioPciPrintDeviceSmall(IOPciDeviceDesc * devPciPtr);
void ioPciPrintDevice(IOPciDeviceDesc * devPciPtr);
void ioPciPrintDevList(void);
void ioPciScan(void);

#ifdef CONFIG_PCI_NAMES
// Naming PCI devices, in names.c
void ioPciNameDevice(IOPciDeviceDesc* devPciPtr); // Fills in name field
void ioPciNameClass(IOPciDeviceDesc* devPciPtr); // Fills in className field
#endif CONFIG_PCI_NAMES


/************************************************************************
 * Under PCI, each device has 256 bytes of configuration address space, *
 * of which the first 64 bytes are standardized as follows:             *
 ************************************************************************/
#define PCI_VENDOR_ID                    0x00   /* 16 bits */
#define PCI_DEVICE_ID                    0x02   /* 16 bits */
#define PCI_COMMAND                      0x04   /* 16 bits */
#define  PCI_COMMAND_IO                  0x1    /* Enable response in I/O space */
#define  PCI_COMMAND_MEMORY              0x2    /* Enable response in Memory space */
#define  PCI_COMMAND_MASTER              0x4    /* Enable bus mastering */
#define  PCI_COMMAND_SPECIAL             0x8    /* Enable response to special cycles */
#define  PCI_COMMAND_INVALIDATE          0x10   /* Use memory write and invalidate */
#define  PCI_COMMAND_VGA_PALETTE         0x20   /* Enable palette snooping */
#define  PCI_COMMAND_PARITY              0x40   /* Enable parity checking */
#define  PCI_COMMAND_WAIT                0x80   /* Enable address/data stepping */
#define  PCI_COMMAND_SERR                0x100  /* Enable SERR */
#define  PCI_COMMAND_FAST_BACK           0x200  /* Enable back-to-back writes */


#define PCI_STATUS                       0x06   /* 16 bits */
#define  PCI_STATUS_CAP_LIST             0x10   /* Support Capability List */
#define  PCI_STATUS_66MHZ                0x20   /* Support 66 Mhz PCI 2.1 bus */
#define  PCI_STATUS_UDF                  0x40   /* Support User Definable Features [obsolete] */
#define  PCI_STATUS_FAST_BACK            0x80   /* Accept fast-back to back */
#define  PCI_STATUS_PARITY               0x100  /* Detected parity error */
#define  PCI_STATUS_DEVSEL               0x600  /* DEVSEL timing */
#define  PCI_STATUS_SIG_TARGET_ABORT     0x800  /* Set on target abort */
#define  PCI_STATUS_REC_TARGET_ABORT     0x1000 /* Master ack of " */
#define  PCI_STATUS_REC_MASTER_ABORT     0x2000 /* Set on master abort */
#define  PCI_STATUS_SIG_SYSTEM_ERROR     0x4000 /* Set when we drive SERR */
#define  PCI_STATUS_DETECTED_PARITY      0x8000 /* Set on parity error */

#define PCI_CLASS_REVISION               0x08   /* High 24 bits are class Code, low 8

revision */

#define PCI_CACHE_LINE_SIZE              0x0c   /* 8 bits */
#define PCI_LATENCY_TIMER                0x0d   /* 8 bits */

#define PCI_HEADER_TYPE                  0x0e   /* 8 bits */
#define  PCI_HEADER_TYPE_NORMAL          0
#define  PCI_HEADER_TYPE_BRIDGE          1
#define  PCI_HEADER_TYPE_CARDBUS         2

#define PCI_BIST                         0x0f   /* 8 bits */
#define  PCI_BIST_CODE_MASK              0x0f   /* Return result */
#define  PCI_BIST_START                  0x40   /* 1 to start BIST, 2 secs or less */
#define  PCI_BIST_CAPABLE                0x80   /* 1 if BIST capable */

#define PCI_BASE_ADDRESS_0               0x10   /* 32 bits [htype 0,1 only] */
#define PCI_BASE_ADDRESS_1               0x14   /* 32 bits [htype 0,1 only] */
#define PCI_BASE_ADDRESS_2               0x18   /* 32 bits [htype 0 only] */
#define PCI_BASE_ADDRESS_3               0x1c   /* 32 bits [htype 0 only] */
#define PCI_BASE_ADDRESS_4               0x20   /* 32 bits [htype 0 only] */
#define PCI_BASE_ADDRESS_5               0x24   /* 32 bits [htype 0 only] */
#define  PCI_BASE_ADDRESS_SPACE          0x01   /* 0 = memory, 1 = I/O */
#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK  0x06
#define  PCI_BASE_ADDRESS_MEM_TYPE_32    0x00   /* 32 bit address */
#define  PCI_BASE_ADDRESS_MEM_TYPE_1M    0x02   /* Below 1M [obsolete] */
#define  PCI_BASE_ADDRESS_MEM_TYPE_64    0x04   /* 64 bit address */
#define  PCI_BASE_ADDRESS_MEM_PREFETCH   0x08   /* prefetchable? */
/* bit 1 is reserved if address_space = 1 */


/**********************************
 * Header type 0 (normal devices) *
 **********************************/
#define PCI_CARDBUS_CIS                  0x28
#define PCI_SUBSYSTEM_VENDOR_ID          0x2c
#define PCI_SUBSYSTEM_ID                 0x2e
#define PCI_ROM_ADDRESS                  0x30   /* Bits 31..11 are address, 10..1 reserved */
#define  PCI_ROM_ADDRESS_ENABLE          0x01
#define PCI_ROM_ADDRESS_MASK           (~0x7ffUL)

#define PCI_CAPABILITY_LIST              0x34   /* Offset of first capability list entry */

/* 0x35-0x3b are reserved */
#define PCI_INTERRUPT_LINE               0x3c   /* 8 bits */
#define PCI_INTERRUPT_PIN                0x3d   /* 8 bits */
#define PCI_MIN_GNT                      0x3e   /* 8 bits */
#define PCI_MAX_LAT                      0x3f   /* 8 bits */


/**************************************
 * Header type 1 (PCI-to-PCI bridges) *
 **************************************/
#define PCI_PRIMARY_BUS                  0x18   /* Primary bus number */
#define PCI_SECONDARY_BUS                0x19   /* Secondary bus number */
#define PCI_SUBORDINATE_BUS              0x1a   /* Highest bus number behind the bridge */
#define PCI_SEC_LATENCY_TIMER            0x1b   /* Latency timer for secondary interface */
#define PCI_IO_BASE                      0x1c   /* I/O range behind the bridge */
#define PCI_IO_LIMIT                     0x1d
#define  PCI_IO_RANGE_TYPE_MASK          0x0f   /* I/O bridging type */
#define  PCI_IO_RANGE_TYPE_16            0x00
#define  PCI_IO_RANGE_TYPE_32            0x01
#define  PCI_IO_RANGE_MASK              ~0x0f
#define PCI_SEC_STATUS                   0x1e   /* Secondary status register, only bit 14 used */
#define PCI_MEMORY_BASE                  0x20   /* Memory range behind */
#define PCI_MEMORY_LIMIT                 0x22
#define  PCI_MEMORY_RANGE_TYPE_MASK      0x0f
#define  PCI_MEMORY_RANGE_MASK          ~0x0f
#define PCI_PREF_MEMORY_BASE             0x24   /* Prefetchable memory range behind */
#define PCI_PREF_MEMORY_LIMIT            0x26
#define  PCI_PREF_RANGE_TYPE_MASK        0x0f
#define  PCI_PREF_RANGE_TYPE_32          0x00
#define  PCI_PREF_RANGE_TYPE_64          0x01
#define  PCI_PREF_RANGE_MASK            ~0x0f
#define PCI_PREF_BASE_UPPER32            0x28   /* Upper half of prefetchable memory range */
#define PCI_PREF_LIMIT_UPPER32           0x2c
#define PCI_IO_BASE_UPPER16              0x30   /* Upper half of I/O addresses */
#define PCI_IO_LIMIT_UPPER16             0x32
/* 0x34 same as for htype 0 */
/* 0x35-0x3b is reserved */
#define PCI_ROM_ADDRESS1                 0x38   /* Same as PCI_ROM_ADDRESS, but for htype 1 */
/* 0x3c-0x3d are same as for htype 0 */
#define PCI_BRIDGE_CONTROL               0x3e
#define  PCI_BRIDGE_CTL_PARITY           0x01   /* Enable parity detection on secondary interface */
#define  PCI_BRIDGE_CTL_SERR             0x02   /* The same for SERR forwarding */
#define  PCI_BRIDGE_CTL_NO_ISA           0x04   /* Disable bridging of ISA ports */
#define  PCI_BRIDGE_CTL_VGA              0x08   /* Forward VGA addresses */
#define  PCI_BRIDGE_CTL_MASTER_ABORT     0x20   /* Report master aborts */
#define  PCI_BRIDGE_CTL_BUS_RESET        0x40   /* Secondary bus reset */
#define  PCI_BRIDGE_CTL_FAST_BACK        0x80   /* Fast Back2Back enabled on secondary interface */


/***********************************
 * Header type 2 (CardBus bridges) *
 ***********************************/
#define PCI_CB_CAPABILITY_LIST           0x14
/* 0x15 reserved */
#define PCI_CB_SEC_STATUS                0x16   /* Secondary status */
#define PCI_CB_PRIMARY_BUS               0x18   /* PCI bus number */
#define PCI_CB_CARD_BUS                  0x19   /* CardBus bus number */
#define PCI_CB_SUBORDINATE_BUS           0x1a   /* Subordinate bus number */
#define PCI_CB_LATENCY_TIMER             0x1b   /* CardBus latency timer */
#define PCI_CB_MEMORY_BASE_0             0x1c
#define PCI_CB_MEMORY_LIMIT_0            0x20
#define PCI_CB_MEMORY_BASE_1             0x24
#define PCI_CB_MEMORY_LIMIT_1            0x28
#define PCI_CB_IO_BASE_0                 0x2c
#define PCI_CB_IO_BASE_0_HI              0x2e
#define PCI_CB_IO_LIMIT_0                0x30
#define PCI_CB_IO_LIMIT_0_HI             0x32
#define PCI_CB_IO_BASE_1                 0x34
#define PCI_CB_IO_BASE_1_HI              0x36
#define PCI_CB_IO_LIMIT_1                0x38
#define PCI_CB_IO_LIMIT_1_HI             0x3a
#define  PCI_CB_IO_RANGE_MASK           ~0x03
/* 0x3c-0x3d are same as for htype 0 */
#define PCI_CB_BRIDGE_CONTROL            0x3e
#define  PCI_CB_BRIDGE_CTL_PARITY        0x01   /* Similar to standard bridge control register */
#define  PCI_CB_BRIDGE_CTL_SERR          0x02
#define  PCI_CB_BRIDGE_CTL_ISA           0x04
#define  PCI_CB_BRIDGE_CTL_VGA           0x08
#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT  0x20
#define  PCI_CB_BRIDGE_CTL_CB_RESET      0x40   /* CardBus reset */
#define  PCI_CB_BRIDGE_CTL_16BIT_INT     0x80   /* Enable interrupt for 16-bit cards */
#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100  /* Prefetch enable for both memory regions */
#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
#define  PCI_CB_BRIDGE_CTL_POST_WRITES   0x400
#define PCI_CB_SUBSYSTEM_VENDOR_ID       0x40
#define PCI_CB_SUBSYSTEM_ID              0x42
#define PCI_CB_LEGACY_MODE_BASE          0x44   /* 16-bit PC Card legacy mode base address (ExCa) */
/* 0x48-0x7f reserved */

#endif CONFIG_PCI
#endif _IOPCI_H
