summaryrefslogtreecommitdiff
path: root/sys/arch/arc/pci
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>1998-03-16 09:38:53 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>1998-03-16 09:38:53 +0000
commita963ca51673d0d081904efce31dd28f05d83e730 (patch)
treef51de935de8777cae9204bbaa29b11aa7007425d /sys/arch/arc/pci
parentc1aa08ed9b8f4b392adef8685e4f55ff3b189dbb (diff)
DDB.
Support for Algorithmics R5000/R10000 evaluation board. So far only the RM5260 is supported. RM5270 - RM7000 later. R5000 and R10000 depending on access to cpu modules. vm_machdep.c moved to arch/mips/mips.
Diffstat (limited to 'sys/arch/arc/pci')
-rw-r--r--sys/arch/arc/pci/pbcpcibus.c189
-rw-r--r--sys/arch/arc/pci/pci_machdep.h9
-rw-r--r--sys/arch/arc/pci/v962pcbreg.h27
3 files changed, 184 insertions, 41 deletions
diff --git a/sys/arch/arc/pci/pbcpcibus.c b/sys/arch/arc/pci/pbcpcibus.c
index d3055a1dae2..d084dc427bc 100644
--- a/sys/arch/arc/pci/pbcpcibus.c
+++ b/sys/arch/arc/pci/pbcpcibus.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: pbcpcibus.c,v 1.5 1998/01/29 14:54:55 pefo Exp $ */
+/* $OpenBSD: pbcpcibus.c,v 1.6 1998/03/16 09:38:48 pefo Exp $ */
/*
- * Copyright (c) 1997 Per Fogelstrom
+ * Copyright (c) 1997, 1998 Per Fogelstrom, Opsycon AB
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +14,7 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed under OpenBSD by
- * Per Fogelstrom.
+ * Per Fogelstrom, Opsycon AB.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -51,7 +51,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <arc/arc/arctype.h>
+#include <mips/archtype.h>
#include <arc/algor/algor.h>
#include <arc/pci/pcibrvar.h>
#include <arc/pci/v962pcbreg.h>
@@ -85,9 +85,27 @@ struct cfdriver pbcpcibr_cd = {
NULL, "pbcpcibr", DV_DULL,
};
+/*
+ * Code from "pci/if_de.c" used to calculate crc32 of ether rom data.
+ * Another example can be found in document EC-QPQWA-TE from DEC.
+ */
+#define TULIP_CRC32_POLY 0xEDB88320UL
+static __inline__ unsigned
+srom_crc32(
+ const unsigned char *databuf,
+ size_t datalen)
+{
+ u_int idx, bit, data, crc = 0xFFFFFFFFUL;
+
+ for (idx = 0; idx < datalen; idx++)
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1)
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0);
+ return crc;
+}
static int pbcpcibrprint __P((void *, const char *pnp));
struct pcibr_config pbc_config;
+static int pbc_version;
int
pbcpcibrmatch(parent, match, aux)
@@ -114,6 +132,7 @@ pbcpcibrattach(parent, self, aux)
switch(system_type) {
case ALGOR_P4032:
+ case ALGOR_P5064:
V96X_PCI_BASE0 = V96X_PCI_BASE0 & 0xffff0000;
lcp = sc->sc_pcibr = &pbc_config;
@@ -132,6 +151,7 @@ pbcpcibrattach(parent, self, aux)
lcp->lc_pc.pc_conf_read = pbc_conf_read;
lcp->lc_pc.pc_conf_write = pbc_conf_write;
lcp->lc_pc.pc_ether_hw_addr = pbc_ether_hw_addr;
+ lcp->lc_pc.pc_flush_cache = R4K_HitFlushDCache;
lcp->lc_pc.pc_intr_v = lcp;
lcp->lc_pc.pc_intr_map = pbc_intr_map;
@@ -139,7 +159,8 @@ pbcpcibrattach(parent, self, aux)
lcp->lc_pc.pc_intr_establish = pbc_intr_establish;
lcp->lc_pc.pc_intr_disestablish = pbc_intr_disestablish;
- printf(": V3 V962, Revision %x.\n", V96X_PCI_CC_REV);
+ pbc_version = V96X_PCI_CC_REV;
+ printf(": V3 V962, Revision %x.\n", pbc_version);
break;
}
@@ -170,13 +191,14 @@ pbcpcibrprint(aux, pnp)
*/
vm_offset_t
-vtophys(p)
- void *p;
+vtophysaddr(dp, p)
+ struct device *dp;
+ vm_offset_t p;
{
vm_offset_t pa;
vm_offset_t va;
- va = (vm_offset_t)p;
+ va = p;
if(va >= UADDR) { /* Stupid driver have buf on stack!! */
va = (vm_offset_t)curproc->p_addr + (va & ~UADDR);
}
@@ -186,6 +208,10 @@ vtophys(p)
else {
pa = pmap_extract(vm_map_pmap(phys_map), va);
}
+ if(dp->dv_class == DV_IFNET && pbc_version < V96X_VREV_C0) {
+ /* BUG in early V962PBC's */
+ pa |= 0xc0000000; /* Use aparture II */
+ }
return(pa);
}
@@ -219,7 +245,7 @@ pbc_decompose_tag(cpv, tag, busp, devp, fncp)
int *busp, *devp, *fncp;
{
if (busp != NULL)
- *busp = (tag >> 16) & 0xff;
+ *busp = (tag >> 16) & 0x7;
if (devp != NULL)
*devp = (tag >> 11) & 0x1f;
if (fncp != NULL)
@@ -234,26 +260,50 @@ pbc_conf_read(cpv, tag, offset)
{
pcireg_t data;
u_int32_t addr;
- int device;
+ int bus, device, func, ad_low;
int s;
- if((tag >> 16) != 0)
- return(~0);
if(offset & 3 || offset < 0 || offset >= 0x100) {
printf ("pci_conf_read: bad reg %x\n", offset);
return(~0);
}
+ pbc_decompose_tag(cpv, tag, &bus, &device, &func);
+ ad_low = 0;
- device = (tag >> 11) & 0x1f;
- addr = (0x800 << device) | (tag & 0x380) | offset;
+ if(system_type == ALGOR_P4032) {
+ if(bus != 0 || device > 5 || func > 7) {
+ return(~0);
+ }
+ addr = (0x800 << device) | (func << 8) | offset;
+ ad_low = 0;
+ }
+ else { /* P5064 */
+ if(bus == 0) {
+ if(device > 5 || func > 7) {
+ return(~0);
+ }
+ addr = (1L << (device + 24)) | (func << 8) | offset;
+ ad_low = 0;
+ }
+ else if(pbc_version >= V96X_VREV_C0) {
+ if(bus > 255 || device > 15 || func > 7) {
+ return(~0);
+ }
+ addr = (bus << 16) | (device << 11) | (func << 8);
+ ad_low = V96X_LB_MAPx_AD_LOW_EN;
+ }
+ else {
+ return(~0);
+ }
+ }
s = splhigh();
+ /* high 12 bits of address go in map register, and set for conf space */
+ V96X_LB_MAP0 = ((addr >> 16) & V96X_LB_MAPx_MAP_ADR) | ad_low | V96X_LB_TYPE_CONF;
/* clear aborts */
V96X_PCI_STAT |= V96X_PCI_STAT_M_ABORT | V96X_PCI_STAT_T_ABORT;
- /* high 12 bits of address go in map register, and set for conf space */
- V96X_LB_MAP0 = ((addr >> 16) & V96X_LB_MAPx_MAP_ADR) | V96X_LB_TYPE_CONF;
wbflush();
/* low 20 bits of address are in the actual address */
@@ -261,14 +311,13 @@ pbc_conf_read(cpv, tag, offset)
if (V96X_PCI_STAT & V96X_PCI_STAT_M_ABORT) {
V96X_PCI_STAT |= V96X_PCI_STAT_M_ABORT;
- printf ("device %d: master abort\n", device);
- return(~0);
+ return(~0); /* Nothing there */
}
if (V96X_PCI_STAT & V96X_PCI_STAT_T_ABORT) {
V96X_PCI_STAT |= V96X_PCI_STAT_T_ABORT;
printf ("PCI slot %d: target abort!\n", device);
- return(~0);
+ return(~0); /* Ooops! */
}
splx(s);
@@ -283,19 +332,46 @@ pbc_conf_write(cpv, tag, offset, data)
pcireg_t data;
{
u_int32_t addr;
- int device;
+ int bus, device, func, ad_low;
int s;
- device = (tag >> 11) & 0x1f;
- addr = (0x800 << device) | (tag & 0x380) | offset;
+ pbc_decompose_tag(cpv, tag, &bus, &device, &func);
+ ad_low = 0;
+
+ if(system_type == ALGOR_P4032) {
+ if(bus != 0 || device > 5 || func > 7) {
+ return;
+ }
+ addr = (0x800 << device) | (func << 8) | offset;
+ ad_low = 0;
+ }
+ else { /* P5064 */
+ if(bus == 0) {
+ if(device > 5 || func > 7) {
+ return;
+ }
+ addr = (1L << (device + 24)) | (func << 8) | offset;
+ ad_low = 0;
+ }
+ else if(pbc_version >= V96X_VREV_C0) {
+ if(bus > 255 || device > 15 || func > 7) {
+ return;
+ }
+ addr = (bus << 16) | (device << 11) | (func << 8);
+ ad_low = V96X_LB_MAPx_AD_LOW_EN;
+ }
+ else {
+ return;
+ }
+ }
s = splhigh();
+ /* high 12 bits of address go in map register, and set for conf space */
+ V96X_LB_MAP0 = ((addr >> 16) & V96X_LB_MAPx_MAP_ADR) | ad_low | V96X_LB_TYPE_CONF;
/* clear aborts */
V96X_PCI_STAT |= V96X_PCI_STAT_M_ABORT | V96X_PCI_STAT_T_ABORT;
- /* high 12 bits of address go in map register, and set for conf space */
- V96X_LB_MAP0 = ((addr >> 16) & V96X_LB_MAPx_MAP_ADR) | V96X_LB_TYPE_CONF;
wbflush();
/* low 20 bits of address are in the actual address */
@@ -319,17 +395,60 @@ pbc_conf_write(cpv, tag, offset, data)
}
/*
- * Hook to get ethernet hardware address when not in dev rom
+ * Build the serial rom info normaly stored in an EEROM on
+ * PCI DEC21x4x boards. Cheapo designs skips the rom so
+ * we do the job here. The setup is not 100% correct but
+ * close enough to make the driver happy!
*/
int
-pbc_ether_hw_addr(cp)
- u_int8_t *cp;
+pbc_ether_hw_addr(p)
+ u_int8_t *p;
{
- if(system_type == ALGOR_P4032) {
- bcopy(eth_hw_addr, cp, 6);
- return(0);
+ int i;
+
+ for(i = 0; i < 128; i++)
+ p[i] = 0x00;
+ p[18] = 0x03; /* Srom version. */
+ p[19] = 0x01; /* One chip. */
+ /* Next six, ethernet address. */
+ bcopy(eth_hw_addr, &p[20], 6);
+
+ p[26] = 0x00; /* Chip 0 device number */
+ p[27] = 30; /* Descriptor offset */
+ p[28] = 00;
+ p[29] = 00; /* MBZ */
+ /* Descriptor */
+ p[30] = 0x00; /* Autosense. */
+ p[31] = 0x08;
+ if(system_type == ALGOR_P4032 ||
+ system_type == ALGOR_P5064) {
+ p[32] = 0x01; /* Block cnt */
+ p[33] = 0x02; /* Medium type is AUI */
+ }
+ else {
+ p[32] = 0xff; /* GP cntrl */
+ p[33] = 0x01; /* Block cnt */
+#define GPR_LEN 0
+#define RES_LEN 0
+ p[34] = 0x80 + 12 + GPR_LEN + RES_LEN;
+ p[35] = 0x01; /* MII PHY type */
+ p[36] = 0x00; /* PHY number 0 */
+ p[37] = 0x00; /* GPR Length */
+ p[38] = 0x00; /* Reset Length */
+ p[39] = 0x00; /* Media capabilities */
+ p[40] = 0x78; /* Media capabilities */
+ p[41] = 0x00; /* Autoneg advertisment */
+ p[42] = 0x78; /* Autoneg advertisment */
+ p[43] = 0x00; /* Full duplex map */
+ p[44] = 0x50; /* Full duplex map */
+ p[45] = 0x00; /* Treshold map */
+ p[46] = 0x18; /* Treshold map */
}
- return(-1);
+
+ i = (srom_crc32(p, 126) & 0xFFFF) ^ 0xFFFF;
+ p[126] = i;
+ p[127] = i >> 8;
+ return(1); /* Got it! */
}
int
@@ -358,11 +477,11 @@ pbc_intr_map(lcv, bustag, buspin, line, ihp)
pirq = buspin - 1;
switch(device) {
- case 5: /* DC21041 */
- pirq = 1;
+ case 0: /* DC21041 */
+ pirq = 9;
break;
- case 8: /* NCR SCSI */
- pirq = 0;
+ case 1: /* NCR SCSI */
+ pirq = 10;
break;
default:
switch (buspin) {
diff --git a/sys/arch/arc/pci/pci_machdep.h b/sys/arch/arc/pci/pci_machdep.h
index 5543d2c1f7e..dfeb5995c67 100644
--- a/sys/arch/arc/pci/pci_machdep.h
+++ b/sys/arch/arc/pci/pci_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.h,v 1.2 1997/04/19 17:20:02 pefo Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.3 1998/03/16 09:38:49 pefo Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@@ -61,6 +61,7 @@ struct arc_pci_chipset {
int, int (*)(void *), void *, char *));
void (*pc_intr_disestablish) __P((void *, void *));
int (*pc_ether_hw_addr) __P((u_int8_t *));
+ void (*pc_flush_cache) __P((vm_offset_t, int));
};
/*
@@ -88,6 +89,10 @@ struct arc_pci_chipset {
(*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv))
#define pci_ether_hw_addr(c, p) \
(*(c)->pc_ether_hw_addr)((p))
+#define pci_flush_cache(p, s) \
+ (*(c)->pc_flush_cache)((p, s))
-vm_offset_t vtophys __P((void *));
+vm_offset_t vtophysaddr __P((struct device *, vm_offset_t));
+#define TULIP_KVATOPHYS(sc, va) vtophysaddr(&sc->tulip_dev, (vm_offset_t)va)
+#define NCR_KVATOPHYS(sc, va) vtophysaddr(&sc->sc_dev, (vm_offset_t)va)
diff --git a/sys/arch/arc/pci/v962pcbreg.h b/sys/arch/arc/pci/v962pcbreg.h
index e0e4865213b..9320bafee6b 100644
--- a/sys/arch/arc/pci/v962pcbreg.h
+++ b/sys/arch/arc/pci/v962pcbreg.h
@@ -11,7 +11,7 @@
/* offsets from base pointer, this construct allows optimisation */
static char * const _v96xp = (char *)P4032_V96x;
-#if #endian(little)
+#if BYTE_ORDER == LITTLE_ENDIAN
#define V96XW(x) *(volatile unsigned long *)(_v96xp + (x))
#define V96XH(x) *(volatile unsigned short *)(_v96xp + (x))
#define V96XB(x) *(volatile unsigned char *)(_v96xp + (x))
@@ -26,10 +26,11 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_PCI_CMD V96XH(0x04)
#define V96X_PCI_STAT V96XH(0x06)
#define V96X_PCI_CC_REV V96XW(0x08)
+#define V96X_PCI_I20_BASE V96XW(0x10) /* B.2 only */
#define V96X_PCI_HDR_CFG V96XW(0x0c)
#define V96X_PCI_IO_BASE V96XW(0x10)
#define V96X_PCI_BASE0 V96XW(0x14)
-#define V96X_PCI_BASE1 V96XW(0x1c)
+#define V96X_PCI_BASE1 V96XW(0x18)
#define V96X_PCI_BPARAM V96XW(0x3c)
#define V96X_PCI_MAP0 V96XW(0x40)
#define V96X_PCI_MAP1 V96XW(0x44)
@@ -39,6 +40,9 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_LB_BASE1 V96XW(0x58)
#define V96X_LB_MAP0 V96XH(0x5e)
#define V96X_LB_MAP1 V96XH(0x62)
+#define V96X_LB_BASE2 V96XH(0x64) /* B.2 only */
+#define V96X_LB_MAP2 V96XH(0x66) /* B.2 only */
+#define V96X_LB_SIZE V96XW(0x68) /* B.2 only */
#define V96X_LB_IO_BASE V96XW(0x6c)
#define V96X_FIFO_CFG V96XH(0x70)
#define V96X_FIFO_PRIORITY V96XH(0x72)
@@ -46,7 +50,9 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_LB_ISTAT V96XB(0x76)
#define V96X_LB_IMASK V96XB(0x77)
#define V96X_SYSTEM V96XH(0x78)
+#define V96X_LB_CFGL V96XB(0x7a)
#define V96X_LB_CFG V96XB(0x7b)
+#define V96X_PCI_CFG V96XB(0x7c) /* B.2 only */
#define V96X_DMA_PCI_ADDR0 V96XW(0x80)
#define V96X_DMA_LOCAL_ADDR0 V96XW(0x84)
#define V96X_DMA_LENGTH0 V96XW(0x88)
@@ -87,7 +93,8 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_VREV_A 0x0
#define V96X_VREV_B0 0x1
#define V96X_VREV_B1 0x2
-#define V96X_VREV_C0 0x3
+#define V96X_VREV_B2 0x3
+#define V96X_VREV_C0 0x4
#define V96X_PCI_HDR_CFG_LT 0x0000ff00
#define V96X_PCI_HDR_CFG_LT_SHIFT 8
@@ -143,8 +150,9 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_SWAP_NONE (0x0<<8)
#define V96X_SWAP_16BIT (0x1<<8)
#define V96X_SWAP_8BIT (0x2<<8)
+#define V96X_SWAP_AUTO (0x3<<8)
-/* pci interruprt status register */
+/* pci interrupt status register */
#define V96X_PCI_INT_STAT_MAILBOX 0x80000000
#define V96X_PCI_INT_STAT_LOCAL 0x40000000
#define V96X_PCI_INT_STAT_DMA1 0x02000000
@@ -210,6 +218,7 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_LB_TYPE_IO (0x1<<1)
#define V96X_LB_TYPE_MEM (0x3<<1)
#define V96X_LB_TYPE_CONF (0x5<<1)
+#define V96X_LB_MAPx_AD_LOW_EN 0x0001 /* C.0 only */
/* local bus interrupt control, status and masks */
#define V96X_LB_INTR_MAILBOX 0x80
@@ -226,6 +235,16 @@ static char * const _v96xp = (char *)P4032_V96x;
#define V96X_LB_CFG_ERR_EN 0x02
#define V96X_LB_CFG_RDY_EN 0x01
+/* PCI bus configuration */
+#define V96X_PCI_CFG_I2O_EN 0x8000
+#define V96X_PCI_CFG_IO_REG_DIS 0x4000
+#define V96X_PCI_CFG_IO_DIS 0x2000
+#define V96X_PCI_CFG_EN3V 0x1000
+#define V96X_PCI_CFG_AD_LOW 0x0300
+#define V96X_PCI_CFG_AD_LOW_SHIFT 8
+#define V96X_PCI_CFG_DMA_RTYPE 0x00e0
+#define V96X_PCI_CFG_DMA_WTYPE 0x000e
+
/* fifo configuration register */
#define V96X_FIFO_CFG_PBRST_MAX 0xc000
#define V96X_FIFO_CFG_PBRST_MAX_SHIFT 14