]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/alpha/pci/t2_pci.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / sys / alpha / pci / t2_pci.c
1 /*-
2  * Copyright (c) 2000 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPELCAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/bus.h>
35 #include <machine/bus.h>
36 #include <sys/rman.h>
37 #include <dev/pci/pcivar.h>
38 #include <machine/swiz.h>
39 #include <machine/md_var.h>
40
41 #include <alpha/pci/t2reg.h>
42 #include <alpha/pci/t2var.h>
43 #include <alpha/pci/pcibus.h>
44
45 #include "alphapci_if.h"
46 #include "pcib_if.h"
47
48 #define KV(pa)                  ALPHA_PHYS_TO_K0SEG((pa) + sable_lynx_base)
49
50 static devclass_t       pcib_devclass;
51
52 static int
53 t2_pcib_probe(device_t dev)
54 {
55         device_t child;
56
57         device_set_desc(dev, "T2 PCI host bus adapter");
58
59         pci_init_resources();
60
61         child = device_add_child(dev, "pci", 0);
62         device_set_ivars(child, 0);
63
64         return 0;
65 }
66
67 static int
68 t2_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
69 {
70         if (which == PCIB_IVAR_BUS) {
71                 *result = 0;
72                 return 0;
73         }
74         return ENOENT;
75 }
76
77 static void *
78 t2_pcib_cvt_dense(device_t dev, vm_offset_t addr)
79 {
80         addr &= 0xffffffffUL;
81         return (void *) KV(addr | T2_PCI_DENSE);
82 }
83
84 static int
85 t2_pcib_maxslots(device_t dev)
86 {
87         return 9;
88 }
89
90 #define T2_CFGOFF(b, s, f, r)                                   \
91         ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r))   \
92          : ((1 << ((s) + 11)) | ((f) << 8) | (r)))
93
94 #define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) {                  \
95         do {                                                    \
96                 (s) = intr_disable();                           \
97                 (old_hae3) = REGVAL(T2_HAE0_3);                 \
98                 alpha_mb();                                     \
99                 REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30);       \
100                 alpha_mb();                                     \
101         } while(0);                                             \
102 }
103
104 #define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) {       \
105         do {                                            \
106                 alpha_mb();                             \
107                 REGVAL(T2_HAE0_3) = (old_hae3);         \
108                 alpha_mb();                             \
109                 intr_restore((s));                      \
110         } while(0);                                     \
111 }
112
113 #define SWIZ_CFGREAD(b, s, f, r, width, type) do {                       \
114         type val = ~0;                                                   \
115         register_t ipl = 0;                                              \
116         u_int32_t old_hae3 = 0;                                          \
117         vm_offset_t off = T2_CFGOFF(b, s, f, r);                         \
118         vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
119         alpha_mb();                                                      \
120         T2_TYPE1_SETUP(b,ipl,old_hae3);                                  \
121         if (!badaddr((caddr_t)kv, sizeof(type))) {                       \
122                 val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv));    \
123         }                                                                \
124         T2_TYPE1_TEARDOWN(b,ipl,old_hae3);                               \
125         return val;                                                      \
126 } while (0)
127
128 #define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do {                \
129         register_t ipl = 0;                                                      \
130         u_int32_t old_hae3 = 0;                                          \
131         vm_offset_t off = T2_CFGOFF(b, s, f, r);                         \
132         vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
133         alpha_mb();                                                      \
134         T2_TYPE1_SETUP(b,ipl,old_hae3);                                  \
135         if (!badaddr((caddr_t)kv, sizeof(type))) {                       \
136                 SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data));    \
137                 alpha_wmb();                                             \
138         }                                                                \
139         T2_TYPE1_TEARDOWN(b,ipl,old_hae3);                               \
140         return;                                                          \
141 } while (0)
142
143 static u_int32_t
144 t2_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
145                     u_int reg, int width)
146 {
147         switch (width) {
148         case 1:
149                 SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t);
150                 break;
151         case 2:
152                 SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t);
153                 break;
154         case 4:
155                 SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t);
156         }
157         return ~0;
158 }
159
160 static void
161 t2_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
162                      u_int reg, u_int32_t val, int width)
163 {
164         switch (width) {
165         case 1:
166                 SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t);
167                 break;
168         case 2:
169                 SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t);
170                 break;
171         case 4:
172                 SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t);
173         }
174 }
175
176 static device_method_t t2_pcib_methods[] = {
177         /* Device interface */
178         DEVMETHOD(device_probe,         t2_pcib_probe),
179         DEVMETHOD(device_attach,        bus_generic_attach),
180
181         /* Bus interface */
182         DEVMETHOD(bus_print_child,      bus_generic_print_child),
183         DEVMETHOD(bus_read_ivar,        t2_pcib_read_ivar),
184         DEVMETHOD(bus_alloc_resource,   alpha_pci_alloc_resource),
185         DEVMETHOD(bus_release_resource, pci_release_resource),
186         DEVMETHOD(bus_activate_resource, pci_activate_resource),
187         DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
188         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
189         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
190
191         /* alphapci interface */
192         DEVMETHOD(alphapci_cvt_dense,   t2_pcib_cvt_dense),
193
194         /* pcib interface */
195         DEVMETHOD(pcib_maxslots,        t2_pcib_maxslots),
196         DEVMETHOD(pcib_read_config,     t2_pcib_read_config),
197         DEVMETHOD(pcib_write_config,    t2_pcib_write_config),
198         DEVMETHOD(pcib_route_interrupt, alpha_pci_route_interrupt),
199
200         { 0, 0 }
201 };
202
203 static driver_t t2_pcib_driver = {
204         "pcib",
205         t2_pcib_methods,
206         1,
207 };
208
209 DRIVER_MODULE(pcib, t2, t2_pcib_driver, pcib_devclass, 0, 0);