]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/pci/pcibus.c
This commit was generated by cvs2svn to compensate for changes in r52894,
[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_MEMORY:
211                 rm = &mem_rman;
212                 break;
213
214         default:
215                 return 0;
216         }
217
218         rv = rman_reserve_resource(rm, start, end, count, flags, child);
219         if (rv == 0)
220                 return 0;
221
222         switch (type) {
223         case SYS_RES_MEMORY:
224                 rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM);
225                 rman_set_bushandle(rv, rv->r_start);
226                 if (flags & PCI_RF_DENSE)
227                         rman_set_virtual(rv, pci_cvt_to_dense(rv->r_start));
228                 else if (flags & PCI_RF_BWX)
229                         rman_set_virtual(rv, pci_cvt_to_bwx(rv->r_start));
230                 else
231                         rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */
232                 break;
233
234         case SYS_RES_IOPORT:
235                 rman_set_bustag(rv, ALPHA_BUS_SPACE_IO);
236                 rman_set_bushandle(rv, rv->r_start);
237                 break;
238         }
239
240         return rv;
241 }
242
243 int
244 pci_activate_resource(device_t bus, device_t child, int type, int rid,
245                       struct resource *r)
246 {
247         return (rman_activate_resource(r));
248 }
249
250 int
251 pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
252                           struct resource *r)
253 {
254         return (rman_deactivate_resource(r));
255 }
256
257 int
258 pci_release_resource(device_t bus, device_t child, int type, int rid,
259                        struct resource *r)
260 {
261         return (rman_release_resource(r));
262 }
263
264 void
265 memcpy_fromio(void *d, u_int32_t s, size_t size)
266 {
267     char *cp = d;
268
269     while (size--)
270         *cp++ = readb(s++);
271 }
272
273 void
274 memcpy_toio(u_int32_t d, void *s, size_t size)
275 {
276     char *cp = s;
277
278     while (size--)
279         writeb(d++, *cp++);
280 }
281
282 void
283 memcpy_io(u_int32_t d, u_int32_t s, size_t size)
284 {
285     while (size--)
286         writeb(d++, readb(s++));
287 }
288
289 void
290 memset_io(u_int32_t d, int val, size_t size)
291 {
292     while (size--)
293         writeb(d++, val);
294 }
295
296 void
297 memsetw(void *d, int val, size_t size)
298 {
299     u_int16_t *sp = d;
300
301     while (size--)
302         *sp++ = val;
303 }
304
305 void
306 memsetw_io(u_int32_t d, int val, size_t size)
307 {
308     while (size--) {
309         writew(d, val);
310         d += sizeof(u_int16_t);
311     }
312 }
313
314 #include "opt_ddb.h"
315 #ifdef DDB
316 #include <ddb/ddb.h>
317
318 DB_COMMAND(in, db_in)
319 {
320     int c;
321     int size;
322
323     if (!have_addr)
324         return;
325
326     size = -1;
327     while ((c = *modif++) != '\0') {
328         switch (c) {
329         case 'b':
330             size = 1;
331             break;
332         case 'w':
333             size = 2;
334             break;
335         case 'l':
336             size = 4;
337             break;
338         }
339     }
340
341     if (size < 0) {
342         db_printf("bad size\n");
343         return;
344     }
345
346     if (count <= 0) count = 1;
347     while (--count >= 0) {
348         db_printf("%08lx:\t", addr);
349         switch (size) {
350         case 1:
351             db_printf("%02x\n", inb(addr));
352             break;
353         case 2:
354             db_printf("%04x\n", inw(addr));
355             break;
356         case 4:
357             db_printf("%08x\n", inl(addr));
358             break;
359         }
360     }
361 }
362
363 #endif