1 /* $OpenBSD: qlw_pci.c,v 1.14 2024/09/04 07:54:52 mglocker Exp $ */
2
3 /*
4 * Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
5 * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
6 * Copyright (c) 2014 Mark Kettenis <kettenis@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/device.h>
24
25 #include <machine/bus.h>
26
27 #include <dev/pci/pcireg.h>
28 #include <dev/pci/pcivar.h>
29 #include <dev/pci/pcidevs.h>
30
31 #ifdef __sparc64__
32 #include <dev/ofw/openfirm.h>
33 #endif
34
35 #include <scsi/scsi_all.h>
36 #include <scsi/scsiconf.h>
37
38 #include <dev/ic/qlwreg.h>
39 #include <dev/ic/qlwvar.h>
40
41 #ifndef ISP_NOFIRMWARE
42 #include <dev/microcode/isp/asm_1040.h>
43 #include <dev/microcode/isp/asm_1080.h>
44 #include <dev/microcode/isp/asm_12160.h>
45 #endif
46
47 #define QLW_PCI_MEM_BAR 0x14
48 #define QLW_PCI_IO_BAR 0x10
49
50 int qlw_pci_match(struct device *, void *, void *);
51 void qlw_pci_attach(struct device *, struct device *, void *);
52 int qlw_pci_detach(struct device *, int);
53
54 struct qlw_pci_softc {
55 struct qlw_softc psc_qlw;
56
57 pci_chipset_tag_t psc_pc;
58 pcitag_t psc_tag;
59
60 void *psc_ih;
61 };
62
63 const struct cfattach qlw_pci_ca = {
64 sizeof(struct qlw_pci_softc),
65 qlw_pci_match,
66 qlw_pci_attach
67 };
68
69 static const struct pci_matchid qlw_devices[] = {
70 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 },
71 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 },
72 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 },
73 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 },
74 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 },
75 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 },
76 };
77
78 int
qlw_pci_match(struct device * parent,void * match,void * aux)79 qlw_pci_match(struct device *parent, void *match, void *aux)
80 {
81 struct pci_attach_args *pa = aux;
82
83 /* Silly AMI MegaRAID exposes its ISP12160 to us. */
84 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_QLOGIC_ISP12160) {
85 pcireg_t subid;
86
87 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBVEND_0);
88 if (PCI_VENDOR(subid) == PCI_VENDOR_AMI)
89 return (0);
90 }
91
92 return (pci_matchbyid(aux, qlw_devices, nitems(qlw_devices)) * 2);
93 }
94
95 void
qlw_pci_attach(struct device * parent,struct device * self,void * aux)96 qlw_pci_attach(struct device *parent, struct device *self, void *aux)
97 {
98 struct qlw_pci_softc *psc = (void *)self;
99 struct qlw_softc *sc = &psc->psc_qlw;
100 struct pci_attach_args *pa = aux;
101 pci_intr_handle_t ih;
102 const char *intrstr;
103 u_int32_t pcictl;
104 #ifdef __sparc64__
105 int node, initiator;
106 #endif
107
108 pcireg_t bars[] = { QLW_PCI_MEM_BAR, QLW_PCI_IO_BAR };
109 pcireg_t memtype;
110 int r;
111
112 psc->psc_pc = pa->pa_pc;
113 psc->psc_tag = pa->pa_tag;
114 psc->psc_ih = NULL;
115 sc->sc_dmat = pa->pa_dmat;
116 sc->sc_ios = 0;
117
118 for (r = 0; r < nitems(bars); r++) {
119 memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, bars[r]);
120 if (pci_mapreg_map(pa, bars[r], memtype, 0,
121 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, 0) == 0)
122 break;
123
124 sc->sc_ios = 0;
125 }
126 if (sc->sc_ios == 0) {
127 printf(": unable to map registers\n");
128 return;
129 }
130
131 if (pci_intr_map(pa, &ih)) {
132 printf(": unable to map interrupt\n");
133 goto unmap;
134 }
135 intrstr = pci_intr_string(psc->psc_pc, ih);
136 psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
137 qlw_intr, sc, DEVNAME(sc));
138 if (psc->psc_ih == NULL) {
139 printf(": unable to establish interrupt");
140 if (intrstr != NULL)
141 printf(" at %s", intrstr);
142 printf("\n");
143 goto deintr;
144 }
145
146 printf(": %s\n", intrstr);
147
148 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
149 pcictl |= PCI_COMMAND_INVALIDATE_ENABLE |
150 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
151 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pcictl);
152
153 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
154 pcictl &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
155 pcictl &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
156 pcictl |= (0x80 << PCI_LATTIMER_SHIFT);
157 pcictl |= (0x10 << PCI_CACHELINE_SHIFT);
158 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, pcictl);
159
160 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
161 pcictl &= ~1;
162 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, pcictl);
163
164 switch (PCI_PRODUCT(pa->pa_id)) {
165 case PCI_PRODUCT_QLOGIC_ISP1020:
166 sc->sc_isp_gen = QLW_GEN_ISP1040;
167 switch (PCI_REVISION(pa->pa_class)) {
168 case 0:
169 sc->sc_isp_type = QLW_ISP1020;
170 break;
171 case 1:
172 sc->sc_isp_type = QLW_ISP1020A;
173 break;
174 case 2:
175 sc->sc_isp_type = QLW_ISP1040;
176 break;
177 case 3:
178 sc->sc_isp_type = QLW_ISP1040A;
179 break;
180 case 4:
181 sc->sc_isp_type = QLW_ISP1040B;
182 break;
183 case 5:
184 default:
185 sc->sc_isp_type = QLW_ISP1040C;
186 break;
187 }
188 sc->sc_numbusses = 1;
189 if (PCI_REVISION(pa->pa_class) < 2)
190 sc->sc_clock = 40; /* ISP1020/1020A */
191 else
192 sc->sc_clock = 60; /* ISP1040/1040A/1040B/1040C */
193 break;
194
195 case PCI_PRODUCT_QLOGIC_ISP1240:
196 sc->sc_isp_gen = QLW_GEN_ISP1080;
197 sc->sc_isp_type = QLW_ISP1240;
198 sc->sc_numbusses = 2;
199 sc->sc_clock = 60;
200 break;
201
202 case PCI_PRODUCT_QLOGIC_ISP1080:
203 sc->sc_isp_gen = QLW_GEN_ISP1080;
204 sc->sc_isp_type = QLW_ISP1080;
205 sc->sc_numbusses = 1;
206 sc->sc_clock = 100;
207 break;
208
209 case PCI_PRODUCT_QLOGIC_ISP1280:
210 sc->sc_isp_gen = QLW_GEN_ISP1080;
211 sc->sc_isp_type = QLW_ISP1280;
212 sc->sc_numbusses = 2;
213 sc->sc_clock = 100;
214 break;
215
216 case PCI_PRODUCT_QLOGIC_ISP10160:
217 sc->sc_isp_gen = QLW_GEN_ISP12160;
218 sc->sc_isp_type = QLW_ISP10160;
219 sc->sc_numbusses = 1;
220 sc->sc_clock = 100;
221 break;
222
223 case PCI_PRODUCT_QLOGIC_ISP12160:
224 sc->sc_isp_gen = QLW_GEN_ISP12160;
225 sc->sc_isp_type = QLW_ISP12160;
226 sc->sc_numbusses = 2;
227 sc->sc_clock = 100;
228 break;
229
230 default:
231 printf("unknown pci id %x", pa->pa_id);
232 return;
233 }
234
235 #ifndef ISP_NOFIRMWARE
236 switch (sc->sc_isp_gen) {
237 case QLW_GEN_ISP1040:
238 sc->sc_firmware = isp_1040_risc_code;
239 break;
240 case QLW_GEN_ISP1080:
241 sc->sc_firmware = isp_1080_risc_code;
242 break;
243 case QLW_GEN_ISP12160:
244 sc->sc_firmware = isp_12160_risc_code;
245 break;
246 default:
247 break;
248 }
249 #endif
250
251 /*
252 * The standard SCSI initiator ID is 7.
253 * Add-on cards should have a valid nvram, which will override
254 * these defaults.
255 */
256 sc->sc_initiator[0] = sc->sc_initiator[1] = 7;
257
258 #ifdef __sparc64__
259 /*
260 * Walk up the Open Firmware device tree until we find a
261 * "scsi-initiator-id" property.
262 */
263 node = PCITAG_NODE(pa->pa_tag);
264 while (node) {
265 if (OF_getprop(node, "scsi-initiator-id",
266 &initiator, sizeof(initiator)) == sizeof(initiator)) {
267 /*
268 * Override the SCSI initiator ID provided by
269 * the nvram.
270 */
271 sc->sc_flags |= QLW_FLAG_INITIATOR;
272 sc->sc_initiator[0] = sc->sc_initiator[1] = initiator;
273 break;
274 }
275 node = OF_parent(node);
276 }
277 #endif
278
279 sc->sc_host_cmd_ctrl = QLW_HOST_CMD_CTRL_PCI;
280 sc->sc_mbox_base = QLW_MBOX_BASE_PCI;
281
282 if (qlw_attach(sc) != 0) {
283 /* error printed by qlw_attach */
284 goto deintr;
285 }
286
287 return;
288
289 deintr:
290 pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
291 psc->psc_ih = NULL;
292 unmap:
293 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
294 sc->sc_ios = 0;
295 }
296
297 int
qlw_pci_detach(struct device * self,int flags)298 qlw_pci_detach(struct device *self, int flags)
299 {
300 struct qlw_pci_softc *psc = (struct qlw_pci_softc *)self;
301 struct qlw_softc *sc = &psc->psc_qlw;
302 int rv;
303
304 if (psc->psc_ih == NULL) {
305 /* we didn't attach properly, so nothing to detach */
306 return (0);
307 }
308
309 rv = qlw_detach(sc, flags);
310 if (rv != 0)
311 return (rv);
312
313 pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
314 psc->psc_ih = NULL;
315
316 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
317 sc->sc_ios = 0;
318
319 return (0);
320 }
321