summaryrefslogtreecommitdiff
path: root/sys/arch/arc/pci/pbcpcibus.c
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/pbcpcibus.c
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/pbcpcibus.c')
-rw-r--r--sys/arch/arc/pci/pbcpcibus.c189
1 files changed, 154 insertions, 35 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) {