summaryrefslogtreecommitdiff
path: root/sys/alpha/pci
diff options
context:
space:
mode:
authorAndrew Gallatin <gallatin@FreeBSD.org>1999-07-29 16:44:22 +0000
committerAndrew Gallatin <gallatin@FreeBSD.org>1999-07-29 16:44:22 +0000
commit3a1b3a3fa7b1085eb3747224d33a9b49d113de0d (patch)
tree437db6efbd34db7edbb481826e73bcc0de9ce9a0 /sys/alpha/pci
parente4268c5913413b8166e72091dfb6f99d9020336f (diff)
Notes
Diffstat (limited to 'sys/alpha/pci')
-rw-r--r--sys/alpha/pci/cia.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/sys/alpha/pci/cia.c b/sys/alpha/pci/cia.c
index 772eaa48755b..c121804e8abf 100644
--- a/sys/alpha/pci/cia.c
+++ b/sys/alpha/pci/cia.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cia.c,v 1.19 1999/06/05 13:30:13 dfr Exp $
+ * $Id: cia.c,v 1.20 1999/07/01 20:25:39 peter Exp $
*/
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -557,19 +557,42 @@ cia_swiz_maxdevs(u_int b)
} while(0); \
}
+/*
+ * From NetBSD:
+ * Some (apparently-common) revisions of EB164 and AlphaStation
+ * firmware do the Wrong thing with PCI master and target aborts,
+ * which are caused by accesing the configuration space of devices
+ * that don't exist (for example).
+ *
+ * To work around this, we clear the CIA error register's PCI
+ * master and target abort bits before touching PCI configuration
+ * space and check it afterwards. If it indicates a master or target
+ * abort, the device wasn't there so we return ~0
+ */
+
+
#define SWIZ_CFGREAD(b, s, f, r, width, type) \
type val = ~0; \
int ipl = 0; \
- u_int32_t old_cfg = 0; \
+ u_int32_t old_cfg = 0, errbits; \
vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \
+ REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;\
alpha_mb(); \
CIA_TYPE1_SETUP(b,ipl,old_cfg); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \
- return val;
+ errbits = REGVAL(CIA_CSR_CIA_ERR); \
+ if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) \
+ val = ~0; \
+ if (errbits) { \
+ REGVAL(CIA_CSR_CIA_ERR) = errbits; \
+ alpha_mb(); \
+ alpha_pal_draina(); \
+ } \
+ return val;
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \
int ipl = 0; \