Annotation of sys/arch/alpha/pci/cia_pci.c, Revision 1.1.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