1 /* $NetBSD: ttwoga_pci.c,v 1.3 2008/01/05 00:31:51 ad Exp $ */
4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34 __KERNEL_RCSID(0, "$NetBSD: ttwoga_pci.c,v 1.3 2008/01/05 00:31:51 ad Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/simplelock.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcivar.h>
45 #include <alpha/pci/ttwogareg.h>
46 #include <alpha/pci/ttwogavar.h>
48 void ttwoga_attach_hook(struct device
*, struct device
*,
49 struct pcibus_attach_args
*);
50 int ttwoga_bus_maxdevs(void *, int);
51 pcitag_t
ttwoga_make_tag(void *, int, int, int);
52 void ttwoga_decompose_tag(void *, pcitag_t
, int *, int *,
54 pcireg_t
ttwoga_conf_read(void *, pcitag_t
, int);
55 void ttwoga_conf_write(void *, pcitag_t
, int, pcireg_t
);
57 paddr_t
ttwoga_make_type0addr(int, int);
60 * The T2 has an annoying bug that can manifest itself while
61 * probing for devices. If a non-existent CBUS address is
62 * accessed with a read, "a few" subsequent write cycles
63 * will generate spurious memory errors. We work around this
64 * by tracking which CPU has the PCI configuration mutex and
65 * "expect" machine checks on that CPU for the duraction of
66 * the PCI configuration access routine.
69 struct simplelock ttwoga_conf_slock
;
70 cpuid_t ttwoga_conf_cpu
; /* XXX core logic bug */
72 #define TTWOGA_CONF_LOCK(s) \
75 simple_lock(&ttwoga_conf_slock); \
76 ttwoga_conf_cpu = cpu_number(); \
79 #define TTWOGA_CONF_UNLOCK(s) \
81 ttwoga_conf_cpu = (cpuid_t)-1; \
82 simple_unlock(&ttwoga_conf_slock); \
87 ttwoga_pci_init(pci_chipset_tag_t pc
, void *v
)
90 simple_lock_init(&ttwoga_conf_slock
);
93 pc
->pc_attach_hook
= ttwoga_attach_hook
;
94 pc
->pc_bus_maxdevs
= ttwoga_bus_maxdevs
;
95 pc
->pc_make_tag
= ttwoga_make_tag
;
96 pc
->pc_decompose_tag
= ttwoga_decompose_tag
;
97 pc
->pc_conf_read
= ttwoga_conf_read
;
98 pc
->pc_conf_write
= ttwoga_conf_write
;
102 ttwoga_attach_hook(struct device
*parent
, struct device
*self
,
103 struct pcibus_attach_args
*pba
)
108 ttwoga_bus_maxdevs(void *cpv
, int busno
)
115 ttwoga_make_tag(void *cpv
, int b
, int d
, int f
)
118 /* This is the format used for Type 1 configuration cycles. */
119 return (b
<< 16) | (d
<< 11) | (f
<< 8);
123 ttwoga_decompose_tag(void *cpv
, pcitag_t tag
, int *bp
, int *dp
, int *fp
)
127 *bp
= (tag
>> 16) & 0xff;
129 *dp
= (tag
>> 11) & 0x1f;
131 *fp
= (tag
>> 8) & 0x7;
135 ttwoga_make_type0addr(int d
, int f
)
138 if (d
> 8) /* XXX ??? */
139 return ((paddr_t
) -1);
140 return ((0x0800UL
<< d
) | (f
<< 8));
144 ttwoga_conf_read(void *cpv
, pcitag_t tag
, int offset
)
146 struct ttwoga_config
*tcp
= cpv
;
147 pcireg_t
*datap
, data
;
152 pci_decompose_tag(&tcp
->tc_pc
, tag
, &b
, &d
, &f
);
154 addr
= b
? tag
: ttwoga_make_type0addr(d
, f
);
155 if (addr
== (paddr_t
)-1)
156 return ((pcireg_t
) -1);
161 old_hae3
= T2GA(tcp
, T2_HAE0_3
) & ~HAE0_3_PCA
;
162 T2GA(tcp
, T2_HAE0_3
) =
163 old_hae3
| ((b
? 1UL : 0UL) << HAE0_3_PCA_SHIFT
);
168 (pcireg_t
*)ALPHA_PHYS_TO_K0SEG(tcp
->tc_sysmap
->tsmap_conf_base
|
169 addr
<< 5UL | /* address shift */
170 (offset
& ~0x03) << 5UL | /* address shift */
171 0x3 << 3UL); /* 4-byte, size shift */
173 if (!(ba
= badaddr(datap
, sizeof *datap
)))
177 T2GA(tcp
, T2_HAE0_3
) = old_hae3
;
185 TTWOGA_CONF_UNLOCK(s
);
188 printf("ttwoga_conf_read: tag 0x%lx, reg 0x%x -> 0x%x @ %p%s\n",
189 tag
, offset
, data
, datap
, ba
? " (badaddr)" : "");
196 ttwoga_conf_write(void *cpv
, pcitag_t tag
, int offset
, pcireg_t data
)
198 struct ttwoga_config
*tcp
= cpv
;
204 pci_decompose_tag(&tcp
->tc_pc
, tag
, &b
, &d
, &f
);
206 addr
= b
? tag
: ttwoga_make_type0addr(d
, f
);
207 if (addr
== (paddr_t
)-1)
213 old_hae3
= T2GA(tcp
, T2_HAE0_3
) & ~HAE0_3_PCA
;
214 T2GA(tcp
, T2_HAE0_3
) =
215 old_hae3
| ((b
? 1UL : 0UL) << HAE0_3_PCA_SHIFT
);
220 (pcireg_t
*)ALPHA_PHYS_TO_K0SEG(tcp
->tc_sysmap
->tsmap_conf_base
|
221 addr
<< 5UL | /* address shift */
222 (offset
& ~0x03) << 5UL | /* address shift */
223 0x3 << 3UL); /* 4-byte, size shift */
231 T2GA(tcp
, T2_HAE0_3
) = old_hae3
;
235 TTWOGA_CONF_UNLOCK(s
);
238 printf("ttwoga_conf_write: tag 0x%lx, reg 0x%x -> 0x%x @ %p\n",
239 tag
, offset
, data
, datap
);