]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/pci/pcibus.c
This commit was generated by cvs2svn to compensate for changes in r51363,
[FreeBSD/FreeBSD.git] / sys / alpha / pci / pcibus.c
1 /*
2  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
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 unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
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/interrupt.h>
37 #include <sys/sysctl.h>
38 #include <sys/rman.h>
39
40 #include <pci/pcivar.h>
41 #include <machine/chipset.h>
42 #include <machine/cpuconf.h>
43 #include <machine/resource.h>
44 #include <machine/md_var.h>
45 #include <alpha/pci/pcibus.h>
46 #include <alpha/isa/isavar.h>
47
48 char chipset_type[10];
49 int chipset_bwx = 0;
50 long chipset_ports = 0;
51 long chipset_memory = 0;
52 long chipset_dense = 0;
53 long chipset_hae_mask = 0;
54
55 SYSCTL_NODE(_hw, OID_AUTO, chipset, CTLFLAG_RW, 0, "PCI chipset information");
56 SYSCTL_STRING(_hw_chipset, OID_AUTO, type, CTLFLAG_RD, chipset_type, 0,
57               "PCI chipset type");
58 SYSCTL_INT(_hw_chipset, OID_AUTO, bwx, CTLFLAG_RD, &chipset_bwx, 0,
59            "PCI chipset supports BWX access");
60 SYSCTL_LONG(_hw_chipset, OID_AUTO, ports, CTLFLAG_RD, &chipset_ports,
61             "PCI chipset port address");
62 SYSCTL_LONG(_hw_chipset, OID_AUTO, memory, CTLFLAG_RD, &chipset_memory,
63             "PCI chipset memory address");
64 SYSCTL_LONG(_hw_chipset, OID_AUTO, dense, CTLFLAG_RD, &chipset_dense,
65             "PCI chipset dense memory address");
66 SYSCTL_LONG(_hw_chipset, OID_AUTO, hae_mask, CTLFLAG_RD, &chipset_hae_mask,
67             "PCI chipset mask for HAE register");
68
69 #ifdef notyet
70
71 /* return max number of devices on the bus */
72 int
73 pci_maxdevs(pcicfgregs *cfg)
74 {
75         return chipset.maxdevs(cfg->bus);
76 }
77
78 #endif
79
80 /* read configuration space register */
81
82 int
83 pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
84 {
85         switch (bytes) {
86         case 1:
87                 return chipset.cfgreadb(cfg->hose, cfg->bus, 
88                                         cfg->slot, cfg->func, reg);
89         case 2:
90                 return chipset.cfgreadw(cfg->hose, cfg->bus, 
91                                         cfg->slot, cfg->func, reg);
92         case 4:
93                 return chipset.cfgreadl(cfg->hose, cfg->bus, 
94                                         cfg->slot, cfg->func, reg);
95         }
96         return ~0;
97 }               
98
99
100 /* write configuration space register */
101
102 void
103 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
104 {
105         switch (bytes) {
106         case 1:
107                 return chipset.cfgwriteb(cfg->hose, cfg->bus, 
108                                          cfg->slot, cfg->func, reg, data);
109         case 2:
110                 return chipset.cfgwritew(cfg->hose, cfg->bus, 
111                                          cfg->slot, cfg->func, reg, data);
112         case 4:
113                 return chipset.cfgwritel(cfg->hose, cfg->bus, 
114                                          cfg->slot, cfg->func, reg, data);
115         }
116 }
117
118 vm_offset_t 
119 pci_cvt_to_dense(vm_offset_t sparse)
120 {
121         if(chipset.cvt_to_dense)
122                 return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_dense(sparse));
123         else
124                 return NULL;
125 }
126
127 vm_offset_t
128 pci_cvt_to_bwx(vm_offset_t sparse)
129 {
130         if(chipset.cvt_to_bwx)
131                 return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_bwx(sparse));
132         else
133                 return NULL;
134 }
135
136 void
137 alpha_platform_assign_pciintr(pcicfgregs *cfg)
138 {
139         if(platform.pci_intr_map)
140                 platform.pci_intr_map((void *)cfg);
141 }
142
143 int
144 alpha_platform_setup_ide_intr(int chan, driver_intr_t *fn, void *arg)
145 {
146         if (platform.pci_setup_ide_intr)
147                 return platform.pci_setup_ide_intr(chan, fn, arg);
148         else {
149                 int irqs[2] = { 14, 15 };
150                 void *junk;
151                 struct resource *res;
152                 res = isa_alloc_intr(0, 0, irqs[chan]);
153                 if (res)
154                         return isa_setup_intr(0, 0, res, INTR_TYPE_BIO,
155                                               fn, arg, &junk);
156                 else
157                         return ENOMEM;
158         }
159 }
160
161 static struct rman irq_rman, port_rman, mem_rman;
162
163 void pci_init_resources()
164 {
165         irq_rman.rm_start = 0;
166         irq_rman.rm_end = 64;
167         irq_rman.rm_type = RMAN_ARRAY;
168         irq_rman.rm_descr = "PCI Interrupt request lines";
169         if (rman_init(&irq_rman)
170             || rman_manage_region(&irq_rman, 0, 63))
171                 panic("pci_init_resources irq_rman");
172
173         port_rman.rm_start = 0;
174         port_rman.rm_end = ~0u;
175         port_rman.rm_type = RMAN_ARRAY;
176         port_rman.rm_descr = "I/O ports";
177         if (rman_init(&port_rman)
178             || rman_manage_region(&port_rman, 0x0, (1L << 32)))
179                 panic("pci_init_resources port_rman");
180
181         mem_rman.rm_start = 0;
182         mem_rman.rm_end = ~0u;
183         mem_rman.rm_type = RMAN_ARRAY;
184         mem_rman.rm_descr = "I/O memory";
185         if (rman_init(&mem_rman)
186             || rman_manage_region(&mem_rman, 0x0, (1L << 32)))
187                 panic("pci_init_resources mem_rman");
188 }
189
190 /*
191  * Allocate a resource on behalf of child.  NB: child is usually going to be a
192  * child of one of our descendants, not a direct child of the pci chipset.
193  */
194 struct resource *
195 pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
196                    u_long start, u_long end, u_long count, u_int flags)
197 {
198         struct  rman *rm;
199         struct  resource *rv;
200
201         switch (type) {
202         case SYS_RES_IRQ:
203                 rm = &irq_rman;
204                 break;
205
206         case SYS_RES_IOPORT:
207                 rm = &port_rman;
208                 break;
209
210         case SYS_RES_DENSE:
211         case SYS_RES_BWX:
212         case SYS_RES_MEMORY:
213                 rm = &mem_rman;
214                 break;
215
216         default:
217                 return 0;
218         }
219
220         rv = rman_reserve_resource(rm, start, end, count, flags, child);
221         if (rv == 0)
222                 return 0;
223
224         switch (type) {
225         case SYS_RES_MEMORY:
226                 rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM);
227                 rman_set_bushandle(rv, rv->r_start);
228                 rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */
229                 break;
230
231         case SYS_RES_DENSE:
232                 rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM);
233                 rman_set_bushandle(rv, rv->r_start);
234                 rman_set_virtual(rv, pci_cvt_to_dense(rv->r_start));
235                 break;
236
237         case SYS_RES_BWX:
238                 rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM);
239                 rman_set_bushandle(rv, rv->r_start);
240                 rman_set_virtual(rv, pci_cvt_to_bwx(rv->r_start));
241                 break;
242
243         case SYS_RES_IOPORT:
244                 rman_set_bustag(rv, ALPHA_BUS_SPACE_IO);
245                 rman_set_bushandle(rv, rv->r_start);
246                 break;
247         }
248
249         return rv;
250 }
251
252 int
253 pci_activate_resource(device_t bus, device_t child, int type, int rid,
254                       struct resource *r)
255 {
256         return (rman_activate_resource(r));
257 }
258
259 int
260 pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
261                           struct resource *r)
262 {
263         return (rman_deactivate_resource(r));
264 }
265
266 int
267 pci_release_resource(device_t bus, device_t child, int type, int rid,
268                        struct resource *r)
269 {
270         return (rman_release_resource(r));
271 }
272
273 void
274 memcpy_fromio(void *d, u_int32_t s, size_t size)
275 {
276     char *cp = d;
277
278     while (size--)
279         *cp++ = readb(s++);
280 }
281
282 void
283 memcpy_toio(u_int32_t d, void *s, size_t size)
284 {
285     char *cp = s;
286
287     while (size--)
288         writeb(d++, *cp++);
289 }
290
291 void
292 memcpy_io(u_int32_t d, u_int32_t s, size_t size)
293 {
294     while (size--)
295         writeb(d++, readb(s++));
296 }
297
298 void
299 memset_io(u_int32_t d, int val, size_t size)
300 {
301     while (size--)
302         writeb(d++, val);
303 }
304
305 void
306 memsetw(void *d, int val, size_t size)
307 {
308     u_int16_t *sp = d;
309
310     while (size--)
311         *sp++ = val;
312 }
313
314 void
315 memsetw_io(u_int32_t d, int val, size_t size)
316 {
317     while (size--) {
318         writew(d, val);
319         d += sizeof(u_int16_t);
320     }
321 }
322
323 #include "opt_ddb.h"
324 #ifdef DDB
325 #include <ddb/ddb.h>
326
327 DB_COMMAND(in, db_in)
328 {
329     int c;
330     int size;
331
332     if (!have_addr)
333         return;
334
335     size = -1;
336     while ((c = *modif++) != '\0') {
337         switch (c) {
338         case 'b':
339             size = 1;
340             break;
341         case 'w':
342             size = 2;
343             break;
344         case 'l':
345             size = 4;
346             break;
347         }
348     }
349
350     if (size < 0) {
351         db_printf("bad size\n");
352         return;
353     }
354
355     if (count <= 0) count = 1;
356     while (--count >= 0) {
357         db_printf("%08lx:\t", addr);
358         switch (size) {
359         case 1:
360             db_printf("%02x\n", inb(addr));
361             break;
362         case 2:
363             db_printf("%04x\n", inw(addr));
364             break;
365         case 4:
366             db_printf("%08x\n", inl(addr));
367             break;
368         }
369     }
370 }
371
372 #endif