This commit is contained in:
cinap_lenrek 2020-09-13 20:34:30 +02:00
commit d3ebd02bef
111 changed files with 2400 additions and 5125 deletions

View file

@ -9,6 +9,7 @@
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "../port/pci.h"
#include "sysreg.h"
typedef struct Mbox Mbox;

View file

@ -183,28 +183,9 @@ extern void screeninit(void);
extern int isaconfig(char*, int, ISAConf*);
/* pci */
typedef struct Pcidev Pcidev;
extern int pcicfgr32(Pcidev* pcidev, int rno);
extern void pcicfgw32(Pcidev* pcidev, int rno, int data);
extern int pcicfgr16(Pcidev* pcidev, int rno);
extern void pcicfgw16(Pcidev* pcidev, int rno, int data);
extern int pcicfgr8(Pcidev* pcidev, int rno);
extern void pcicfgw8(Pcidev* pcidev, int rno, int data);
extern Pcidev* pcimatch(Pcidev* prev, int vid, int did);
extern Pcidev* pcimatchtbdf(int tbdf);
extern void pcisetioe(Pcidev* p);
extern void pciclrioe(Pcidev* p);
extern void pcisetbme(Pcidev* p);
extern void pciclrbme(Pcidev* p);
extern void pcisetmwi(Pcidev* p);
extern void pciclrmwi(Pcidev* p);
extern int pcicap(Pcidev *p, int cap);
extern int pcinextcap(Pcidev *pci, int offset);
extern int pcihtcap(Pcidev *p, int cap);
extern int pcigetpms(Pcidev* p);
extern int pcisetpms(Pcidev* p, int state);
extern void pcienable(Pcidev *p);
extern void pcidisable(Pcidev *p);
/* pcibcm */
extern int pcicfgrw8(int tbdf, int rno, int data, int read);
extern int pcicfgrw16(int tbdf, int rno, int data, int read);
extern int pcicfgrw32(int tbdf, int rno, int data, int read);
extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a);
extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a);

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "sysreg.h"
#include "../port/error.h"

View file

@ -6,233 +6,5 @@ enum {
IRQether = IRQgic + 29,
};
/*
* PCI
*/
enum {
BusCBUS = 0, /* Corollary CBUS */
BusCBUSII, /* Corollary CBUS II */
BusEISA, /* Extended ISA */
BusFUTURE, /* IEEE Futurebus */
BusINTERN, /* Internal bus */
BusISA, /* Industry Standard Architecture */
BusMBI, /* Multibus I */
BusMBII, /* Multibus II */
BusMCA, /* Micro Channel Architecture */
BusMPI, /* MPI */
BusMPSA, /* MPSA */
BusNUBUS, /* Apple Macintosh NuBus */
BusPCI, /* Peripheral Component Interconnect */
BusPCMCIA, /* PC Memory Card International Association */
BusTC, /* DEC TurboChannel */
BusVL, /* VESA Local bus */
BusVME, /* VMEbus */
BusXPRESS, /* Express System Bus */
};
#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
#define BUSTYPE(tbdf) ((tbdf)>>24)
#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
enum { /* type 0 & type 1 pre-defined header */
PciVID = 0x00, /* vendor ID */
PciDID = 0x02, /* device ID */
PciPCR = 0x04, /* command */
PciPSR = 0x06, /* status */
PciRID = 0x08, /* revision ID */
PciCCRp = 0x09, /* programming interface class code */
PciCCRu = 0x0A, /* sub-class code */
PciCCRb = 0x0B, /* base class code */
PciCLS = 0x0C, /* cache line size */
PciLTR = 0x0D, /* latency timer */
PciHDT = 0x0E, /* header type */
PciBST = 0x0F, /* BIST */
PciBAR0 = 0x10, /* base address */
PciBAR1 = 0x14,
PciCAP = 0x34, /* capabilities pointer */
PciINTL = 0x3C, /* interrupt line */
PciINTP = 0x3D, /* interrupt pin */
};
/* ccrb (base class code) values; controller types */
enum {
Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
Pcibcstore = 1, /* mass storage */
Pcibcnet = 2, /* network */
Pcibcdisp = 3, /* display */
Pcibcmmedia = 4, /* multimedia */
Pcibcmem = 5, /* memory */
Pcibcbridge = 6, /* bridge */
Pcibccomm = 7, /* simple comms (e.g., serial) */
Pcibcbasesys = 8, /* base system */
Pcibcinput = 9, /* input */
Pcibcdock = 0xa, /* docking stations */
Pcibcproc = 0xb, /* processors */
Pcibcserial = 0xc, /* serial bus (e.g., USB) */
Pcibcwireless = 0xd, /* wireless */
Pcibcintell = 0xe, /* intelligent i/o */
Pcibcsatcom = 0xf, /* satellite comms */
Pcibccrypto = 0x10, /* encryption/decryption */
Pcibcdacq = 0x11, /* data acquisition & signal proc. */
};
/* ccru (sub-class code) values; common cases only */
enum {
/* mass storage */
Pciscscsi = 0, /* SCSI */
Pciscide = 1, /* IDE (ATA) */
Pciscsata = 6, /* SATA */
/* network */
Pciscether = 0, /* Ethernet */
/* display */
Pciscvga = 0, /* VGA */
Pciscxga = 1, /* XGA */
Pcisc3d = 2, /* 3D */
/* bridges */
Pcischostpci = 0, /* host/pci */
Pciscpcicpci = 1, /* pci/pci */
/* simple comms */
Pciscserial = 0, /* 16450, etc. */
Pciscmultiser = 1, /* multiport serial */
/* serial bus */
Pciscusb = 3, /* USB */
};
enum { /* type 0 pre-defined header */
PciCIS = 0x28, /* cardbus CIS pointer */
PciSVID = 0x2C, /* subsystem vendor ID */
PciSID = 0x2E, /* subsystem ID */
PciEBAR0 = 0x30, /* expansion ROM base address */
PciMGNT = 0x3E, /* burst period length */
PciMLT = 0x3F, /* maximum latency between bursts */
};
enum { /* type 1 pre-defined header */
PciPBN = 0x18, /* primary bus number */
PciSBN = 0x19, /* secondary bus number */
PciUBN = 0x1A, /* subordinate bus number */
PciSLTR = 0x1B, /* secondary latency timer */
PciIBR = 0x1C, /* I/O base */
PciILR = 0x1D, /* I/O limit */
PciSPSR = 0x1E, /* secondary status */
PciMBR = 0x20, /* memory base */
PciMLR = 0x22, /* memory limit */
PciPMBR = 0x24, /* prefetchable memory base */
PciPMLR = 0x26, /* prefetchable memory limit */
PciPUBR = 0x28, /* prefetchable base upper 32 bits */
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
PciIUBR = 0x30, /* I/O base upper 16 bits */
PciIULR = 0x32, /* I/O limit upper 16 bits */
PciEBAR1 = 0x28, /* expansion ROM base address */
PciBCR = 0x3E, /* bridge control register */
};
enum { /* type 2 pre-defined header */
PciCBExCA = 0x10,
PciCBSPSR = 0x16,
PciCBPBN = 0x18, /* primary bus number */
PciCBSBN = 0x19, /* secondary bus number */
PciCBUBN = 0x1A, /* subordinate bus number */
PciCBSLTR = 0x1B, /* secondary latency timer */
PciCBMBR0 = 0x1C,
PciCBMLR0 = 0x20,
PciCBMBR1 = 0x24,
PciCBMLR1 = 0x28,
PciCBIBR0 = 0x2C, /* I/O base */
PciCBILR0 = 0x30, /* I/O limit */
PciCBIBR1 = 0x34, /* I/O base */
PciCBILR1 = 0x38, /* I/O limit */
PciCBSVID = 0x40, /* subsystem vendor ID */
PciCBSID = 0x42, /* subsystem ID */
PciCBLMBAR = 0x44, /* legacy mode base address */
};
enum {
/* bar bits */
Barioaddr = 1<<0, /* vs. memory addr */
Barwidthshift = 1,
Barwidthmask = 3,
Barwidth32 = 0,
Barwidth64 = 2,
Barprefetch = 1<<3,
};
enum
{ /* command register */
IOen = (1<<0),
MEMen = (1<<1),
MASen = (1<<2),
MemWrInv = (1<<4),
PErrEn = (1<<6),
SErrEn = (1<<8),
};
/* capabilities */
enum {
PciCapPMG = 0x01, /* power management */
PciCapAGP = 0x02,
PciCapVPD = 0x03, /* vital product data */
PciCapSID = 0x04, /* slot id */
PciCapMSI = 0x05,
PciCapCHS = 0x06, /* compact pci hot swap */
PciCapPCIX = 0x07,
PciCapHTC = 0x08, /* hypertransport irq conf */
PciCapVND = 0x09, /* vendor specific information */
PciCapPCIe = 0x10,
PciCapMSIX = 0x11,
PciCapSATA = 0x12,
PciCapHSW = 0x0c, /* hot swap */
};
typedef struct Pcidev Pcidev;
struct Pcidev
{
int tbdf; /* type+bus+device+function */
ushort vid; /* vendor ID */
ushort did; /* device ID */
ushort pcr;
uchar rid;
uchar ccrp;
uchar ccru;
uchar ccrb;
uchar cls;
uchar ltr;
struct {
uvlong bar; /* base address */
int size;
} mem[6];
uchar intl; /* interrupt line */
Pcidev* list;
Pcidev* link; /* next device on this bno */
Pcidev* parent; /* up a bus */
Pcidev* bridge; /* down a bus */
int pmrb; /* power management register block */
struct {
uvlong bar;
int size;
} ioa, mema;
};
#define PCIWINDOW 0
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
#pragma varargck type "T" int
#pragma varargck type "T" uint

View file

@ -103,6 +103,7 @@ trap.$O main.$O: /sys/include/tos.h
l.$O cache.v8.$O mmu.$O rebootcode.$O: mem.h
l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O rebootcode.$O: sysreg.h
main.$O: rebootcode.i
pcibcm.$O: ../port/pci.h
devmouse.$O mouse.$O screen.$O: screen.h
usbdwc.$O: dwcotg.h ../port/usb.h

310
sys/src/9/bcm64/pcibcm.c Normal file
View file

