Annotation of sys/arch/alpha/pci/cia_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cia_pci.c,v 1.11 2006/03/26 20:23:08 brad Exp $ */
! 2: /* $NetBSD: cia_pci.c,v 1.25 2000/06/29 08:58:46 mrg Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995, 1996 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: Chris G. Demetriou
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and
! 11: * its documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: #include <sys/param.h>
! 32: #include <sys/systm.h>
! 33: #include <sys/kernel.h>
! 34: #include <sys/device.h>
! 35:
! 36: #include <uvm/uvm_extern.h>
! 37:
! 38: #include <dev/pci/pcireg.h>
! 39: #include <dev/pci/pcivar.h>
! 40: #include <alpha/pci/ciareg.h>
! 41: #include <alpha/pci/ciavar.h>
! 42:
! 43: void cia_attach_hook(struct device *, struct device *,
! 44: struct pcibus_attach_args *);
! 45: int cia_bus_maxdevs(void *, int);
! 46: pcitag_t cia_make_tag(void *, int, int, int);
! 47: void cia_decompose_tag(void *, pcitag_t, int *, int *,
! 48: int *);
! 49: pcireg_t cia_conf_read(void *, pcitag_t, int);
! 50: void cia_conf_write(void *, pcitag_t, int, pcireg_t);
! 51:
! 52: void
! 53: cia_pci_init(pc, v)
! 54: pci_chipset_tag_t pc;
! 55: void *v;
! 56: {
! 57:
! 58: pc->pc_conf_v = v;
! 59: pc->pc_attach_hook = cia_attach_hook;
! 60: pc->pc_bus_maxdevs = cia_bus_maxdevs;
! 61: pc->pc_make_tag = cia_make_tag;
! 62: pc->pc_decompose_tag = cia_decompose_tag;
! 63: pc->pc_conf_read = cia_conf_read;
! 64: pc->pc_conf_write = cia_conf_write;
! 65: }
! 66:
! 67: void
! 68: cia_attach_hook(parent, self, pba)
! 69: struct device *parent, *self;
! 70: struct pcibus_attach_args *pba;
! 71: {
! 72: }
! 73:
! 74: int
! 75: cia_bus_maxdevs(cpv, busno)
! 76: void *cpv;
! 77: int busno;
! 78: {
! 79:
! 80: return 32;
! 81: }
! 82:
! 83: pcitag_t
! 84: cia_make_tag(cpv, b, d, f)
! 85: void *cpv;
! 86: int b, d, f;
! 87: {
! 88:
! 89: return (b << 16) | (d << 11) | (f << 8);
! 90: }
! 91:
! 92: void
! 93: cia_decompose_tag(cpv, tag, bp, dp, fp)
! 94: void *cpv;
! 95: pcitag_t tag;
! 96: int *bp, *dp, *fp;
! 97: {
! 98:
! 99: if (bp != NULL)
! 100: *bp = (tag >> 16) & 0xff;
! 101: if (dp != NULL)
! 102: *dp = (tag >> 11) & 0x1f;
! 103: if (fp != NULL)
! 104: *fp = (tag >> 8) & 0x7;
! 105: }
! 106:
! 107: pcireg_t
! 108: cia_conf_read(cpv, tag, offset)
! 109: void *cpv;
! 110: pcitag_t tag;
! 111: int offset;
! 112: {
! 113: struct cia_config *ccp = cpv;
! 114: pcireg_t *datap, data;
! 115: int s, secondary, ba;
! 116: u_int32_t old_cfg, errbits;
! 117:
! 118: #ifdef __GNUC__
! 119: s = 0; /* XXX gcc -Wuninitialized */
! 120: old_cfg = 0; /* XXX gcc -Wuninitialized */
! 121: #endif
! 122:
! 123: /*
! 124: * Some (apparently common) revisions of EB164 and AlphaStation
! 125: * firmware do the Wrong thing with PCI master and target aborts,
! 126: * which are caused by accessing the configuration space of devices
! 127: * that don't exist (for example).
! 128: *
! 129: * To work around this, we clear the CIA error register's PCI
! 130: * master and target abort bits before touching PCI configuration
! 131: * space and check it afterwards. If it indicates a master or target
! 132: * abort, the device wasn't there so we return 0xffffffff.
! 133: */
! 134: REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;
! 135: alpha_mb();
! 136: alpha_pal_draina();
! 137:
! 138: /* secondary if bus # != 0 */
! 139: pci_decompose_tag(&ccp->cc_pc, tag, &secondary, 0, 0);
! 140: if (secondary) {
! 141: s = splhigh();
! 142: old_cfg = REGVAL(CIA_CSR_CFG);
! 143: alpha_mb();
! 144: REGVAL(CIA_CSR_CFG) = old_cfg | 0x1;
! 145: alpha_mb();
! 146: }
! 147:
! 148: /*
! 149: * We just inline the BWX support, since this is the only
! 150: * difference between BWX and swiz for config space.
! 151: */
! 152: if (ccp->cc_flags & CCF_PCI_USE_BWX) {
! 153: if (secondary) {
! 154: datap =
! 155: (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF1 |
! 156: tag | (offset & ~0x03));
! 157: } else {
! 158: datap =
! 159: (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF0 |
! 160: tag | (offset & ~0x03));
! 161: }
! 162: } else {
! 163: datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF |
! 164: tag << 5UL | /* XXX */
! 165: (offset & ~0x03) << 5 | /* XXX */
! 166: 0 << 5 | /* XXX */
! 167: 0x3 << 3); /* XXX */
! 168: }
! 169: data = (pcireg_t)-1;
! 170: alpha_mb();
! 171: if (!(ba = badaddr(datap, sizeof *datap)))
! 172: data = *datap;
! 173: alpha_mb();
! 174: alpha_mb();
! 175:
! 176: if (secondary) {
! 177: alpha_mb();
! 178: REGVAL(CIA_CSR_CFG) = old_cfg;
! 179: alpha_mb();
! 180: splx(s);
! 181: }
! 182:
! 183: alpha_pal_draina();
! 184: alpha_mb();
! 185: errbits = REGVAL(CIA_CSR_CIA_ERR);
! 186: if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) {
! 187: ba = 1;
! 188: data = 0xffffffff;
! 189: }
! 190:
! 191: if (errbits) {
! 192: REGVAL(CIA_CSR_CIA_ERR) = errbits;
! 193: alpha_mb();
! 194: alpha_pal_draina();
! 195: }
! 196:
! 197: #if 0
! 198: printf("cia_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg,
! 199: data, datap, ba ? " (badaddr)" : "");
! 200: #endif
! 201:
! 202: return data;
! 203: }
! 204:
! 205: void
! 206: cia_conf_write(cpv, tag, offset, data)
! 207: void *cpv;
! 208: pcitag_t tag;
! 209: int offset;
! 210: pcireg_t data;
! 211: {
! 212: struct cia_config *ccp = cpv;
! 213: pcireg_t *datap;
! 214: int s, secondary;
! 215: u_int32_t old_cfg;
! 216:
! 217: #ifdef __GNUC__
! 218: s = 0; /* XXX gcc -Wuninitialized */
! 219: old_cfg = 0; /* XXX gcc -Wuninitialized */
! 220: #endif
! 221:
! 222: /* secondary if bus # != 0 */
! 223: pci_decompose_tag(&ccp->cc_pc, tag, &secondary, 0, 0);
! 224: if (secondary) {
! 225: s = splhigh();
! 226: old_cfg = REGVAL(CIA_CSR_CFG);
! 227: alpha_mb();
! 228: REGVAL(CIA_CSR_CFG) = old_cfg | 0x1;
! 229: alpha_mb();
! 230: }
! 231:
! 232: /*
! 233: * We just inline the BWX support, since this is the only
! 234: * difference between BWX and swiz for config space.
! 235: */
! 236: if (ccp->cc_flags & CCF_PCI_USE_BWX) {
! 237: if (secondary) {
! 238: datap =
! 239: (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF1 |
! 240: tag | (offset & ~0x03));
! 241: } else {
! 242: datap =
! 243: (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF0 |
! 244: tag | (offset & ~0x03));
! 245: }
! 246: } else {
! 247: datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF |
! 248: tag << 5UL | /* XXX */
! 249: (offset & ~0x03) << 5 | /* XXX */
! 250: 0 << 5 | /* XXX */
! 251: 0x3 << 3); /* XXX */
! 252: }
! 253: alpha_mb();
! 254: *datap = data;
! 255: alpha_mb();
! 256: alpha_mb();
! 257:
! 258: if (secondary) {
! 259: alpha_mb();
! 260: REGVAL(CIA_CSR_CFG) = old_cfg;
! 261: alpha_mb();
! 262: splx(s);
! 263: }
! 264:
! 265: #if 0
! 266: printf("cia_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag,
! 267: reg, data, datap);
! 268: #endif
! 269: }
CVSweb