]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/alpha/pci/lca.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / sys / alpha / pci / lca.c
1 /*-
2  * Copyright (c) 1998 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, SPECIAL, 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/malloc.h>
35 #include <sys/bus.h>
36 #include <machine/bus.h>
37 #include <sys/rman.h>
38 #include <sys/proc.h>
39 #include <sys/sched.h>
40
41 #include <alpha/pci/lcareg.h>
42 #include <alpha/pci/lcavar.h>
43 #include <alpha/isa/isavar.h>
44
45 #include <machine/cpuconf.h>
46 #include <machine/intr.h>
47 #include <machine/md_var.h>
48 #include <machine/sgmap.h>
49 #include <machine/swiz.h>
50
51 #include <vm/vm.h>
52 #include <vm/vm_page.h>
53
54 #define KV(pa)                  ALPHA_PHYS_TO_K0SEG(pa)
55
56 static devclass_t       lca_devclass;
57 static device_t         lca0;           /* XXX only one for now */
58
59 struct lca_softc {
60         int             junk;
61 };
62
63 #define LCA_SOFTC(dev)  (struct lca_softc*) device_get_softc(dev)
64
65 static alpha_chipset_read_hae_t lca_read_hae;
66 static alpha_chipset_write_hae_t lca_write_hae;
67
68 static alpha_chipset_t lca_chipset = {
69         lca_read_hae,
70         lca_write_hae,
71 };
72
73 /*
74  * The LCA HAE is write-only.  According to NetBSD, this is where it starts.
75  */
76 static u_int32_t        lca_hae_mem = 0x80000000;
77
78 /*
79  * The first 16Mb ignores the HAE.  The next 112Mb uses the HAE to set
80  * the high bits of the PCI address.
81  */
82 #define REG1 (1UL << 24)
83
84 static u_int32_t
85 lca_set_hae_mem(void *arg, u_int32_t pa)
86 {
87         int s; 
88         u_int32_t msb;
89         if(pa >= REG1){
90                 msb = pa & 0xf8000000;
91                 pa -= msb;
92                 s = splhigh();
93                 if (msb != lca_hae_mem) {
94                         lca_hae_mem = msb;
95                         REGVAL(LCA_IOC_HAE) = lca_hae_mem;
96                         alpha_mb();
97                         alpha_mb();
98                 }
99                 splx(s);
100         }
101         return pa;
102 }
103
104 static u_int64_t
105 lca_read_hae(void)
106 {
107         return lca_hae_mem & 0xf8000000;
108 }
109
110 static void
111 lca_write_hae(u_int64_t hae)
112 {
113         u_int32_t pa = hae;
114         lca_set_hae_mem(0, pa);
115 }
116
117 static int lca_probe(device_t dev);
118 static int lca_attach(device_t dev);
119 static device_method_t lca_methods[] = {
120         /* Device interface */
121         DEVMETHOD(device_probe,         lca_probe),
122         DEVMETHOD(device_attach,        lca_attach),
123
124         /* Bus interface */
125         DEVMETHOD(bus_setup_intr,       isa_setup_intr),
126         DEVMETHOD(bus_teardown_intr,    isa_teardown_intr),
127
128         { 0, 0 }
129 };
130
131 static driver_t lca_driver = {
132         "lca",
133         lca_methods,
134         sizeof(struct lca_softc),
135 };
136
137 #define LCA_SGMAP_BASE          (8*1024*1024)
138 #define LCA_SGMAP_SIZE          (8*1024*1024)
139
140 static void
141 lca_sgmap_invalidate(void)
142 {
143         alpha_mb();
144         REGVAL(LCA_IOC_TBIA) = 0;
145         alpha_mb();
146 }
147
148 static void
149 lca_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
150 {
151         u_int64_t *sgtable = arg;
152         int index = alpha_btop(ba - LCA_SGMAP_BASE);
153
154         if (pa) {
155                 if (pa > (1L<<32))
156                         panic("lca_sgmap_map: can't map address 0x%lx", pa);
157                 sgtable[index] = ((pa >> 13) << 1) | 1;
158         } else {
159                 sgtable[index] = 0;
160         }
161         alpha_mb();
162         lca_sgmap_invalidate();
163 }
164
165 static void
166 lca_init_sgmap(void)
167 {
168         void *sgtable;
169
170         /*
171          * First setup Window 0 to map 8Mb to 16Mb with an
172          * sgmap. Allocate the map aligned to a 32 boundary.
173          */
174         REGVAL64(LCA_IOC_W_BASE0) = LCA_SGMAP_BASE |
175                 IOC_W_BASE_SG | IOC_W_BASE_WEN;
176         alpha_mb();
177
178         REGVAL64(LCA_IOC_W_MASK0) = IOC_W_MASK_8M;
179         alpha_mb();
180
181         sgtable = contigmalloc(8192, M_DEVBUF, M_NOWAIT,
182                                0, (1L<<34),
183                                32*1024, (1L<<34));
184         if (!sgtable)
185                 panic("lca_init_sgmap: can't allocate page table");
186         chipset.sgmap = sgmap_map_create(LCA_SGMAP_BASE,
187                                          LCA_SGMAP_BASE + LCA_SGMAP_SIZE,
188                                          lca_sgmap_map, sgtable);
189
190         
191         REGVAL64(LCA_IOC_W_T_BASE0) = pmap_kextract((vm_offset_t) sgtable);
192         alpha_mb();
193         REGVAL64(LCA_IOC_TB_ENA) = IOC_TB_ENA_TEN;
194         alpha_mb();
195         lca_sgmap_invalidate();
196 }
197
198 void
199 lca_init()
200 {
201         static int initted = 0;
202         static struct swiz_space io_space, mem_space;
203
204         if (initted) return;
205         initted = 1;
206
207         swiz_init_space(&io_space, KV(LCA_PCI_SIO));
208         swiz_init_space_hae(&mem_space, KV(LCA_PCI_SPARSE),
209                             lca_set_hae_mem, 0);
210
211         busspace_isa_io = (struct alpha_busspace *) &io_space;
212         busspace_isa_mem = (struct alpha_busspace *) &mem_space;
213
214         /* Type 0 PCI conf access. */
215         REGVAL64(LCA_IOC_CONF) = 0;
216
217         if (platform.pci_intr_init)
218                 platform.pci_intr_init();
219
220         chipset = lca_chipset;
221 }
222
223 static void
224 lca_machine_check(unsigned long mces, struct trapframe *framep,
225     unsigned long vector, unsigned long param);
226
227 static void lca_cpu_idle (void);
228
229 static int
230 lca_probe(device_t dev)
231 {
232         if (lca0)
233                 return ENXIO;
234         lca0 = dev;
235         device_set_desc(dev, "21066 Core Logic chipset"); /* XXX */
236
237         isa_init_intr();
238         lca_init_sgmap();
239
240         platform.mcheck_handler = lca_machine_check;
241         platform.cpu_idle = lca_cpu_idle;
242
243         device_add_child(dev, "pcib", 0);
244
245         return 0;
246 }
247
248 static int
249 lca_attach(device_t dev)
250 {
251         lca_init();
252
253         set_iointr(alpha_dispatch_intr);
254
255         snprintf(chipset_type, sizeof(chipset_type), "lca");
256         chipset_bwx = 0;
257         chipset_ports = LCA_PCI_SIO;
258         chipset_memory = LCA_PCI_SPARSE;
259         chipset_dense = LCA_PCI_DENSE;
260         chipset_hae_mask = IOC_HAE_ADDREXT;
261
262         bus_generic_attach(dev);
263         return 0;
264 }
265
266 static void
267 lca_machine_check(unsigned long mces, struct trapframe *framep,
268     unsigned long vector, unsigned long param)
269 {
270         long stat0;
271
272         machine_check(mces, framep, vector, param);
273         /* clear error flags in IOC_STATUS0 register */
274         stat0 = REGVAL64(LCA_IOC_STAT0);
275         REGVAL64(LCA_IOC_STAT0) = stat0;
276 }
277
278 void
279 lca_cpu_idle (void)
280 {
281         /*
282          * 0x0 =  1
283          * 0x1 =  1.5
284          * 0x2 =  2
285          * 0x3 =  4
286          * 0x4 =  8
287          * 0x5 = 16
288          */
289         long override = 0x0;
290         long primary = 0x5;
291         long dma_ovr = 1;
292         long intr_ovr = 1;
293
294         REGVAL64(LCA_PMR) =
295             (dma_ovr << 7) | (intr_ovr << 6) | (override << 3) | primary;
296         if (sched_runnable()) {
297                 REGVAL64(LCA_PMR) =
298                     (override << 3) | override;
299         }
300 }
301
302 DRIVER_MODULE(lca, root, lca_driver, lca_devclass, 0, 0);
303