@ -0,0 +1,310 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
/* bcmstb PCIe controller registers */
enum{
RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 = 0x0188/4,
RC_CFG_PRIV1_ID_VAL3 = 0x043c/4,
RC_DL_MDIO_ADDR = 0x1100/4,
RC_DL_MDIO_WR_DATA = 0x1104/4,
RC_DL_MDIO_RD_DATA = 0x1108/4,
MISC_MISC_CTRL = 0x4008/4,
MISC_CPU_2_PCIE_MEM_WIN0_LO = 0x400c/4,
MISC_CPU_2_PCIE_MEM_WIN0_HI = 0x4010/4,
MISC_RC_BAR1_CONFIG_LO = 0x402c/4,
MISC_RC_BAR2_CONFIG_LO = 0x4034/4,
MISC_RC_BAR2_CONFIG_HI = 0x4038/4,
MISC_RC_BAR3_CONFIG_LO = 0x403c/4,
MISC_MSI_BAR_CONFIG_LO = 0x4044/4,
MISC_MSI_BAR_CONFIG_HI = 0x4048/4,
MISC_MSI_DATA_CONFIG = 0x404c/4,
MISC_EOI_CTRL = 0x4060/4,
MISC_PCIE_CTRL = 0x4064/4,
MISC_PCIE_STATUS = 0x4068/4,
MISC_REVISION = 0x406c/4,
MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT = 0x4070/4,
MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI = 0x4080/4,
MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI = 0x4084/4,
MISC_HARD_PCIE_HARD_DEBUG = 0x4204/4,
INTR2_CPU_BASE = 0x4300/4,
MSI_INTR2_BASE = 0x4500/4,
INTR_STATUS = 0,
INTR_SET,
INTR_CLR,
INTR_MASK_STATUS,
INTR_MASK_SET,
INTR_MASK_CLR,
EXT_CFG_INDEX = 0x9000/4,
RGR1_SW_INIT_1 = 0x9210/4,
EXT_CFG_DATA = 0x8000/4,
};
#define MSI_TARGET_ADDR 0xFFFFFFFFCULL
static u32int *regs = (u32int*)(VIRTIO1 + 0x500000);
static Pcidev* pciroot;
static void*
cfgaddr(int tbdf, int rno)
{
if(BUSBNO(tbdf) == 0 && BUSDNO(tbdf) == 0)
return (uchar*)regs + rno;
regs[EXT_CFG_INDEX] = BUSBNO(tbdf) << 20 | BUSDNO(tbdf) << 15 | BUSFNO(tbdf) << 12;
coherence();
return ((uchar*)&regs[EXT_CFG_DATA]) + rno;
}
int
pcicfgrw32(int tbdf, int rno, int data, int read)
{
u32int *p;
if((p = cfgaddr(tbdf, rno & ~3)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
int
pcicfgrw16(int tbdf, int rno, int data, int read)
{
u16int *p;
if((p = cfgaddr(tbdf, rno & ~1)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
int
pcicfgrw8(int tbdf, int rno, int data, int read)
{
u8int *p;
if((p = cfgaddr(tbdf, rno)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
enum {
MSICtrl = 0x02, /* message control register (16 bit) */
MSIAddr = 0x04, /* message address register (64 bit) */
MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */
MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */
};
typedef struct Pciisr Pciisr;
struct Pciisr {
void (*f)(Ureg*, void*);
void *a;
Pcidev *p;
};
static Pciisr pciisr[32];
static Lock pciisrlk;
void
pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a)
{
int cap, ok64;
u32int dat;
u64int adr;
Pcidev *p;
Pciisr *isr;
if((p = pcimatchtbdf(tbdf)) == nil){
print("pciintrenable: %T: unknown device\n", tbdf);
return;
}
if((cap = pcicap(p, PciCapMSI)) < 0){
print("pciintrenable: %T: no MSI cap\n", tbdf);
return;
}
lock(&pciisrlk);
for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
if(isr->p == p){
isr->p = nil;
regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr);
break;
}
}
for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
if(isr->p == nil){
isr->p = p;
isr->a = a;
isr->f = f;
regs[MSI_INTR2_BASE + INTR_CLR] = 1 << (isr-pciisr);
regs[MSI_INTR2_BASE + INTR_MASK_CLR] = 1 << (isr-pciisr);
break;
}
}
unlock(&pciisrlk);
if(isr >= &pciisr[nelem(pciisr)]){
print("pciintrenable: %T: out of isr slots\n", tbdf);
return;
}
adr = MSI_TARGET_ADDR;
ok64 = (pcicfgr16(p, cap + MSICtrl) & (1<<7)) != 0;
pcicfgw32(p, cap + MSIAddr, adr);
if(ok64) pcicfgw32(p, cap + MSIAddr + 4, adr>>32);
dat = regs[MISC_MSI_DATA_CONFIG];
dat = ((dat >> 16) & (dat & 0xFFFF)) | (isr-pciisr);
pcicfgw16(p, cap + (ok64 ? MSIData64 : MSIData32), dat);
pcicfgw16(p, cap + MSICtrl, 1);
}
void
pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a)
{
Pciisr *isr;
lock(&pciisrlk);
for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
if(isr->p != nil && isr->p->tbdf == tbdf && isr->f == f && isr->a == a){
regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr);
isr->p = nil;
isr->f = nil;
isr->a = nil;
break;
}
}
unlock(&pciisrlk);
}
static void
pciinterrupt(Ureg *ureg, void*)
{
Pciisr *isr;
u32int sts;
sts = regs[MSI_INTR2_BASE + INTR_STATUS];
if(sts == 0)
return;
regs[MSI_INTR2_BASE + INTR_CLR] = sts;
for(isr = pciisr; sts != 0 && isr < &pciisr[nelem(pciisr)]; isr++, sts>>=1){
if((sts & 1) != 0 && isr->f != nil)
(*isr->f)(ureg, isr->a);
}
regs[MISC_EOI_CTRL] = 1;
}
static void
pcicfginit(void)
{
uvlong base, limit;
ulong ioa;
fmtinstall('T', tbdffmt);
pciscan(0, &pciroot);
if(pciroot == nil)
return;
/*
* Work out how big the top bus is
*/
ioa = 0;
base = soc.pciwin;
pcibusmap(pciroot, &base, &ioa, 0);
limit = base-1;
/*
* Align the windows and map it
*/
base = soc.pciwin;
regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = base;
regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = base >> 32;
base >>= 20, limit >>= 20;
regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = (base & 0xFFF) << 4 | (limit & 0xFFF) << 20;
regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = base >> 12;
regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = limit >> 12;
ioa = 0;
base = soc.pciwin;
pcibusmap(pciroot, &base, &ioa, 1);
pcihinv(pciroot);
}
void
pcibcmlink(void)
{
int log2dmasize = 30; // 1GB
regs[RGR1_SW_INIT_1] |= 3;
delay(200);
regs[RGR1_SW_INIT_1] &= ~2;
regs[MISC_PCIE_CTRL] &= ~5;
delay(200);
regs[MISC_HARD_PCIE_HARD_DEBUG] &= ~0x08000000;
delay(200);
regs[MSI_INTR2_BASE + INTR_CLR] = -1;
regs[MSI_INTR2_BASE + INTR_MASK_SET] = -1;
regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = 0;
regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = 0;
regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = 0;
regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = 0;
regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = 0;
// SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE
regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27;
regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15);
regs[MISC_RC_BAR2_CONFIG_HI] = 0;
regs[MISC_RC_BAR1_CONFIG_LO] = 0;
regs[MISC_RC_BAR3_CONFIG_LO] = 0;
regs[MISC_MSI_BAR_CONFIG_LO] = MSI_TARGET_ADDR | 1;
regs[MISC_MSI_BAR_CONFIG_HI] = MSI_TARGET_ADDR>>32;
regs[MISC_MSI_DATA_CONFIG] = 0xFFF86540;
intrenable(IRQpci, pciinterrupt, nil, BUSUNKNOWN, "pci");
// force to GEN2
regs[(0xAC + 12)/4] = (regs[(0xAC + 12)/4] & ~15) | 2; // linkcap
regs[(0xAC + 48)/4] = (regs[(0xAC + 48)/4] & ~15) | 2; // linkctl2
regs[RGR1_SW_INIT_1] &= ~1;
delay(500);
if((regs[MISC_PCIE_STATUS] & 0x30) != 0x30){
print("pcireset: phy link is down\n");
return;
}
regs[RC_CFG_PRIV1_ID_VAL3] = 0x060400;
regs[RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1] &= ~0xC;
regs[MISC_HARD_PCIE_HARD_DEBUG] |= 2;
pcicfginit();
}

View file

@ -26,7 +26,7 @@ dev
link
gisb
pci
pcibcm
archbcm4 pci
usbxhci pci archbcm4
ethergenet ethermii
@ -49,7 +49,7 @@ misc
dma
gic
vcore
pci pcibcm
dtracysys
dtracytimer

View file

@ -130,31 +130,6 @@ extern int splflo(void);
extern void sysprocsetup(Proc*);
extern int isaconfig(char*, int, ISAConf*); /* only devusb.c */
/*
* PCI
*/
ulong pcibarsize(Pcidev*, int);
void pcibussize(Pcidev*, ulong*, ulong*);
int pcicfgr8(Pcidev*, int);
int pcicfgr16(Pcidev*, int);
int pcicfgr32(Pcidev*, int);
void pcicfgw8(Pcidev*, int, int);
void pcicfgw16(Pcidev*, int, int);
void pcicfgw32(Pcidev*, int, int);
void pciclrbme(Pcidev*);
void pciclrioe(Pcidev*);
void pciclrmwi(Pcidev*);
int pcigetpms(Pcidev*);
void pcihinv(Pcidev*);
uchar pciipin(Pcidev*, uchar);
Pcidev* pcimatch(Pcidev*, int, int);
Pcidev* pcimatchtbdf(int);
void pcireset(void);
int pciscan(int, Pcidev**);
void pcisetbme(Pcidev*);
void pcisetioe(Pcidev*);
void pcisetmwi(Pcidev*);
int pcisetpms(Pcidev*, int);
int cas32(void*, u32int, u32int);
int tas32(void*);

View file

@ -27,168 +27,6 @@ enum {
#define BUSTYPE(tbdf) ((tbdf)>>24)
#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
/*
* PCI support code.
*/
enum { /* type 0 & type 1 pre-defined header */
PciVID = 0x00, /* vendor ID */
PciDID = 0x02, /* device ID */
PciPCR = 0x04, /* command */
PciPSR = 0x06, /* status */
PciRID = 0x08, /* revision ID */
PciCCRp = 0x09, /* programming interface class code */
PciCCRu = 0x0A, /* sub-class code */
PciCCRb = 0x0B, /* base class code */
PciCLS = 0x0C, /* cache line size */
PciLTR = 0x0D, /* latency timer */
PciHDT = 0x0E, /* header type */
PciBST = 0x0F, /* BIST */
};
/* ccrb (base class code) values; controller types */
enum {
Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
Pcibcstore = 1, /* mass storage */
Pcibcnet = 2, /* network */
Pcibcdisp = 3, /* display */
Pcibcmmedia = 4, /* multimedia */
Pcibcmem = 5, /* memory */
Pcibcbridge = 6, /* bridge */
Pcibccomm = 7, /* simple comms (e.g., serial) */
Pcibcbasesys = 8, /* base system */
Pcibcinput = 9, /* input */
Pcibcdock = 0xa, /* docking stations */
Pcibcproc = 0xb, /* processors */
Pcibcserial = 0xc, /* serial bus (e.g., USB) */
Pcibcwireless = 0xd, /* wireless */
Pcibcintell = 0xe, /* intelligent i/o */
Pcibcsatcom = 0xf, /* satellite comms */
Pcibccrypto = 0x10, /* encryption/decryption */
Pcibcdacq = 0x11, /* data acquisition & signal proc. */
};
/* ccru (sub-class code) values; common cases only */
enum {
/* mass storage */
Pciscscsi = 0, /* SCSI */
Pciscide = 1, /* IDE (ATA) */
/* network */
Pciscether = 0, /* Ethernet */
/* display */
Pciscvga = 0, /* VGA */
Pciscxga = 1, /* XGA */
Pcisc3d = 2, /* 3D */
/* bridges */
Pcischostpci = 0, /* host/pci */
Pciscpcicpci = 1, /* pci/pci */
/* simple comms */
Pciscserial = 0, /* 16450, etc. */
Pciscmultiser = 1, /* multiport serial */
/* serial bus */
Pciscusb = 3, /* USB */
};
enum { /* type 0 pre-defined header */
PciCIS = 0x28, /* cardbus CIS pointer */
PciSVID = 0x2C, /* subsystem vendor ID */
PciSID = 0x2E, /* subsystem ID */
PciEBAR0 = 0x30, /* expansion ROM base address */
PciMGNT = 0x3E, /* burst period length */
PciMLT = 0x3F, /* maximum latency between bursts */
};
enum { /* type 1 pre-defined header */
PciPBN = 0x18, /* primary bus number */
PciSBN = 0x19, /* secondary bus number */
PciUBN = 0x1A, /* subordinate bus number */
PciSLTR = 0x1B, /* secondary latency timer */
PciIBR = 0x1C, /* I/O base */
PciILR = 0x1D, /* I/O limit */
PciSPSR = 0x1E, /* secondary status */
PciMBR = 0x20, /* memory base */
PciMLR = 0x22, /* memory limit */
PciPMBR = 0x24, /* prefetchable memory base */
PciPMLR = 0x26, /* prefetchable memory limit */
PciPUBR = 0x28, /* prefetchable base upper 32 bits */
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
PciIUBR = 0x30, /* I/O base upper 16 bits */
PciIULR = 0x32, /* I/O limit upper 16 bits */
PciEBAR1 = 0x28, /* expansion ROM base address */
PciBCR = 0x3E, /* bridge control register */
};
enum { /* type 2 pre-defined header */
PciCBExCA = 0x10,
PciCBSPSR = 0x16,
PciCBPBN = 0x18, /* primary bus number */
PciCBSBN = 0x19, /* secondary bus number */
PciCBUBN = 0x1A, /* subordinate bus number */
PciCBSLTR = 0x1B, /* secondary latency timer */
PciCBMBR0 = 0x1C,
PciCBMLR0 = 0x20,
PciCBMBR1 = 0x24,
PciCBMLR1 = 0x28,
PciCBIBR0 = 0x2C, /* I/O base */
PciCBILR0 = 0x30, /* I/O limit */
PciCBIBR1 = 0x34, /* I/O base */
PciCBILR1 = 0x38, /* I/O limit */
PciCBSVID = 0x40, /* subsystem vendor ID */
PciCBSID = 0x42, /* subsystem ID */
PciCBLMBAR = 0x44, /* legacy mode base address */
};
typedef struct Pcisiz Pcisiz;
struct Pcisiz
{
Pcidev* dev;
int siz;
int bar;
};
typedef struct Pcidev Pcidev;
struct Pcidev
{
int tbdf; /* type+bus+device+function */
ushort vid; /* vendor ID */
ushort did; /* device ID */
ushort pcr;
uchar rid;
uchar ccrp;
uchar ccru;
uchar ccrb;
uchar cls;
uchar ltr;
struct {
ulong bar; /* base address */
int size;
} mem[6];
struct {
ulong bar;
int size;
} rom;
uchar intl; /* interrupt line */
Pcidev* list;
Pcidev* link; /* next device on this bno */
Pcidev* bridge; /* down a bus */
struct {
ulong bar;
int size;
} ioa, mema;
int pmrb; /* power management register block */
};
#define PCIWINDOW 0
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -65,21 +65,9 @@ void outs(int, ushort);
void outss(int, void*, int);
void outl(int, ulong);
void outsl(int, void*, int);
int pciscan(int, Pcidev **);
ulong pcibarsize(Pcidev *, int);
int pcicfgr8(Pcidev*, int);
int pcicfgr16(Pcidev*, int);
int pcicfgr32(Pcidev*, int);
void pcicfgw8(Pcidev*, int, int);
void pcicfgw16(Pcidev*, int, int);
void pcicfgw32(Pcidev*, int, int);
void pciclrbme(Pcidev*);
void pcihinv(Pcidev*);
uchar pciipin(Pcidev *, uchar);
Pcidev* pcimatch(Pcidev*, int, int);
Pcidev* pcimatchtbdf(int);
void pcireset(void);
void pcisetbme(Pcidev*);
int pcicfgrw8(int, int, int, int);
int pcicfgrw16(int, int, int, int);
int pcicfgrw32(int, int, int, int);
#define procrestore(p)
void procsave(Proc*);
void procsetup(Proc*);

View file

@ -31,150 +31,12 @@ typedef struct Vctl {
void* a; /* argument to call it with */
} Vctl;
enum {
BusCBUS = 0, /* Corollary CBUS */
BusCBUSII, /* Corollary CBUS II */
BusEISA, /* Extended ISA */
BusFUTURE, /* IEEE Futurebus */
BusINTERN, /* Internal bus */
BusISA, /* Industry Standard Architecture */
BusMBI, /* Multibus I */
BusMBII, /* Multibus II */
BusMCA, /* Micro Channel Architecture */
BusMPI, /* MPI */
BusMPSA, /* MPSA */
BusNUBUS, /* Apple Macintosh NuBus */
BusPCI, /* Peripheral Component Interconnect */
BusPCMCIA, /* PC Memory Card International Association */
BusTC, /* DEC TurboChannel */
BusVL, /* VESA Local bus */
BusVME, /* VMEbus */
BusXPRESS, /* Express System Bus */
};
#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
#define BUSTYPE(tbdf) ((tbdf)>>24)
#define BUSDF(tbdf) ((tbdf)&0x000FF00)
#define BUSBDF(tbdf) ((tbdf)&0x0FFFF00)
#define BUSUNKNOWN (-1)
enum {
MaxEISA = 16,
EISAconfig = 0xC80,
};
/*
* PCI support code.
*/
enum { /* type 0 and type 1 pre-defined header */
PciVID = 0x00, /* vendor ID */
PciDID = 0x02, /* device ID */
PciPCR = 0x04, /* command */
PciPSR = 0x06, /* status */
PciRID = 0x08, /* revision ID */
PciCCRp = 0x09, /* programming interface class code */
PciCCRu = 0x0A, /* sub-class code */
PciCCRb = 0x0B, /* base class code */
PciCLS = 0x0C, /* cache line size */
PciLTR = 0x0D, /* latency timer */
PciHDT = 0x0E, /* header type */
PciBST = 0x0F, /* BIST */
PciBAR0 = 0x10, /* base address */
PciBAR1 = 0x14,
PciINTL = 0x3C, /* interrupt line */
PciINTP = 0x3D, /* interrupt pin */
};
enum { /* type 0 pre-defined header */
PciCIS = 0x28, /* cardbus CIS pointer */
PciSVID = 0x2C, /* subsystem vendor ID */
PciSID = 0x2E, /* subsystem ID */
PciEBAR0 = 0x30, /* expansion ROM base address */
PciMGNT = 0x3E, /* burst period length */
PciMLT = 0x3F, /* maximum latency between bursts */
};
enum { /* type 1 pre-defined header */
PciPBN = 0x18, /* primary bus number */
PciSBN = 0x19, /* secondary bus number */
PciUBN = 0x1A, /* subordinate bus number */
PciSLTR = 0x1B, /* secondary latency timer */
PciIBR = 0x1C, /* I/O base */
PciILR = 0x1D, /* I/O limit */
PciSPSR = 0x1E, /* secondary status */
PciMBR = 0x20, /* memory base */
PciMLR = 0x22, /* memory limit */
PciPMBR = 0x24, /* prefetchable memory base */
PciPMLR = 0x26, /* prefetchable memory limit */
PciPUBR = 0x28, /* prefetchable base upper 32 bits */
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
PciIUBR = 0x30, /* I/O base upper 16 bits */
PciIULR = 0x32, /* I/O limit upper 16 bits */
PciEBAR1 = 0x28, /* expansion ROM base address */
PciBCR = 0x3E, /* bridge control register */
};
enum { /* type 2 pre-defined header */
PciCBExCA = 0x10,
PciCBSPSR = 0x16,
PciCBPBN = 0x18, /* primary bus number */
PciCBSBN = 0x19, /* secondary bus number */
PciCBUBN = 0x1A, /* subordinate bus number */
PciCBSLTR = 0x1B, /* secondary latency timer */
PciCBMBR0 = 0x1C,
PciCBMLR0 = 0x20,
PciCBMBR1 = 0x24,
PciCBMLR1 = 0x28,
PciCBIBR0 = 0x2C, /* I/O base */
PciCBILR0 = 0x30, /* I/O limit */
PciCBIBR1 = 0x34, /* I/O base */
PciCBILR1 = 0x38, /* I/O limit */
PciCBSVID = 0x40, /* subsystem vendor ID */
PciCBSID = 0x42, /* subsystem ID */
PciCBLMBAR = 0x44, /* legacy mode base address */
};
typedef struct Pcisiz Pcisiz;
struct Pcisiz
{
Pcidev* dev;
int siz;
int bar;
};
typedef struct Pcidev Pcidev;
typedef struct Pcidev {
int tbdf; /* type+bus+device+function */
ushort vid; /* vendor ID */
ushort did; /* device ID */
uchar rid;
uchar ccrp;
uchar ccru;
uchar ccrb;
struct {
ulong bar; /* base address */
int size;
} mem[6];
uchar intl; /* interrupt line */
Pcidev* list;
Pcidev* link; /* next device on this bno */
Pcidev* bridge; /* down a bus */
struct {
ulong bar;
int size;
} ioa, mema;
ulong pcr;
};
#define PCIWINDOW 0x80000000
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
#define BUSUNKNOWN (-1)

View file

@ -1,5 +1,5 @@
CONF=mtx
CONFLIST=mtx mtxcpu
CONFLIST=mtx
objtype=power
</$objtype/mkfile

View file

@ -20,11 +20,13 @@ dev
ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium inferno
link
pcimtx
ether2114x pci
ethermedium
netdevmedium
misc
pci pcimtx
uarti8250
ip

View file

@ -1,44 +0,0 @@
dev
root
cons
swap
arch
pnp pci
env
pipe
proc
mnt
srv
dup
ssl
cap
kprof
uart
rtc
ether netif
ip arp chandial ip ipv6 ipaux iproute netif netlog nullmedium pktmedium inferno
link
ether2114x pci
ethermedium
netdevmedium
misc
uarti8250
ip
tcp
udp
ipifc
icmp
icmp6
port
int cpuserver = 1;
bootdir
/$objtype/bin/paqfs
/$objtype/bin/auth/factotum
bootfs.paq
boot

View file

@ -1,908 +0,0 @@
/*
* PCI support code.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#define DBG if(0) pcilog
struct
{
char output[16384];
int ptr;
}PCICONS;
int
pcilog(char *fmt, ...)
{
int n;
va_list arg;
char buf[PRINTSIZE];
va_start(arg, fmt);
n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
memmove(PCICONS.output+PCICONS.ptr, buf, n);
PCICONS.ptr += n;
return n;
}
enum
{ /* configuration mechanism #1 */
PciADDR = 0xCF8, /* CONFIG_ADDRESS */
PciDATA = 0xCFC, /* CONFIG_DATA */
/* configuration mechanism #2 */
PciCSE = 0xCF8, /* configuration space enable */
PciFORWARD = 0xCFA, /* which bus */
MaxFNO = 7,
MaxUBN = 255,
};
enum
{ /* command register */
IOen = (1<<0),
MEMen = (1<<1),
MASen = (1<<2),
MemWrInv = (1<<4),
PErrEn = (1<<6),
SErrEn = (1<<8),
};
static Lock pcicfglock;
static QLock pcicfginitlock;
static int pcicfgmode = -1;
static int pcimaxbno = 7;
static int pcimaxdno;
static Pcidev* pciroot;
static Pcidev* pcilist;
static Pcidev* pcitail;
static int pcicfgrw32(int, int, int, int);
static int pcicfgrw8(int, int, int, int);
static char* bustypes[] = {
"CBUSI",
"CBUSII",
"EISA",
"FUTURE",
"INTERN",
"ISA",
"MBI",
"MBII",
"MCA",
"MPI",
"MPSA",
"NUBUS",
"PCI",
"PCMCIA",
"TC",
"VL",
"VME",
"XPRESS",
};
#pragma varargck type "T" int
static int
tbdffmt(Fmt* fmt)
{
char *p;
int l, r, type, tbdf;
if((p = malloc(READSTR)) == nil)
return fmtstrcpy(fmt, "(tbdfconv)");
switch(fmt->r){
case 'T':
tbdf = va_arg(fmt->args, int);
type = BUSTYPE(tbdf);
if(type < nelem(bustypes))
l = snprint(p, READSTR, bustypes[type]);
else
l = snprint(p, READSTR, "%d", type);
snprint(p+l, READSTR-l, ".%d.%d.%d",
BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
break;
default:
snprint(p, READSTR, "(tbdfconv)");
break;
}
r = fmtstrcpy(fmt, p);
free(p);
return r;
}
ulong
pcibarsize(Pcidev *p, int rno)
{
ulong v, size;
v = pcicfgrw32(p->tbdf, rno, 0, 1);
pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
size = pcicfgrw32(p->tbdf, rno, 0, 1);
if(v & 1)
size |= 0xFFFF0000;
pcicfgrw32(p->tbdf, rno, v, 0);
return -(size & ~0x0F);
}
static int
pcisizcmp(void *a, void *b)
{
Pcisiz *aa, *bb;
aa = a;
bb = b;
return aa->siz - bb->siz;
}
static ulong
pcimask(ulong v)
{
ulong m;
m = BI2BY*sizeof(v);
for(m = 1<<(m-1); m != 0; m >>= 1) {
if(m & v)
break;
}
m--;
if((v & m) == 0)
return v;
v |= m;
return v+1;
}
static void
pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
{
Pcidev *p;
int ntb, i, size, rno, hole;
ulong v, mema, ioa, sioa, smema, base, limit;
Pcisiz *table, *tptr, *mtb, *itb;
extern void qsort(void*, long, long, int (*)(void*, void*));
ioa = *pioa;
mema = *pmema;
DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
wrreg, root->tbdf, mema, ioa);
ntb = 0;
for(p = root; p != nil; p = p->link)
ntb++;
ntb *= (PciCIS-PciBAR0)/4;
table = malloc(2*ntb*sizeof(Pcisiz));
itb = table;
mtb = table+ntb;
/*
* Build a table of sizes
*/
for(p = root; p != nil; p = p->link) {
if(p->ccrb == 0x06) {
if(p->ccru == 0x04 && p->bridge != nil) {
sioa = ioa;
smema = mema;
pcibusmap(p->bridge, &smema, &sioa, 0);
hole = pcimask(smema-mema);
if(hole < (1<<20))
hole = 1<<20;
p->mema.size = hole;
hole = pcimask(sioa-ioa);
if(hole < (1<<12))
hole = 1<<12;
p->ioa.size = hole;
itb->dev = p;
itb->bar = -1;
itb->siz = p->ioa.size;
itb++;
mtb->dev = p;
mtb->bar = -1;
mtb->siz = p->mema.size;
mtb++;
}
if((pcicfgr8(p, PciHDT)&0x7f) != 0)
continue;
}
for(i = 0; i <= 5; i++) {
rno = PciBAR0 + i*4;
v = pcicfgrw32(p->tbdf, rno, 0, 1);
size = pcibarsize(p, rno);
if(size == 0)
continue;
if(v & 1) {
itb->dev = p;
itb->bar = i;
itb->siz = size;
itb++;
}
else {
mtb->dev = p;
mtb->bar = i;
mtb->siz = size;
mtb++;
}
p->mem[i].size = size;
}
}
/*
* Sort both tables IO smallest first, Memory largest
*/
qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
tptr = table+ntb;
qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
/*
* Allocate IO address space on this bus
*/
for(tptr = table; tptr < itb; tptr++) {
hole = tptr->siz;
if(tptr->bar == -1)
hole = 1<<12;
ioa = (ioa+hole-1) & ~(hole-1);
p = tptr->dev;
if(tptr->bar == -1)
p->ioa.bar = ioa;
else {
p->pcr |= IOen;
p->mem[tptr->bar].bar = ioa|1;
if(wrreg)
pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
}
ioa += tptr->siz;
}
/*
* Allocate Memory address space on this bus
*/
for(tptr = table+ntb; tptr < mtb; tptr++) {
hole = tptr->siz;
if(tptr->bar == -1)
hole = 1<<20;
mema = (mema+hole-1) & ~(hole-1);
p = tptr->dev;
if(tptr->bar == -1)
p->mema.bar = mema;
else {
p->pcr |= MEMen;
p->mem[tptr->bar].bar = mema;
if(wrreg)
pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
}
mema += tptr->siz;
}
*pmema = mema;
*pioa = ioa;
free(table);
if(wrreg == 0)
return;
/*
* Finally set all the bridge addresses & registers
*/
for(p = root; p != nil; p = p->link) {
if(p->bridge == nil) {
pcicfgrw8(p->tbdf, PciLTR, 64, 0);
p->pcr |= MASen;
pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0);
continue;
}
base = p->ioa.bar;
limit = base+p->ioa.size-1;
v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
pcicfgrw32(p->tbdf, PciIBR, v, 0);
v = (limit & 0xFFFF0000)|(base>>16);
pcicfgrw32(p->tbdf, PciIUBR, v, 0);
base = p->mema.bar;
limit = base+p->mema.size-1;
v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
pcicfgrw32(p->tbdf, PciMBR, v, 0);
/*
* Disable memory prefetch
*/
pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
pcicfgrw8(p->tbdf, PciLTR, 64, 0);
/*
* Enable the bridge
*/
v = 0xFFFF0000 | IOen | MEMen | MASen;
pcicfgrw32(p->tbdf, PciPCR, v, 0);
sioa = p->ioa.bar;
smema = p->mema.bar;
pcibusmap(p->bridge, &smema, &sioa, 1);
}
}
static int
pcilscan(int bno, Pcidev** list)
{
Pcidev *p, *head, *tail;
int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
maxubn = bno;
head = nil;
tail = nil;
for(dno = 0; dno <= pcimaxdno; dno++){
maxfno = 0;
for(fno = 0; fno <= maxfno; fno++){
/*
* For this possible device, form the
* bus+device+function triplet needed to address it
* and try to read the vendor and device ID.
* If successful, allocate a device struct and
* start to fill it in with some useful information
* from the device's configuration space.
*/
tbdf = MKBUS(BusPCI, bno, dno, fno);
l = pcicfgrw32(tbdf, PciVID, 0, 1);
if(l == 0xFFFFFFFF || l == 0)
continue;
p = malloc(sizeof(*p));
p->tbdf = tbdf;
p->vid = l;
p->did = l>>16;
if(pcilist != nil)
pcitail->list = p;
else
pcilist = p;
pcitail = p;
p->rid = pcicfgr8(p, PciRID);
p->ccrp = pcicfgr8(p, PciCCRp);
p->ccru = pcicfgr8(p, PciCCRu);
p->ccrb = pcicfgr8(p, PciCCRb);
p->pcr = pcicfgr32(p, PciPCR);
p->intl = pcicfgr8(p, PciINTL);
/*
* If the device is a multi-function device adjust the
* loop count so all possible functions are checked.
*/
hdt = pcicfgr8(p, PciHDT);
if(hdt & 0x80)
maxfno = MaxFNO;
/*
* If appropriate, read the base address registers
* and work out the sizes.
*/
switch(p->ccrb) {
case 0x01: /* mass storage controller */
case 0x02: /* network controller */
case 0x03: /* display controller */
case 0x04: /* multimedia device */
case 0x06: /* bridge device */
case 0x07: /* simple comm. controllers */
case 0x08: /* base system peripherals */
case 0x09: /* input devices */
case 0x0A: /* docking stations */
case 0x0B: /* processors */
case 0x0C: /* serial bus controllers */
if((hdt & 0x7F) != 0)
break;
rno = PciBAR0 - 4;
for(i = 0; i < nelem(p->mem); i++) {
rno += 4;
p->mem[i].bar = pcicfgr32(p, rno);
p->mem[i].size = pcibarsize(p, rno);
}
break;
case 0x00:
case 0x05: /* memory controller */
default:
break;
}
if(head != nil)
tail->link = p;
else
head = p;
tail = p;
}
}
*list = head;
for(p = head; p != nil; p = p->link){
/*
* Find PCI-PCI bridges and recursively descend the tree.
*/
if(p->ccrb != 0x06 || p->ccru != 0x04)
continue;
/*
* If the secondary or subordinate bus number is not
* initialised try to do what the PCI BIOS should have
* done and fill in the numbers as the tree is descended.
* On the way down the subordinate bus number is set to
* the maximum as it's not known how many buses are behind
* this one; the final value is set on the way back up.
*/
sbn = pcicfgr8(p, PciSBN);
ubn = pcicfgr8(p, PciUBN);
if(sbn == 0 || ubn == 0) {
sbn = maxubn+1;
/*
* Make sure memory, I/O and master enables are
* off, set the primary, secondary and subordinate
* bus numbers and clear the secondary status before
* attempting to scan the secondary bus.
*
* Initialisation of the bridge should be done here.
*/
pcicfgw32(p, PciPCR, 0xFFFF0000);
l = (MaxUBN<<16)|(sbn<<8)|bno;
pcicfgw32(p, PciPBN, l);
pcicfgw16(p, PciSPSR, 0xFFFF);
maxubn = pcilscan(sbn, &p->bridge);
l = (maxubn<<16)|(sbn<<8)|bno;
pcicfgw32(p, PciPBN, l);
}
else {
maxubn = ubn;
pcilscan(sbn, &p->bridge);
}
}
return maxubn;
}
int
pciscan(int bno, Pcidev **list)
{
int ubn;
qlock(&pcicfginitlock);
ubn = pcilscan(bno, list);
qunlock(&pcicfginitlock);
return ubn;
}
static void
pcicfginit(void)
{
char *p;
int bno;
Pcidev **list;
ulong mema, ioa;
qlock(&pcicfginitlock);
if(pcicfgmode != -1)
goto out;
/*
* Try to determine which PCI configuration mode is implemented.
* Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
* a DWORD at 0xCF8 and another at 0xCFC and will pass through
* any non-DWORD accesses as normal I/O cycles. There shouldn't be
* a device behind these addresses so if Mode2 accesses fail try
* for Mode1 (which is preferred, Mode2 is deprecated).
*/
outb(PciCSE, 0);
if(inb(PciCSE) == 0){
pcicfgmode = 2;
pcimaxdno = 15;
}
else {
outl(PciADDR, 0);
if(inl(PciADDR) == 0){
pcicfgmode = 1;
pcimaxdno = 31;
}
}
if(pcicfgmode < 0)
goto out;
fmtinstall('T', tbdffmt);
if(p = getconf("*pcimaxbno"))
pcimaxbno = strtoul(p, 0, 0);
if(p = getconf("*pcimaxdno"))
pcimaxdno = strtoul(p, 0, 0);
list = &pciroot;
for(bno = 0; bno <= pcimaxbno; bno++) {
int sbno = bno;
bno = pcilscan(bno, list);
while(*list)
list = &(*list)->link;
if (sbno == 0) {
Pcidev *pci;
/*
* If we have found a PCI-to-Cardbus bridge, make sure
* it has no valid mappings anymore.
*/
pci = pciroot;
while (pci) {
if (pci->ccrb == 6 && pci->ccru == 7) {
ushort bcr;
/* reset the cardbus */
bcr = pcicfgr16(pci, PciBCR);
pcicfgw16(pci, PciBCR, 0x40 | bcr);
delay(50);
}
pci = pci->link;
}
}
}
if(pciroot == nil)
goto out;
/*
* Work out how big the top bus is
*/
mema = 0;
ioa = 0;
pcibusmap(pciroot, &mema, &ioa, 0);
DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",
mema, pcimask(mema), ioa);
/*
* Align the windows and map it
*/
ioa = 0x1000;
mema = 0;
pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
pcibusmap(pciroot, &mema, &ioa, 1);
DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
out:
qunlock(&pcicfginitlock);
}
static int
pcicfgrw8(int tbdf, int rno, int data, int read)
{
int o, type, x;
if(pcicfgmode == -1)
pcicfginit();
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
x = -1;
if(BUSDNO(tbdf) > pcimaxdno)
return x;
lock(&pcicfglock);
switch(pcicfgmode){
case 1:
o = rno & 0x03;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
x = inb(PciDATA+o);
else
outb(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
}
unlock(&pcicfglock);
return x;
}
int
pcicfgr8(Pcidev* pcidev, int rno)
{
return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
}
void
pcicfgw8(Pcidev* pcidev, int rno, int data)
{
pcicfgrw8(pcidev->tbdf, rno, data, 0);
}
static int
pcicfgrw16(int tbdf, int rno, int data, int read)
{
int o, type, x;
if(pcicfgmode == -1)
pcicfginit();
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
x = -1;
if(BUSDNO(tbdf) > pcimaxdno)
return x;
lock(&pcicfglock);
switch(pcicfgmode){
case 1:
o = rno & 0x02;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
x = ins(PciDATA+o);
else
outs(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
}
unlock(&pcicfglock);
return x;
}
int
pcicfgr16(Pcidev* pcidev, int rno)
{
return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
}
void
pcicfgw16(Pcidev* pcidev, int rno, int data)
{
pcicfgrw16(pcidev->tbdf, rno, data, 0);
}
static int
pcicfgrw32(int tbdf, int rno, int data, int read)
{
int type, x;
if(pcicfgmode == -1)
pcicfginit();
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
x = -1;
if(BUSDNO(tbdf) > pcimaxdno)
return x;
lock(&pcicfglock);
switch(pcicfgmode){
case 1:
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
x = inl(PciDATA);
else
outl(PciDATA, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
}
unlock(&pcicfglock);
return x;
}
int
pcicfgr32(Pcidev* pcidev, int rno)
{
return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
}
void
pcicfgw32(Pcidev* pcidev, int rno, int data)
{
pcicfgrw32(pcidev->tbdf, rno, data, 0);
}
Pcidev*
pcimatch(Pcidev* prev, int vid, int did)
{
if(pcicfgmode == -1)
pcicfginit();
if(prev == nil)
prev = pcilist;
else
prev = prev->list;
while(prev != nil){
if((vid == 0 || prev->vid == vid)
&& (did == 0 || prev->did == did))
break;
prev = prev->list;
}
return prev;
}
Pcidev*
pcimatchtbdf(int tbdf)
{
Pcidev *pcidev;
if(pcicfgmode == -1)
pcicfginit();
for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
if(pcidev->tbdf == tbdf)
break;
}
return pcidev;
}
uchar
pciipin(Pcidev *pci, uchar pin)
{
if (pci == nil)
pci = pcilist;
while (pci) {
uchar intl;
if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
return pci->intl;
if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
return intl;
pci = pci->list;
}
return 0;
}
static void
pcilhinv(Pcidev* p)
{
int i;
Pcidev *t;
if(p == nil) {
putstrn(PCICONS.output, PCICONS.ptr);
p = pciroot;
print("bus dev type vid did intl memory\n");
}
for(t = p; t != nil; t = t->link) {
print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
for(i = 0; i < nelem(p->mem); i++) {
if(t->mem[i].size == 0)
continue;
print("%d:%.8lux %d ", i,
t->mem[i].bar, t->mem[i].size);
}
if(t->ioa.bar || t->ioa.size)
print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
if(t->mema.bar || t->mema.size)
print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
if(t->bridge)
print("->%d", BUSBNO(t->bridge->tbdf));
print("\n");
}
while(p != nil) {
if(p->bridge != nil)
pcilhinv(p->bridge);
p = p->link;
}
}
void
pcihinv(Pcidev* p)
{
if(pcicfgmode == -1)
pcicfginit();
qlock(&pcicfginitlock);
pcilhinv(p);
qunlock(&pcicfginitlock);
}
void
pcireset(void)
{
Pcidev *p;
int pcr;
if(pcicfgmode == -1)
pcicfginit();
for(p = pcilist; p != nil; p = p->list){
pcr = pcicfgr16(p, PciPCR);
pcr &= ~0x0004;
pcicfgw16(p, PciPCR, pcr);
}
}
void
pcisetbme(Pcidev* p)
{
int pcr;
pcr = pcicfgr16(p, PciPCR);
pcr |= MASen;
pcicfgw16(p, PciPCR, pcr);
}
void
pciclrbme(Pcidev* p)
{
int pcr;
pcr = pcicfgr16(p, PciPCR);
pcr &= ~MASen;
pcicfgw16(p, PciPCR, pcr);
}

224
sys/src/9/mtx/pcimtx.c Normal file
View file

@ -0,0 +1,224 @@
/*
* PCI support code.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
enum {
/* configuration mechanism #1 */
PciADDR = 0xCF8, /* CONFIG_ADDRESS */
PciDATA = 0xCFC, /* CONFIG_DATA */
/* configuration mechanism #2 */
PciCSE = 0xCF8, /* configuration space enable */
PciFORWARD = 0xCFA, /* which bus */
};
static int pcicfgmode = -1;
static int pcimaxbno = 7;
static Pcidev* pciroot;
static void
pcicfginit(void)
{
char *p;
int bno;
Pcidev **list;
uvlong mema;
ulong ioa;
fmtinstall('T', tbdffmt);
/*
* Try to determine which PCI configuration mode is implemented.
* Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
* a DWORD at 0xCF8 and another at 0xCFC and will pass through
* any non-DWORD accesses as normal I/O cycles. There shouldn't be
* a device behind these addresses so if Mode2 accesses fail try
* for Mode1 (which is preferred, Mode2 is deprecated).
*/
outb(PciCSE, 0);
if(inb(PciCSE) == 0){
pcicfgmode = 2;
pcimaxdno = 15;
}
else {
outl(PciADDR, 0);
if(inl(PciADDR) == 0){
pcicfgmode = 1;
pcimaxdno = 31;
}
}
if(pcicfgmode < 0)
return;
if(p = getconf("*pcimaxbno"))
pcimaxbno = strtoul(p, 0, 0);
if(p = getconf("*pcimaxdno"))
pcimaxdno = strtoul(p, 0, 0);
list = &pciroot;
for(bno = 0; bno <= pcimaxbno; bno++) {
int sbno = bno;
bno = pciscan(bno, list);
while(*list)
list = &(*list)->link;
if (sbno == 0) {
Pcidev *pci;
/*
* If we have found a PCI-to-Cardbus bridge, make sure
* it has no valid mappings anymore.
*/
pci = pciroot;
while (pci) {
if (pci->ccrb == 6 && pci->ccru == 7) {
ushort bcr;
/* reset the cardbus */
bcr = pcicfgr16(pci, PciBCR);
pcicfgw16(pci, PciBCR, 0x40 | bcr);
delay(50);
}
pci = pci->link;
}
}
}
if(pciroot == nil)
return;
/*
* Work out how big the top bus is
*/
mema = 0;
ioa = 0;
pcibusmap(pciroot, &mema, &ioa, 0);
/*
* Align the windows and map it
*/
ioa = 0x1000;
mema = 0;
pcibusmap(pciroot, &mema, &ioa, 1);
}
int
pcicfgrw8(int tbdf, int rno, int data, int read)
{
int o, type, x;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x03;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = inb(PciDATA+o);
else
outb(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
int
pcicfgrw16(int tbdf, int rno, int data, int read)
{
int o, type;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x02;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = ins(PciDATA+o);
else
outs(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
int
pcicfgrw32(int tbdf, int rno, int data, int read)
{
int type;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = inl(PciDATA);
else
outl(PciDATA, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
void
pcimtxlink(void)
{
pcicfginit();
}

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "mp.h"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "mp.h"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/audioif.h"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/audioif.h"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
static int
intelcputempok(void)

View file

@ -153,7 +153,6 @@ ioinit(void)
ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
}
}
}
/*

View file

@ -5,6 +5,7 @@
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/pci.h"
#include "../port/error.h"
/* this driver doesn't implement the management interrupts. we

View file

@ -8,6 +8,7 @@
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "../port/pci.h"
#include "devlml.h"

View file

@ -8,6 +8,7 @@
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "../port/pci.h"
#define DEBUG 0
@ -922,7 +923,7 @@ unconfigure(Cardbus *cb)
if (pci->mem[i].size == 0)
continue;
if (pci->mem[i].bar & 1) {
iofree(pci->mem[i].bar & ~1);
iofree(pci->mem[i].bar & ~3);
pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
(ushort)-1);
pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);

View file

@ -8,8 +8,9 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "hcwAMC.h"
#include "io.h"
#include "../port/pci.h"
#include "hcwAMC.h"
#define max(a, b) (((a) > (b))? (a): (b))

View file

@ -7,6 +7,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -62,7 +63,7 @@ ne2000match(Ether* edev, int id)
p = ctlr->pcidev;
if(((p->did<<16)|p->vid) != id)
continue;
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(edev->port != 0 && edev->port != port)
continue;

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1671,7 +1672,7 @@ dec2114xpci(void)
print("dec2114x: can't allocate memory\n");
continue;
}
ctlr->port = p->mem[0].bar & ~0x01;
ctlr->port = p->mem[0].bar & ~3;
ctlr->pcidev = p;
ctlr->id = (p->did<<16)|p->vid;

View file

@ -10,6 +10,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -490,7 +491,7 @@ amd79c970pci(void)
p = nil;
while(p = pcimatch(p, 0x1022, 0x2000)){
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){
print("amd79c970: port 0x%uX in use\n", port);
continue;
@ -501,7 +502,7 @@ amd79c970pci(void)
iofree(port);
continue;
}
ctlr->port = p->mem[0].bar & ~0x01;
ctlr->port = port;
ctlr->pcidev = p;
if(ctlrhead != nil)

View file

@ -9,6 +9,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -693,7 +694,7 @@ rtl8139match(Ether* edev, int id)
p = ctlr->pcidev;
if(((p->did<<16)|p->vid) != id)
continue;
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(edev->port != 0 && edev->port != port)
continue;

View file

@ -13,6 +13,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1102,7 +1103,7 @@ rtl8169pci(void)
break;
}
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
print("rtl8169: port %#ux in use\n", port);
continue;

View file

@ -16,6 +16,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1282,8 +1283,7 @@ gc82543pci(void)
free(ctlr);
continue;
}
cls = pcicfgr8(p, PciCLS);
switch(cls){
switch(p->cls){
case 0x08:
case 0x10:
break;

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -963,7 +964,7 @@ i82557pci(void)
* bar[1] is the I/O port register address (32 bytes) and
* bar[2] is for the flash ROM (1MB).
*/
port = p->mem[1].bar & ~0x01;
port = p->mem[1].bar & ~3;
if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
print("i82557: port %#ux in use\n", port);
continue;

View file

@ -9,6 +9,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -8,6 +8,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -22,6 +22,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1089,7 +1090,7 @@ scanpci83815(void)
print("ns83815: can't allocate memory\n");
continue;
}
ctlr->port = p->mem[0].bar & ~0x01;
ctlr->port = p->mem[0].bar & ~3;
ctlr->pcidev = p;
ctlr->id = id;

View file

@ -13,6 +13,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -10,6 +10,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1475,7 +1476,7 @@ tcm59Xpci(void)
*/
if(!(p->mem[0].bar & 0x01))
continue;
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
0, "tcm59Xpci")) < 0){
print("tcm59Xpci: port 0x%uX in use\n", port);

View file

@ -16,6 +16,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1085,7 +1086,7 @@ print("ga620shutdown\n");
static int
ga620reset(Ctlr* ctlr)
{
int cls, csr, i, r;
int csr, i, r;
if(ga620detach(ctlr) < 0)
return -1;
@ -1108,9 +1109,10 @@ ga620reset(Ctlr* ctlr)
csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
csr |= PCIwcmd|PCIrcmd|PCImrm;
if(ctlr->pcidev->pcr & 0x0010){
cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
if(cls != 32)
pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
if(ctlr->pcidev->cls != 32/4){
ctlr->pcidev->cls = 32/4;
pcicfgw8(ctlr->pcidev, PciCLS, ctlr->pcidev->cls);
}
csr |= PCIwm32;
}
csr32w(ctlr, Ps, csr);

View file

@ -22,6 +22,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1910,7 +1911,6 @@ igbereset(Ctlr* ctlr)
static void
igbepci(void)
{
int cls;
Pcidev *p;
Ctlr *ctlr;
void *mem;
@ -1949,8 +1949,7 @@ igbepci(void)
print("igbe: can't map %llux\n", p->mem[0].bar & ~0xF);
continue;
}
cls = pcicfgr8(p, PciCLS);
switch(cls){
switch(p->cls){
default:
print("igbe: p->cls %#ux, setting to 0x10\n", p->cls);
p->cls = 0x10;
@ -1969,7 +1968,7 @@ igbepci(void)
ctlr->pcidev = p;
pcienable(p);
ctlr->id = (p->did<<16)|p->vid;
ctlr->cls = cls*4;
ctlr->cls = p->cls*4;
ctlr->nic = mem;
if(igbereset(ctlr)){

View file

@ -12,6 +12,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -12,6 +12,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -12,6 +12,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -27,6 +27,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -942,7 +943,7 @@ vgbepci(void)
continue;
}
port &= 0xfffe;
port &= 0xfffc;
if(size != 256){
print("vgbe: invalid io size: %d\n", size);

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -563,6 +564,9 @@ pciprobe(int typ)
/* non-transitional devices will have a revision > 0 */
if(p->rid != 0)
continue;
/* first membar needs to be I/O */
if((p->mem[0].bar & 1) == 0)
continue;
/* non-transitional device will have typ+0x40 */
if(pcicfgr16(p, 0x2E) != typ)
continue;
@ -570,8 +574,7 @@ pciprobe(int typ)
print("ethervirtio: no memory for Ctlr\n");
break;
}
c->port = p->mem[0].bar & ~0x1;
c->port = p->mem[0].bar & ~3;
if(ioalloc(c->port, p->mem[0].size, 0, "ethervirtio") < 0){
print("ethervirtio: port %ux in use\n", c->port);
free(c);

View file

@ -15,6 +15,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -947,7 +948,7 @@ vt6102pci(void)
{
Pcidev *p;
Ctlr *ctlr;
int cls, port;
int port;
p = nil;
while(p = pcimatch(p, 0, 0)){
@ -962,7 +963,7 @@ vt6102pci(void)
break;
}
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
print("vt6102: port 0x%uX in use\n", port);
continue;
@ -977,9 +978,7 @@ vt6102pci(void)
ctlr->pcidev = p;
pcienable(p);
ctlr->id = (p->did<<16)|p->vid;
if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
cls = 0x10;
ctlr->cls = cls*4;
ctlr->cls = p->cls*4;
ctlr->tft = Ctft64;
if(vt6102reset(ctlr)){

View file

@ -18,6 +18,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
@ -1112,7 +1113,7 @@ vt6105Mpci(void)
{
Pcidev *p;
Ctlr *ctlr;
int cls, port;
int port;
p = nil;
while(p = pcimatch(p, 0, 0)){
@ -1126,7 +1127,7 @@ vt6105Mpci(void)
break;
}
port = p->mem[0].bar & ~0x01;
port = p->mem[0].bar & ~3;
if(ioalloc(port, p->mem[0].size, 0, "vt6105M") < 0){
print("vt6105M: port 0x%uX in use\n", port);
continue;
@ -1141,9 +1142,7 @@ vt6105Mpci(void)
ctlr->pcidev = p;
pcienable(p);
ctlr->id = (p->did<<16)|p->vid;
if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
cls = 0x10;
ctlr->cls = cls*4;
ctlr->cls = p->cls*4;
ctlr->tft = CtftSAF;
if(vt6105Mreset(ctlr)){

View file

@ -6,6 +6,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -9,6 +9,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -8,6 +8,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"

View file

@ -125,32 +125,10 @@ void outl(int, ulong);
void outsl(int, void*, int);
ulong paddr(void*);
void patwc(void*, int);
ulong pcibarsize(Pcidev*, int);
void pcibussize(Pcidev*, uvlong*, ulong*);
int pcicfgr8(Pcidev*, int);
int pcicfgr16(Pcidev*, int);
int pcicfgr32(Pcidev*, int);
void pcicfgw8(Pcidev*, int, int);
void pcicfgw16(Pcidev*, int, int);
void pcicfgw32(Pcidev*, int, int);
void pciclrbme(Pcidev*);
void pciclrioe(Pcidev*);
void pciclrmwi(Pcidev*);
int pcigetpms(Pcidev*);
void pcihinv(Pcidev*);
uchar pciipin(Pcidev*, uchar);
Pcidev* pcimatch(Pcidev*, int, int);
Pcidev* pcimatchtbdf(int);
int pcicap(Pcidev*, int);
int pcihtcap(Pcidev*, int);
void pcireset(void);
int pciscan(int, Pcidev**);
void pcisetbme(Pcidev*);
void pcisetioe(Pcidev*);
void pcisetmwi(Pcidev*);
int pcisetpms(Pcidev*, int);
void pcienable(Pcidev*);
void pcidisable(Pcidev*);
void pcicfginit(void);
int (*pcicfgrw8)(int, int, int, int);
int (*pcicfgrw16)(int, int, int, int);
int (*pcicfgrw32)(int, int, int, int);
void pcmcisread(PCMslot*);
int pcmcistuple(int, int, int, void*, int);
PCMmap* pcmmap(int, ulong, int, int);
@ -193,6 +171,7 @@ uvlong tscticks(uvlong*);
ulong umballoc(ulong, ulong, ulong);
void umbfree(ulong, ulong);
uvlong upaalloc(uvlong, ulong, ulong);
uvlong upaallocwin(uvlong, ulong, ulong, ulong);
void upafree(uvlong, ulong);
void vectortable(void);
void* vmap(uvlong, int);

View file

@ -59,230 +59,18 @@ typedef struct Vctl {
void* a; /* argument to call it with */
} Vctl;
enum {
BusCBUS = 0, /* Corollary CBUS */
BusCBUSII, /* Corollary CBUS II */
BusEISA, /* Extended ISA */
BusFUTURE, /* IEEE Futurebus */
BusINTERN, /* Internal bus */
BusISA, /* Industry Standard Architecture */
BusMBI, /* Multibus I */
BusMBII, /* Multibus II */
BusMCA, /* Micro Channel Architecture */
BusMPI, /* MPI */
BusMPSA, /* MPSA */
BusNUBUS, /* Apple Macintosh NuBus */
BusPCI, /* Peripheral Component Interconnect */
BusPCMCIA, /* PC Memory Card International Association */
BusTC, /* DEC TurboChannel */
BusVL, /* VESA Local bus */
BusVME, /* VMEbus */
BusXPRESS, /* Express System Bus */
};
#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
#define BUSTYPE(tbdf) ((tbdf)>>24)
#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
#define BUSUNKNOWN (-1)
enum {
MaxEISA = 16,
CfgEISA = 0xC80,
};
/*
* PCI support code.
*/
enum { /* type 0 & type 1 pre-defined header */
PciVID = 0x00, /* vendor ID */
PciDID = 0x02, /* device ID */
PciPCR = 0x04, /* command */
PciPSR = 0x06, /* status */
PciRID = 0x08, /* revision ID */
PciCCRp = 0x09, /* programming interface class code */
PciCCRu = 0x0A, /* sub-class code */
PciCCRb = 0x0B, /* base class code */
PciCLS = 0x0C, /* cache line size */
PciLTR = 0x0D, /* latency timer */
PciHDT = 0x0E, /* header type */
PciBST = 0x0F, /* BIST */
PciBAR0 = 0x10, /* base address */
PciBAR1 = 0x14,
PciCAP = 0x34, /* capabilities pointer */
PciINTL = 0x3C, /* interrupt line */
PciINTP = 0x3D, /* interrupt pin */
};
/* ccrb (base class code) values; controller types */
enum {
Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
Pcibcstore = 1, /* mass storage */
Pcibcnet = 2, /* network */
Pcibcdisp = 3, /* display */
Pcibcmmedia = 4, /* multimedia */
Pcibcmem = 5, /* memory */
Pcibcbridge = 6, /* bridge */
Pcibccomm = 7, /* simple comms (e.g., serial) */
Pcibcbasesys = 8, /* base system */
Pcibcinput = 9, /* input */
Pcibcdock = 0xa, /* docking stations */
Pcibcproc = 0xb, /* processors */
Pcibcserial = 0xc, /* serial bus (e.g., USB) */
Pcibcwireless = 0xd, /* wireless */
Pcibcintell = 0xe, /* intelligent i/o */
Pcibcsatcom = 0xf, /* satellite comms */
Pcibccrypto = 0x10, /* encryption/decryption */
Pcibcdacq = 0x11, /* data acquisition & signal proc. */
};
/* ccru (sub-class code) values; common cases only */
enum {
/* mass storage */
Pciscscsi = 0, /* SCSI */
Pciscide = 1, /* IDE (ATA) */
/* network */
Pciscether = 0, /* Ethernet */
/* display */
Pciscvga = 0, /* VGA */
Pciscxga = 1, /* XGA */
Pcisc3d = 2, /* 3D */
/* bridges */
Pcischostpci = 0, /* host/pci */
Pciscpcicpci = 1, /* pci/pci */
/* simple comms */
Pciscserial = 0, /* 16450, etc. */
Pciscmultiser = 1, /* multiport serial */
/* serial bus */
Pciscusb = 3, /* USB */
};
enum { /* type 0 pre-defined header */
PciCIS = 0x28, /* cardbus CIS pointer */
PciSVID = 0x2C, /* subsystem vendor ID */
PciSID = 0x2E, /* subsystem ID */
PciEBAR0 = 0x30, /* expansion ROM base address */
PciMGNT = 0x3E, /* burst period length */
PciMLT = 0x3F, /* maximum latency between bursts */
};
enum { /* type 1 pre-defined header */
PciPBN = 0x18, /* primary bus number */
PciSBN = 0x19, /* secondary bus number */
PciUBN = 0x1A, /* subordinate bus number */
PciSLTR = 0x1B, /* secondary latency timer */
PciIBR = 0x1C, /* I/O base */
PciILR = 0x1D, /* I/O limit */
PciSPSR = 0x1E, /* secondary status */
PciMBR = 0x20, /* memory base */
PciMLR = 0x22, /* memory limit */
PciPMBR = 0x24, /* prefetchable memory base */
PciPMLR = 0x26, /* prefetchable memory limit */
PciPUBR = 0x28, /* prefetchable base upper 32 bits */
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
PciIUBR = 0x30, /* I/O base upper 16 bits */
PciIULR = 0x32, /* I/O limit upper 16 bits */
PciEBAR1 = 0x28, /* expansion ROM base address */
PciBCR = 0x3E, /* bridge control register */
};
enum { /* type 2 pre-defined header */
PciCBExCA = 0x10,
PciCBSPSR = 0x16,
PciCBPBN = 0x18, /* primary bus number */
PciCBSBN = 0x19, /* secondary bus number */
PciCBUBN = 0x1A, /* subordinate bus number */
PciCBSLTR = 0x1B, /* secondary latency timer */
PciCBMBR0 = 0x1C,
PciCBMLR0 = 0x20,
PciCBMBR1 = 0x24,
PciCBMLR1 = 0x28,
PciCBIBR0 = 0x2C, /* I/O base */
PciCBILR0 = 0x30, /* I/O limit */
PciCBIBR1 = 0x34, /* I/O base */
PciCBILR1 = 0x38, /* I/O limit */
PciCBSVID = 0x40, /* subsystem vendor ID */
PciCBSID = 0x42, /* subsystem ID */
PciCBLMBAR = 0x44, /* legacy mode base address */
};
/* capabilities */
enum {
PciCapPMG = 0x01, /* power management */
PciCapAGP = 0x02,
PciCapVPD = 0x03, /* vital product data */
PciCapSID = 0x04, /* slot id */
PciCapMSI = 0x05,
PciCapCHS = 0x06, /* compact pci hot swap */
PciCapPCIX = 0x07,
PciCapHTC = 0x08, /* hypertransport irq conf */
PciCapVND = 0x09, /* vendor specific information */
PciCapPCIe = 0x10,
PciCapMSIX = 0x11,
PciCapSATA = 0x12,
PciCapHSW = 0x0c, /* hot swap */
};
typedef struct Pcidev Pcidev;
struct Pcidev
{
int tbdf; /* type+bus+device+function */
ushort vid; /* vendor ID */
ushort did; /* device ID */
ushort pcr;
uchar rid;
uchar ccrp;
uchar ccru;
uchar ccrb;
uchar cls;
uchar ltr;
struct {
uvlong bar; /* base address */
int size;
} mem[6];
struct {
uvlong bar;
int size;
} rom;
uchar intl; /* interrupt line */
Pcidev* list;
Pcidev* link; /* next device on this bno */
Pcidev* parent; /* up a bus */
Pcidev* bridge; /* down a bus */
struct {
uvlong bar;
int size;
} ioa, mema;
int pmrb; /* power management register block */
};
enum {
/* vendor ids */
Vintel = 0x8086,
Vmyricom= 0x14c1,
};
#define PCIWINDOW 0
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
#define ISAWINDOW 0
#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
#define BUSUNKNOWN (-1)
/* SMBus transactions */
enum
{
@ -387,6 +175,3 @@ struct PCMslot
int time;
PCMmap mmap[4]; /* maps, last is always for the kernel */
};
#pragma varargck type "T" int
#pragma varargck type "T" uint

View file

@ -40,6 +40,7 @@ main(void)
ramdiskinit();
confinit();
xinit();
pcicfginit();
bootscreeninit();
if(i8237alloc != nil)
i8237alloc();
@ -57,7 +58,6 @@ main(void)
initseg();
if(delaylink){
bootlinks();
pcimatch(0, 0, 0);
}else
links();
chandevreset();

View file

@ -250,6 +250,24 @@ upaalloc(uvlong pa, ulong size, ulong align)
return memmapalloc(pa, size, align, MemUPA);
}
uvlong
upaallocwin(uvlong pa, ulong win, ulong size, ulong align)
{
uvlong a, base, top = pa + win;
for(base = memmapnext(-1, MemUPA); base != -1 && base < top; base = memmapnext(base, MemUPA)){
if(base < pa){
if(pa >= base + memmapsize(base, 0))
continue;
base = pa;
}
a = upaalloc(base, size, align);
if(a != -1)
return a;
}
return -1ULL;
}
void
upafree(uvlong pa, ulong size)
{

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "mp.h"

View file

@ -27,7 +27,7 @@ dev
draw screen vga vgax vgasoft
mouse mouse
kbd
vga
vga pci
sd
floppy dma
@ -35,7 +35,7 @@ dev
lpt
audio dma
pccard
pccard pci
i82365 cis
uart
usb
@ -45,11 +45,11 @@ dev
link
segdesc
devpccard
devpccard pci
devi82365
cputemp
cputemp pci
apm apmjump
ether2000 ether8390
ether2000 pci ether8390
ether2114x pci
ether589 etherelnk3
ether79c970 pci
@ -73,7 +73,7 @@ link
ethervt6102 pci ethermii
ethervt6105m pci ethermii
ethersink
ethersmc devi82365 cis
ethersmc pci devi82365 cis
etheryuk pci
etherwavelan wavelan devi82365 cis pci
etheriwl pci wifi
@ -84,16 +84,18 @@ link
pcmciamodem
netdevmedium
loopbackmedium
usbuhci
usbohci
usbuhci pci
usbohci pci
usbehci usbehcipc
usbxhci pci
audiosb16 dma
audioac97 audioac97mix
audiohda
audioac97 pci audioac97mix
audiohda pci
misc
pci pcipc
archacpi mp apic squidboy ec
archmp mp apic squidboy
mtrr

File diff suppressed because it is too large Load diff

739
sys/src/9/pc/pcipc.c Normal file
View file

@ -0,0 +1,739 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define DBG if(1) print
enum
{ /* configuration mechanism #1 */
PciADDR = 0xCF8, /* CONFIG_ADDRESS */
PciDATA = 0xCFC, /* CONFIG_DATA */
/* configuration mechanism #2 */
PciCSE = 0xCF8, /* configuration space enable */
PciFORWARD = 0xCFA, /* which bus */
};
static int pcimaxbno = 255;
static int pcicfgmode = -1;
static Pcidev* pciroot;
static int nobios, nopcirouting;
static BIOS32si* pcibiossi;
static int pcicfgrw8raw(int, int, int, int);
static int pcicfgrw16raw(int, int, int, int);
static int pcicfgrw32raw(int, int, int, int);
int (*pcicfgrw8)(int, int, int, int) = pcicfgrw8raw;
int (*pcicfgrw16)(int, int, int, int) = pcicfgrw16raw;
int (*pcicfgrw32)(int, int, int, int) = pcicfgrw32raw;
static int
pcicfgrw8raw(int tbdf, int rno, int data, int read)
{
int o, type;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x03;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = inb(PciDATA+o);
else
outb(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
static int
pcicfgrw16raw(int tbdf, int rno, int data, int read)
{
int o, type;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
o = rno & 0x02;
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = ins(PciDATA+o);
else
outs(PciDATA+o, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
static int
pcicfgrw32raw(int tbdf, int rno, int data, int read)
{
int type;
if(BUSBNO(tbdf))
type = 0x01;
else
type = 0x00;
switch(pcicfgmode){
case 1:
rno &= ~0x03;
outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
if(read)
data = inl(PciDATA);
else
outl(PciDATA, data);
outl(PciADDR, 0);
break;
case 2:
outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
outb(PciFORWARD, BUSBNO(tbdf));
if(read)
data = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
else
outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
outb(PciCSE, 0);
break;
default:
data = -1;
}
return data;
}
static int
pcicfgrw8bios(int tbdf, int rno, int data, int read)
{
BIOS32ci ci;
if(pcibiossi == nil)
return -1;
memset(&ci, 0, sizeof(BIOS32ci));
ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
ci.edi = rno;
if(read){
ci.eax = 0xB108;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return ci.ecx & 0xFF;
}
else{
ci.eax = 0xB10B;
ci.ecx = data & 0xFF;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return 0;
}
return -1;
}
static int
pcicfgrw16bios(int tbdf, int rno, int data, int read)
{
BIOS32ci ci;
if(pcibiossi == nil)
return -1;
memset(&ci, 0, sizeof(BIOS32ci));
ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
ci.edi = rno;
if(read){
ci.eax = 0xB109;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return ci.ecx & 0xFFFF;
}
else{
ci.eax = 0xB10C;
ci.ecx = data & 0xFFFF;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return 0;
}
return -1;
}
static int
pcicfgrw32bios(int tbdf, int rno, int data, int read)
{
BIOS32ci ci;
if(pcibiossi == nil)
return -1;
memset(&ci, 0, sizeof(BIOS32ci));
ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
ci.edi = rno;
if(read){
ci.eax = 0xB10A;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return ci.ecx;
}
else{
ci.eax = 0xB10D;
ci.ecx = data;
if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
return 0;
}
return -1;
}
static BIOS32si*
pcibiosinit(void)
{
BIOS32ci ci;
BIOS32si *si;
if((si = bios32open("$PCI")) == nil)
return nil;
memset(&ci, 0, sizeof(BIOS32ci));
ci.eax = 0xB101;
if(bios32ci(si, &ci) || ci.edx != ((' '<<24)|('I'<<16)|('C'<<8)|'P')){
free(si);
return nil;
}
if(ci.eax & 0x01)
pcimaxdno = 31;
else
pcimaxdno = 15;
pcimaxbno = ci.ecx & 0xff;
return si;
}
static uchar
pIIxget(Pcidev *router, uchar link)
{
uchar pirq;
/* link should be 0x60, 0x61, 0x62, 0x63 */
pirq = pcicfgr8(router, link);
return (pirq < 16)? pirq: 0;
}
static void
pIIxset(Pcidev *router, uchar link, uchar irq)
{
pcicfgw8(router, link, irq);
}
static uchar
viaget(Pcidev *router, uchar link)
{
uchar pirq;
/* link should be 1, 2, 3, 5 */
pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
return (link & 1)? (pirq >> 4): (pirq & 15);
}
static void
viaset(Pcidev *router, uchar link, uchar irq)
{
uchar pirq;
pirq = pcicfgr8(router, 0x55 + (link >> 1));
pirq &= (link & 1)? 0x0f: 0xf0;
pirq |= (link & 1)? (irq << 4): (irq & 15);
pcicfgw8(router, 0x55 + (link>>1), pirq);
}
static uchar
optiget(Pcidev *router, uchar link)
{
uchar pirq = 0;
/* link should be 0x02, 0x12, 0x22, 0x32 */
if ((link & 0xcf) == 0x02)
pirq = pcicfgr8(router, 0xb8 + (link >> 5));
return (link & 0x10)? (pirq >> 4): (pirq & 15);
}
static void
optiset(Pcidev *router, uchar link, uchar irq)
{
uchar pirq;
pirq = pcicfgr8(router, 0xb8 + (link >> 5));
pirq &= (link & 0x10)? 0x0f : 0xf0;
pirq |= (link & 0x10)? (irq << 4): (irq & 15);
pcicfgw8(router, 0xb8 + (link >> 5), pirq);
}
static uchar
aliget(Pcidev *router, uchar link)
{
/* No, you're not dreaming */
static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
uchar pirq;
/* link should be 0x01..0x08 */
pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
return (link & 1)? map[pirq&15]: map[pirq>>4];
}
static void
aliset(Pcidev *router, uchar link, uchar irq)
{
/* Inverse of map in aliget */
static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
uchar pirq;
pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
pirq &= (link & 1)? 0x0f: 0xf0;
pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
}
static uchar
cyrixget(Pcidev *router, uchar link)
{
uchar pirq;
/* link should be 1, 2, 3, 4 */
pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
return ((link & 1)? pirq >> 4: pirq & 15);
}
static void
cyrixset(Pcidev *router, uchar link, uchar irq)
{
uchar pirq;
pirq = pcicfgr8(router, 0x5c + (link>>1));
pirq &= (link & 1)? 0x0f: 0xf0;
pirq |= (link & 1)? (irq << 4): (irq & 15);
pcicfgw8(router, 0x5c + (link>>1), pirq);
}
typedef struct Bridge Bridge;
struct Bridge
{
ushort vid;
ushort did;
uchar (*get)(Pcidev *, uchar);
void (*set)(Pcidev *, uchar, uchar);
};
static Bridge southbridges[] = {
{ 0x8086, 0x122e, pIIxget, pIIxset }, /* Intel 82371FB */
{ 0x8086, 0x1234, pIIxget, pIIxset }, /* Intel 82371MX */
{ 0x8086, 0x7000, pIIxget, pIIxset }, /* Intel 82371SB */
{ 0x8086, 0x7110, pIIxget, pIIxset }, /* Intel 82371AB */
{ 0x8086, 0x7198, pIIxget, pIIxset }, /* Intel 82443MX (fn 1) */
{ 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */
{ 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */
{ 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */
{ 0x8086, 0x2448, pIIxget, pIIxset }, /* Intel 82801BAM/CAM/DBM */
{ 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */
{ 0x8086, 0x244e, pIIxget, pIIxset }, /* Intel 82801 */
{ 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */
{ 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */
{ 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */
{ 0x8086, 0x24cc, pIIxget, pIIxset }, /* Intel 82801DBM */
{ 0x8086, 0x24d0, pIIxget, pIIxset }, /* Intel 82801EB */
{ 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */
{ 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */
{ 0x8086, 0x2641, pIIxget, pIIxset }, /* Intel 82801FBM */
{ 0x8086, 0x2670, pIIxget, pIIxset }, /* Intel 632xesb */
{ 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */
{ 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */
{ 0x8086, 0x27bd, pIIxget, pIIxset }, /* Intel 82801GB/GR */
{ 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801JIR */
{ 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801JI */
{ 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801JI */
{ 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801JI */
{ 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */
{ 0x8086, 0x1c02, pIIxget, pIIxset }, /* Intel 6 Series/C200 */
{ 0x8086, 0x1e53, pIIxget, pIIxset }, /* Intel 7 Series/C216 */
{ 0x8086, 0x8c56, pIIxget, pIIxset }, /* Intel 8 Series/C226 */
{ 0x8086, 0x2810, pIIxget, pIIxset }, /* Intel 82801HB/HR (ich8/r) */
{ 0x8086, 0x2812, pIIxget, pIIxset }, /* Intel 82801HH (ich8dh) */
{ 0x8086, 0x2912, pIIxget, pIIxset }, /* Intel 82801ih ich9dh */
{ 0x8086, 0x2914, pIIxget, pIIxset }, /* Intel 82801io ich9do */
{ 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801ibr ich9r */
{ 0x8086, 0x2917, pIIxget, pIIxset }, /* Intel 82801iem ich9m-e */
{ 0x8086, 0x2918, pIIxget, pIIxset }, /* Intel 82801ib ich9 */
{ 0x8086, 0x2919, pIIxget, pIIxset }, /* Intel 82801? ich9m */
{ 0x8086, 0x3a16, pIIxget, pIIxset }, /* Intel 82801jir ich10r */
{ 0x8086, 0x3a18, pIIxget, pIIxset }, /* Intel 82801jib ich10 */
{ 0x8086, 0x3a40, pIIxget, pIIxset }, /* Intel 82801ji */
{ 0x8086, 0x3a42, pIIxget, pIIxset }, /* Intel 82801ji */
{ 0x8086, 0x3a48, pIIxget, pIIxset }, /* Intel 82801ji */
{ 0x8086, 0x3b06, pIIxget, pIIxset }, /* Intel 82801? ibex peak */
{ 0x8086, 0x3b14, pIIxget, pIIxset }, /* Intel 82801? 3420 */
{ 0x8086, 0x1c49, pIIxget, pIIxset }, /* Intel 82hm65 cougar point pch */
{ 0x8086, 0x1c4b, pIIxget, pIIxset }, /* Intel 82hm67 */
{ 0x8086, 0x1c4f, pIIxget, pIIxset }, /* Intel 82qm67 cougar point pch */
{ 0x8086, 0x1c52, pIIxget, pIIxset }, /* Intel 82q65 cougar point pch */
{ 0x8086, 0x1c54, pIIxget, pIIxset }, /* Intel 82q67 cougar point pch */
{ 0x8086, 0x1e55, pIIxget, pIIxset }, /* Intel QM77 panter point lpc */
{ 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */
{ 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */
{ 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */
{ 0x1106, 0x3177, viaget, viaset }, /* Viatech VT8235 */
{ 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */
{ 0x1106, 0x3287, viaget, viaset }, /* Viatech VT8251 */
{ 0x1106, 0x8410, viaget, viaset }, /* Viatech PV530 bridge */
{ 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */
{ 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */
{ 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */
{ 0x1039, 0x0496, pIIxget, pIIxset }, /* SI 496 */
{ 0x1078, 0x0100, cyrixget, cyrixset }, /* Cyrix 5530 Legacy */
{ 0x1022, 0x790e, nil, nil }, /* AMD FCH LPC bridge */
{ 0x1022, 0x746b, nil, nil }, /* AMD 8111 */
{ 0x10de, 0x00d1, nil, nil }, /* NVIDIA nForce 3 */
{ 0x10de, 0x00e0, nil, nil }, /* NVIDIA nForce 3 250 Series */
{ 0x10de, 0x00e1, nil, nil }, /* NVIDIA nForce 3 250 Series */
{ 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */
{ 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */
{ 0x1002, 0x4372, nil, nil }, /* ATI SB400 */
{ 0x1002, 0x9601, nil, nil }, /* AMD SB710 */
{ 0x1002, 0x438d, nil, nil }, /* AMD SB600 */
{ 0x1002, 0x439d, nil, nil }, /* AMD SB810 */
};
typedef struct Slot Slot;
struct Slot {
uchar bus; /* Pci bus number */
uchar dev; /* Pci device number */
uchar maps[12]; /* Avoid structs! Link and mask. */
uchar slot; /* Add-in/built-in slot */
uchar reserved;
};
typedef struct Router Router;
struct Router {
uchar signature[4]; /* Routing table signature */
uchar version[2]; /* Version number */
uchar size[2]; /* Total table size */
uchar bus; /* Interrupt router bus number */
uchar devfn; /* Router's devfunc */
uchar pciirqs[2]; /* Exclusive PCI irqs */
uchar compat[4]; /* Compatible PCI interrupt router */
uchar miniport[4]; /* Miniport data */
uchar reserved[11];
uchar checksum;
};
static ushort pciirqs; /* Exclusive PCI irqs */
static Bridge *southbridge; /* Which southbridge to use. */
static void
pcirouting(void)
{
Slot *e;
Router *r;
int i, size, tbdf;
Pcidev *sbpci, *pci;
uchar *p, pin, irq, link, *map;
if((p = sigsearch("$PIR", 0)) == nil)
return;
r = (Router*)p;
size = (r->size[1] << 8)|r->size[0];
if(size < sizeof(Router) || checksum(r, size))
return;
if(0) print("PCI interrupt routing table version %d.%d at %p\n",
r->version[0], r->version[1], r);
tbdf = MKBUS(BusPCI, r->bus, (r->devfn>>3)&0x1f, r->devfn&7);
sbpci = pcimatchtbdf(tbdf);
if(sbpci == nil) {
print("pcirouting: Cannot find south bridge %T\n", tbdf);
return;
}
for(i = 0; i < nelem(southbridges); i++)
if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did)
break;
if(i == nelem(southbridges)) {
print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did);
return;
}
southbridge = &southbridges[i];
if(southbridge->get == nil)
return;
pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0];
for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {
if(0) {
print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);
for (i = 0; i < 4; i++) {
map = &e->maps[i * 3];
print("[%d] %.2uX %.4uX ", i, map[0], (map[2] << 8)|map[1]);
}
print("\n");
}
for(i = 0; i < 8; i++) {
tbdf = MKBUS(BusPCI, e->bus, (e->dev>>3)&0x1f, i);
pci = pcimatchtbdf(tbdf);
if(pci == nil)
continue;
pin = pcicfgr8(pci, PciINTP);
if(pin == 0 || pin == 0xff)
continue;
map = &e->maps[((pin - 1) % 4) * 3];
link = map[0];
irq = southbridge->get(sbpci, link);
if(irq == pci->intl)
continue;
if(irq == 0 || (irq & 0x80) != 0){
irq = pci->intl;
if(irq == 0 || irq == 0xff)
continue;
if(southbridge->set == nil)
continue;
southbridge->set(sbpci, link, irq);
}
print("pcirouting: %T at pin %d link %.2uX irq %d -> %d\n", tbdf, pin, link, pci->intl, irq);
pcicfgw8(pci, PciINTL, irq);
pci->intl = irq;
}
}
}
static void
pcireservemem(void)
{
Pcidev *p;
uvlong pa;
int i;
/*
* mark all valid physical address space claimed by pci devices
* as in use, so that upaalloc doesn't give it out.
*/
for(p=pciroot; p != nil; p=p->list){
for(i=0; i<nelem(p->mem); i++){
if(p->mem[i].size == 0)
continue;
if(p->mem[i].bar & 1)
continue;
if((p->mem[i].bar & ~0xFULL) == 0)
continue;
upaalloc(p->mem[i].bar&~0xFULL, p->mem[i].size, 0);
}
}
/*
* allocate physical address space for unassigned membars.
*/
for(p=pciroot; p != nil; p=p->list){
for(i=0; i<nelem(p->mem); i++){
if(p->mem[i].size == 0)
continue;
if(p->mem[i].bar & ~0xEULL)
continue;
if(p->parent == nil){
pa = upaalloc(-1ULL,
p->mem[i].size, p->mem[i].size);
} else if(p->mem[i].bar & 8){
pa = upaallocwin(p->parent->prefa.bar, p->parent->prefa.size,
p->mem[i].size, p->mem[i].size);
if(pa == -1ULL)
goto Mem;
} else {
Mem:
pa = upaallocwin(p->parent->mema.bar, p->parent->mema.size,
p->mem[i].size, p->mem[i].size);
}
if(pa == -1ULL)
continue;
p->mem[i].bar |= pa;
pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar);
DBG("%T: bar%d: fixed %.8lluX %d\n",
p->tbdf, i, p->mem[i].bar, p->mem[i].size);
}
}
}
void
pcicfginit(void)
{
char *p;
Pcidev **list;
int bno, n, pcibios;
fmtinstall('T', tbdffmt);
pcibios = 0;
if(getconf("*nobios"))
nobios = 1;
else if(getconf("*pcibios"))
pcibios = 1;
if(getconf("*nopcirouting"))
nopcirouting = 1;
/*
* Try to determine which PCI configuration mode is implemented.
* Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
* a DWORD at 0xCF8 and another at 0xCFC and will pass through
* any non-DWORD accesses as normal I/O cycles. There shouldn't be
* a device behind these addresses so if Mode1 accesses fail try
* for Mode2 (Mode2 is deprecated).
*/
if(!pcibios){
/*
* Bits [30:24] of PciADDR must be 0,
* according to the spec.
*/
n = inl(PciADDR);
if(!(n & 0x7F000000)){
outl(PciADDR, 0x80000000);
outb(PciADDR+3, 0);
if(inl(PciADDR) & 0x80000000){
pcicfgmode = 1;
pcimaxdno = 31;
}
}
outl(PciADDR, n);
if(pcicfgmode < 0){
/*
* The 'key' part of PciCSE should be 0.
*/
n = inb(PciCSE);
if(!(n & 0xF0)){
outb(PciCSE, 0x0E);
if(inb(PciCSE) == 0x0E){
pcicfgmode = 2;
pcimaxdno = 15;
}
}
outb(PciCSE, n);
}
}
if(pcicfgmode < 0 || pcibios) {
if((pcibiossi = pcibiosinit()) == nil)
goto out;
pcicfgrw8 = pcicfgrw8bios;
pcicfgrw16 = pcicfgrw16bios;
pcicfgrw32 = pcicfgrw32bios;
pcicfgmode = 3;
}
if(p = getconf("*pcimaxbno"))
pcimaxbno = strtoul(p, 0, 0);
if(p = getconf("*pcimaxdno")){
n = strtoul(p, 0, 0);
if(n < pcimaxdno)
pcimaxdno = n;
}
list = &pciroot;
for(bno = 0; bno <= pcimaxbno; bno++) {
int sbno = bno;
bno = pciscan(bno, list);
while(*list)
list = &(*list)->link;
if (sbno == 0) {
Pcidev *pci;
/*
* If we have found a PCI-to-Cardbus bridge, make sure
* it has no valid mappings anymore.
*/
for(pci = pciroot; pci != nil; pci = pci->link){
if (pci->ccrb == 6 && pci->ccru == 7) {
ushort bcr;
/* reset the cardbus */
bcr = pcicfgr16(pci, PciBCR);
pcicfgw16(pci, PciBCR, 0x40 | bcr);
delay(50);
}
}
}
}
if(pciroot == nil)
goto out;
if(nobios) {
uvlong mema;
ulong ioa;
/*
* Work out how big the top bus is
*/
pcibussize(pciroot, &mema, &ioa);
DBG("Size: mem=%.8llux io=%lux\n", mema, ioa);
/*
* Align the windows and map it
*/
mema = upaalloc(-1ULL, mema, mema);
if(mema == -1ULL)
panic("pcicfginit: can't allocate pci window");
ioa = 0x1000;
DBG("Base: mem=%.8llux io=%lux\n", mema, ioa);
pcibusmap(pciroot, &mema, &ioa, 1);
DBG("Limit: mem=%.8llux io=%lux\n", mema, ioa);
goto out;
}
pcireservemem();
if(!nopcirouting)
pcirouting();
out:
if(getconf("*pcihinv"))
pcihinv(pciroot);
}

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
/*
* SMBus support for the PIIX4

View file

@ -13,6 +13,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/sd.h"
/* registers */

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "../port/error.h"

View file

@ -23,6 +23,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/sd.h"
extern SDifc sd53c8xxifc;

View file

@ -9,6 +9,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/sd.h"
#include <fis.h>

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "../port/error.h"
@ -352,7 +353,7 @@ pc87415ienable(Ctlr* ctlr)
return;
x = pcicfgr32(p, 0x40);
if(ctlr->cmdport == p->mem[0].bar)
if(ctlr->cmdport == (p->mem[0].bar & ~3))
x &= ~0x00000100;
else
x &= ~0x00000200;
@ -2142,8 +2143,8 @@ atapnp(void)
if((map & 1<<channel) == 0)
continue;
if(pi & 1<<2*channel){
sdev = ataprobe(p->mem[0+2*channel].bar & ~0x01,
p->mem[1+2*channel].bar & ~0x01,
sdev = ataprobe(p->mem[0+2*channel].bar & ~3,
p->mem[1+2*channel].bar & ~3,
p->intl, 3);
tbdf = p->tbdf;
}
@ -2169,7 +2170,7 @@ atapnp(void)
ctlr->span = span;
ctlr->irqack = irqack;
if((pi & 0x80) && (p->mem[4].bar & 0x01))
ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8;
ctlr->bmiba = (p->mem[4].bar & ~3) + channel*8;
if(head != nil)
tail->next = sdev;
else

View file

@ -15,6 +15,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/sd.h"
#include <fis.h>

View file

@ -15,6 +15,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "../port/error.h"
@ -1054,7 +1055,7 @@ mylexpnp(void)
p = nil;
head = tail = nil;
while(p = pcimatch(p, 0x104B, 0)){
if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
if((sdev = mylexprobe(p->mem[0].bar & ~3, p->intl)) == nil)
continue;
ctlr = sdev->ctlr;

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "../port/error.h"

View file

@ -10,6 +10,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/sd.h"
#include <fis.h>

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "ureg.h"
#include "../port/error.h"
@ -203,13 +204,15 @@ viopnpdevs(int typ)
continue;
if(p->rid != 0)
continue;
if((p->mem[0].bar & 1) == 0)
continue;
if(pcicfgr16(p, 0x2E) != typ)
continue;
if((vd = malloc(sizeof(*vd))) == nil){
print("virtio: no memory for Vdev\n");
break;
}
vd->port = p->mem[0].bar & ~0x1;
vd->port = p->mem[0].bar & ~3;
if(ioalloc(vd->port, p->mem[0].size, 0, "virtio") < 0){
print("virtio: port %lux in use\n", vd->port);
free(vd);

View file

@ -7,6 +7,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "uartaxp.i"

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
extern PhysUart i8250physuart;
@ -21,21 +22,21 @@ uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name,
char buf[64];
Uart *head, *uart;
head = malloc(sizeof(Uart)*n);
if(head == nil){
print("uartpci: no memory for Uarts\n");
if((p->mem[barno].bar & 1) == 0)
return nil;
}
io = p->mem[barno].bar & ~0x01;
io = p->mem[barno].bar & ~3;
snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
print("uartpci: I/O 0x%uX in use\n", io);
free(head);
return nil;
}
pcienable(p);
head = malloc(sizeof(Uart)*n);
if(head == nil){
print("uartpci: no memory for Uarts\n");
iofree(io);
return nil;
}
uart = head;
for(i = 0; i < n; i++){
ctlr = i8250alloc(io + i*iosize, p->intl, p->tbdf);

View file

@ -10,6 +10,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/usb.h"
#include "usbehci.h"

View file

@ -16,6 +16,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/usb.h"

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#include "../port/usb.h"
@ -2131,7 +2132,7 @@ scanpci(void)
case 0:
if((p->mem[4].bar & 1) == 0)
continue;
io = (int)p->mem[4].bar & ~0xF;
io = p->mem[4].bar & ~3;
break;
default:
continue;

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -46,6 +46,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -8,6 +8,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -7,6 +7,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Ureg Ureg386

View file

@ -4,6 +4,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
#define Image IMAGE

View file

@ -124,32 +124,10 @@ void outl(int, ulong);
void outsl(int, void*, int);
uintptr paddr(void*);
void patwc(void*, int);
ulong pcibarsize(Pcidev*, int);
void pcibussize(Pcidev*, uvlong*, ulong*);
int pcicfgr8(Pcidev*, int);
int pcicfgr16(Pcidev*, int);
int pcicfgr32(Pcidev*, int);
void pcicfgw8(Pcidev*, int, int);
void pcicfgw16(Pcidev*, int, int);
void pcicfgw32(Pcidev*, int, int);
void pciclrbme(Pcidev*);
void pciclrioe(Pcidev*);
void pciclrmwi(Pcidev*);
int pcigetpms(Pcidev*);
void pcihinv(Pcidev*);
uchar pciipin(Pcidev*, uchar);
Pcidev* pcimatch(Pcidev*, int, int);
Pcidev* pcimatchtbdf(int);
int pcicap(Pcidev*, int);
int pcihtcap(Pcidev*, int);
void pcireset(void);
int pciscan(int, Pcidev**);
void pcisetbme(Pcidev*);
void pcisetioe(Pcidev*);
void pcisetmwi(Pcidev*);
int pcisetpms(Pcidev*, int);
void pcienable(Pcidev*);
void pcidisable(Pcidev*);
void pcicfginit(void);
int (*pcicfgrw8)(int, int, int, int);
int (*pcicfgrw16)(int, int, int, int);
int (*pcicfgrw32)(int, int, int, int);
void pcmcisread(PCMslot*);
int pcmcistuple(int, int, int, void*, int);
PCMmap* pcmmap(int, ulong, int, int);
@ -192,6 +170,7 @@ uvlong tscticks(uvlong*);
ulong umballoc(ulong, ulong, ulong);
void umbfree(ulong, ulong);
uvlong upaalloc(uvlong, ulong, ulong);
uvlong upaallocwin(uvlong, ulong, ulong, ulong);
void upafree(uvlong, ulong);
void vectortable(void);
void vmxprocrestore(Proc *);

View file

@ -190,6 +190,7 @@ main(void)
ramdiskinit();
confinit();
xinit();
pcicfginit();
bootscreeninit();
if(i8237alloc != nil)
i8237alloc();
@ -207,7 +208,6 @@ main(void)
initseg();
if(delaylink){
bootlinks();
pcimatch(0, 0, 0);
}else
links();
chandevreset();

View file

@ -26,7 +26,7 @@ dev
draw screen vga vgax vgasoft
mouse mouse
kbd
vga
vga pci
sd
# floppy dma
@ -44,9 +44,9 @@ dev
dtracy
link
# devpccard
# devpccard pci
# devi82365
cputemp
cputemp pci
# ether2000 ether8390
# ether2114x pci
# ether589 etherelnk3
@ -82,16 +82,17 @@ link
# pcmciamodem
netdevmedium
loopbackmedium
usbuhci
usbohci
usbehci usbehcipc
usbuhci pci
usbohci pci
usbehci pci usbehcipc
usbxhci pci
# audiosb16 dma
# audioac97 audioac97mix
audiohda
# audioac97 pci audioac97mix
audiohda pci
misc
pci pcipc
archacpi mp apic squidboy ec
archmp mp apic squidboy
mtrr

View file

@ -14,6 +14,7 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
#include "../port/error.h"
typedef struct Pnp Pnp;

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more