pci_map.c revision 1.4 1 1.3 lonhyn /* $NetBSD: pci_map.c,v 1.4 1997/10/06 21:01:24 thorpej Exp $ */
2 1.1 mycroft
3 1.1 mycroft /*
4 1.1 mycroft * Copyright (c) 1994, 1997 Charles M. Hannum. All rights reserved.
5 1.1 mycroft *
6 1.1 mycroft * Redistribution and use in source and binary forms, with or without
7 1.1 mycroft * modification, are permitted provided that the following conditions
8 1.1 mycroft * are met:
9 1.1 mycroft * 1. Redistributions of source code must retain the above copyright
10 1.1 mycroft * notice, this list of conditions and the following disclaimer.
11 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 mycroft * notice, this list of conditions and the following disclaimer in the
13 1.1 mycroft * documentation and/or other materials provided with the distribution.
14 1.1 mycroft * 3. All advertising materials mentioning features or use of this software
15 1.1 mycroft * must display the following acknowledgement:
16 1.1 mycroft * This product includes software developed by Charles M. Hannum.
17 1.1 mycroft * 4. The name of the author may not be used to endorse or promote products
18 1.1 mycroft * derived from this software without specific prior written permission.
19 1.1 mycroft *
20 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 1.1 mycroft * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 1.1 mycroft * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 1.1 mycroft * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 1.1 mycroft * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 1.1 mycroft * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 1.1 mycroft * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 1.1 mycroft * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 1.1 mycroft * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 1.1 mycroft * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 1.1 mycroft */
31 1.1 mycroft
32 1.1 mycroft /*
33 1.1 mycroft * PCI device mapping.
34 1.1 mycroft */
35 1.1 mycroft
36 1.1 mycroft #include <sys/param.h>
37 1.1 mycroft #include <sys/systm.h>
38 1.1 mycroft #include <sys/device.h>
39 1.1 mycroft
40 1.1 mycroft #include <dev/pci/pcireg.h>
41 1.1 mycroft #include <dev/pci/pcivar.h>
42 1.1 mycroft
43 1.1 mycroft static int pci_io_find __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t,
44 1.1 mycroft bus_addr_t *, bus_size_t *, int *));
45 1.1 mycroft static int pci_mem_find __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t,
46 1.1 mycroft bus_addr_t *, bus_size_t *, int *));
47 1.1 mycroft
48 1.1 mycroft static int
49 1.1 mycroft pci_io_find(pc, tag, reg, type, basep, sizep, flagsp)
50 1.1 mycroft pci_chipset_tag_t pc;
51 1.1 mycroft pcitag_t tag;
52 1.1 mycroft int reg;
53 1.1 mycroft pcireg_t type;
54 1.1 mycroft bus_addr_t *basep;
55 1.1 mycroft bus_size_t *sizep;
56 1.1 mycroft int *flagsp;
57 1.1 mycroft {
58 1.1 mycroft pcireg_t address, mask;
59 1.1 mycroft int s;
60 1.1 mycroft
61 1.1 mycroft if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
62 1.1 mycroft panic("pci_io_find: bad request");
63 1.1 mycroft
64 1.1 mycroft /*
65 1.1 mycroft * Section 6.2.5.1, `Address Maps', tells us that:
66 1.1 mycroft *
67 1.1 mycroft * 1) The builtin software should have already mapped the device in a
68 1.1 mycroft * reasonable way.
69 1.1 mycroft *
70 1.1 mycroft * 2) A device which wants 2^n bytes of memory will hardwire the bottom
71 1.1 mycroft * n bits of the address to 0. As recommended, we write all 1s and see
72 1.1 mycroft * what we get back.
73 1.1 mycroft */
74 1.1 mycroft s = splhigh();
75 1.1 mycroft address = pci_conf_read(pc, tag, reg);
76 1.1 mycroft pci_conf_write(pc, tag, reg, 0xffffffff);
77 1.1 mycroft mask = pci_conf_read(pc, tag, reg);
78 1.1 mycroft pci_conf_write(pc, tag, reg, address);
79 1.1 mycroft splx(s);
80 1.1 mycroft
81 1.1 mycroft if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
82 1.1 mycroft printf("pci_io_find: expected type i/o, found mem\n");
83 1.1 mycroft return (1);
84 1.1 mycroft }
85 1.1 mycroft
86 1.2 mycroft if (PCI_MAPREG_IO_SIZE(mask) == 0) {
87 1.2 mycroft printf("pci_io_find: void region\n");
88 1.2 mycroft return (1);
89 1.2 mycroft }
90 1.2 mycroft
91 1.1 mycroft if (basep != 0)
92 1.1 mycroft *basep = PCI_MAPREG_IO_ADDR(address);
93 1.1 mycroft if (sizep != 0)
94 1.1 mycroft *sizep = PCI_MAPREG_IO_SIZE(mask);
95 1.1 mycroft if (flagsp != 0)
96 1.1 mycroft *flagsp = 0;
97 1.1 mycroft
98 1.1 mycroft return (0);
99 1.1 mycroft }
100 1.1 mycroft
101 1.1 mycroft static int
102 1.1 mycroft pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp)
103 1.1 mycroft pci_chipset_tag_t pc;
104 1.1 mycroft pcitag_t tag;
105 1.1 mycroft int reg;
106 1.1 mycroft pcireg_t type;
107 1.1 mycroft bus_addr_t *basep;
108 1.1 mycroft bus_size_t *sizep;
109 1.1 mycroft int *flagsp;
110 1.1 mycroft {
111 1.1 mycroft pcireg_t address, mask;
112 1.1 mycroft int s;
113 1.1 mycroft
114 1.1 mycroft if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
115 1.1 mycroft panic("pci_find_mem: bad request");
116 1.1 mycroft
117 1.1 mycroft /*
118 1.1 mycroft * Section 6.2.5.1, `Address Maps', tells us that:
119 1.1 mycroft *
120 1.1 mycroft * 1) The builtin software should have already mapped the device in a
121 1.1 mycroft * reasonable way.
122 1.1 mycroft *
123 1.1 mycroft * 2) A device which wants 2^n bytes of memory will hardwire the bottom
124 1.1 mycroft * n bits of the address to 0. As recommended, we write all 1s and see
125 1.1 mycroft * what we get back.
126 1.1 mycroft */
127 1.1 mycroft s = splhigh();
128 1.1 mycroft address = pci_conf_read(pc, tag, reg);
129 1.1 mycroft pci_conf_write(pc, tag, reg, 0xffffffff);
130 1.1 mycroft mask = pci_conf_read(pc, tag, reg);
131 1.1 mycroft pci_conf_write(pc, tag, reg, address);
132 1.1 mycroft splx(s);
133 1.1 mycroft
134 1.1 mycroft if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
135 1.1 mycroft printf("pci_mem_find: expected type mem, found i/o\n");
136 1.1 mycroft return (1);
137 1.1 mycroft }
138 1.1 mycroft if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
139 1.1 mycroft printf("pci_mem_find: expected mem type %08x, found %08x\n",
140 1.1 mycroft PCI_MAPREG_MEM_TYPE(type),
141 1.1 mycroft PCI_MAPREG_MEM_TYPE(address));
142 1.2 mycroft return (1);
143 1.2 mycroft }
144 1.2 mycroft
145 1.2 mycroft if (PCI_MAPREG_MEM_SIZE(mask) == 0) {
146 1.2 mycroft printf("pci_mem_find: void region\n");
147 1.1 mycroft return (1);
148 1.1 mycroft }
149 1.1 mycroft
150 1.1 mycroft switch (PCI_MAPREG_MEM_TYPE(address)) {
151 1.1 mycroft case PCI_MAPREG_MEM_TYPE_32BIT:
152 1.1 mycroft case PCI_MAPREG_MEM_TYPE_32BIT_1M:
153 1.1 mycroft break;
154 1.1 mycroft case PCI_MAPREG_MEM_TYPE_64BIT:
155 1.1 mycroft printf("pci_mem_find: 64-bit memory mapping register\n");
156 1.1 mycroft return (1);
157 1.1 mycroft default:
158 1.1 mycroft printf("pci_mem_find: reserved mapping register type\n");
159 1.1 mycroft return (1);
160 1.1 mycroft }
161 1.1 mycroft
162 1.1 mycroft if (basep != 0)
163 1.1 mycroft *basep = PCI_MAPREG_MEM_ADDR(address);
164 1.1 mycroft if (sizep != 0)
165 1.1 mycroft *sizep = PCI_MAPREG_MEM_SIZE(mask);
166 1.1 mycroft if (flagsp != 0)
167 1.1 mycroft *flagsp = PCI_MAPREG_MEM_CACHEABLE(address) ?
168 1.1 mycroft BUS_SPACE_MAP_CACHEABLE : 0;
169 1.1 mycroft
170 1.1 mycroft return (0);
171 1.1 mycroft }
172 1.1 mycroft
173 1.1 mycroft int
174 1.4 thorpej pci_mapreg_info(pc, tag, reg, type, basep, sizep, flagsp)
175 1.4 thorpej pci_chipset_tag_t pc;
176 1.4 thorpej pcitag_t tag;
177 1.1 mycroft int reg;
178 1.1 mycroft pcireg_t type;
179 1.1 mycroft bus_addr_t *basep;
180 1.1 mycroft bus_size_t *sizep;
181 1.4 thorpej int *flagsp;
182 1.1 mycroft {
183 1.1 mycroft
184 1.1 mycroft if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
185 1.4 thorpej return (pci_io_find(pc, tag, reg, type, basep, sizep,
186 1.4 thorpej flagsp));
187 1.1 mycroft else
188 1.4 thorpej return (pci_mem_find(pc, tag, reg, type, basep, sizep,
189 1.4 thorpej flagsp));
190 1.1 mycroft }
191 1.1 mycroft
192 1.1 mycroft int
193 1.1 mycroft pci_mapreg_map(pa, reg, type, busflags, tagp, handlep, basep, sizep)
194 1.1 mycroft struct pci_attach_args *pa;
195 1.1 mycroft int reg, busflags;
196 1.1 mycroft pcireg_t type;
197 1.1 mycroft bus_space_tag_t *tagp;
198 1.1 mycroft bus_space_handle_t *handlep;
199 1.1 mycroft bus_addr_t *basep;
200 1.1 mycroft bus_size_t *sizep;
201 1.1 mycroft {
202 1.1 mycroft bus_space_tag_t tag;
203 1.1 mycroft bus_space_handle_t handle;
204 1.1 mycroft bus_addr_t base;
205 1.1 mycroft bus_size_t size;
206 1.1 mycroft int flags;
207 1.1 mycroft
208 1.1 mycroft if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
209 1.1 mycroft if ((pa->pa_flags & PCI_FLAGS_IO_ENABLED) == 0)
210 1.1 mycroft return (1);
211 1.1 mycroft if (pci_io_find(pa->pa_pc, pa->pa_tag, reg, type, &base,
212 1.1 mycroft &size, &flags))
213 1.1 mycroft return (1);
214 1.1 mycroft tag = pa->pa_iot;
215 1.1 mycroft } else {
216 1.1 mycroft if ((pa->pa_flags & PCI_FLAGS_MEM_ENABLED) == 0)
217 1.1 mycroft return (1);
218 1.1 mycroft if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg, type, &base,
219 1.1 mycroft &size, &flags))
220 1.1 mycroft return (1);
221 1.1 mycroft tag = pa->pa_memt;
222 1.1 mycroft }
223 1.1 mycroft
224 1.1 mycroft if (bus_space_map(tag, base, size, busflags | flags, &handle))
225 1.1 mycroft return (1);
226 1.1 mycroft
227 1.1 mycroft if (tagp != 0)
228 1.1 mycroft *tagp = tag;
229 1.1 mycroft if (handlep != 0)
230 1.1 mycroft *handlep = handle;
231 1.1 mycroft if (basep != 0)
232 1.1 mycroft *basep = base;
233 1.1 mycroft if (sizep != 0)
234 1.1 mycroft *sizep = size;
235 1.1 mycroft
236 1.1 mycroft return (0);
237 1.1 mycroft }
238