diff options
| author | Andrew Gallatin <gallatin@FreeBSD.org> | 1999-07-29 16:44:22 +0000 |
|---|---|---|
| committer | Andrew Gallatin <gallatin@FreeBSD.org> | 1999-07-29 16:44:22 +0000 |
| commit | 3a1b3a3fa7b1085eb3747224d33a9b49d113de0d (patch) | |
| tree | 437db6efbd34db7edbb481826e73bcc0de9ce9a0 /sys/alpha/pci | |
| parent | e4268c5913413b8166e72091dfb6f99d9020336f (diff) | |
Notes
Diffstat (limited to 'sys/alpha/pci')
| -rw-r--r-- | sys/alpha/pci/cia.c | 29 |
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; \ |
