Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / include / pci_dev.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: pci_dev.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named 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 work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
#ifndef _PCI_DEV_NEW_H
#define _PCI_DEV_NEW_H
#include <stdio.h>
#include <stdarg.h>
#include "arg.h"
#include "pci_common.h"
#include <map>
using namespace std;
#define Here _Here(__FILE__, __LINE__)
//this class encapsulates all the pci device related
//functions. the class provides a functional level
//model (eg simulation of optimizing pci commands is not
//provided).
//XXX Does not supports yet -
// message signalled interrupts (msi)
// expansion rom
//no byte swapping is done at the device level. It is
//assumed that the system (OS/bridge etc) will take care
//of these issues before the data is presented to device
class genericPciDev:public genericPciDevIf, pciTargetIf, pciMasterIf, pciDebug{
private:
const char * busName; //name of the bus to which this device is connected
pciBusIf *busIf; //private : no direct access to pciBus by the device specific model
pciBusIf * intrptIf;
int32_t device; //device number
int32_t function; //function number
public:
pciConfSpace * confSpace;
// functions used to map, unmap address spaces to pciBus
bool mapBar(pci_space_t space, uint64_t base, uint64_t size){
assert(busIf);
return busIf->busif_map(pciDev_getName(),space, base, size);
}
bool unMapBar(pci_space_t space,uint64_t base){
assert(busIf);
return busIf->busif_unmap(pciDev_getName(),space, base);
}
// fakeprom devices call this function to get the
// base address from the bus.
uint64_t getBase(pci_space_t space, uint64_t size){
assert(busIf);
return busIf->busif_get_lowest_base(space,size);
}
genericPciDev(confHeaderType htype = pciHeaderNull);
// dump restore functions. the filename for dump/restore is <dir>/<filename>.pci
bool dump(const char * dir,const char *file);
bool restore(const char * dir, const char *file);
// XXX only for now protected:
public:
void pciDevInfo();
//accessing memory from device
//pci bus exported functions
const char *devif_getBusName() { return busName;}
int devif_getDevice() { return device;}
int devif_getFunction() { return function;}
mmi_instance_t devif_getInstance() { return pciDev_getInstance();}
const char *devif_getName() { return pciDev_getName();}
pciXactnStatus devif_special_cycle(uint16_t mssg, uint16_t data) { return pciTarget_special_cycle(mssg,data);}
pciXactnStatus devif_intr_ack(uint64_t *data) { return pciTarget_intr_ack(data);}
pciXactnStatus devif_access_w_size(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size,SAM_DeviceId * samId);
pciXactnStatus devif_access_w_byte_enable(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable,SAM_DeviceId * samId);
//functions to be called by specific device implementation
//to allow parsing of busName and attach to pci bus, at right points of time.
bool dev_parse_arg(const char *arg); /*to be called from parse_args()*/
bool dev_check_args(); /*to be called from check_arg()*/
bool dev_module_added(const char *bus_name);/*to be called from module_added()*/
bool dev_module_deleted(const char *target_name);/*to be called from module_deleted()*/
void dev_init_done(int debug_level = 0); /*to be called from init_done()*/
//fakeprom/v4 stuff.
int dev_type;
int slot_irl[4];
bool interrupt_added;
bool int_pin_status[4];
bool isMultiFunction; //XXX to be removed when v4 dump restore is stopped being supported in v5
/* Functions that MUST be implemented by the derived class */
// to support genericPciDevIf::devif_getInstance,devif_getName
virtual mmi_instance_t pciDev_getInstance() = 0; //return the mmi_instance
virtual const char * pciDev_getName() = 0; //return the device instnace name
virtual void pciDev_confAccessCb(bool_t wr, uint64_t offset, uint8_t size) = 0;
//this function should be implemented by specific device implementation. the device
//can perform any device specific activity related to a r/w on a particular register.
//this is left pure virtual, so if there is no special handling then an implementation
//must provide a function definition with empty body.
/* functions that MAY be implemented by the derived class */
//override pci target access functions, providing a default implementation
pciXactnStatus pciTarget_mem32access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size);
pciXactnStatus pciTarget_mem64access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size);
pciXactnStatus pciTarget_ioaccess(uint64_t offset, bool wr,uint64_t * buf, uint8_t size);
pciXactnStatus pciTarget_special_cycle(uint16_t mssg, uint16_t data);
pciXactnStatus pciTarget_intr_ack(uint64_t *data);
// the functions a device can call as a master
bool pciMaster_set_int(int line, bool raise); // oddball
public:
pciXactnStatus pciMaster_dma(bool wr, uint64_t vaddr, void *data, long count);
protected:
pciXactnStatus pciMaster_intr_ack_cycle(uint64_t * data);
pciXactnStatus pciMaster_special_cycle(uint16_t mssg, uint16_t data);
pciXactnStatus pciMaster_bus_access_w_size(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size);
pciXactnStatus pciMaster_bus_access_w_byte_enable(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable);
};
class baseAddrReg:public pciConfReg{
/*
Format of BAR - - -
I/O space bit 0 - hardwired to 1
bit 1 - reserved, hardwired to 0
memory space bit 0 - hardwired to 0
bit [2,1] - 00 => locate anywhere in 32 bit address space
- 01 => reserved
- 10 => locate anywhere in 64 bit address space
- 11 => reserved
bit 3 - hardwired to 1 if device memory space has no side
effects on reads and host bridge can merge writes
into this range. (ie prefetchable)
*/
public:
bool isPrefetchable; //if memory then prefetchable or not?
uint32_t val_32To63; //upper 32 bits in case of 64 bit reg
uint32_t mask_32To63; //mask " " " " " " etc
uint64_t mapSize;
bool isMapped;
uint64_t oldVal;
pci_space_t space;
static const int IO = 0x1; //0001
static const int MEM32 = 0x0; //0000
static const int MEM64 = 0x4; //0100
static const int PREFETCH = 0x8; //1000
public:
//constructor: default is mem32, non-prefetchable mapping
baseAddrReg(const char * name, genericPciDev * d,uint64_t spaceSize,pci_space_t space , bool isPrefetchable = false);
virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write);
virtual void print(){
pciConfReg::print();
printf("\tSpace<%s>Size<%llx>\n",(space == PCI_MEM32 || space == PCI_MEM64)?((space == PCI_MEM32) ? "Mem32":"Mem64"):("I/O"),size);
}
void reMap();
bool map();
bool unmap();
};
class pciCommandReg:public pciConfReg{
//command register reset value is 0. Device specific model should set
//the write mask for this register, so that the probing software can determine
//the capabilities of the device. in general if a device does not support
//a particular feature/operation, the corresponding mask bit should be set
//to 0 to disable writes.
/*
bit # Function
0 Control I/O space response. Devices that do not support
i/o access must h/w this bit to 0, ie bit 0 of write mask is 0
1 Control memory space access.
2 Control a devices ability to act as master. Devices that do
not generate PCI accesses must hardwire this bit to 0
3 Special cycle control.
4 Enable bit for memory write and invalidate command. This bit
must be hardwired to 0 if the device while acting as a master
can not generate the command.
5 palette register access for VGA compatible devices
6 Controls devices response to parity errors
7 controls data/address stepping
8 controls SERR# driver
9 controls a masters ability to do fast back to back transactions
10-15 reserved, writes ignored, read back as 0
reference:pci spec rev 2.2
*/
public:
enum commandRegBits {IO_SPACE, MEM_SPACE, BUS_MASTER, SPECIAL_CYCLES, MWI_ENABLE, VGA_SNOOP,\
PARITY_RESPONSE, SERR_ENABLE, STEPPING_CTRL, FAST_B2B, NUMBITS};
pciCommandReg(const char * name, genericPciDev * d, uint16_t write_mask,uint16_t val=0):\
pciConfReg(name,2,val,write_mask & 0x3ff, (void *)d){
if(d == 0){
printf("pci command reg constructor error: must provide genericPciDev device pointer\n");
return;
}
}
virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write);
private:
//try to map/unmap all the base registers if they map pci space 'spc'
void mapSpace(pci_space_t spc);
void unMapSpace(pci_space_t spc);
};
class pciStatusReg:public pciConfReg{
//status register provides additional information about a devices
//capabilities. This register may not be 0 at reset. A device must
//provide the initial value of this register at reset, as well as the mask
//describing writable bits. this register is RW1C
//devices set the writable bits to indicate abnormal conditions during xactns.
public:
enum statusRegBits{ CAPABILITIES_LIST = 0x4, MHZ66 = 0x5, FAST_B2B_XACTN = 0x7, MASTER_DATA_PARITY_ERROR = 0x8,\
SIGNALED_TARGET_ABORT = 0xb, RECEIVED_TARGET_ABORT = 0xc, RECEIVED_MASTER_ABORT = 0xd, \
SIGNALED_SYSTEM_ERROR = 0xe, DETECTED_PARITY_ERROR = 0xf};
enum devselTiming { FAST = 0x0, MEDIUM = 0x1, SLOW = 0x2};
pciStatusReg(const char * name, genericPciDev * d, uint16_t init_val, uint16_t write_mask): \
pciConfReg(name,2,init_val, write_mask & 0xff90 ,d){
if(d == 0){
printf("pci status reg constructor error: must provide genericPciDev device pointer\n");
return;
}
}
};
//COMMENTS:
/*
Master Abort: xactn termination by master when no targets respond.
A master comes to know of this when DEVSEL# remains deasserted
on clock 6. The master in this case assumes that either the
target is incapable of responding to the command, the address was
bad, or the target is not present and should not repeat the xactn.
Target Abort: refers to an abnormal termination of a xactn that
indicates that a target will never be able to complete the request
or the target had a fatal error. eg unmapped csr access, misaligned
access etc.
Fast back to back xactn: refers to xactns when there are no idle
state on the pci bus bw contiguous transactions. either the master
or the target takes the responsibility of avoiding contention.
If a target supports this kind xactn, then the corresponding status
bit may be hardwired to 1. This mode is enabled by configuration s/w
by setting the corresponding bit in command register. This bit is
meaningful only for masters. This bit would be set in a master by s/w
only after ensuring that all the targets are capable of these xactns.
Special Cycles: this provides a simple message broadcast mechanism on
a single pci bus segment (command does not cross bridges). No targets
assert DEVSEL# for this command, and it terminates with a master abort
(normal). During the address phase, the A/D lines are random. During the
data phase AD[15::00] contain encoded message
AD[31::16] contain message dependent options data field.
SW requirements:
1. For non existent devices bridge must return 0xffff for reads
of vendor id. {these accesses must be terminated with a master abort}
2. Conf space writes to reserved registers are no-ops ie discard the data.
Read access to reserved or unimplemeted registers must return 0.
3. Device identification: The following read only registers help configuration
s/w to determine what devices are present on system. Hence these must be
configured for attaching drivers.
a) vendor Id: identifies manufacturer of device. 0xffff is invalid.
b) device id: identifies a particular device. assigned by vendor.
Resource: http://pciids.sourceforge.net/pci.ids
c) revision id: device specific revision id.
d) header type: defines the layout of 2nd part of conf space.
00h : normal pci devices
01h : pci to pci bridges
02h : pc card standard
e) class code: this is composed of 3 byte sized fields.
base class code : addr 0bh broadly classifies the type of
function the device performs. eg 02h for network controllers
sub class code : addr 0ah identifies more specifically the
function of the device eg 00h for ethernet controller
programming interface : addr 09h identifies a specific register
level programming interface( if any).
Refer to Appendix D of PCI spec 2.2 for existing base and sub
class codes.
*/
#endif