xref: /openbsd/sys/dev/pci/qlw_pci.c (revision 9593dc34)
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