1 | /* $NetBSD: siop_pci_common.c,v 1.36 2016/10/17 16:02:10 flxd Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2000 Manuel Bouyer. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following 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 | |
27 | /* SYM53c8xx PCI-SCSI I/O Processors driver: PCI front-end */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: siop_pci_common.c,v 1.36 2016/10/17 16:02:10 flxd Exp $" ); |
31 | |
32 | #include <sys/param.h> |
33 | #include <sys/systm.h> |
34 | #include <sys/device.h> |
35 | #include <sys/malloc.h> |
36 | #include <sys/buf.h> |
37 | #include <sys/kernel.h> |
38 | |
39 | #include <machine/endian.h> |
40 | |
41 | #include <dev/pci/pcireg.h> |
42 | #include <dev/pci/pcivar.h> |
43 | #include <dev/pci/pcidevs.h> |
44 | |
45 | #include <dev/scsipi/scsipi_all.h> |
46 | #include <dev/scsipi/scsipiconf.h> |
47 | |
48 | #include <dev/ic/siopreg.h> |
49 | #include <dev/ic/siopvar_common.h> |
50 | #include <dev/pci/siop_pci_common.h> |
51 | |
52 | /* List (array, really :) of chips we know how to handle */ |
53 | static const struct siop_product_desc siop_products[] = { |
54 | { PCI_PRODUCT_SYMBIOS_810, |
55 | 0x00, |
56 | "Symbios Logic 53c810 (fast scsi)" , |
57 | SF_PCI_RL | SF_CHIP_LS, |
58 | 4, 8, 3, 250, 0 |
59 | }, |
60 | { PCI_PRODUCT_SYMBIOS_810, |
61 | 0x10, |
62 | "Symbios Logic 53c810a (fast scsi)" , |
63 | SF_PCI_RL | SF_PCI_BOF | SF_CHIP_PF | SF_CHIP_LS, |
64 | 4, 8, 3, 250, 0 |
65 | }, |
66 | { PCI_PRODUCT_SYMBIOS_810AP, |
67 | 0x00, |
68 | "Symbios Logic 53c810ap (fast scsi)" , |
69 | SF_PCI_RL | SF_PCI_BOF | SF_CHIP_PF | SF_CHIP_LS, |
70 | 4, 8, 3, 250, 0 |
71 | }, |
72 | { PCI_PRODUCT_SYMBIOS_815, |
73 | 0x00, |
74 | "Symbios Logic 53c815 (fast scsi)" , |
75 | SF_PCI_RL | SF_PCI_BOF, |
76 | 4, 8, 3, 250, 0 |
77 | }, |
78 | { PCI_PRODUCT_SYMBIOS_820, |
79 | 0x00, |
80 | "Symbios Logic 53c820 (fast wide scsi)" , |
81 | SF_PCI_RL | SF_CHIP_LS | SF_BUS_WIDE, |
82 | 4, 8, 3, 250, 0 |
83 | }, |
84 | { PCI_PRODUCT_SYMBIOS_825, |
85 | 0x00, |
86 | "Symbios Logic 53c825 (fast wide scsi)" , |
87 | SF_PCI_RL | SF_PCI_BOF | SF_BUS_WIDE, |
88 | 4, 8, 3, 250, 0 |
89 | }, |
90 | { PCI_PRODUCT_SYMBIOS_825, |
91 | 0x10, |
92 | "Symbios Logic 53c825a (fast wide scsi)" , |
93 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
94 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS | |
95 | SF_BUS_WIDE, |
96 | 7, 8, 3, 250, 4096 |
97 | }, |
98 | { PCI_PRODUCT_SYMBIOS_860, |
99 | 0x00, |
100 | "Symbios Logic 53c860 (ultra scsi)" , |
101 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
102 | SF_CHIP_PF | SF_CHIP_LS | |
103 | SF_BUS_ULTRA, |
104 | 4, 8, 5, 125, 0 |
105 | }, |
106 | { PCI_PRODUCT_SYMBIOS_875, |
107 | 0x00, |
108 | "Symbios Logic 53c875 (ultra-wide scsi)" , |
109 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
110 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_LS | SF_CHIP_10REGS | |
111 | SF_BUS_ULTRA | SF_BUS_WIDE, |
112 | 7, 16, 5, 125, 4096 |
113 | }, |
114 | { PCI_PRODUCT_SYMBIOS_875, |
115 | 0x02, |
116 | "Symbios Logic 53c875 (ultra-wide scsi)" , |
117 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
118 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | |
119 | SF_CHIP_LS | SF_CHIP_10REGS | |
120 | SF_BUS_ULTRA | SF_BUS_WIDE, |
121 | 7, 16, 5, 125, 4096 |
122 | }, |
123 | { PCI_PRODUCT_SYMBIOS_875J, |
124 | 0x00, |
125 | "Symbios Logic 53c875j (ultra-wide scsi)" , |
126 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
127 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | |
128 | SF_CHIP_LS | SF_CHIP_10REGS | |
129 | SF_BUS_ULTRA | SF_BUS_WIDE, |
130 | 7, 16, 5, 125, 4096 |
131 | }, |
132 | { PCI_PRODUCT_SYMBIOS_885, |
133 | 0x00, |
134 | "Symbios Logic 53c885 (ultra-wide scsi)" , |
135 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
136 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_DBLR | |
137 | SF_CHIP_LS | SF_CHIP_10REGS | |
138 | SF_BUS_ULTRA | SF_BUS_WIDE, |
139 | 7, 16, 5, 125, 4096 |
140 | }, |
141 | { PCI_PRODUCT_SYMBIOS_895, |
142 | 0x00, |
143 | "Symbios Logic 53c895 (ultra2-wide scsi)" , |
144 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
145 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | |
146 | SF_CHIP_LS | SF_CHIP_10REGS | |
147 | SF_BUS_ULTRA2 | SF_BUS_WIDE, |
148 | 7, 31, 7, 62, 4096 |
149 | }, |
150 | { PCI_PRODUCT_SYMBIOS_896, |
151 | 0x00, |
152 | "Symbios Logic 53c896 (ultra2-wide scsi)" , |
153 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
154 | SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | |
155 | SF_CHIP_LS | SF_CHIP_10REGS | |
156 | SF_BUS_ULTRA2 | SF_BUS_WIDE, |
157 | 7, 31, 7, 62, 8192 |
158 | }, |
159 | { PCI_PRODUCT_SYMBIOS_895A, |
160 | 0x00, |
161 | "Symbios Logic 53c895a (ultra2-wide scsi)" , |
162 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
163 | SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | |
164 | SF_CHIP_LS | SF_CHIP_10REGS | |
165 | SF_BUS_ULTRA2 | SF_BUS_WIDE, |
166 | 7, 31, 7, 62, 8192 |
167 | }, |
168 | { PCI_PRODUCT_SYMBIOS_1010, |
169 | 0x00, |
170 | "Symbios Logic 53c1010-33 rev 0 (ultra3-wide scsi)" , |
171 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
172 | SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | |
173 | SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | |
174 | SF_CHIP_GEBUG | |
175 | SF_BUS_ULTRA3 | SF_BUS_WIDE, |
176 | 7, 31, 0, 62, 8192 |
177 | }, |
178 | { PCI_PRODUCT_SYMBIOS_1010, |
179 | 0x01, |
180 | "Symbios Logic 53c1010-33 (ultra3-wide scsi)" , |
181 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
182 | SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | |
183 | SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | SF_CHIP_DT | |
184 | SF_CHIP_GEBUG | |
185 | SF_BUS_ULTRA3 | SF_BUS_WIDE, |
186 | 7, 62, 0, 62, 8192 |
187 | }, |
188 | { PCI_PRODUCT_SYMBIOS_1010_2, |
189 | 0x00, |
190 | "Symbios Logic 53c1010-66 (ultra3-wide scsi)" , |
191 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
192 | SF_CHIP_LEDC | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | |
193 | SF_CHIP_LS | SF_CHIP_10REGS | SF_CHIP_DFBC | SF_CHIP_DBLR | SF_CHIP_DT | |
194 | SF_CHIP_AAIP | |
195 | SF_BUS_ULTRA3 | SF_BUS_WIDE, |
196 | 7, 62, 0, 62, 8192 |
197 | }, |
198 | { PCI_PRODUCT_SYMBIOS_1510D, |
199 | 0x00, |
200 | "Symbios Logic 53c1510d (ultra2-wide scsi)" , |
201 | SF_PCI_RL | SF_PCI_CLS | SF_PCI_WRI | SF_PCI_RM | |
202 | SF_CHIP_FIFO | SF_CHIP_PF | SF_CHIP_RAM | SF_CHIP_QUAD | |
203 | SF_CHIP_LS | SF_CHIP_10REGS | |
204 | SF_BUS_ULTRA2 | SF_BUS_WIDE, |
205 | 7, 31, 7, 62, 4096 |
206 | }, |
207 | { 0, |
208 | 0x00, |
209 | NULL, |
210 | 0x00, |
211 | 0, 0, 0, 0, 0 |
212 | }, |
213 | }; |
214 | |
215 | const struct siop_product_desc * |
216 | siop_lookup_product(uint32_t id, int rev) |
217 | { |
218 | const struct siop_product_desc *pp; |
219 | const struct siop_product_desc *rp = NULL; |
220 | |
221 | if (PCI_VENDOR(id) != PCI_VENDOR_SYMBIOS) |
222 | return NULL; |
223 | |
224 | for (pp = siop_products; pp->name != NULL; pp++) { |
225 | if (PCI_PRODUCT(id) == pp->product && pp->revision <= rev) |
226 | if (rp == NULL || pp->revision > rp->revision) |
227 | rp = pp; |
228 | } |
229 | return rp; |
230 | } |
231 | |
232 | int |
233 | siop_pci_attach_common(struct siop_pci_common_softc *pci_sc, |
234 | struct siop_common_softc *siop_sc, struct pci_attach_args *pa, |
235 | int (*intr)(void *)) |
236 | { |
237 | pci_chipset_tag_t pc = pa->pa_pc; |
238 | pcitag_t tag = pa->pa_tag; |
239 | const char *intrstr; |
240 | pci_intr_handle_t intrhandle; |
241 | bus_space_tag_t iot, memt; |
242 | bus_space_handle_t ioh, memh; |
243 | pcireg_t memtype; |
244 | prop_dictionary_t dict; |
245 | int memh_valid, ioh_valid; |
246 | bus_addr_t ioaddr, memaddr; |
247 | bool use_pciclock; |
248 | char intrbuf[PCI_INTRSTR_LEN]; |
249 | |
250 | aprint_naive(": SCSI controller\n" ); |
251 | |
252 | pci_sc->sc_pp = |
253 | siop_lookup_product(pa->pa_id, PCI_REVISION(pa->pa_class)); |
254 | if (pci_sc->sc_pp == NULL) { |
255 | aprint_error("sym: broken match/attach!!\n" ); |
256 | return 0; |
257 | } |
258 | /* copy interesting infos about the chip */ |
259 | siop_sc->features = pci_sc->sc_pp->features; |
260 | #ifdef SIOP_SYMLED /* XXX Should be a devprop! */ |
261 | siop_sc->features |= SF_CHIP_LED0; |
262 | #endif |
263 | dict = device_properties(siop_sc->sc_dev); |
264 | if (prop_dictionary_get_bool(dict, "use_pciclock" , &use_pciclock)) |
265 | if (use_pciclock) |
266 | siop_sc->features |= SF_CHIP_USEPCIC; |
267 | siop_sc->maxburst = pci_sc->sc_pp->maxburst; |
268 | siop_sc->maxoff = pci_sc->sc_pp->maxoff; |
269 | siop_sc->clock_div = pci_sc->sc_pp->clock_div; |
270 | siop_sc->clock_period = pci_sc->sc_pp->clock_period; |
271 | siop_sc->ram_size = pci_sc->sc_pp->ram_size; |
272 | |
273 | siop_sc->sc_reset = siop_pci_reset; |
274 | aprint_normal(": %s\n" , pci_sc->sc_pp->name); |
275 | pci_sc->sc_pc = pc; |
276 | pci_sc->sc_tag = tag; |
277 | siop_sc->sc_dmat = pa->pa_dmat; |
278 | |
279 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x14); |
280 | switch (memtype) { |
281 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: |
282 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: |
283 | memh_valid = (pci_mapreg_map(pa, 0x14, memtype, 0, |
284 | &memt, &memh, &memaddr, NULL) == 0); |
285 | break; |
286 | default: |
287 | memh_valid = 0; |
288 | } |
289 | |
290 | ioh_valid = (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, |
291 | &iot, &ioh, &ioaddr, NULL) == 0); |
292 | |
293 | if (memh_valid) { |
294 | siop_sc->sc_rt = memt; |
295 | siop_sc->sc_rh = memh; |
296 | siop_sc->sc_raddr = memaddr; |
297 | } else if (ioh_valid) { |
298 | siop_sc->sc_rt = iot; |
299 | siop_sc->sc_rh = ioh; |
300 | siop_sc->sc_raddr = ioaddr; |
301 | } else { |
302 | aprint_error_dev(siop_sc->sc_dev, |
303 | "unable to map device registers\n" ); |
304 | return 0; |
305 | } |
306 | |
307 | if (siop_sc->features & SF_CHIP_RAM) { |
308 | int bar; |
309 | switch (memtype) { |
310 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: |
311 | bar = 0x18; |
312 | break; |
313 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: |
314 | bar = 0x1c; |
315 | break; |
316 | default: |
317 | aprint_error_dev(siop_sc->sc_dev, |
318 | "invalid memory type %d\n" , |
319 | memtype); |
320 | return 0; |
321 | } |
322 | if (pci_mapreg_map(pa, bar, memtype, 0, |
323 | &siop_sc->sc_ramt, &siop_sc->sc_ramh, |
324 | &siop_sc->sc_scriptaddr, NULL) == 0) { |
325 | aprint_normal_dev(siop_sc->sc_dev, |
326 | "using on-board RAM\n" ); |
327 | } else { |
328 | aprint_error_dev(siop_sc->sc_dev, |
329 | "can't map on-board RAM\n" ); |
330 | siop_sc->features &= ~SF_CHIP_RAM; |
331 | } |
332 | } |
333 | |
334 | if (pci_intr_map(pa, &intrhandle) != 0) { |
335 | aprint_error_dev(siop_sc->sc_dev, "couldn't map interrupt\n" ); |
336 | return 0; |
337 | } |
338 | intrstr = pci_intr_string(pa->pa_pc, intrhandle, intrbuf, sizeof(intrbuf)); |
339 | pci_sc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, |
340 | intr, siop_sc); |
341 | if (pci_sc->sc_ih != NULL) { |
342 | aprint_normal_dev(siop_sc->sc_dev, "interrupting at %s\n" , |
343 | intrstr ? intrstr : "unknown interrupt" ); |
344 | } else { |
345 | aprint_error_dev(siop_sc->sc_dev, |
346 | "couldn't establish interrupt" ); |
347 | if (intrstr != NULL) |
348 | aprint_error(" at %s" , intrstr); |
349 | aprint_error("\n" ); |
350 | return 0; |
351 | } |
352 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, |
353 | pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | |
354 | PCI_COMMAND_MASTER_ENABLE); |
355 | return 1; |
356 | } |
357 | |
358 | void |
359 | siop_pci_reset(struct siop_common_softc *sc) |
360 | { |
361 | int dmode; |
362 | |
363 | dmode = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE); |
364 | if (sc->features & SF_PCI_RL) |
365 | dmode |= DMODE_ERL; |
366 | if (sc->features & SF_PCI_RM) |
367 | dmode |= DMODE_ERMP; |
368 | if (sc->features & SF_PCI_BOF) |
369 | dmode |= DMODE_BOF; |
370 | if (sc->features & SF_PCI_CLS) |
371 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, |
372 | bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) | |
373 | DCNTL_CLSE); |
374 | if (sc->features & SF_PCI_WRI) |
375 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3, |
376 | bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) | |
377 | CTEST3_WRIE); |
378 | if (sc->maxburst) { |
379 | int ctest5 = bus_space_read_1(sc->sc_rt, sc->sc_rh, |
380 | SIOP_CTEST5); |
381 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, |
382 | bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) & |
383 | ~CTEST4_BDIS); |
384 | dmode &= ~DMODE_BL_MASK; |
385 | dmode |= ((sc->maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK; |
386 | ctest5 &= ~CTEST5_BBCK; |
387 | ctest5 |= (sc->maxburst - 1) & CTEST5_BBCK; |
388 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5, ctest5); |
389 | } else { |
390 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, |
391 | bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4) | |
392 | CTEST4_BDIS); |
393 | } |
394 | bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DMODE, dmode); |
395 | } |
396 | |